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

Molinko

Members
  • Content Count

    451
  • Joined

  • Last visited

  • Days Won

    35

Posts posted by Molinko

  1. I believe term.read returns its input with a newline char (\n) appended to the end of its output. So, typing 'exit' would return 'exit\n'.

    One option is to use io.read if you don't need all of the options term.read offers. io.read will return the input without a newline. Or, you can

    strip the newline and compare as usual.

    local input = term.read()
    
    if input:sub(-2) == 'exit' then
    	-- # I believe input:sub(-2) should strip the last two chars (\n) from the input variable...
    end

     

  2. It's pretty hard to tell where exactly this is coming from. I dont have br and im too lazy to install a modpack with it.... However, I would usggest littering your code with print statements to see where specifically the code is failing... Try this and see if provides any clues...

    local modem=component.proxy(component.list("modem")())
    local turbine=component.proxy(component.list("br_turbine")())
    modem.open(1)
    local target = false
    print "main loop start."
    while true do
    	local e, to, from, _, _, command = computer.pullSignal()
    	if e == "modem_message" then
        	print("modem_message event. from: '" .. from .. "'")
    		if command == "s" then
          		print "'s' command. sending handshake."
    			modem.send(from,1, "Handshake")
    			local target = from
    		elseif command == "a" then
          		print "active command"
    			if (turbine.getActive()) then
    				turbine.setActive(false)
            		print "turbine inactive"
    			else
    				turbine.setActive(true)
            		print "turbine active"
    			end
    		elseif command == "c" then
          		print "inductor command"
    			if (turbine.getInductorEngaged()) then
            		print "inductor disengaged"
    				turbine.setInductorEngaged(false)
    			else
            		print "inductor engaged"
    				turbine.setInductorEngaged(true)
    			end
    		elseif (target) then
          		print "target... how did we get here..."
    			local data1 = tostring(turbine.getActive())
    			local data2 = tostring(turbine.setInductorEngaged())
    			local data3 = tostring(turbine.getRotorSpeed())
          		print("sending turbine data to target")
          		print("target: " .. (type(target)=="string" and target or "target should be string not bool.."))
    			modem.send(target,1, data1, data2, data3)
    		end
    	end
    end
    print "we made it..."

     

  3. I'm pretty sure your problem is here..

        data1 = pct -- pct is nil
        data2 = nrj -- nrj is nil
        data3 = nrjMax -- nrjMax is nil
        gpu.set(4,8,nrj) -- This is where the error comes from. "Bad Argument #3 (string expected, got nil.)"...
        gpu.set(4,10,nrjMax) -- so on..
        gpu.set(4,12,pct) -- and so on..

    Nowhere in the above code you supplied did you define the values of pct, nrj, or nrjMax. So, they are nil.

  4. From looking at the modem component API you should be able to send up to 8 basic datums in each message.  From what I can see in your example It should work fine sending. Could you post your receiving code? The 'modem_message' event has 5 return values before the data you've sent.

    local _event, localAddress, remoteAddress, portNumber, distance, sentData1, sentData2, sentData3, sentData4 = event.pull("modem_message")

     

  5. I'm sorry for the headache rather than the help..

    local component = require("component")
    local sides = require("sides")
    local event = require("event")
    local term = require("term")
    local thread = require("thread")
    local rs = component.redstone
    local gpu = component.gpu
    
    
    -- Config
    local delay, isOpen = 5, (rs.getOutput(sides.right) > 0) and true or false
    local timer = nil
    
    term.clear()
    term.setCursor(1, 1)
    gpu.setForeground(0x00FF00)
    print("--------------------------- ToNELvision MICROSYTEMS ---------------------------\n")
    gpu.setForeground(0xFFFFFF)
    print("Welcome. Please enter one of the displayed commands. It may take a few seconds for the command to be interpreted.\n")
    gpu.setForeground(0xE6AB38)
    print("Open\nClose")
    term.setCursor(1, 9)
    
    
    local inputThread
    inputThread = thread.create(function()
        while true do
          local input = term.read(nil, false)
          if type(input) == "string" then
            input = input:sub(1, -2)
          elseif type(input) == "boolean" and input == false then
            print("interrupted")
            inputThread:kill()
          end
          
          term.clearLine()
          
          if input == "open" or input == "Open" then
            if not isOpen then
              rs.setOutput(sides.right, 15)
              isOpen = true
              if timer then event.cancel(timer) end
              timer = event.timer(delay, function()
                  if isOpen then
                    rs.setOutput(sides.right, 0)
                    isOpen = false
                    timer = nil
                  end
                end)
            end
          elseif input == "close" or input == "Close" then
            if isOpen then
              rs.setOutput(sides.right, 0)
              event.cancel(timer)
              isOpen = false
            end
          elseif input == "quit" or input == "Quit" then
            inputThread:kill()
          end
        end
      end)
    
    local motionThread = thread.create(function()
        while true do
          local _, _, x, y, name = event.pull("motion")
          if not isOpen then
              rs.setOutput(sides.right, 15)
              isOpen = true
              if timer then event.cancel(timer) end
              timer = event.timer(delay, function()
                  if isOpen then
                    rs.setOutput(sides.right, 0)
                    isOpen = false
                    timer = nil
                  end
                end)
          else
            event.cancel(timer)
            timer = event.timer(delay, function()
                  if isOpen then
                    rs.setOutput(sides.right, 0)
                    isOpen = false
                    timer = nil
                  end
                end)
          end
        end
      end)
    
    thread.waitForAny({inputThread, motionThread})
    print("\nProgram Exit")
    os.exit()

    Tested... sorry for the headache... :P 

  6. 3 hours ago, deace_nuts said:

    I see, I've noticed that the motion sensor works, but neither Open nor Quit does anything.

    I edited the original script in my post. I'm confident I fixed open() however I'm not sure if threads can call thread:kill() from within themselves.. So quitting may still be bugged :/

  7. local component = require("component")
    local sides = require("sides")
    local event = require("event")
    local term = require("term")
    local thread = require("thread")
    local rs = component.redstone
    local gpu = component.gpu
    
    
    -- Config
    local delay = 5
    
    local function open()
      rs.setOutput(sides.right, 15)
      os.sleep(delay)
      rs.setOutput(sides.right, 0)
    end
    
    
    local inputThread
    inputThread = thread.create(function()
        while true do
          term.clear()
          term.setCursor(1, 1)
    	  gpu.setForeground(0x00FF00)
    	  print("--------------------------- ToNELvision MICROSYTEMS ---------------------------\n")
    	  gpu.setForeground(0xFFFFFF)
    	  print("Welcome. Please enter one of the displayed commands. It may take a few seconds for the command to be interpreted.\n")
          gpu.setForeground(0xE6AB38)
          print("Open\nClose")
          term.setCursor(1, 9)
          
          local input = term.read()
          if input == "open" or input == "Open" then
            open()
          elseif input == "quit" or input == "Quit" then
            inputThread:kill()
          end
        end
      end)
    
    local motionThread = thread.create(function()
        while true do
          local _, _, x, y, name = event.pull("motion")
          open()
        end
      end)
    
    thread.waitForAny({inputThread, motionThread})
    print("\nProgram Exit")

    This is and example using payonels thread api. I haven't used it yet myself but it is very powerful. Hats off to payonel for this one.

    If this example has a bug, (its untested), lets me know the error and ill try to remedy it..

  8. The or keyword is binary and can only work on two variables. Each function you have is returning multiple values and only the first of each are being used and assigned.

  9. 7 minutes ago, Fingercomp said:

    When I was writing that response, I didn't really know, well, how experienced you are at Lua programming. :)

    Thanks, you're nice :). It was my first language.

    7 minutes ago, Fingercomp said:

    OOP in general, not in Lua, isn't really advanced. Many languages allow to write in object-oriented style. To name a few: Java, Python, C++. If you don't know what OOP is, writing a few programs in these languages can help to understand the subject.

    ^^^ THIS. So much yes. I had a hard time grasping the concept of OOP at first because Lua doesn't have many of the features an OO language like Java and so on.. 

    Personally an OOP-like library is the only real practical way in my opinion to even use OO in Lua. Writing actual program logic doesn't work so well this way..  Gets bloated quick. BUT, an OO library is easy to extend for a use case should you need it.

    13 minutes ago, Fingercomp said:

    It's just me searching for the greatest library possible, and someone would need quite a lot of Lua experience to create a library I would be satisfied with.

    Oh boy I've been trying forever to get this right. When I do I'll let you know :P.

    @Dustpuppy

    15 minutes ago, Fingercomp said:

    If you can't do OOP, do what you can, or you can easily lose the motivation. Create the library you want, not I. Your current way is very beginner-friendly, so Lua beginners might use it

    I agree. I just wanted to show you how big the world is... lol. If you really want to twist your brain for the better check out Functional programming. Also, a useful mind-fuck. As for the intended style Lua was built for... I believe its intended to be Procedural with a dash of meta-programming. As I said earlier, Lua was my first and still my favorite.

    This has been a nice discussion :).

  10. yeah.. I was worried it might just look like spaghetti...

    3 hours ago, Dustpuppy said:

    Don't you think it is too complicated for the normal user? Most people using lua in OC are beginners , not coders. Even it is complicated to me, i am talking about the normal player, who just want to put some information on his screen.

    Yes and No. Yes. The user of the library doesn't need or want to know how the library works to be able to use it and shouldn't have to either. No, because anyone like @Fingercomp who might like to use your library, even if it lacks a specific element, might like to be able to integrate a custom element and not have to write an entire library to do it. A good example would be to think of how similar a 'Label' and a 'Button' object are to each other. They can share ~90% of their code, so why rewrite the other 90% of a button if its just like a label with a touch event listener. 

    -- # ... more gui shit above..
    
    local Label = {}
    Label.__index = Label
    
    function Label:draw(fg, bg)
      local ofg, obg = gpu.setForground(fg), gpu.setBackground(bg)
      -- # self here refers to the label instance. The specific label calling draw. Label:draw is really a shorcut for Label.draw(labelInstance, fg, bg)
      gpu.fill(self.x, self.y, self.width, self.height, " ") -- # draw the box
      gpu.set( math.floor((self.x + self.width - 1) / 2 + #self.text / 2 + .5), math.floor(self.height / 2 + .5), self.text ) -- # center the label text. ugly
      gpu.setForground(ofg) -- # reset the fg and bg colors
      gpu.setBackground(obg)
    end
    
    local function newLabel(x, y, text, w, h)
      return setmetatable({
        x = x,
        y = y,
        text = text,
        width = w,
        height = h
      }, Label)
    end
    
    local Button = setmetatable({}, {__index = Label}) -- # look to Label for :draw method
    Button.__index = Button
    
    local function newButton(x, y, text, w, h, action)
      local button = newLabel(x, y, text, w, h)
      button.action = action
      
      local listener = function(...)
        local _, x, y = ...
        if x >= self.x and x <= self.x + self.width - 1 then
          if y >= self.y and y <= self.y + self.height - 1 then
            action()
          end
        end
      end
      
      event.listen('touch', listener) -- # this is easy for the demo here but can be a memory leak if left after the program ends...
      
      return setmetatable(button, Button)
    end
    
    -- # End

    I hope this example, although not much less complicated, will help convey the point.

  11. @Fingercomp makes a great point. 

    1 hour ago, Fingercomp said:

    Why not use OOP? So that GUI elements could be modified in some way by calling its method (...)

    Without trying to use too much jargon.. OOP or Object Oriented Programming is a style of program or library organization that pairs 'Classes' with 'Instances'.

    This is hard to explain so I'll use an example that hopefully will demonstrate why OOP can be a powerful paradigm and useful to learn.

    -- # Person. Our 'Base' class for a set of more complex classes.
    local Person = {} -- # Use Person(name, age, sex) to use as an instance constructor.
    Person.__index = Person
    setmetatable(Person, {
      __call = function(_, name, age, sex)
      	local person = {
          name = name,
          age = age,
          sex = sex
        }
        
        return setmetatable(person, Person)
      end
    })
    
    function Person:introduce()
      return ("Hello, my name is %s."):format(self.name)
    end
    
    function Person:greet(otherPerson)
      return self:introduce() .. (" Nice to meet you %s."):format(otherPerson.name)
    end
    
    
    -- # Now we can create 'Persons' or 'instances' of Persons as we call them in OOP.
    local bob = Person('Bob', 49, 'male')
    local jane = Person('Jane', 33, 'female')
    
    print( bob:greet(jane) ) -- # > "Hello, my name is Bob. Nice to meet you Jane."
    
    -- # This is where OOP really shines and why it would be recommeneded. 'Inheritance'.
    local Wizard = {}
    Wizard.__index = Wizard
    
    setmetatable(Wizard, {
      __call = function(_, name, age, sex, spells)
      	local wizard = Person(name, age, sex) -- # create a wizard from the Person class. Wizards are people too. Not all People are Wizards.
        wizard.spells = spells -- # Wizard specific
        
        return setmetatable(wizard, Wizard) -- # bestow Wizard methods upon wizard instance.
      end,
      
      -- # inheritance
      __index = Person -- # If a method or field isn't within a 'Wizard' then fallback to the 'Base' which is 'Person'. i.e wizardInstance:greet(bob)
    })
    
    -- # Sub-class method override.
    function Wizard:introduce() -- # Wizard introductions should state the prestige that they are Wizards!
      return ("Hello, my name is %s the wizard."):format(self.name)
    end
    
    -- # Wizard:greet is inherited from Person. 
    
    function Wizard:cast(spell, target)
      assert(self.spells[spell], "Invalid spell. Your Wizard is weak.")
      return ("%s the wizard casts '%s' upon %s for %d damage."):format(self.name, spell, target.name, self.spells.damage)
    end
    
    local merlin = Wizard("Merlin", 61, "male", {
      ["Abbra"] = {
      	name = "Abbra",
        damage = 12
      }
    })
    
    -- # Notice :greet() is inherited from Person class but uses the merlin instances version of :introduce()
    print( merlin:greet(bob) ) -- # > "Hello, my name is Merlin the wizard. Nice to meet you Bob."
    print( merlin:cast('Abbra', bob) ) -- # > "Merlin the wizard casts 'Abbra' upon Bob for 12 damage."
    
    -- # End

    I hope this example can illustrate to you the advantages of  OOP design. Any questions? ask away :)

  12. This looks great. Taking @Nexarius ' advice is a good idea. No term.clear(). bad, badbadbad. This makes the flicker. This angers the gods. 

    Also, I would suggest using a gui library. Maybe @Gophers' GML or Zer0Galaxys' libforms. One more suggestion would definitely be, again @Nexarius suggestion, to use a lookup table rather than the long if-else chains you have set up. This would help with functions like 'reactorDataTable()' or 'captureKeys()'.

     

×
×
  • Create New...

Important Information

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