Перейти к содержимому
  • 0
StalkerMeyr

Управление несколькими редстоун-контроллерами с одного ПК?

Вопрос

Рекомендуемые сообщения

Да, конечно, почему бы и нет. Сложность в том, что component.componentName возвращает прокси только одного компонента, а нам надо и других тоже получить. Здесь есть 2 варианта действий.

 

1. component.invoke

Эта функция первым аргументом принимает адрес компонента, а вторым — имя метода. Остальные параметры — это аргументы к этому методу. Например, если компонент по адресу "12345678-1234-1234-1234-123456789012" — видеокарточка, поменять разрешение у неё можно вот так:

local com = require("component")
local address = "12345678-1234-1234-1234-123456789012"

com.invoke(address, "setResolution", 80, 25)

В одиночестве функция выглядит страшно, если сравнивать с проксями. Обычно её используют, итерируя компоненты с помощью component.list, потому что итератор этот выдаёт адрес очередного компонента:

local com = require("component")

for addr in com.list("gpu", true) do
  local w, h = com.invoke(addr, "getResolution")
  com.invoke(addr, "fill", 1, 1, w, h, " ")
end

Я предпочитаю использовать этот способ, когда надо в цикле проходиться по всем компонентам и вызывать у них пару-тройку методов.

local com = require("component")
local event = require("event")

local function hsv2rgb(h, s, v)
  local function f(n)
    local k = (n + h / 60) % 6

    return v - v * s * math.max(0, math.min(k, 4 - k, 1))
  end
  
  local r = math.floor(f(5) * 0x1f + 0.5)
  local g = math.floor(f(3) * 0x1f + 0.5)
  local b = math.floor(f(1) * 0x1f + 0.5)
  
  return (r << 10) | (g << 5) | b
end

repeat
  for addr in com.list("colorful_lamp", true) do
    local color = hsv2rgb(math.random(0, 360), math.random(.85, 1), math.random(.85, 1))
    com.invoke(addr, "setLampColor", color)
  end
until event.pull(0.1, "interrupted")

Здесь у компонента метод вызывается лишь один раз, поэтому проще использовать component.invoke. В противном случае лучше делать прокси.

 

2. component.proxy

Если список компонентов, с которыми работает программа, более-менее статичен, удобнее использовать component.proxy. Это функция, которая возвращает прокси компонента по данному адресу. С проксями мы уже знакомы: когда делаем в коде component.componentName, на самом деле вызывается component.proxy(component.getPrimary("componentName")).

 

Когда компонентов несколько, обычный шаблон — это один раз напихать проксей в таблицу и использовать уже её.

local com = require("component")
local event = require("event")

local gpus = {}

for addr in com.list("gpu", true) do
  table.insert(gpus, com.proxy(addr))
end

assert(#gpus >= 4, "4 gpus required")

gpu[1].set(1, 1, "first gpu")
gpu[2].set(2, 2, "second gpu")
gpu[3].set(3, 3, "third gpu")
gpu[4].set(4, 4, "fourth gpu")

Важно, что после заполнения таблицы компоненты эти отключаться не должны. В противном случае нужно ставить листнеры на component_added, component_removed.

 

Прокси также можно использовать в цикле component.list, как в первом способе, чтобы упростить жизнь, если внутри цикла приходится трогать методы компонента по нескольку раз. Вот программка, которая чистит экран и принтит число почищенных символов.

local com = require("component")
local event = require("event")

for addr in com.list("gpu", true) do
  local gpu = com.proxy(addr)  
  local litChars = 0
  local w, h = gpu.getResolution()
  
  local oldBg = gpu.getBackground()
  gpu.setBackground(0x000000)
  
  for x = 1, w, 1 do
    for y = 1, h, 1 do
      local char, _fg, bg = gpu.get(x, y)
      
      if char ~= " " or bg ~= 0x000000 then
        litChars = litChars + 1
      end

      gpu.set(x, y, " ")
    end
  end
  
  gpu.set(1, 1, ("%d lit characters"):format(litChars))
  gpu.setBackground(oldBg)
end

Как видно, я активно использую кучу методов гпу. Вместо того, чтобы каждый раз печатать component.invoke, я один раз взял прокси, а дальше работаю с ним.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Лайк за ответ, который в 42 раза длиннее вопроса. :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...