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

Totoro

Гуру
  • Публикации

    1 950
  • Зарегистрирован

  • Посещение

  • Победитель дней

    289

Сообщения, опубликованные пользователем Totoro


  1. Думаю написать удобное API для линий, коробок и т.д. Иначе я запарюсь по отдельности воксели приписывать.

     

    Ещё наверно будет геморрой с коллизией, но... Яжпрограммист на ИТ, что нибудь придумаю.

     

    Заведи двухмерный массивчик (трехмерный, если лабиринт по хардкору в 3D :D ), затем сгенери в нем лабиринт любым понравившимся алгоритмом, затем кинь этот массив функции отрисовки.

     

    Типа того (псевдокод, возможны очепятки):

    -- это - наш массив и обертки get/set к нему
    local map = {}
    
    local function set(x, y, value)
      if map[x] == nil then map[x] = {} end
      map[x][y] = value
    end
    local function get(x, y)
      if map[x] == nil then return nil end
      return map[x][y]
    end
    
    -- тут генерим лабиринт -- для простоты 1 будет стеной, а 0 пустотой
    local function generate(...)
      ...
    end
    
    -- тут рисуем лабиринт на проектор исходя из данных массива
    local function render(...)
      for x=1 to W do
        for y=1 to H do
          holo.set(x, 1, y, get(x, y))
        end
      end
    end
    

    Соответственно с коллизиями - никакого геморроя, достаточно спросить функцией get(x, y) что за "клетка" у нас по координатам (x, y).

     

     

    P.S. Гениальную конструкцию

    if ra == true then
      ra=false
    elseif ra==false then
      ra=true
    end
    

    предлагаю заменить на

    ra = not ra
    

    ;)

    • Нравится 2

  2. К сожалению, проверить код в игре я в ближайшее время не смогу. Однако, если верить документации, провода из мода Project RED поддерживаются и должны работать корректно.

     

    И примерно так можно получить сигнал с красного провода в пучке (к примеру):

    local component = require("component")
    local sides = require("sides")
    local colors = require("colors")
    
    local rs = component.redstone
    print("Красный сверху: "..rs.getBundledInput(sides.top, colors.red))
    

    Многожильный провод должен быть подведен к корпусу компьютера (в котором красная плата) сверху.

     

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


  3. Для bundled-кабелей скорее всего потребуется не простая редстоун плата, а второго уровня.

     

    Сигнал с датчика движения ловится так же как и другие эвенты. Например, так:

    local com = require('component')
    local event = require('event')
    
    while true do
      local eventName, address, rx, ry, rz, entityName = event.pull("motion")
      print("Замечено шевеление: "..entityName.." ("..rx..", "..ry..", "..rz..")")
    end
    

    Можно не передавать функции event.pull() никаких параметров, а просто вставить проверку типа if eventName == "motion".

    • Нравится 3

  4. Поясни, в чем конкретно состоит проблема. Что именно не получается реализовать?

     

    Я не могу понять из твоих постов, что именно вызывает трудности.

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

    В таком случае можно просто положить в корень диска файл autorun.lua, который будет жестко биндить нужный монитор к основной видеокарте. Адреса можно вписать вручную, используя первые четыре уникальных символа адреса, и далее автоматически получая полный адрес в программе через команду component.get("xxxx").

     

    (Будет полезен этот сайт: http://ocdoc.cil.li/api:component)

     

     

     

    Эвенты от мониторов (события touch/drag) и клавиатур (key_down/key_up) вообще обрабатываются вне зависимости от наличия привязанной видеокарты. Адрес компонента, который отправлил эвент, всегда идет вторым параметром в этом самом эвенте (как ты несомненно знаешь).

     

    На этом принципе работает моя программа Smart Lock. Она использует всего две видеокарты - одна привязана к "консольному монитору", через который пользователь может вводить команды с клавиатуры. Вторая видеокарта в любой момент работы программы может быть привязана к любому из нескольких десятков мониторов-замков в системе.

    В тот момент, когда пользователь "звонит" в дверь, программа определяет адрес монитора, с которого пришел "звонок" и биндит в нему видеокарту номер 2. Далее уже идет отрисовка графики через эту видеокарту на нужный монитор.

    Соответственно, когда приходит следующий звонок, видеокарта "перепривязывается" опять.

    • Нравится 3

  5. Если мониторы принадлежат разным компьютерам - можно разнести их распределителем или свитчем.

    Если мониторы и карты принадлежат одному компьютеру - надо биндить.

     

    Загвоздка в том, что если написать просто component.gpu.bind() - он обратится только к одной видеокарте - той, которую считает "основной".

    Поэтому сначала надо получить список видеокарт компьютера - их компонентов, точнее.

    local component = require('component')
    
    -- создаем таблички для хранения адресов компонентов
    local gpu = {}
    local screen = {}
    
    -- получаем список видеокарт
    for address, componentType in component.list("gpu") do
      table.insert(gpu, address)
    end
    -- получаем список мониторов (можно и вручную составить в принципе)
    for address, componentType in component.list("screen") do
      table.insert(screen, address)
    end
    
    -- биндим попарно
    -- (контрольные проверки не делаются, поэтому, во избежание ошибок,
    -- мониторов и карт должно быть одинаковое количество)
    for number, address in pairs(gpu) do
      component.proxy(address).bind(screen[number])
    end
    

    Есть еще один путь - можно оставить в компьютере только одну видеокарту. И биндить ее к нужному монитору перед рисованием.

    Но тогда надо следить за разрешением (разрешение монитора при биндинге карты изменяется на разрешение карты).

    • Нравится 3

  6. Извиняюсь может я невнимательно изучил блог. В проге можно выставить чтоб робот на один сундук работал?

     

    Нет, к сожалению такого режима у робота нет. Он движется "линейно", углубляя шахту дальше и дальше, и назад не возвращается. Поэтому он оставляет сундуки по сторонам своей шахты.

     

    P.S. Обновил первый пост. Теперь там есть ссылка на последнюю версию программы.

    • Нравится 1

  7. Предлагаю реализовать эту фичу следующим образом:

    Поставить возле банка небольшую будку "КБ Роботы Васи". Внутри будет стоять ассемблер, терминал банка и скамейка.

    Дядя Вася приходит, садится на скамейку и ждет покупателей.

    Далее происходит следующее.

     

    Приходит покупатель, говорит: "Дядь Вась, а дядь Вась? Мне бы робота вот такого, бы. Чтобы тут сундук, тут печка, а сзади ракетница торчала."

    Дядя Вася стучит по большому калькулятору и отвечает: "$ 2 000 000"

    Покупатель идет в банк и переводит дяде Васе N-ое количество дензнаков на счет. Дядя Вася проверяет в своем терминале получение суммы, покупает через этот же терминал запчасти, распихивает их по ассемблерам, и через пару минут выдает в окошечко готового робота!

    Все довольны, как говорится.

     

    P.S. На стену вешаем прайс:

    * Рекурсивный майнер - 4 ляма

    * Крутая черепаха - 1 лям (при покупке 3 штук - четвертая в подарок)

    • Нравится 3

  8. Самое простое решение - взять по настоящему последнюю версию программы из моего блога: http://pastebin.com/L21VMm7S   :)

    Насколько помню, я пофиксил там баг с сундуком, и вообще провел оптимизацию программы.

    (В том же блоге - подробные инструкции по установке и использованию)

     

    P.S. Ванильные эндер-сундуки, как выяснилось с роботами не работают. Оригинальная программа использовала сундуки мода EnderStorage. Поэтому, если у вас не стоит подобный мод, лучше использовать деревянные.

    • Нравится 2

  9. Не всё так просто. Попытайтесь применить true/false для функции use() выполняемой над кропсом, растущим на жердочке, а я посмеюсь. Даже объехать на кривом козле с геолизером это нельзя - нет способа получить состояние кропса.  Перемещение - это лишь самые примитивные и очевидные команды.

     

    Этокакэто? У нас сервер в несколько потоков работает? И один поток пихает в очередь другого задачи асинхронно,  не интересуясь выполнением предыдущей команды? Иначе описанное Вами "нитро" нереализуемо.

    А вот то, что я вполне допускаю - сервер при перегрузке сбрасывает с очереди обработки низкоприоритетные задачи - падение гравия, распространение воды, мобов и т.д. в это я готов поверить. И движение роботов попало туда-же. При том, что виртуальная машина lua осталась высокоприоритетной и добросовестно исполняется. Результат на лице.

    P.S. Это лишь мои домыслы. То, как я реализовал бы обработку будучи разработчиком серва. Реально работы сервера я не знаю.

     

    Функция use() возвращает true/false так же, как и остальные функции. В случае true добавляет описание произведенного действия.

    Под "робот пропускает действия" имеется ввиду, что робот возвращает "успех операции" не выполняя ее физически?

     

    По поводу мультипоточности я погорячился, да. Мне уже указали тут. Что, однако, не отменяет необходимости ставить слипы и делать проверки.


  10. Практически все команды робота возвращают true/false как индикатор успеха выполнения.

    Если вы вызываете еще один forward в то время, как робот еще предыдущий не завершил - не ждите, что он "включит нитро" и понесется быстрее.

    Проверяйте, и будет все хорошо. И организуйте ему слипы в цикле. Во время слипов обрабатываются эвенты и фоновые задачи.

    • Нравится 1

  11. Полезно. Но ты сравнивал по производительности с библиотекой OC Serialization API?

    (https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/serialization.lua)

     

    Твой пример под OC:

    local serial = require('serialization')
    
    -- Таблица, которую мы превращаем в строку
    local obj = {[0]=1, 2, 3, ["fieldName"]=0, {6,7,8}}
    
    -- Сериализация
    local s = serial.serialize(obj)
    
    -- Обратно из строки в таблицу
    local _obj = serial.unserialize(s)
    

  12. FAQ

     

    А как вообще пользоваться 3D принтером?

     

    Итак, как использовать какую-либо модель из этой темы? Что для этого потребуется?

     

    Вам не нужны знания программирования. Вам нужно:

    * простой компьютер из ОС (все равно какие детали и программы, все равно каких уровней, главное - чтобы работал)

    * скрафтить 3D-принтер

    * скрафтить к нему картридж и заправить красителями

    * накрафтить печатной массы (хамелиума)

    * подключить принтер к компьютеру (поставьте вплотную, или соедините кабелем)

    * распихать картриджи и массу по слотам в принтере

     

    Теперь вам нужна программка для печати. Берем ее здесь: http://pastebin.com/b5rD8KcY

    Если есть интернет-плата то просто напишите в консоли: 

    pastebin get b5rD8KcY print3d

    Если платы нет, то напишите: 

    edit print3d

    Откроется редактор. Скопируйте код с Пастебина, вставьте в редактор кнопкой [insert], затем нажмите [Ctrl+S] (сохранить) и [Ctrl+W] (закрыть редактор).

     

    Осталось скачать модель. Делается это точно также. Либо залейте модель на Пастебин, а потом скачайте ее через pastebin get, либо откройте редактор (например edit model), и вставьте код напрямую. Не забудьте сохранить.

     

    Для того чтобы наконец распечатать модель - просто напишите в консоли компьютера:

    print3d model
    

    (где model - название файла с вашей моделькой)

    Готово!

     

    P.S. Если вам интересны подробности, загляните также сюда: Трехмерная печать в Minecraft


  13. Итак, есть мнение, что на сервере ИТ не хватает декора. Что же нам делать? Как спасти ситуацию?

     

    Ответ прост. 3D-Принтер!

    Все что нам надо - это взять в зубы блокноты и карандаши и начать печатать декор! И если взяться за дело как следует, декора нам хватит лет на 10 вперед.

     

    Выкладывайте свои схемы в этой теме, и не забывайте про картинку.

    Вот несложная схемка для начала.

     

     

    Укрепленные ставни (в стиле military =)

    Код:

     

     

    {
      label = "Reinforced Slider",
      tooltip = "Protect your windows",
      shapes = {
        {0,0,14,16,14,16, texture="ic2:blockAlloy:4"},
        {0,14,12,16,16,16, texture="ic2:blockAlloy:4"},
        {0,14,12,16,16,16, texture="ic2:blockAlloy:4", state=true}
      }
    } 

     

    Управляемые редстоуном защитные ставни помогут придать вашей базе законченный вид. Могут использоватся как со стеклом, так и без него, обеспечивая надежную защиту от проникновения и широкий обзор!

    В схеме использована текстура укрепленного камня. Вы можете сменить ее на любую другую, по желанию (воспользуйтесь Определителем Текстур чтобы узнать название)

     

    Как выглядит:

    1. Вид снаружи

    2015-04-16_03.41.05.png

     

    2. Ставни закрываются

    2015-04-16_03.52.03.png

     

    На скриншотах для управления защитными ставнями используется вот такая несложная программка:

     

     

    -- Reinforced Protection Sliders [OpenComputers]
    -- computercraft.ru (c) Totoro / 16.04.2015
    
    local event = require('event')
    local term = require('term')
    local sides = require('sides')
    local com = require('component')
    local gpu = com.gpu
    
    -- загружаем все красные контроллеры
    local redstone = {}
    for a, b in com.list('redstone') do table.insert(redstone, com.proxy(a)) end
    
    -- сохраняем параметры экрана
    local ow, oh = gpu.getResolution()
    
    -- ставни закрыты
    local status = false
    
    
    -- функция подачи сигнала вверх со всех контроллеров
    local function setSignal(strength)
      for a, proxy in pairs(redstone) do
        proxy.setOutput(sides.up, strength)
      end
    end
    -- функция изменения состояния ставней
    local function setSliders(open)
      status = open
      if open then
        for i=5, 15 do
          setSignal(i)
          os.sleep(0.1)
        end
      else
        for i=15, 0, -1 do
          setSignal(i)
          os.sleep(0.1)
        end
      end
    end
    
    -- функция рисования интерфейса
    local function drawGUI()
      gpu.setResolution(10,1)
      gpu.setForeground(0x1CDCF2)
      gpu.setBackground(0x000000)
      term.clear()
      gpu.set(1,1, "//")
      gpu.set(9,1, "//")
      gpu.setForeground(0x000000)
      gpu.setBackground(0x1CDCF2)
      gpu.set(3,1, " OPEN ")
    end
    
    -- рисуем интерфейс
    drawGUI()
    
    -- главный цикл
    while true do
      -- слушаем эвенты
      local name, address = event.pull()
      
      -- если была нажата любая кнопка клавиатуры - выходим
      if name == 'key_down' then
        break
      -- если было касание экрана/клик мышкой
      elseif name == 'touch' then
        setSliders(not status)
      end
    end
    
    -- восстанавливаем параметры экрана
    gpu.setResolution(ow, oh)
    gpu.setForeground(0xFFFFFF)
    gpu.setBackground(0x000000)
    term.clear() 

     

    Однако можно управлять и при помощи обычного рычага.

    Let's go!

    • Нравится 8
    • Спасибо 1

  14. Для рулетки не хватает зрелищности.

    Советую цифры сделать цветными, и большими:

         #      ###
        ##     #   #
       # #         #
         #        #
         #       #
         #      #
        ###    #####
    

    И т.д.

    Также можно добавить им эффект "кручения", когда следующая цифра "вползает" на экран построчно, "сдвигая" предыдущую.

    Хотя на сервере это возможно не будет хорошо смотреться.


  15. Можно ли одним нажатием получить в буфер обмена адрес карты или вбивать посимвольно нужно?

     

    Адрес карты?

    Получаешь его на экран сначала.

    Например через интерпретатор lua в консоли:

    =component.gpu.address
    

    или

    =component.modem.address 

    Затем берешь анализатор и Shift+ПКМ по нужной строчке.

    Вставить в текст потом - просто ПКМ анализатором.

    • Нравится 2

  16. Кинуть в трубу можно. Ах! У нас труб уже нет. Да, тут надо думать. User707, когда будешь тестить в сингле, учитывай какие моды стоят на сервере

     

    :D

    Сундук был бы идеальным вариантом как для бартера, так и для банка. Однако для этого нужен сундук который плюет на приваты.

    А после упорной борьбы на искоренение всего, что не приватится, их не осталось.

     

    Что касается трубы, то засасывание роботом напрямую быстрее и удобнее, как в плане постройки кабинки, так и в плане программирования.


  17. Постоянно наблюдаются проблемы с мониторами если компьютеры объединены в локальную сеть. Так и норовят написать что то на чужой монитор. Что то можно сделать?

     

    Поставить между компьютерами свитч (если нужно сохранить сетевые пакеты).

    Или дистрибутор (если нужно распределить только энергию, а сетевые пакеты не нужны)

     

    Возможно адрес отправителя в эвенте сменится на адрес свитча, при прохождении через него.

    Если этого не нужно, можно поробовать либо отправлять настоящий адрес в теле пакета,

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

    Для этого используется функция gpu.bind(address):

    local com = require('component')
    local gpu = com.gpu
    
    -- связываем с видеокартой компьютера нужный монитор
    gpu.bind('xxx-xxx-....-xxxx')
    
×
×
  • Создать...