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

Почему package.lua не видит модуль?

Вопрос

Всем привет! Пытаюсь сделать так, чтобы программа использовала функции в модуле из папки вне корневой папки Майнкрафт-а, а из папки, допустим, D:/23 Вот код основной, вызывающей модуль программы:

local printermodule = require("printermodule")
printermodule.pr()

Вот модуль:

printermodule = {}

function printermodule.pr()
  print("hello")
end
return printermodule

В package.lua, что в папке lib папки жесткого диска робота, добавил конце строку "/D:/23/?.lua". Пытался и без слеша "D:/23/?.lua", но в этом случае ищет в "home/D:/23/?.lua":

package.path = "/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua;/D:/23/?.lua"

Скрин ошибки прикрепил.

2.jpg

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


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

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

В 18.05.2023 в 13:59, ECS сказал:

local event = require("event")

Нужна ли эта строчка в send.lua? В этом файле ничего не принимается, вроде.

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


Ссылка на сообщение
Поделиться на других сайтах
В 20.05.2023 в 15:19, WheatComp сказал:

Не совсем понял эту фразу. Во время игры пользоваться внеигровыми символьными ссылками? Чтобы программа робота обращалась к папке вне корневой папки Майнкрафта? Так мне это и требовалось.

Что именно требовалось, мне до сих пор не особо понятно. Для примера опишу свой подход.

 

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

 

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

 

При последующих экспериментах я создаю ссылки на нужные мне файлы и каталоги, используя комбинацию клавиш C-x s в Midnight Commander.

 

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

 

Если требуется провести масштабный эксперимент с десятками роботов, то я беру их из креатива. В момент установки роботов в мир появляются каталоги, соответствующие их дискам. Для массовой подмены каталогов я использую скрипт, подменяющий только пустые каталоги с подходящими именами:

#!/bin/bash
# Подмена каталогов жёстких дисков OpenComputers ссылками на каталог-источник 
# Параметры запуска: каталог-источник, каталог OpenComputers сохранения игры

dirSource=$1
dirTarget=$2

for dir in $dirTarget/*; do
  # обрабатывать только каталоги
  if [ ! -d "$dir" ]
    then continue; fi
  # обрабатывать только каталоги с подходящими именами
  if ! (basename "$dir" | egrep -q \
    '^[0-9,a-f]{8}-[0-9,a-f]{4}-[0-9,a-f]{4}-[0-9,a-f]{4}-[0-9,a-f]{12}$') \
    then continue; fi
  # обрабатывать только пустые каталоги
  if [ -n "$(ls -A ""$dir"")" ]
    then continue; fi
  # подмена каталога ссылкой на источник
  rm -r "$dir"
  ln -s "$dirSource" "$dir"
done

 

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


Ссылка на сообщение
Поделиться на других сайтах
22 часа назад, WheatComp сказал:

Нужна ли эта строчка в send.lua? В этом файле ничего не принимается, вроде.

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

 

Вообще роботы с дронами, имхо, самая балдёжная часть мода. Тут и автоматизация рутины, и распределенное выполнение задач, и сетевой код, и инфо-безопасность. Когда кодил аналогичную систему контроля в сурве, то сформулировал для себя несколько рекомендейшнов:

 

  • Метод modem.setWakeMessage() - имба. Когда робот выполнил все задачи, можно смело его выключать, оставляя где-то на глубине в границах привата. Когда необходимо продолжить работу, шлём сетевой пакет на включение - профит. И энергия сохранена, и нажимать кнопку Power не надо
  • Широковещательные пакеты через modem.broadcast() опасны на публичных серверах, и в 100% случаев станут причиной угона робота. В идеале, когда все машинки скрафчены, необходимо внести адреса их модемов в конфиг на хосте, а впоследствии общаться приватными пакетами через modem.send(). Либо захардкодить в роботах адрес хоста и доверять лишь ему одному, как в примере выше
  • Дополнительные батареи - мусор. Вместо них лучше установить апгрейд опыта, построить ферму кобблы и позволить роботу фармить экспу. Спустя 2-4 реальных часа у тебя раскачается "алмазный" робот с колоссальным буфером энергии
  • Апгрейд навигации для вычисления позиции/поворота - мусор. Вместо него куда дешевле и интереснее накодить софтверную триангуляцию, основанную на перемещениях робота и расстоянии, которое "пролетел" сетевой пакет. А поворот можно определить с помощью геоанализатора, ломания/установки блоков и вращения робота
  • Софтверное позиционирование - имба. Вычисляешь единожды координаты/поворот робота - и корректируешь их при вызове move/turn. Взамен появляется возможность автоматизировать перемещение в любую указанную точку. При отключении питания имеет смысл сохранять эти данные на диске, либо определять их автоматически при включении
  • Геоанализатор - легальный чит. Однако использовать его в штатном режиме, сканируя вертикальными "столбцами" - выстрел в ногу, т.к. точность результатов на расстоянии в 10+ блоков будет отвратная. Вместо этого стоит заюзать опциональные аргументы scan(), анализируя небольшие горизонтальные плоскости 8х8 блоков вокруг робота, постепенно прокапывая вниз. Точность при этом станет как советском станке
  • Экран/клавиатура/дисковод и полноценная ОС - штуки ситуативные, т.к. стоимость сборки улетает в космос, а выхлоп сомнительный. Мнение не навязываю, но я предпочитаю ставить больше апгрейдов инвентаря/крафтинг/редстоун-плату/etc., делая машинку универсальнее и контролируя её по сети
  • Апгрейд крафтинга очень недооценён. Каким бы большим ни был инвентарь, он гарантированно заполнится всякими андезитами/мусоритами. Эту проблему в соло решает крафтинг, упаковывающий ресурсы в стаки, особенно на серверах с модами типа экстраутилит, позволяющими "сжимать" кобблу
  • Жёсткий диск 1 тира - топ за свои деньги. Всегда приятно иметь возможность сохранять/загружать координаты робота или довольно объёмные "снимки" местности с геоанализатора

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


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

Оказалось, что поторопился радоваться с computer.pullSignal(5). В коде (robot.lua) ниже эта команда не выполняется, робот сразу поворачивается:

local robot = component.proxy(component.list("robot")())

computer.pullSignal(5)

for i = 1, 4 do
  robot.turn(true)
end

Скопировал функцию os.sleep(), тоже не выполняется, программа send.lua высылает только строчку "executeFailed", причину не высылает:

local robot = component.proxy(component.list("robot")())

    function os.sleep(timeout)
  checkArg(1, timeout, "number", "nil")
  local deadline = computer.uptime() + (timeout or 0)
  repeat
    event.pull(deadline - computer.uptime())
  until computer.uptime() >= deadline
end
os.sleep(5)

for i = 1, 4 do
  robot.turn(true)
end

 

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


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

computer.pullSignal ждёт первого сигнала определённое время. То, что ей передана пятёрка, означает, что ждать будет не дольше 5 секунд, но если какое-то событие придёт раньше (что здесь и происходит: возможно, подключение компонентов), то выйдет раньше.

 

UPD. @ECS уже говорил про это в предыдущих сообщениях. Просьба внимательнее читать ответы.

В 21.05.2023 в 02:24, ECS сказал:

Эта штука ждёт каких-либо сигналов в течение 3 секунд. Если сигнал получен - pullSignal вернёт информацию о нём досрочно. Если сигналов не было - pullSignal будет честно ждать 3 секунды, а затем вернет nil

 

А os.sleep так не заработает: синтаксис

function tbl.func()
  ...
end

создаёт новую функцию и кладёт её в поле "func" таблицы tbl. В данном случае функция кладётся в поле "sleep" таблицы os. Но такой таблицы в биосах нет.

 

Либо нужно определить табличку эту:

local os = {}

function os.sleep(timeout)
  --[[ сюда код функции ]]--
end

Либо вообще не пытаться класть функции в таблицы (что наиболее разумно):

local function sleep(timeout)
  checkArg(1, timeout, "number", "nil")
  local deadline = computer.uptime() + (timeout or 0)
  repeat
    computer.pullSignal(deadline - computer.uptime())
  until computer.uptime() >= deadline
end

Здесь ещё пропал event.pull, потому что event в биосах тоже отсутствует. (Да и в OpenOS event сначала нужно получить через require.) computer.pullSignal для наших целей достаточен.

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


Ссылка на сообщение
Поделиться на других сайтах
40 минут назад, Fingercomp сказал:

То, что ей передана пятёрка, означает, что ждать будет не дольше 5 секунд, но если какое-то событие придёт раньше

Да, Вы правы, пришел еще один сигнал. Я не стал выкладывать весь код, дабы не загромождать сообщение. В конце send.lua была еще одна строчка, отсылающая сигнал:

modem.broadcast(port, "execute", data)
component.invoke(address, "broadcast", port, "execute", data)

это я экспериментировал с первичностью модема а modem.boradcast() почему-то не стал комментить. Она и прерывала, оказывается, pullSignal(). При удалении одной из этих строк pullSignal работает нормально, придется быть осторожнее.

Изменено пользователем WheatComp

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


Ссылка на сообщение
Поделиться на других сайтах
7 часов назад, ECS сказал:

Метод modem.setWakeMessage() - имба.

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

7 часов назад, ECS сказал:

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

До апгрейда опыта еще не дошел. Можно поподробнее, где хранится этот буфер энергии? И где смотреть "алмазность", или "железность" робота?

7 часов назад, ECS сказал:

Геоанализатор - легальный чит.

До его функции анализа ископаемых тоже не дошел, пока определяю растения.

7 часов назад, ECS сказал:

Апгрейд крафтинга очень недооценён. Каким бы большим ни был инвентарь, он гарантированно заполнится всякими андезитами/мусоритами. Эту проблему в соло решает крафтинг,

А если просто выкидывать мусор? Прописать названия, если == то дропнуть.

7 часов назад, ECS сказал:

Жёсткий диск 1 тира - топ за свои деньги.

Пока им и пользуюсь, программы небольшие.

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


Ссылка на сообщение
Поделиться на других сайтах
13 часа назад, WheatComp сказал:

Можно поподробнее, где хранится этот буфер энергии? И где смотреть "алмазность", или "железность" робота?

Хранится в роботе, получить объем буфера можно через computer.maxEnergy(), а смотреть "алмазность" можно либо через experience.level(), либо визуально, т.к. с накоплением опыта робот меняет свой цвет сначала на золотой, а затем на алмазный:

 

image.png.aab2d72090afbe146291a625e4292a99.png

 

13 часа назад, WheatComp сказал:

А если просто выкидывать мусор? Прописать названия, если == то дропнуть.

А выкидывание никто не отменял, его нужно грамотно комбинировать с упаковкой. Например, если робот накопал 9 стаков реда, их можно упаковать в стак блоков, освободив целых 8 слотов под другие ресурсы. Это в любом случае быстрее, чем перемещаться на базу, сбрасывать инвентарь, возвращаться на раскопки и продолжать работу

 

В случае с мусором - да, только выкидывать по черному/белому списку или заправлять апгрейд генератора, если ресурс сжигаемый. Однако мусора много, сканить инвентарь придётся часто, а этот процесс не слишком быстрый. В теории его можно ускорить, реализовав RAM-кеш содержимого инвентаря - но придётся сильно попотеть и учесть тысячу и один нюанс

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


Ссылка на сообщение
Поделиться на других сайтах
В 22.05.2023 в 18:26, ECS сказал:

Геоанализатор - легальный чит.

 

В 22.05.2023 в 18:26, ECS сказал:

Апгрейд навигации для вычисления позиции/поворота - мусор.

Только что узнал, наконец-то, для чего нужно зеленое пятно у планшета. Оказывается, можно в планшет положить геоанализатор или апгрейд навигации, долго нажать на блоке и получить какую-нибудь информацию о блоке, на которой пятно. Там пишется, что нужно нажимать ПКМ 1 секунду, но у меня почему-то не пищит, и информацию не дает, ни в терминал планшета, ни в интерпретатор. Пробовал component.geolyzer.analyze(3), но показывает воздух.

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


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, WheatComp сказал:

Там пишется, что нужно нажимать ПКМ 1 секунду, но у меня почему-то не пищит, и информацию не дает, ни в терминал планшета, ни в интерпретатор. Пробовал component.geolyzer.analyze(3), но показывает воздух.

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

while true do print(serialization.serialize({event.pull()}))end

 

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


Ссылка на сообщение
Поделиться на других сайтах
19 часов назад, eu_tomat сказал:

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

Иногда встречается вложенная таблица. Интересно, можно ли вложенную таблицу напечатать посредством for key, value in pairs do? Например, component.tank_controller.getFluidInTank(5) возвращает вложенную таблицу:

12.jpg

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


Ссылка на сообщение
Поделиться на других сайтах
В 22.05.2023 в 18:26, ECS сказал:

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

Апгрейд опыта поставил, пытаюсь выкачать с помощью саженца, сажает, убирает, сажает, убирает. За 5 часов только до 6-го уровня дошел, цвет не поменялся. Пытался на ферме кобблы ставить, там раза в 2 медленнее.

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


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

@eu_tomat понимаю, что проще всего сериализацией вывести, насчет for-а стало интересно ради понимания Lua.

 

@serafim посмотрел рыбную ферму для робота-рыболова. Это отдельное строительство. Нет ли чего попроще для набивания опыта?

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


Ссылка на сообщение
Поделиться на других сайтах
1 минуту назад, WheatComp сказал:

@eu_tomat понимаю, что проще всего сериализацией вывести, насчет for-а стало интересно ради понимания Lua.

Да, можно. Пишем функцию, выводящую таблицу в цикле for k,v in pairs(table). Добавляем условие. Если очередное поле оказалось таблицей, то рекурсивно вызываем эту же функцию уже для вложенной таблицы. В противном случае печатаем поле как обычно. Это самый простой способ. Если требуется наглядность, можем добавить параметр функции, задающий размер отступа для вложенных элементов.

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


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

@eu_tomat а нельзя ли обойтись без сложностей? Нельзя ли захардкоджить и получить доступ к значениям внутренних таблиц при помощи индекса цикла for и простого доступа вроде table[1][1][key] или table[1.1.key] или table[1][1].key? Мы же знаем, что внутри внешней таблицы - таблица?

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


Ссылка на сообщение
Поделиться на других сайтах
28 минут назад, WheatComp сказал:

@eu_tomat а нельзя ли обойтись без сложностей? Нельзя ли захардкоджить и получить доступ к значениям внутренних таблиц при помощи индекса цикла for и простого доступа вроде table[1][1][key] или table[1.1.key] или table[1][1].key? Мы же знаем, что внутри внешней таблицы - таблица?

Если мы собираемся работать с конкретной таблицей с неизменной структурой, можно и захардкодить. Конструкции вида table[key1][key2] и table.key1.key2 позволяют это сделать.

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


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

@eu_tomat Сделал таблицу, имитирующую таблицу, возвращаемую tank_controller:

tank1 = {amount = 222, capacity = 333}
tank2 = {amount = 452, capacity = 349}
tankTable = {tank1, tank2}

for key, value in pairs(tankTable) do
print(value)
print(tankTable[1][key])
end

Выводит nil nil.

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


Ссылка на сообщение
Поделиться на других сайтах
5 минут назад, WheatComp сказал:

Выводит nil nil.

Так и должно быть. Ты перебираешь ключи таблицы tankTable, но пытаешься по этим ключам получить значение в таблице tankTable[1].

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


Ссылка на сообщение
Поделиться на других сайтах
27 минут назад, eu_tomat сказал:

но пытаешься по этим ключам получить значение в таблице tankTable[1].

Значение получить-то можно, если так изменить первую таблицу:

tank1 = {222, capacity = 333}

и выводить так:

print(tankTable[key][key])

А вот к значению переменной capacity уже нет доступа таким образом. Понятно, что можно получить доступ напрямую: print(tankTable[key].capacity, но как получить доступ через средства индексации и цикла?

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


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

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

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

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

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

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

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

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

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


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