Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

CptMercury

Members
  • Content Count

    54
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by CptMercury

  1. You want a progress bar for the file transfer via modems?

    There is no built-in method available, so you need custom scripts for this.

    My approach would start with calculating the file's size and transmitting it to the receiving computer. Then the file is split into packets and transferred; by the size of the arriving packets the progress can easily be calculated.

    The remaining question is how to split the file. You could either send line by line or send a fixed number of bytes. Depending on your choice, the calculation method for the file size will vary.

    Number of lines:

    local n = 0  -- number of your lines
    
    for _ in io.lines("path/to/file") do
      n = n + 1
    end

    Number of bytes:

    -- Method 1:
    
    local function filesize (file)
      local pos = file:seek()
      local size = file:seek("end")
      file:seek("set", pos)
      return size
    end
    
    -- open file and call function with file
    local f = assert(io.open("path/to/file"))
    local n = filesize(f)
    
    -- Method 2:
    
    local f = assert(io.open("path/to/file"))
    local data = f:read("*all")
    local size = #data

    The only thing you then need is a way to display the progress, either by simply printing the percentage or by drawing a more or less detailed progress bar.

    I hope in correctly interpreted your question and this gets you started. Feel free to ask if you need further assistance.

  2. Well, you can use “not“, which will do exactly what you‘re trying to do.

    if not (val > x and val < y) then
      -- do stuff
    end

    But:

    - not greater than is the same as less than (actually less or equal <=)

    - not less then is the same as greater than (greater or equal)

    It would look like this:

    if val <= x and val >= y then
      -- do stuff
    end

     

     

  3. Well, you actually just need a computer and an adapter to interact with me-components (not even an inventory_controller upgrade). You also require an database component to configure me I/o stuff (export busses, import busses and interfaces)

    In order to properly use the export bus, you need to have access to the items in the network. Then, using the database component, you can store information about a stack of items in the database and use this to configure the export bus. The functions for accessing the items in the network are provided by the "common network api", which should be shared by all me-components. BUT for some reason, this api can only be accessed by the me-controller (at least in the 1.12 I'm using atm). Which means, you need to directly place your adapter next to the me-controller.

    There might be a work-around, tho. Look for an item called MFU by open computers. If you have it in your version, shift-right-click with this item on the me controller and place it in an adapter. Then you should find the component me_controller.

    If this works for you, let me know and I'll help you with the database stuff to actually configure the export bus if you have trouble to do so.

  4. Ok, as promised, here is a more advanced function.

    Instead of giving it one string and specify its color, you mark parts of the string and specify foreground (and also background) color by using a xml/html like syntax.

    If you want to change on part of the string, put it between <color fg=hex, bg=hex>your string goes here</color>.

    Hex is the color code starting with 0x (like 0xFFFFFF).

    You don't have to specify both, background and foreground, just set the color you like to change; if you set both, use a comma (,) as delimiter.

    local component = require "component"
    local term = require "term"
    -------------------------------------------------------------------------------
    local gpu = component.gpu
    
    local adWrite = {}
    
    function adWrite.write(s)
      local cbg, cfg = gpu.getBackground(), gpu.getForeground()
      local i = 1
      s:gsub('()<color(.-)>(.-)</color>()', function(i1, tag, content, i2)
        local bg, fg
        if not i1 then return end
        term.write(s:sub(i, i1-1))
        tag = tag:gsub('%s', "")  -- remove whites paces
        for colortype, color in tag:gmatch '([bfg][bfg])=(0[xX]%x+)' do
          if colortype == "bg" and color then
            bg = tonumber(color)
          elseif colortype == "fg" and color then
            fg = tonumber(color)
          end
        end
        if bg and bg ~= cbg then
          gpu.setBackground(bg)
        end
        if fg and fg ~= color then
          gpu.setForeground(fg)
        end
        term.write(content)
        gpu.setBackground(cbg)
        gpu.setForeground(cfg)
        i = i2
      end)
      if i <= #s then
        term.write(s:sub(i, #s))
      end
    end
    
    -------------------------------------------------------------------------------
    return adWrite

    Here is an example:

     

    screenshot.png

  5. I assume you are currently using the term lib for writing stuff on the screen?

    For full control over the screen, you need to interact with the gnu component directly. You then need to also specify the x and y coordinate where your text starts.

    But it's easy to write a function that works exactly like term.write but allows you to specify the colors of each part of the string.

    local component = require "component"
    local term = require "term"
    local unicode = require "unicode"
    
    local gpu = component.gpu
    
    local function advancedWrite(s, c) -- s is the string, c is its color
      local x, y = term.getCursor()
      local max_x, max_y = gpu.getResolution
      local len = unicode.len(s)
      local old_fg = gpu.setForeground(c)
      gpu.set(x, y, s)
      gpu.setForeground(old_fg)
      if x + len >= max_x then
        x = 1
        y = y + 1
      else
        x = x + len
      end
      term.setCursor(x, y)
      if x + len >= max_x then
        return advancedWrite(unicode.sub(s, max_x-x), c)
      end
    end

    This is a really simple and inefficient approach. I haven't tested it yet but I will once I'm back at my computer. I will also post a proper function later, if that is the type of solution you're looking for.

  6. Well, first of all, if you only need the message to contain one string, then you are better off by just sending the string as the message, so no need to make a table with that string, serialize the table transforming it into a string which is then send via the modem, once received, transformed back into a table which is then indexed to get the string you want to send...

    But anyways, I would assume the error with the serialization comes from trying to serialize a nil value. You're using a timeout with your event.pull, that means, event.pull returns nil if no modem_message was received within that 239 seconds. So either you simply remove the number specifying the timeout, or you add an if-statement checking whether you actually received a message and skip the serialization part when the message is nil.

    -- without the timeout, if this is possible, but it looks like you want your robot to execute some stuff every 239 seconds
    function loopWait()
      loopOff = false
      db.clear(1)
      me.store({name = "minecraft:record_wait"}, db.address, 1)
      selectEmpty()
      me.requestItems(db.address, 1, 1)
      ic.equip()
      robot.useUp()
      repeat
        _, _, _, _, _, serialized_message = event.pull("modem_message")
        received_table = require("serialization").unserialize(serialized_message)
        if recieved_table.loopSwitch == "off" then
          loopOff = true
        end
        robot.useUp()
        selectFull()
        ic.equip()
        robot.useUp()
      until loopOff == true
      robot.useUp()
      selectFull()
      me.sendItems()
    end
    --------------------------------
    -- with an if statement verifying there actually was a message received
    function loopWait()
      loopOff = false
      db.clear(1)
      me.store({name = "minecraft:record_wait"}, db.address, 1)
      selectEmpty()
      me.requestItems(db.address, 1, 1)
      ic.equip()
      robot.useUp()
      repeat
        _, _, _, _, _, serialized_message = event.pull(239, "modem_message")
        if serialized_message then
          received_table = require("serialization").unserialize(serialized_message)
          if recieved_table.loopSwitch == "off" then
            loopOff = true
          end
        end
        robot.useUp()
        selectFull()
        ic.equip()
        robot.useUp()
      until loopOff == true
      robot.useUp()
      selectFull()
      me.sendItems()
    end

    But the easiest and best way would be to send your string directly as the message

    -- the computer sending the message
    modem.send(address, port, "off")
    
    
    -- receiving computer
    function loopWait()
      loopOff = false
      db.clear(1)
      me.store({name = "minecraft:record_wait"}, db.address, 1)
      selectEmpty()
      me.requestItems(db.address, 1, 1)
      ic.equip()
      robot.useUp()
      repeat
        _, _, _, _, _, message = event.pull(239, "modem_message")
        if message == "off" then
          loopOff = true
        end
        robot.useUp()
        selectFull()
        ic.equip()
        robot.useUp()
      until loopOff == true
      robot.useUp()
      selectFull()
      me.sendItems()
    end

     

  7. Like Molinko said, you need a custom program that will allow you to manipulate another computer. And using network cards might be the best option.

    There are several ways to write programs that allow sending commands to a second computer; a very naive implementation would use the function load.

    When passed a string, the string is loaded as a chunk of Lua code and returns a function, that, when called, does whatever was coded in the string.

    And yes, you need to use event.pull or register a listener via event.listen, but your code needs to "pause" at least  every 5 seconds anyways, via event.pull or os.sleep (which is essentially the same as event.pull), so that shouldn't be an issue.

    So a simple code would look like this:

    The computer receiving the commands:

    local event = require "event"
    
    while true do
      local _, _, from, _, _, message = event.pull("modem_message")
      local res, err_msg = load(message)
      if not res then
        -- an error occured while loading the string, so here you can do error management
        -- like throwing an error and ending the program, printing the error message or write it to a log file,
        -- ignore the error and continue running the main loop etc
        print(err_msg)
      else
        res()  -- on success, load returns a funtion, so call it
      end
    end
    
    ---------------------------------------------------------------------------------
    -- if you want to throw an error on failure, using assert would be the way to go
    ---------------------------------------------------------------------------------
    local event = require "event"
    
    while true do
      local _, _, from, _, _, message = event.pull("modem_message")
      assert(load(message))()
      -- if load returns the function, i.e. loading the string was successfull, the function is called
      -- when an exception was catched, an error with the error message is thrown
    end

    So then you can send a message containing "io.write('test')", and the second computer will execute this task. You can also open files etc, so basically you can do everything remotely. But as I said, this is not a very optimized program since load is quite heavy on the machine since it has to compile the code, but it is probably the most versatile approach.

    (keep in mind, when you want to use strings inside your code, you need to use the correct quotes, if you wrap your string in ", you can't use " for strings inside, so you need to use ' for example, or you wrap your main string in [[..your code goes here..]] these brackets).

  8. 16 hours ago, Hakz_Studios said:

    I have a question why type 3 ends? I am thinking one ends the loop,another ends the main function and the last ends the program. Am I right?

    In what piece of code you have 3 ends? I only find 3 ends in the last program I posted. There you have one end for closing the main function (2nd end), one for closing the if-statement (1st end) and the last end is for closing the while loop.

    And for the error:

    First it would be good if you could post the actual screenshot.

    Second,  could you post the code of the program you were running?

    From what I currently see, there‘s propably a typo in line 18, but I can‘t tell exactly, what is wrong until I see the actual code.

  9. Hey,

    in these if statements, you need to use relational operators. Since you want to see if you're variable is equal to a certain string, you need the '==' (two equal signs).

    So you're code would look like this

    -- local require commands start
    
    local component= require (“component”)
    
    local sides = require(“sides”)
    
    local rs = component.redstone
    
    local event = require(“event”)
    
    -- local os = require(“os”)	remove this, the os lib does not need to be required, I think
    
    -- local  require commands end
    
    -- Main function start
    
    local function main()
    
      local username, message = event.pull(“chat_message”)	-- you head a period (.) between both variables
    
      -- problematic loop start
    
      if username == Hakz_Studios and message ==  Alice Refuel then
    
      component.speech_box.say(“Refueling”)
    
      component.chat_box.say(“Refueling”)
    
      repeat
    
        local username,message = event.pull(“chat_message”)
    
        rs.setoutput(sides.bottom, 15)	-- you need to give the redstone output a value, otherwise it wont turn on
        -- also, by putting it into a loop, the redstone output will be set a ton of times
        -- it helps putting the statement before the repeat until loop
    
      until username == Hakz_Studios and message == Stop Refueling
    
      -- restarting function
    
    function main() -- idk what is this line about, but i dont think it belongs here
    
      elseif username == Hakz_Studios and message == Stop Refuel Systems
    
      os.execute(“Shutdown”) -- it will look for a program called 'Shutdown' with a capital S
    
      else
        function main() -- also, dont know what you want to do here, do you want to start the function again (to have the code repeated endlessly)
      --problematic loop end 
      end
    
    -- main function end
    end

    Some small info: you don't have to put brackets around your condition in the if-statements, you can, but it's not necessary.

    Also, here is a program that repeats the main loop over and over again, as I think that is what you want to do in your original code, if I'm wrong tho and misinterpreting you're code, just ignore my suggestion:D

    -- require libs
    
    local component = require("component")
    local rs = component.redstone
    local sides = require("sides")
    local event = require("event")
    
    -- main function
    
    local function main()
      local username, message = event.pull("chat_message")
      if username == "Hakz_Studios" and message == "Alice Refuel" then
        component.speech_box.say("Refueling")
        component.chat_box.say("Refueling")
        -- this time I set the redstone output once, and then wait for the message 'Stop refueling' then deactivate the redstoneoutput again
        rs.setOutput(sides.bottom, 15)
        repeat
          username, message = event.pull("chat_message")
          -- you dont have to use 'local' in front of username and message here, since you already created these variables at the top of the main function
          -- it will override these values but it actually doesnt matter since from this part you will skip to the end and these initial values for both variables
          -- wont be needed anymore
        until username == "Hakz_Studios" and message == "Stop Refueling"
        rs.setOutput(sides.bottom, 0)	-- I assume you want to deactivate the redstone after you're done refueling
        
      elseif username == "Hakz_Studios" and message == "Stop Refuel System" then
        os.execute("Shutdown")	-- again, this will start the program "Shutdown" with a capital "S"
      end
      	-- as you can see, we skip the last else statement, as it will call the main function recursively, resulting in a overflow error pretty fast
      	-- you could get away with returning a call to the main function, but this wouldnt be good practice eiter, I guess
    end
    
    -- we add a last while loop, which will repeat endlessly calling the main function
    
    while true do
      main()
    end

    I hope this helps.

    Also you did great for your first shot at programming!

  10. I‘m not 100% sure, what causes the error, but it seems the installer doesn‘t handle the http request user data properly.

    You could try running the following command:

    wget https://raw.githubusercontent.com/zenith391/Fuchas/master/Installers/openos.lua installer
    
    installer

    Sadly I can‘t test this right now, but it might be worth trying.

    Edit:

    Ok, i figured out what is causing the error. The colon (:) in function call "data = con:read(math.huge)" in line 11 must be replaced with a period (.).

    So what definitely works is running

    pastebin get s2YZJ0T6 installer.lua

    replacing ":" with "." in line 11, and then run the installer.

    But I get an unrecoverable error on restarting the computer after successful installation...

  11. You can also use event timers. Then you need a function to check and send your stuff.

    local event = require "event"
    
    local function dostuff()
      -- this is ur function that is doing stuff
    end
    
    local interval = 20		-- time in seconds between the runs of the function
    
    event.timer(interval, dostuff, math.huge)	-- math.huge for infinite repeats

    Or if you want to keep Skript as it is, you can use Molinko's approach with os.execute

    Then your code would be:

    event.timer(interval, function() os.execute("/path"), math.huge)

     

  12. @payonel

    Hey,

    I was wondering if there is any chance to see a high precision computer.pull function in OpenComputers, allowing to have timeouts below one tick (I believe the currently used computer.uptime only returns time with .05 s precision).

    With that in hand, non-blocking sleeps and timers for small time intervals should be realizable. I was trying to implement this in openOS by adding a computer.pull function using os.clock instead of computer.uptime and changing some other libs accordingly, but it didn't work out.

    So I'm asking if there is any reason against adding a higher precision version of computer.pull to "machine"?

    Thanks:)

  13. Hey,

    7 hours ago, Elijahlorden said:

    But getmetatable does not return the string metatable.  I am assuming this is because the string metatable is protected for some reason.

    you are correct, string metatables are protected, so you can‘t change or add functions.

    I assume, unicode.len(string) is not what you want, or is it?

    In case you want to have an object, you could interact with, you could build one.

    local unicode = require"unicode"
    local ucode = {}
    
    local mt = {
      __len = function(self)
        return unicode.len(self.string)
      end
    }
    
    function ucode.new(str)
      local obj = {
        string = str
      }
      return setmetatable(obj, mt)
    end
    
    return ucode

    Sorry for the code being just plane text, I’m on my mobile and dont know how to insert some code properly so i‘ll will make a proper one as soon as i get to my pc.

    You then add all the missing functions of the unicode or string lib that you want to the metatable, and then you are good to go.

    Btw, with the __len function, you should be able to call #objname, and it should return the correct length.

  14. Ok, so the issue with locals you had is the following.

    When using local, it's important to have the right order of variable/function definitions, let me give an example:

    local function func_x()
      print("X")
     end
    -- that is some random function
    
    local function func_xy()
      func_x()
      func_y()
    end
    -- a function that will call func_x amd func_y
    -- this will throw an error, because func_y is defined after it is called by func_xy
    
    local function func_y()
      print("Y")
    end
    
    -- you have to ensure the right order!
    
      

    Ok, so I did some rearrangement of your functions, I hope it works.

    local API       = require("buttonAPI") -- On appelle l'API "buttonAPI"
    local component = require("component") -- On appelle l'API "component"
    local term      = require("term")      -- On appelle l'API "term"
    local event     = require("event")     -- On appelle l'API "event"
    local colors    = require("colors")    -- On appelle l'API "colors"
    -- you are overwriting the colors api later, do you actually need that api?
    
    local mon = component.gpu
    local trm = term
    local egy = component.energy_device
    local brR = component.br_reactor
    local brT = component.br_turbine
    
    local steamReactor = brR.isActivelyCooled()
    local menuType = "Reactor"
    
    local numCapacitors = 36
    local turnOnAt = 50
    local turnOffAt = 90
    
    local targetSpeed = 1840
    
    local energy = 0
    local energyStored = 0
    local energyMax = 0
    local energyStoredPercent = 0
    local timerCode
    local mode = "Automatic"
    local RFProduction = 0
    local fuelUse = 0
    local coreTemp = 0
    local reactorOnline = false
    local rodLevel = 0
    
    local turbineOnline = false
    local turbineRotorSpeed = 0
    local turbineRFGen = 0
    local turbineFluidRate = 0
    local turbineInductor = false
    
    local OptFuelRodLevel = 0
    
    -- COLORS
    -- here are you overwriting colors. If you only need this table, you can remove 'require("colors")' above.
    local colors = {}
    colors.white     = 0xFFFFFF
    colors.orange    = 0xFFA500
    colors.magenta   = 0xFF00FF
    colors.lightblue = 0x00AEEF
    colors.yellow    = 0xFFFF00
    colors.lime      = 0x00FF00
    colors.pink      = 0xFFC0CB
    colors.gray      = 0x555555
    colors.lightGray = 0xD3D3D3
    colors.grey      = 0x555555
    colors.silver    = 0xAAAAAA
    colors.cyan      = 0x00FFFF
    colors.purple    = 0x800080
    colors.blue      = 0x0000FF
    colors.brown     = 0x603913
    colors.green     = 0x008000
    colors.red       = 0xFF0000
    colors.black     = 0x000000
    
    local function checkMode()
      API.toggleButton(mode)
    end
    
    local function menuMode()
      if steamReactor then
        if menuType == "Reactor" then
          API.setButton("Reactor", true)
          API.setButton("Turbine", false)
        else
          API.setButton("Reactor", false)
          API.setButton("Turbine", true)
        end
      end
    end
    
    local function online()
      brR.setActive(true)
      --API.flash("Online")
    end
    
    local function offline()
      brR.setActive(false)
      --API.flash("Offline")
    end
    
    local function setTurbineOnline()
      brT.setActive(true)
      --API.flash("Online")
    end
    
    local function setTurbineOffline()
      brT.setActive(false)
      --API.flash("Offline")
    end
    
    local function reactorOnOff()
      API.setButton("Online", brR.getActive())
      API.setButton("Offline", not brR.getActive())
    end
    
    local function turbineOnOff()
      API.setButton("Online", brT.getActive())
      API.setButton("Offline", not brT.getActive())
    end
    
    local function coilsOnOff()
      API.setButton("Coils On", brT.getInductorEngaged())
      API.setButton("Coils Off", not brT.getInductorEngaged())
    end
    
    local function coilsOn()
      brT.setInductorEngaged(true)
    end
    
    local function coilsOff()
      brT.setInductorEngaged(false)
    end
    
    local function fuelRodLevel()
      rodLevel = brR.getControlRodLevel(0)
      --print(rodLevel)
      trm.setCursor(30,5)
      trm.write(tostring(rodLevel).."%")
      mon.setBackground(colors.white)
      trm.setCursor(28,6)
      trm.write("       ")
      for i = 1,10 do
        trm.setCursor(28,i+6)
        mon.setBackground(colors.white)
        trm.write(" ")
        mon.setBackground(colors.yellow)
        trm.write(" ")
        if rodLevel/10 >= i then
          mon.setBackground(colors.red)
        else
          mon.setBackground(colors.yellow)
        end
        trm.write("   ")
        mon.setBackground(colors.yellow)
        trm.write(" ")
        mon.setBackground(colors.white)
        trm.write(" ")
      end
      trm.setCursor(28,17)
      trm.write("       ")
      mon.setBackground(colors.black)
    end
    
    local function turbineInductorDisplay()
      turbineInductor = brT.getInductorEngaged()
      trm.setCursor(30,5)
      if turbineInductor then
        trm.write("On")
      else
        trm.write("Off")
      end
      mon.setBackground(colors.gray)
      trm.setCursor(28,6)
      trm.write("       ")
      for i = 1,7 do
        trm.setCursor(28,i+6)
        mon.setBackground(colors.gray)
        trm.write(" ")
        mon.setBackground(colors.lightGray)
        trm.write(" ")
        if i % 2 == 0 then
          mon.setBackground(colors.gray)
        end
        trm.write(" ")
        mon.setBackground(colors.gray)
        trm.write(" ")
        if i % 2 ~= 0 then
          mon.setBackground(colors.lightGray)
        end
        trm.write(" ")
        mon.setBackground(colors.lightGray)
        trm.write(" ")
        mon.setBackground(colors.gray)
        trm.write(" ")
      end
      for i = 8,10 do
        trm.setCursor(28,i+6)
        mon.setBackground(colors.gray)
        trm.write(" ")
        mon.setBackground(colors.lightGray)
        trm.write(" ")
        if turbineInductor then
          mon.setBackground(colors.red)
        else
          mon.setBackground(colors.blue)
        end
        trm.write(" ")
        mon.setBackground(colors.gray)
        trm.write(" ")
        if turbineInductor then
          mon.setBackground(colors.red)
        else
          mon.setBackground(colors.blue)
        end
        trm.write(" ")
        mon.setBackground(colors.lightGray)
        trm.write(" ")
        mon.setBackground(colors.gray)
        trm.write(" ")
      end
      trm.setCursor(28,17)
      trm.write("       ")
      mon.setBackground(colors.black)
    end
    
    local function getClick()
      local event, side, x, y = event.pull(1,"touch") -- This should be the string "touch" as you want to look for a touch event, right?
      if x == nil or y == nil then
        local h, w = mon.getResolution()
        mon.set(h, w, ".")
        mon.set(h, w, " ")
      else 
        API.checkxy(x,y)
      end
    end
    
    local function comma_value(amount)
      local formatted = amount
      local swap = false
      if formatted < 0 then
        formatted = formatted*-1
        swap = true
      end
      while true do
        formatted, k = string.gsub(tostring(formatted), "^(%d+)(%d%d%d)", '%1,%2')
        if k == 0 then
          break
        end
      end
      if swap then
        formatted = "-"..formatted
      end
      return formatted
    end
    
    local function displayEn()
      trm.clear()
      trm.setCursor(1,1)
      --print("Energy Use: "..energy)
      trm.write("Energy Use: ")
      if energy < 0 then
        mon.setForeground(colors.red)
      else
        mon.setForeground(colors.green)
      end
      trm.write(comma_value(math.floor(energy)).. "RF/t")
      mon.setForeground(colors.white)
      trm.setCursor(1,2)
      trm.write("Energy Stored: "..energyStoredPercent.."%")
      if menuType == "Reactor" then
        trm.setCursor(1,3)
        trm.write("Reactor is: ")
        if reactorOnline then
          mon.setForeground(colors.green)
          trm.write("Online")
        else
          mon.setForeground(colors.red)
          trm.write("Offline")
        end
        mon.setForeground(colors.white)
        trm.setCursor(22,1)
        if steamReactor then
          trm.write("Steam: ")
          mon.setForeground(colors.green)
          trm.write(comma_value(math.floor(RFProduction)).."MB/t")
        else
          trm.write("RF Gen: ")
          mon.setForeground(colors.green)
          trm.write(comma_value(math.floor(RFProduction)).."RF/t")
        end
        mon.setForeground(colors.white)
        trm.setCursor(22,2)
        trm.write("Core Temp: "..math.floor(coreTemp).."c")
        trm.setCursor(22,3)
        trm.write("Fuel Use: "..fuelUse.."MB/t")  
      else
        trm.setCursor(1,3)
        trm.write("Turbine is: ")
        if turbineOnline then
          mon.setForeground(colors.green)
          trm.write("Online")
        else
          mon.setForeground(colors.red)
          trm.write("Offline")
        end
        trm.setCursor(1,4)
        mon.setForeground(colors.white)
        trm.write("Reactor is: ")
        if reactorOnline then
          mon.setForeground(colors.green)
          trm.write("Online")
        else
          mon.setForeground(colors.red)
          trm.write("Offline")
        end
        mon.setForeground(colors.white)
        trm.setCursor(22,1)
        trm.write("RFGen: ")
        mon.setForeground(colors.green)
        trm.write(comma_value(math.floor(turbineRFGen)).."RF/t")
         
        mon.setForeground(colors.white)
        trm.setCursor(22,2)
        trm.write("Rotor: "..comma_value(math.floor(turbineRotorSpeed)).." RPM")
        trm.setCursor(22,3)
        trm.write("Steam: "..comma_value(turbineFluidRate).."MB/t")  
      end 
    end
     
    local function checkEn()
      local tempEnergy = 0
      energyStored = egy.getEnergyStored()
      energyMax = egy.getMaxEnergyStored()
      energyStoredPercent = math.floor((energyStored/energyMax)*100)
      RFProduction = brR.getEnergyProducedLastTick()
      fuelUse = brR.getFuelConsumedLastTick()
      fuelUse = math.floor(fuelUse*100)
      fuelUse = fuelUse/100
      coreTemp = brR.getFuelTemperature()
      reactorOnline = brR.getActive()
      tempEnergy = egy.getEnergyStored()
      os.sleep(0.1)
      energy = (egy.getEnergyStored()-tempEnergy)/2
      energy = energy*numCapacitors
      if steamReactor then
        turbineOnline = brT.getActive()
        turbineRotorSpeed = brT.getRotorSpeed()
        turbineRFGen = brT.getEnergyProducedLastTick()
        turbineFluidRate = brT.getFluidFlowRate()
      end
    end
    
    local function findOptFuelRods()
      trm.clear()
      brR.setActive(false)
      checkEn()
      displayEn()
      fuelRodLevel()
      while brR.getFuelTemperature() > 99 do
        for i= 1,3 do
          checkEn()
          displayEn()
          fuelRodLevel()
            trm.setCursor(3,6)
          trm.write("Finding Optimal Rod Level")
          trm.setCursor(3,7)
          trm.write("Core Temp: "..brR.getFuelTemperature())
            trm.setCursor(3,8)
            trm.write("Waiting for 99c")
          os.sleep(1)
        end
      end
      while brR.getHotFluidAmount() > 10000 do
        for i = 1,3 do
          checkEn()
          displayEn()
          fuelRodLevel()
            trm.setCursor(3,6)
          trm.write("Finding Optimal Rod Level, please wait ....")
          trm.setCursor(3,7)
          trm.write("Fluid Amount: "..comma_value(brR.getHotFluidAmount()).."mb")
            trm.setCursor(3,8)
            trm.write("Waiting for 10,000mb")
          os.sleep(1)
        end
      end
      brR.setAllControlRodLevels(99)
      brR.setActive(true)
      while brR.getFuelTemperature() < 100 do
        for i = 1,5 do
          checkEn()
          displayEn()
          fuelRodLevel()
            trm.setCursor(3,6)
            trm.write("Set all rod levels to 99")
            trm.setCursor(3,7)
            trm.write("Waiting 5 seconds...")
          os.sleep(1)
        end
      end
      for i = 1,5 do
        checkEn()
        displayEn()
        fuelRodLevel()
          trm.setCursor(3,6)
          trm.write("Set all rod levels to 99")
          trm.setCursor(3,7)
          trm.write("Waiting 5 seconds...")
        os.sleep(1)
      end
      local tempMB = brR.getEnergyProducedLastTick()
      print(tempMB.."MB/t of steam")
      local tempRodLevels = math.floor(2000/tempMB)
      print("2000/"..tempMB.." = "..tempRodLevels)
      tempRodLevels = 100-tempRodLevels+5
      print("Adding 5 to Rod Levels: "..math.floor(tempRodLevels))
      brR.setAllControlRodLevels(math.floor(tempRodLevels))
      print("Waiting 10 seconds to confirm...")
      for i = 1,10 do
        checkEn()
        displayEn()
        fuelRodLevel()
          trm.setCursor(3,6)
          trm.write("Estimated Level: "..tempRodLevels)
          trm.setCursor(3,7)
          trm.write("Waiting 10 seconds...")
        os.sleep(1)
      end
      tempMB = brR.getEnergyProducedLastTick()
      while tempMB > 2000 do
        tempRodLevels = tempRodLevels+1
        brR.setAllControlRodLevels(math.floor(tempRodLevels))
        print("Setting Rod Levels to: "..tempRodLevels)
        for i = 1,5 do
          checkEn()
          displayEn()
          fuelRodLevel()
            trm.setCursor(3,6)
            trm.write("Getting below 2000mb/t")
            trm.setCursor(3,7)
            trm.write("Currently at: "..tempMB)
          os.sleep(1)
        end
        tempMB = brR.getEnergyProducedLastTick()
      end
      while tempMB < 2000 do
        tempRodLevels = tempRodLevels -1
        brR.setAllControlRodLevels(math.floor(tempRodLevels))
        print("Setting Rod Levels to: "..tempRodLevels)
        for i = 1,5 do
          checkEn()
          displayEn()
          fuelRodLevel()
            trm.setCursor(3,6)
            trm.write("Getting Above 2000mb/t")
            trm.setCursor(3,7)
            trm.write("Currently at: "..tempMB)
          os.sleep(1)
        end
        tempMB = brR.getEnergyProducedLastTick()
      end
      OptFuelRodLevel = tempRodLevels
    end
    
    local function setRods(setLevel)
      print("Setting Rod Level: "..setLevel)
      API.flash(tostring(setLevel))
      brR.setAllControlRodLevels(setLevel)
      fuelRodLevel()
    end
    
    local function rodPlus()
      API.flash("+")
      brR.setAllControlRodLevels(rodLevel+1)
      fuelRodLevel()
    end
    
    local function rodMinus()
      API.flash("-")
      brR.setAllControlRodLevels(rodLevel-1)
      fuelRodLevel()
    end
    
    local function autoReactor()
      if not steamReactor then
        brR.setAllControlRodLevels(0)
        if energyStoredPercent < turnOnAt then
          if not reactorOnline then
            online()
          end
        end
        if energyStoredPercent > turnOffAt then
          if reactorOnline then
            offline()
          end
        end
      else
        brR.setAllControlRodLevels(OptFuelRodLevel)
        if energyStoredPercent < turnOnAt then
          --online()
          setTurbineOnline()
          coilsOn()
        end
        if energyStoredPercent > turnOffAt then
          --if turbineRotorSpeed > 1800 then
          --   offline()
          --else
          --   online()
          --end
          setTurbineOnline()
          coilsOff()
        end
        if turbineRotorSpeed > targetSpeed then
          offline()
        else
          online()
        end
      end
    end
    
    local displayScreen   -- some of your functions calle ach other, that makes it hard to find a correct order
    -- so I just define displayScreen, so the function can be defined later
    local manualMode
    
    local function autoMode()
      local mode = "Automatic"
      displayScreen()
    end
    
    local function reactorMenu()
      local menuType = "Reactor"
      displayScreen()
    end
    
    local function turbineMenu()
      local menuType = "Turbine"
      displayScreen()
    end
    
    local function manualMenu()
      API.clearTable()
      API.setTable("Automatic", autoMode, "", 3, 13, 6, 6)
      API.setTable("Manual", manualMode, "", 15, 25, 6, 6)
      API.setTable("Online", online, "", 3, 13, 8, 8)
      API.setTable("Offline", offline, "", 15, 25, 8, 8)
      API.setTable("0", setRods, 0, 11,14, 10, 10)
      API.setTable("10", setRods, 10, 5,8, 12, 12)
      API.setTable("20", setRods, 20, 11,14, 12, 12)
      API.setTable("30", setRods, 30, 17,20, 12, 12)
      API.setTable("40", setRods, 40, 5,8, 14, 14)
      API.setTable("50", setRods, 50, 11,14, 14, 14)
      API.setTable("60", setRods, 60, 17,20, 14, 14)
      API.setTable("70", setRods, 70, 5,8, 16, 16)
      API.setTable("80", setRods, 80, 11,14, 16, 16)
      API.setTable("90", setRods, 90, 17,20, 16, 16)
      API.setTable("+", rodPlus, "", 23, 25, 12, 12)
      API.setTable("-", rodMinus, "", 23, 25, 16, 16)
      if steamReactor then
        API.setTable("Reactor", reactorMenu, "", 5, 18, 19, 19)
        API.setTable("Turbine", turbineMenu, "", 22, 35, 19, 19)
      end
      API.screen()
      checkMode()
      reactorOnOff()
      menuMode()
    end
    
    function manualMode()
      local mode = "Manual"
      manualMenu()
    end
    
    local function autoMenu()
      API.clearTable()
      API.setTable("Automatic", autoMode, "", 3, 13, 6, 6)
      API.setTable("Manual", manualMode, "", 15, 25, 6, 6)
      if steamReactor then
        API.setTable("Reactor", reactorMenu, "", 5, 18, 19, 19)
        API.setTable("Turbine", turbineMenu, "", 22, 35, 19, 19)
      end
      API.screen()
      checkMode()
      menuMode()
    end
    
    local function turbineAutoMenu()
      API.clearTable()
      API.setTable("Automatic", autoMode, "", 3, 13, 6, 6)
      API.setTable("Manual", manualMode, "", 15, 25, 6, 6)
      API.setTable("Reactor", reactorMenu, "", 5, 18, 19, 19)
      API.setTable("Turbine", turbineMenu, "", 22, 35, 19, 19)
      API.screen()
      checkMode()
      menuMode()
    end
    
    local function turbineManualMenu()
      API.clearTable()
      API.setTable("Automatic", autoMode, "", 3, 13, 6, 6)
      API.setTable("Manual", manualMode, "", 15, 25, 6, 6)
      API.setTable("Reactor", reactorMenu, "", 5, 18, 19, 19)
      API.setTable("Turbine", turbineMenu, "", 22, 35, 19, 19)
      API.setTable("Online", setTurbineOnline, "", 3, 13, 8, 8)
      API.setTable("Offline", setTurbineOffline, "", 15, 25, 8, 8)
      API.setTable("Coils On", coilsOn, "", 3, 13, 10, 10)
      API.setTable("Coils Off", coilsOff, "", 15, 25, 10, 10)
      API.screen()
      checkMode()
      turbineOnOff()
      coilsOnOff()
      menuMode()
    end
    
    function displayScreen()
     --  repeat
      checkEn()
      displayEn()
      if menuType == "Reactor" then
        fuelRodLevel()
        if mode == "Automatic" then
          autoMenu()
          autoReactor()
        else
          manualMenu()
        end
      else
        turbineInductorDisplay()
        if mode == "Automatic" then
          turbineAutoMenu()
          autoReactor()
        else
          turbineManualMenu()
        end
      end
      getClick()
    end
    
    if steamReactor then
      findOptFuelRods()
    end
    
    while true do
      displayScreen()
      
      os.sleep(1)
    end

     

  15. So I did some small changes to  your AE2Crafting.lua file, it should work now as intended.

    I wasn't able to test it yet, so tell me if it works or not.

    -- Original by Palagius : https://oc.cil.li/index.php?/topic/1426-ae2-level-auto-crafting/
    -- Modfied by Dalden 2018-07-28
    --           - Store crafting result object to check for status
    --           - If crafting job is not yet finished from previous cycle then skip this cycle
    local arg = {...}
    if not arg[1] then
    arg[1] = "009" else arg[1] = tostring(arg[1]) end
    if not arg[2] then
    arg[2] = "ac7" else arg[2] = tostring(arg[2]) end
    local component = require("component")
    local term = require("term")
    --local thread = require("thread")
    local event = require("event")
    local meController = component.proxy(component.me_controller.address)
    local gpu2p = component.proxy(component.get(arg[1]))
    local screen2 = component.get(arg[2])
    local count = 0
    startScreen(arg[1],arg[2])
    gpu2p.setForeground(0xFFFFFF)
    --term.setViewport(nil, nil, nil, nil, nil, nil, window)
     
     
    -- Each element of the array is "item", "damage", "number wanted", "max craft size"
    -- Damage value should be zero for base items
     
    items = {
        { "minecraft:coal",      1, 100, 300 }
    --    { "minecraft:coal_block",       0, 10, 256 }
    --    { "minecraft:iron_ingot",       0, 16384, 256 },
    --    { "minecraft:gold_ingot",       0, 16384, 256 },
    --    { "minecraft:glass",      0, 16384, 256 },
    --    { "minecraft:quartz",      0, 16384, 256 },
    --    { "minecraft:diamond",      0, 16384, 256 },
    --    { "minecraft:emerald",      0, 16384, 256 },
    --    { "draconicevolution:draconium_ingot",      0, 16384, 256 },
    --    { "thermalfoundation:material",       128, 1024, 256 }, -- Copper Ingot
    --    { "thermalfoundation:material",       129, 1024, 256 }, -- Tin Ingot
    --    { "thermalfoundation:material",       130, 1024, 256 }, -- Silver Ingot
    --    { "thermalfoundation:material",       131, 1024, 256 }, -- Lead Ingot
    --    { "thermalfoundation:material",       161, 1024, 256 }, -- Electrum Ingot
    --    { "thermalfoundation:material",       162, 1024, 256 }, -- Invar Ingot
    --    { "thermalfoundation:material",       163, 1024, 256 }, -- Bronze Ingot
    --    { "thermalfoundation:material",       164, 1024, 256 }, -- Constantan Ingot
    --    { "thermalfoundation:material",       165, 1024, 256 }, -- Signalum Ingot
    --    { "thermalfoundation:material",       166, 1024, 256 }, -- Lumium Ingot
    --    { "thermalfoundation:material",       167, 1024, 256 }, -- Enderium Ingot
    --    { "appliedenergistics2:material",       24, 4096, 256 }, -- Engineering Processor
    --    { "appliedenergistics2:material",       23, 4096, 256 }, -- Calculation Processor
    --    { "appliedenergistics2:material",       22, 4096, 256 }, -- Logic Processor
    --    { "appliedenergistics2:material",       11, 4096, 256 }, -- Pure Nether Quartz Crystal
    --    { "appliedenergistics2:material",       10, 4096, 256 }, -- Pure Certus Quartz Crystal
    --    { "appliedenergistics2:material",       7, 4096, 256 }, -- Fluix Crystal
    --    { "appliedenergistics2:material",       12, 4096, 256 }, -- Pure Fluix Crystal
    --    { "appliedenergistics2:material",       0, 4096, 256 }, -- Certus Quartz Crystal
    --    { "appliedenergistics2:material",       1, 4096, 256 }, -- Charged Certus Quartz Crystal
    --    { "appliedenergistics2:material",       8, 4096, 256 }, -- Fluix Dust
    --    { "appliedenergistics2:material",       2, 4096, 256 }, -- Certus Quartz Dust
    --    { "actuallyadditions:item_dust",       5, 4096, 256 }, -- Crushed Quartz
    --    { "enderio:item_material",       5, 4096, 256 }, -- Silicon
    --    { "enderio:item_alloy_ingot",       1, 1024, 256 }, -- Energetic Alloy Ingot
    --    { "enderio:item_alloy_ingot",       2, 1024, 256 }, -- Vibrant Alloy Ingot
    --    { "enderio:item_alloy_ingot",       5, 1024, 256 }, -- Pulsating Iron Ingot
    --    { "enderio:item_alloy_ingot",       6, 1024, 256 }, -- Dark Steel Ingot
    --    { "enderio:item_alloy_ingot",       7, 1024, 256 }, -- Soularium Ingot
    --    { "enderio:item_alloy_ingot",       8, 1024, 256 }, -- End Steel Ingot
    --    { "enderio:item_alloy_ingot",       0, 1024, 256 } -- Electrical Steel Ingot
    }
     
    loopDelay = 60 -- Seconds between runs
     
    -- Init list with crafting status
    for curIdx = 1, #items do
        items[curIdx][5] = false -- Crafting status set to false
        items[curIdx][6] = nil -- Crafting object null
    end
    
    local function loop()
      for curIdx = 1, #items do
        curName = items[curIdx][1]
        curDamage = items[curIdx][2]
        curMinValue = items[curIdx][3]
        curMaxRequest = items[curIdx][4]
        curCrafting = items[curIdx][5]
        curCraftStatus = items[curIdx][6]
     
        -- io.write("Checking for " .. curMinValue .. " of " .. curName .. "\n")
        storedItem = meController.getItemsInNetwork({
        name = curName,
        damage = curDamage
        })
        drawText("Network contains ",gpu2p)
        gpu2p.setForeground(0xCC24C0) -- Purple-ish
        drawText(storedItem[1].size,gpu2p)
        gpu2p.setForeground(0xFFFFFF) -- White
        drawText(" items with label ",gpu2p)
        gpu2p.setForeground(0x00FF00) -- Green
        drawText(storedItem[1].label .. "\n",gpu2p)
        gpu2p.setForeground(0xFFFFFF) -- White
        if storedItem[1].size < curMinValue then
          delta = curMinValue - storedItem[1].size
          craftAmount = delta
          if delta > curMaxRequest then
            craftAmount = curMaxRequest
          end
     
          drawText("  Need to craft ",gpu2p)
          gpu2p.setForeground(0xFF0000) -- Red
          drawText(delta,gpu2p)
          gpu2p.setForeground(0xFFFFFF) -- White
          drawText(", requesting ",gpu2p)
          gpu2p.setForeground(0xCC24C0) -- Purple-ish
          drawText(craftAmount .. "... ",gpu2p)
          gpu2p.setForeground(0xFFFFFF) -- White
     
          craftables = meController.getCraftables({
            name = curName,
            damage = curDamage
            })
          if craftables.n >= 1 then
            cItem = craftables[1]
            if curCrafting then
              if curCraftStatus.isCanceled() or curCraftStatus.isDone() then
                drawText("Previous Craft completed\n",gpu2p)
                items[curIdx][5] = false
                curCrafting = false
              end
            end
            if curCrafting then
              drawText("Previous Craft busy\n",gpu2p)
            end
            if not curCrafting then
              retval = cItem.request(craftAmount)
              items[curIdx][5] = true
              items[curIdx][6] = retval
              gpu2p.setForeground(0x00FF00) -- Green
              drawText("Requested - ",gpu2p)
              --while (not retval.isCanceled()) and (not retval.isDone()) do
              --      os.sleep(1)
              --        io.write(".")
              -- end
              gpu2p.setForeground(0xFFFFFF) -- White
              drawText("Done \n",gpu2p)
            end
          else
            gpu2p.setForeground(0xFF0000) -- Red
            drawText("    Unable to locate craftable for " .. storedItem[1].name .. "\n",gpu2p)
            gpu2p.setForeground(0xFFFFFF) -- White
          end
        end
      end
      drawText("Sleeping for " .. loopDelay .. " seconds...\n\n",gpu2p)
    end
    
    event.timer(loopDelay, loop, math.huge)

    So what I did was removing your while loop, and just put the entire code inside that loop into a function called "loop". Then I set a timer with event.timer, that will wait "loopDelay" seconds until it calls the loop function. Since I added math.huge as third variable, the loop function will be called repeatedly.

  16. Well, I haven't done something similar yet, so I don't know if there's a way to have a program with and while loop running in the background, I did some quick test with coroutines, but it didn't seem to work.

    What would work is to use an event driven program, but that would require you to do some rewriting of your code.

    So what you would do is registering some events with event.listen(event_type, callback) and then having the corresponding callback do your stuff.

    For periodically stuff like checking your me system for items or whatever, you can register timers that are repeated infinitely with event.timer(interval, callback, math.huge), doing stuff that need to be triggered by time and not some user input or incoming modem messages or sth like that.

    That way, open os would run with the me programming running simultaneously.

  17. Hey,

    I didn't check the entire code, it's a lot of stuff to go through, but I found the reason for your error.

    You are calling string.gsub on a number, but it's a string lib, so you have to convert the number to a string first, by calling tostring(number). Your while loop in lines 219-224 would then look like this:

    while true do
      formatted, k = string.gsub(tostring(formatted), "^(%d+)(%d%d%d)", '%1,%2')
      if k == 0 then
      break
      end
    end

    May I also suggest to use local whenever possible? Like all variables, functions etc. It helps to reduce errors in form of variable overrides etc, plus access to locals is faster.

    Try that and see, if it works, if not, just post the error message and I'll have a look again.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.