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

Fingercomp

Members
  • Content Count

    120
  • Joined

  • Last visited

  • Days Won

    35

Posts posted by Fingercomp

  1. OpenOS has the filesystem API. There's the page about it on the wiki. You'll see the filesystem.list function there. It's exactly what you need.

    local fs = require("filesystem")
    
    for node in fs.list("/path") do
      print(node)
    end

    This code prints all files and directories in /path.

    You should also check if the node is a file or a directory. This can be done using the filesystem.isDirectory function.

    local fs = require("filesystem")
    
    for file in fs.list("/path") do
      if not fs.isDirectory(file) then
        print(file)
      end
    end

    You shouldn't use require to load your addon scripts. It just won't work. Use dofile instead.

    local fs = require("filesystem")
    
    for file in fs.list("/path") do
      if fs.isDirectory(file) do
        dofile(fs.concat("/path", file))
      end
    end

    dir "PATH" /b is a Windows command. It won't work in OpenOS.

  2. So you are porting the program that already has the OpenComputers port, right? But... why? I've told you (link) to just download and use the OC version of the program. It actually works perfectly.

    As for the problem, though... You're probably doing something like file.read() instead of file:read(). You need to call the method using the comma. But, again, just use the OC version.

  3. Oh, sorry. I was wrong. It can't redirect error() messages.

     

    I wrote a simple program that writes error message to file when a program crashes. Run the following command to download it.

    $ wget https://gist.githubusercontent.com/Fingercomp/6563c64d70a4472f26923f78d77caeb9/raw/aa4f461ddee2af70a8040065be8974069e240e27/crash.lua /usr/bin/crash.lua

    Usage:

    $ crash /crash.log /home/bin/program.lua arg1 arg2

    /crash.log is the file where the crash will be written.

    /home/bin/program.lua is the path to your program.

    arg1 arg2 are arguments passed to the program.

  4. OpenComputers version of the program doesn't have peripheral.find. If you're still getting an error related to peripheral.find, you're running the ComputerCraft version.

    You can try to download the program:

    $ wget https://raw.githubusercontent.com/asiekierka/Computronics/master/main/resources/assets/computronics/loot/tape/usr/bin/tape.lua /usr/bin/tape.lua

     

  5. Why do you need to open and close the port every time you send a message over the port? You can open the port at the beginning of the program, and close the port at the end.

    Also, you were almost right with your "if we could" code. You just didn't need to make the port a string.

    local com = require("component")
    
    local modem = com.modem
    
    local port = 123
    
    modem.open(port)
    
    modem.broadcast(port, "Hello")
    modem.broadcast(port, "world")
    modem.broadcast(port, "Another message")
    
    modem.close(port)
  6. component.list returns an iterator. It's a function that returns a new value when it's called. The iteration stops when the iterator returns nil. Example:

    local component = require("component")
    
    local iter = component.list("screen")
    
    local addr1 = iter()
    local addr2 = iter()

    If only one screen is connected, the value of addr1 will be the address of that screen, and the value of addr2 will be nil. If you connect another screen, addr1 will contain the address of one of two screens, and addr2 will contain the address of another screen.

     

    Iterators are really useful when you're using the for ... in loop. Here's an example of such loop.

    for key, value in pairs(table) do
      print(key, value)
    end

    pairs() returns an interator. When the iterator is called the first time, it will choose some key/value pair and return two values: the key and the value. Next time you call it, the iterator returns another pair. And so on.

    The key, value part that comes before in is the list of variables the iterator return values are assigned to. It's like running the following line inside each loop iteration:

    local key, value = iterator()

    (iterator is the function returned by pairs)

    Here's how you can rewrite the for ... in loop:

    local iterator = pairs(table)
    while true do
      local key, value = iterator()
      if key == nil then
        break
      end
      print(key, value)
    end

     

    I said the iterator returned by component.list is useful when using the for ... in loop. Hopefully you've guessed why.

    It makes it easier to iterate over the addresses of connected components. In the following example I turn off every screen connected to the computer running that code.

    local component = require("component")
    
    for address in component.list("screen") do
      component.invoke(address, "turnOff")
    end

     

    Now I'm going to answer the question you asked. Let's find out what the code you gave does step-by-step.

    1. component.proxy(component.list("redstone")()).getInput(sides.north)
      The selected code will return an iterator that returns the address of one of the connected redstone components when called.
    2. component.proxy(component.list("redstone")()).getInput(sides.north)
      Then we call the iterator. It will return the address of one of the connected redstone components.
    3. component.proxy(component.list("redstone")()).getInput(sides.north)
      Now we use that address as an argument to the component.proxy function. It returns the component proxy, the table of all methods and values provided by component.
    4. component.proxy(component.list("redstone")()).getInput(sides.north)
      And then we call the getInput method of the component with the argument sides.north.

    By the way, if you're coding under OpenOS, component.proxy(component.list("redstone")()) is the same as component.redstone. That makes your code way more readable.

  7. I've released a hpm update today. Now you can create a manifest for your program if you don't want to mess with uploading it to the repository.

     

    Suppose you're developing your OC project that has a lot of files and dependencies. It actually becomes tedious to manage all of such things up. No problem! Upload dependencies to the repository, and then create the manifest.

    {name="name-of-program",
     version="1.0.5-dev",
     dependencies={
      {name="logging", version="^1,!=1.5", type="required"},
      {name="network", version="^2", type="required"}
     },
     files={
      {url="path/relative/to/manifest/script.lua", dir="/usr/bin", name="script.lua"},
      {url="path/relative/to/manifest/another-file.lua", dir="/usr/lib/program", name="another-file.lua"}
     }}

    Then use tar to create an archive containing project files, and send the file somebody.

    That person extracts files from the archive and runs the following command.

    $ hpm install -l .

    Well, the program becomes installed.

     

    Btw, there's a command to install the dependencies of program, leaving the project itself untouched.

    $ hpm install -ld path/to/project

     

    I'm already going to use this feature for our large project. You can take a look at our manifest file as an example: https://github.com/cc-ru/ut-server/blob/master/manifest

    I hope you'll find this feature useful as we did!

  8. Okay, so I forgot that the tmpfs size is limited to 512 bytes. The installer was about seven times larger than that. I've fixed the bug. Rerun the command, it should work now. I hope you'll like what we've made. :)

     

    Oh, I'm aware of this issue and already working on resolving the bug.

    There's a workaround you can try using for now. Hopefully it will work.

    $ pastebin get vf6upeAN ./installer.lua
    $ ./installer.lua
    $ rm ./installer.lua

    The bug is going to be fixed as soon as possible. Thanks for reminding me, anyway.

  9. about.6c5ea71c.png

    Greetings! Today we've finally released the Hel Repository, the project we've been working for a half of year (we have no idea why it took so long).

    We collected many good ideas about an ideal package repository, melted all of them together, and forged a solution to OC package distributing problems.

    It's really easy to use, not harder than downloading programs from Pastebin. To install a program type the following command in the OpenOS shell:

    $ hpm install <package name>

    A few moments later the package becomes installed with all of its dependencies, ready to be used.


    Why Hel? It's cool, lightweight, simple. All you need is the client program. It's small, yet powerful.
    And a rather fast OpenPrograms module is included in the client. With cache.

    To install an OpenPrograms package, first update the cache:

    $ hpm oppm:cache update

    And then use the following command:

    $ hpm oppm:install <package name>

    Of course, hpm has a few more features than what we've described. Have a look at the manpage that hpm automatically downloads.


    Okay, enough speaking of the OC client, let's think about program developers.
    You can easily maintain several versions of your applications. You can use any repository package as dependency.

    Create an account. Describe your package (use Markdown to format description), attach code samples (in Lua, Moonscript, or 20 more languages). Tag the package. Attach a few images related to the program if you have them.

    That's it! The package will become available immediately. Everyone will be able see it, and everyone will be able to install it.

    By the way, the repository stores metadata of packages (not the actual file contents) that's used by hpm to download programs -- regardless of where they're stored.

     
    The Hel project consists of three parts.

    •  The backend. It's written in Python. The backend stores all data in database. It's documented on the wiki. Take a look at it if you want to add Hel integration to your app.
    •  The frontend. Created with the power of functional programming and the Elm language. It's the web interface we've mentioned above.
    •  The OpenComputers client. It's small (3k lines of code) but mighty. :) Written in MoonScript.

    Sources of these parts are available on GitHub.

    Report found bugs or feature requests here or at the Github issue tracker. If you want to contribute, open a pull request.


    Okay, that sounds good, but how to use it?

    The frontend is hosted here. There's nothing to describe. Open the site and, well, use it.

    The API is available here. The wiki tells how to use the API.

    The OC client can be installed by running the following:

    $ pastebin run vf6upeAN

    This command will fetch the latest version of hpm. You should also run this command if hpm breaks. Usually this happens when we make a breaking change to the API. In this case, we'll update hpm as soon as possible.


    Licensed under the MIT license.
    Authors: @Fingercomp, @MoonlightOwl.

  10. Ah, sorry, I didn't notice that you have two GPUs. Well, as you said, print functions work by default with the primary GPU component. An obvious way to do what you want is to access the two GPU components directly.

    local component = require("component")
    
    local gpu1 = component.proxy(component.get("897c"))  -- the first GPU
    local gpu2 = component.proxy(component.get("b2bd"))  -- the second GPU
    
    local screen1 = component.get("10da")  -- the first screen
    local screen2 = component.get("e52a")  -- the second screen
    
    -- bind the screens to the GPUs
    gpu1.bind(screen1)
    gpu2.bind(screen2)
    
    -- use the `set` method to write text
    gpu1.set(10, 1, "Hello, world!")
    gpu2.set(1, 2, "Hello.")
    
    -- the arguments are: x, y, text
    -- if x is 1, the text will be printed at the beginning of line
    -- if y is 1, the text will be printed at the top line
    
    -- [1, 1] [2, 1] [3, 1] [4, 1] [5, 1]
    -- [1, 2] [2, 2] [3, 2] [4, 2] [5, 2]
    -- [1, 3] [2, 3] [3, 3] [4, 3] [5, 3]
    -- [1, 4] [2, 4] [3, 4] [4, 4] [5, 4]
    -- [1, 5] [2, 5] [3, 5] [4, 5] [5, 5]

    ...Or you can use an undocumented term library feature.

    local component = require("component")
    local term = require("term")
    
    local gpu2 = component.get("a562")  -- the non-primary GPU
    local screen2 = component.get("cd64")  -- the non-primary screen
    
    local window = term.internal.open()  -- create a new window
    window.gpu = gpu2  -- set window GPU...
    window.screen = screen2  -- ...and screen
    
    term.setViewport(nil, nil, nil, nil, nil, nil, window)  -- assign viewport values (resolution, cursor position, etc.)
    
    -- now you can use term.drawText to write text on the second screen
    --            text value       , should wrap, window
    term.drawText("Hello, world!\n", false,       window)
    term.drawText("Hello", false, window)
    term.drawText(" again", false, window)

    Much easier than the first way.

  11. term.read, print, io.write print text on the first screen, as you said, because it is a primary component. Primary components are choosen randomly when the computer boots up. Proxies of such components are returned when they are accessed like that: component.screen (or component.redstone, component.gpu, etc.).

    The primary GPU is automatically bound to the primary screen. So you have to bind GPU to the second screen. The following example prints "Hello, world!" on the second screen.

    local component = require("component")
    local gpu = component.gpu  -- get the proxy of the primary GPU
    
    local addr1 = component.get("ad03")  -- the address of the first screen
    local addr2 = component.get("235f")  -- the address of the second screen
    
    gpu.bind(addr2, false)  -- switch GPU to the second screen (false means that it won't clear the screen)
    
    io.write("Hello, ")
    print("world!")
    
    gpu.bind(addr1, false)  -- switch GPU back to the first screen
  12. 4 hours ago, Mods_o_joy said:

    Yeah i figured this out a few hours after i posted that. now if only the dev(i think its lizzy.. right?) would add the option to make prints into working chairs or even Moar usefull things.

    Some 3D print features:

    • They can glow (unfortunately, the light can't be toggled).
    • They can act as switch, lever, or whatever else, emitting the redstone signal in active state.
    • A 3D print can consist of two states (well, one "3D print" block can actually have two different 3D models), toggled by clicking.

    A lot of things can be created already!

    And, well, chairs. There is a 3D print of chair. It was created by Krutoy242.

    ayiZsqC.pngXU92W4A.png

    The bottom part can be toggled by clicking. Stand on the seat, click on it, and, tada, you're "sitting" on the chair.

    {
      label = "Крутое кресло",
      tooltip = "Для работы за крутым компьютером",
      buttonMode=true,
      shapes = {
        { 0,0,7,2,2,9,texture = "coal_block" },
        { 7,0,0,9,2,2,texture = "coal_block" },
        { 7,0,14,9,2,16,texture = "coal_block" },
        { 14,0,7,16,2,9,texture = "coal_block" },
        { 1,2,7,15,3,9,texture = "iron_block", tint = 0xc4dbee },
        { 7,2,1,9,3,15,texture = "iron_block", tint = 0xc4dbee },
        { 6,3,7,10,8,9,texture = "coal_block" },
        { 7,3,6,9,8,10,texture = "coal_block" },
        { 7,8,7,9,12,9,texture = "coal_block" },
        { 1,12,7,2,14,14,texture = "iron_block", tint = 0xc4dbee },
        { 2,12,2,6,14,14,texture = "coal_block" },
        { 4,12,0,6,14,14,texture = "coal_block" },
        { 6,12,0,10,14,14,texture = "wool_colored_white", tint = 0x00c3ff },
        { 10,12,0,12,14,14,texture = "coal_block" },
        { 12,12,2,14,14,14,texture = "coal_block" },
        { 14,12,7,15,14,14,texture = "iron_block", tint = 0xc4dbee },
        { 0,14,12,1,16,14,texture = "coal_block" },
        { 1,14,12,2,16,14,texture = "iron_block", tint = 0xc4dbee },
        { 2,14,12,14,16,15,texture = "coal_block" },
        { 14,14,12,15,16,14,texture = "iron_block", tint = 0xc4dbee },
        { 15,14,12,16,16,14,texture = "coal_block" },
        { 0,0,0,16,7,16,texture = "iron_block", tint = 0xc4dbee , state=true},
      }
    },
     
    {
      label = "Крутое кресло",
      tooltip = "Для работы за крутым компьютером",
      shapes = {
        { 1,0,11,2,4,13,texture = "iron_block", tint = 0xc4dbee },
        { 1,0,13,2,2,14,texture = "iron_block", tint = 0xc4dbee },
        { 2,0,12,6,5,14,texture = "coal_block" },
        { 6,0,12,10,5,14,texture = "wool_colored_white", tint = 0x00c3ff },
        { 10,0,12,14,5,14,texture = "coal_block" },
        { 14,0,11,15,4,13,texture = "iron_block", tint = 0xc4dbee },
        { 14,0,13,15,2,14,texture = "iron_block", tint = 0xc4dbee },
        { 1,2,4,2,4,13,texture = "iron_block", tint = 0xc4dbee },
        { 2,2,14,6,12,15,texture = "coal_block" },
        { 6,2,14,10,11,15,texture = "wool_colored_white", tint = 0x00c3ff },
        { 10,2,14,14,12,15,texture = "coal_block" },
        { 14,2,4,15,4,13,texture = "iron_block", tint = 0xc4dbee },
        { 0,3,4,2,4,11,texture = "iron_block", tint = 0xc4dbee },
        { 15,3,4,16,4,11,texture = "iron_block", tint = 0xc4dbee },
        { 0,4,4,2,5,11,texture = "coal_block" },
        { 14,4,4,16,5,11,texture = "coal_block" },
        { 2,5,13,6,12,15,texture = "coal_block" },
        { 6,5,13,10,11,15,texture = "wool_colored_white", tint = 0x00c3ff },
        { 10,5,13,14,12,15,texture = "coal_block" },
        { 4,12,13,12,15,15,texture = "coal_block" },
        { 5,15,13,11,16,15,texture = "coal_block" },
      }
    }

    By the way, Lizzy is a forum administrator. The author of the mod is Sangar.

  13. Connect the charger to the power converter (you can place them next to each other, or connect via the OC cable). Provide IC2 energy to the power converter (use IC2 wires). Put a lever on the charger and flip it. And then you're done, pretty much. Robots will charge up if they are next to the charger.

     

    Adapters are used when you want to control non-component blocks (note blocks, for example).

     

    Capacitors store energy. You need them because many OC components don't have a huge energy buffer, meaning they will shut down in a short time if no energy is supplied. So if you can't maintain non-stop energy supply, use capacitors.

  14. The RFC 5246 describes the TLS 1.2 protocol that's very heavily used today to encrypt the traffic sent over regular sockets. Have you noticed the "https" part of this page's URL? It means that a HTTP server listens, generally, on the 443 port for HTTP requests sent over a TLS connection.

     

    Currently you can only send HTTPS requests, there's no built-in solution for establishing TLS sockets to send arbitrary data. An issue on GitHub asks exactly for this feature to be added. Now, look at the date of posting. After 1.5 years, we still don't have TLS socket support.

     

    Oh, maybe, not really now. Yes, I have a fully working TLS 1.2 implementation (without certificate validation, though).

    It uses the tier 2 data card (it provides the secure random and hashing functions), and the Computronics's advanced cipher block (RSA encryption). And it isn't even incredibly slow! It only takes 4 seconds to connect.

     

    d7K3vqv.png

     

    I've tried to connect to some https servers, and all of them worked perfectly.

     

    The library is hosted on my OpenPrograms repository, and can be installed via OPPM: oppm install libtls.

     

    Here's my another creation that uses the library: a simple and dumb (yet working, huh) HTTP 1.1 library. It's solely purpose is to allow to specify the request method (which also has its own issue, that, unfortunately, is still open), like PUT or PATCH. It uses raw sockets or TLS sockets to do so. It's also hosted on my repository, and can be downloaded via OPPM (oppm install libhttp), too.

     

    Hopefully you'll make use of these two libraries I've written.

  15. First, these two chunks of code are completely unnecessary.

    if event.onError(interrupted) then
    c.shutdown(true)
    end
    
    event.shouldInterrupt(false)
    

    Second, to prevent program interruption by pressing the key combination you mentioned in the title, you'll need to override the event.shouldInterrupt function to make it always return false. This can be done the following way:

    event.shouldInterrupt = function()
      return false
    end
    

    This code should be run after requiring event library.

     

    On the final note, I'd recommend you to learn about code indentation. It makes code look cleaner, nicer, and easier-to-read, especially a large and complex one.

  16. This happens because package library caches return values of libraries. This is simply workarounded, though.

    local lib = {}
    -- the following line is important
    lib.__index = lib
    
    -- the "word" variable will be defined later, so it will not be cached
    
    -- define your functions (note: colons should be used)
    function lib:talk()
      -- use "self" to access fields of library table
      print(self.word)
    end
    
    function lib:setWord(s)
      -- and here, too
      self.word = s
    end
    
    function lib:setWordAndTalk(s)
      -- if you need to access *methods* (functions) of your library, you should use the colon!
      self:setWord(s)
      self:talk()
    end
    
    return function()
      local object = {
        -- declare your variables here if you want them to be created with each new instance
        word = "Hello"
      }
      setmetatable(object, lib)
      return object
    end
    

    As I already said, the return value is cached. If you just return the table, it gets cached, and the result will be the same (a single library table for all programs that require'd the library.
    In the code above, though, the thing that's cached is a function. It's sole purpose is to create a new instance of library. It defines some variables that won't be cached, and sets the library table as a metatable for the object. Then it just returns the object.
    The library should be used differently than a regular one:

    local lib = require("lib")()  -- get the function, and call it
    
    -- use colon to access methods of library...
    lib:talk()
    lib:setWord("Test")
    -- and dot to access properties (regular variables) of library:
    print(lib.word)
    
    lib:setWordAndTalk("Hello, world!")
    

    Speaking of tables, they are not copied when passed as an argument to a function. Here's the code that demostrates this:

    local function setValue(tbl, value)
      tbl.test = value
    end
    
    local someTable = {test="Hello"}
    print(someTable.test)
    setValue(someTable, "Hi")
    print(someTable.test)
    

    The output:

    Hello
    Hi
    

    As you can see, the function didn't get a copy of table, instead, it modified a field of the same table! In the C (C++) programming language, this is called a reference to the value, and it's used to avoid creating a copy of big objects.
    Moreover, this is a key concept of Lua's object-oriented programming: all methods of some class, when called, get a reference to the class which they can use. That's why methods should be generally called like this: class:method(args). This implicitly passes the class variable as the first argument for the method.

  17. As far as I can understand the problem, you've downloaded not an image, but a HTML page with the downloader script. Type edit <image file name>, and you'll see that the file starts with <!DOCTYPE blah...

    To download the file instead, you'd better get a direct link to the file, not to download page or other things like that.

     

    Luckily for you, files stored on Dropbox can be easily downloaded directly. Simply replace www.dropbox.com with dl.dropboxusercontent.com.

  18. First parameter event.pull returns is always a name of event. Here's the loop that should work.

    while true do
      local touch = {}
      touch.eventName, touch.screenAddress, touch.x, touch.y, touch.button, touch.playerName = event.pull("touch")
      for buttonName,buttonContent in pairs(buttons) do
        if ((touch.x >= buttonContent.x and touch.x < buttonContent.x + buttonContent.width) and (y >= buttonContent.y and y < buttonContent.y + buttonContent.height)) == true then --here is the error
          teleport(buttonName,touch.playerName)
        end
      end
    end
    
×
×
  • Create New...

Important Information

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