Поиск по сайту
Результаты поиска по тегам 'Lua'.
Найдено 147 результатов
-
На форуме в последнее время начали появляться темы с сетевыми библиотеками и браузерами. Продолжу это движение (да, скоро и мой браузер будет). Итак, представляю вам ThunderNet! Кстати, анонс уже был: вот это сообщение как раз рассказывало про пришествие ThunderNet. ThunderNet - это сеть, позволяющая объединить множество компьютеров OC, даже на разных серверах. По топологии это (почти) дерево, при этом корнем может быть любой компьютер. Уровней может быть любое количество. Компьютеры взаимодействуют по некоторому каналу: сетевая/соединённая карта/красный камень/Stem/звёздные врата и т.д. Идентификация происходит при помощи MUID (Minecraft-Unique IDentifiers): кодов, уникальных для каждого запуска на каждом компьютере OC. Спецификация протокола: 1. Подключение к сети: — WTC <uid> (Want-To-Connect) Ближайшие компьютеры запоминают этого соседа и отвечают (или не отвечают) — CAC <uid> <level> (Can-Accept-Connection) (level - глубина дерева от корня до отвечающего компьютера); Подключаемый компьютер подтверждает соединение: — AC <uid> (Accept-Connection) Отвечающий компьютер ("родитель") отправляет сообщение до корня: — UCA <uid> (Underlying-Connection-Accepted) Все компьютеры от корня до отвечающего запоминают, в каком направлении посылать сообщение новому. 2. Пересылка сообщений: — RM <message> <target-uid> (Retranslate-Message) Компьютер, получивший такое сообщение, должен: 1) Если он знает путь до <target-uid>, переслать этот пакет по пути. 2) Если он не знает путь и не является корнем, отправить этот пакет родителю. 3) Если он не знает путь и является корнем, забыть это сообщение (потому что куда его отправить? некуда.) При получении сообщения с target-uid, равным uid текущего компьютера, библиотека вызывает событие: thunderlib_incoming <message> 3. Отключение от сети: — DC <disconnected-uid> Компьютеры выше по дереву забывают путь до указанного компьютера и его потомков. Моя реализация этого протокола: Библиотека сейчас состоит из трёх файлов: th_inform.lua, thlib.lua и th_interfaces.lua. Для работы их надо сложить в ту папку, откуда будет запускаться программа. Важное замечание: все методы Thunderlib являются синхронными, т.е. блокируют вызывающий поток! В некоторых функциях есть параметр is_timeout, который завершает выполнение, когда функция возвращает true. Документация по методам: thunderlib.connect([is_timeout]) - подключение к ThunderNet thunderlib.disconnect() - отключение Отключение после использования крайне рекомендовано! В противном случае у компьютеров выше в иерархии может кончиться память. thunderlib.send(<address>,<data>) - посылка сообщения заданному компьютеру по его MUID thunderlib.run_server([is_timeout[, allow_connections]]) - запуск сервера ThunderNet Сервер нужен для приёма входящих подключений и обнаружения соседних компьютеров. thunderlib.uid() - возвращает MUID текущего компьютера thunderlib.parent_node() - возвращает MUID родительского компьютера
- 6 ответов
-
- 7
-
-
-
-
- opencomputers
- lua
-
(и ещё 1 )
Теги:
-
Здравствуйте, не знаю в чём проблема, во мне, или в моде. Есть биг улей, подключил его к ОС через адаптер. Посадил туда в 1 слот принцесску. Вызвал интерпретатор, пишу: =component.items.getAllStacks(0) Ответ: {} Думаю ладно, пойду иначе: =component.items.getStackInSlot(1) Ответ: nil "slot id (1) must be less than 1" Подумал вообще безумие, но как скажете, пишу: =component.items.getStackInSlot(0) Ответ: nil "slot id (0) must be at least 1" Было бы смешно, если бы не было так грустно...) С другими ульями всё в порядке, эти, просто так, начали вот так меня дразнить. Подскажите, пожалуйста, в чём может быть причина?
-
Привет. Пишу програмку для варпа и столкнулся с проблемкой сортировки. Тематика такая: Прога выводит на экран всех владельцев варпа и показывает как долго они онлайн/оффлайн что-бы посетители знали к кому можно обратиться по каким-то вопросам. Я сортирую последовательную таблицу участников варпа по функции: https://pastebin.com/aE4EHBk3 Сортировка буд-то бы в случайном порядке сортирует людей на экране: Это так-же не работает с кастомной функцией сортировки: https://pastebin.com/tnY2PeTR В итоге должно было получиться что-то вроде: сначала идут онлайн пользователи, они отсортированы по 'время сессии'. далее идут оффлайн юзеры, они отсортированы по 'был в сети'. Что я делаю не так?
- 12 ответов
-
- bubble sorting
- table.sort
-
(и ещё 1 )
Теги:
-
Помню @@1Ridav разрабатывал мост для связи игры и ПК, чтобы можно было получать уведомления от роботов и компьютеров. Чуть посидев (а как вы помните я Lua не знаю) получилось вот это: https://pastebin.com/rZC8BZMs Что позволяет? Вы можете или запускать эту "штуку" просто с аргументом или вырезать те 2 строчки, которые принимают аргументы и просто включить этот код в код вашей программы и получать уведомления в телеграмм. Назвал я эту штуку TGInformer. Что нужно для работы? Со стороны Telegram: Добавить вот этого бота: https://t.me/ShowJsonBot, написать ему и в секции from найти id и записать его Добавить бота https://t.me/OC_InformerBot и написать ему любое сообщение. Со стороны OpenComputers: Компьютер с сетевой картой Загрузить код информера и открыть его для редактирования. Вверху в поле chatid впишите ID, который получили пунктами выше. Выполните tginformer test В результате в телеграм должно прийти test, а в игре код ответа: ОК Теперь осталось вписать это в свою программу и робот будет присылать уведомления типа я покакаль я выкопал ту большую яму P.S. Спасибо @@Alex за правки
- 12 ответов
-
- 14
-
-
В прошлый раз я патчил OpenComputers, чтобы пробрасывать нативную либу debug. Пойдём дальше. Добавим нативных либ package и os. Прокинем дефолтное окружение внутрь песочницы. Пропатчим мод, чтобы можно было загружать си-модули. Загрузим профилятор и посмотрим, что из этого вышло. На винде ничего не заработает. Гарантирую. Если надо профилировать, ставьте нормальные оси или мучайтесь. 0. Сырцы мода Так как мы будем патчить мод, надо сначала подготовить исходники. $ git clone https://github.com/MightyPirates/OpenComputers.git $ cd OpenComputers $ git checkout master-MC1.12 $ ./gradlew setupDecompWorkspace На третьей строке версию выбираем по вкусу и выпекаем всё необходимое для компиляции. 1. Нативные либы Здесь всё просто. Открываем файл src/main/scala/li/cil/oc/server/machine/luac/LuaStateFactory.scala. Творим следующее: Вуаля. Теперь в machine.lua будут глобальные переменные package и _os. Отмечу отдельно, что меняем мы только архитектуру Lua 5.3. Уже на этом этапе у нас может сломаться персистентность. Это не страшно: она и должна сломаться. 2. Прокидываем окружение Поступаем аналогично тому, что делали в прошлой записи: меняем src/main/resources/assets/opencomputers/lua/machine.lua: Внутри песочницы в глобальной переменной env запечатлено будет всё окружение machine.lua. 3. C-модули Уже сейчас можно загрузить OpenOS и прописать env.require("libname"). Проблема в том, что C-модули так подключить не получится. Связано это с особенностью Lua. Абстрактно задача заключается в том, чтобы загрузить библиотку Lua с dlopen(..., RTLD_GLOBAL). System.loadLibrary в жаве флаг этот упускает по очевидным причинам, а нам он нужен. Значит, пришло время костылей. 3.1. Подключаем JNA: build.gradle Первый ханк нужен, чтобы можно было потом компилировать мод. Почему-то у курсов мавен не работает, а разбираться мне лень. 3.2. Патчим ещё раз src/main/scala/li/cil/oc/server/machine/luac/LuaStateFactory.scala Во-первых, подключаем хэшмапу. Потребуется. Во-вторых, импортируем JNA. Вернее, его часть. В-третьих, патчим код, чтобы он загружал Lua 5.3 через JNA. Магическая константа 0x101 — это значение RTLD_LAZY | RTLD_GLOBAL на моей системе. На фряхе, маке оно может отличаться. На этом этапе Lua 5.2 не будет работать. Включаться будет только Lua 5.3 из-за конфликта имён. Кроме того, JNA — это, вообще, огромная либа. Ради одной функции её подключать — это оверкилл. Но я в тонкостях JVM и JNI не силён. Как уже сказал, разбираться мне лень. 3.3. Компилируем $ ./gradlew assemble Выхлоп в build/libs. Берём жарник без суффиксов вроде -javadoc, -api, -sources. 4. Настраиваем профилятор Профилятор я написал сам на Rust. Вот ссылка: https://github.com/Fingercomp/lprofile-rs Очевидно, нам надо его скомпилировать. 4.1. Компилируем профилятор Ставим cargo (мультитул раста такой) любым удобным способом. Собираем: $ cd .. $ git clone --recurse-submodules https://github.com/Fingercomp/lprofile-rs.git $ cd lprofile-rs $ cargo build --release В target/release будет лежать liblprofile.so. Тырим его. 4.2. Определяем pwd Кидаем пропатченный OC в моды и запускаем игру. Пишем в опенкомпе env._os.getenv("PWD"), чтобы определить текущую директорию. Кидаем либу-профилятор в неё. 4.3. Профилируем Наконец, можно заняться мясом. local profiler = env.require("lprofile").Profiler() local result = profiler(function() local v = 0 for i = 1, 10e6, 1 do v = v + i end end) table.sort(result, function(lhs, rhs) return lhs.totalTime < rhs.totalTime end) print("Name", "# of calls", "Total time", "Total time, excluding inner calls") for _, v in ipairs(result) do print(("%s\t%d\t%.6f s\t%.6f s"):format(v.name, v.calls, v.totalTime, v.totalSelfTime)) end print("total time:", result.totalTime) 5. Зачем Мы получили наполовину сломанную версию OpenComputers: без Lua 5.3, без персистентности. Зато можем профилировать программы. Этот пост я написал, чтобы не забыть самому. Сомневаюсь, что кому-то интересно заниматься такой норкомагией.
- 3 комментария
-
- 7
-
-
-
- opencomputers
- lua
-
(и ещё 3 )
Теги:
-
"Дело было вечером, Делать было нечего." С. В. Михалков Писал я себе спокойно программы на Java, но захотелось мне изучить C++. С этим я легко справился и подумал - что бы мне такое написать для практики? Решил написать что-нибудь с использованием какой-нибудь интересной библиотеки. Например Lua. Тут я и вспомнил про OC и решил накодить эмулятор. Не буду про него ничего писать - просто оставлю ссыль на реп - вот. Там в ридми все разжевано. Эмулятор написан на C++ с использованием библиотек lua и SDL. Код писал полностью сам, кроме поддержки юникода - библиотеку для этого я нашел на гитхабе и Crl+C Ctrl+V (ну лень было разбираться в этих кодировках). Эмулятор еще написан не до конца, но OpenOS на нем работает. Сейчас пишу поддержку интернет-карт. Да, я знаю о том, что этих эмуляторов уже хоть пруд пруди, но вдруг кому-то мой покажется лучше. В общем, пользуйтесь на здоровье.
-
Сейчас я покажу, как сделать это: На скрине выше — улучшенный debug.debug(). Он умеет: Бегать вверх-вниз по стэку вызовов независимо от того, где запущен. Показывать красивые стэктрейсы. Имитировать динамический скоуп: получать значения локальных переменных, редактировать их, не требуя возни с либой debug. При этом учитывает, на каком уровне в стэке вызовов он находится. Он не умеет: «Шагать» по коду, заходить внутрь функций, проскакивать над ними. Таким образом, это не совсем дебаггер. Но он может показать состояние всех доступных переменных. Чтобы заюзать в коде, нужно сделать так: require("dbg")() Впрочем, если в проге есть какой-то часто вызываемый сегмент, то безусловно падать в мини-дебаггер на каждой итерации очень печально. Поэтому можно задать условие, при котором его запускать. Например: require("dbg")(nonNegative < 0) У нас есть переменная nonNegative, которая семантически всегда неотрицательна. Если ж внезапно попалось что-то меньше нуля, есть смысл попросить программиста проверить, кто (и как) изобрёл свою алгебру. Команды: :bt — показать стэктрейс. :up — прыгнуть на уровень вверх. :down — спуститься на уровень вниз. :frame N — перейти на N-ый уровень. Выйти из интерпретатора можно, нажав Ctrl-D или Ctrl-C. Код: https://gist.github.com/Fingercomp/58388304f45bf6b2b8108e3b7a555315 (задумывался одноразовым, качество соответствующее). В обычной Lua надо просто кинуть содержимое куда-нибудь, откуда require тащит файлы. Чтобы это работало в OpenComputers, придётся пропатчить содержимое мода: Открываем jar-файл мода в архиваторе. Идём в /assets/opencomputers/lua. Открываем файл machine.lua и в районе 971 строки делаем как-то так: Сохраняемся и выходим. Если всё сделано правильно, в OpenComputers теперь доступна полная либа debug. Остаётся закинуть код мини-дебаггера, например, в /home/lib, дальше используем как обычно. Очевидно, что на серверах такое делать не надо. Ну, совсем не надо. Полной либой debug легко выудить нативную load. А это уже уязвимость. Но в сингле вещь незаменимая. Цитирую отзыв пользователя, пожелавшего остаться анонимным: Успехов вам в дезинсекции кода.
-
- 12
-
-
-
-
- opencomputers
- lua
-
(и ещё 3 )
Теги:
-
Программа позволяет создавать снимки экрана. Сохраняет она его в файл /screenshots/Screenshot-Год-День-Час-Минута.ast Формат ast Для выхода из программы после распечатывания экрана надо по нему нажать(создать ивент touch). Вот код "AsumScreenshoter"'а: local mode = ({...})[1] if mode==nil then print("Использование: screenshot init для создания ивента сохранения экрана(Кнопка Print Screen, папка screenshots)\n screenshot <имя файла> для просмотра(По окончанию просмотра нажмите на экран)"); os.exit() return end local fs = require("filesystem") local unicode = require("unicode") local gpu = require("component").gpu local event = require("event") local function dec2hex(n, s) local h = string.format("%x", n) return string.rep("0", s-string.len(h))..h end local function hex2dec(s) return tonumber("0x"..s) end local function createScreenshotFile() DD, HH, MM, SS = os.date("%Y"), os.date("%H"), os.date("%M"), os.date("%S") if not fs.isDirectory("/screenshots") then fs.makeDirectory("/screenshots") end return io.open("/screenshots/Screenshot-"..DD.."-"..HH.."-"..MM.."-"..SS..".ast", "w") end local function getScreen() local W, H = gpu.getResolution() local screenshot = dec2hex(W, 2)..dec2hex(H, 2) local lfg, lbg for y=1, H do for x=1, W do local symbol, fgcolor, bgcolor = gpu.get(x, y) if lfg ~= fgcolor then lfg = fgcolor screenshot = screenshot .. "␑" screenshot = screenshot .. dec2hex(fgcolor, 6) end if lbg ~= bgcolor then lbg = bgcolor screenshot = screenshot .. "␒" screenshot = screenshot .. dec2hex(bgcolor, 6) end screenshot = screenshot .. symbol end end return screenshot end local function writeScreen() local file=createScreenshotFile() file:write(getScreen()) file:flush() file:close() end local function printScreen(filename) local screenshot=io.lines(filename)() local oldw, oldh = gpu.getResolution() local header = screenshot:sub(1, 4) screenshot = screenshot:sub(5) local W = hex2dec(header:sub(1, 2)) local x = 0 local H = hex2dec(header:sub(3, 4)) local y = 0 gpu.setResolution(W, H) while y < H do y = y + 1 x = 0 while x < W do local sym = unicode.sub(screenshot, 1, 1) if sym == "␑" then gpu.setForeground(hex2dec(unicode.sub(screenshot, 2, 7))) screenshot = unicode.sub(screenshot, 8) elseif sym == "␒" then gpu.setBackground(hex2dec(unicode.sub(screenshot, 2, 7))) screenshot = unicode.sub(screenshot, 8) else x = x + 1 gpu.set(x, y, sym) screenshot = unicode.sub(screenshot, 2) end end end event.pull("touch") gpu.setResolution(oldw, oldh) end local function saveScreenByKey(_, _, key1, key2) if key1==0 and key2==183 then writeScreen() end end if mode=="init" then event.listen("key_down", saveScreenByKey) else printScreen(mode) end Надеюсь вы будете пользоваться этой программой!=) Для того,что бы начать делать скриншоты, после каждой перезагрузки надо запустить приложение с параметром init Для того,что бы создать скриншот после инициализации-надо нажать кнопку Print Screen
- 18 ответов
-
- opencomputers
- lua
-
(и ещё 1 )
Теги:
-
Я видел статью про ООП (Объектно-Ориентированного Программирования), написанную на этом форуме, и вот, что могу сказать, он может быть немного непонятен новичкам в Lua. Я всегда пользовался другим способом создания "классов". Сначала следует разобраться со значениями. Класс - это набор методов (в нашем случае функций), процедур и переменных которые дальше будут наследоваться объектом или другим классом. Объектами называют сущности, обладающие набором свойств и операций над ними. Объект - это производное класса. В Lua классов как таковых нет, но если пофантазировать, то можно представить функцию как класс, а объект как таблицу. Создание простого псевдо-класса Наследование Экономия оперативной памяти Только читаемые свойства Вывод. Этот способ реализации ООП в Lua будет работать и в OC и в СС. "Классы" очень похожи на классы из других языков программирования. В моём варианте нет двоеточия, которое приносит странную возможность обработки одного объекта методом другого. Использовать ООП в игре можно для удобной разметки интерфейса в вашей программе (например для создания кнопок), и для экономии системных ресурсов в вашем компьютере внутри компьютера.
-
Предисловие Я думал на новый сервер запилить прогу — мост между чатом сервера и IRC. У меня уже были такие программки: я насчитал минимум 6 различных версий мостов — каждая была немного переделанным клиентом IRC, который на дискете встроенной есть. Понять, в чём разница, даже с вимдиффом было сложно. Потому я плюнул и решил запилить полноценную ирколибу с красивой апишкой. Как это выглядит Вот полный код бота — моста. Сто двадцать шесть строчек. Прокомментирую некоторые из них. ① Подключаем либу и для укорачивания имён ещё вытаскиваем events, в которых хранятся все ивенты и priority. ② Создаем клиент с помощью билдера. ③ Через :connection задаём настройки соединения. Самое важное — адрес иркосервера. Порт обязателен. ④ Ирколиба знает меру в флуде. Опасаться, что бота выкосит флуд-фильтром, можно гораздо меньше. Это опционально, конечно. ⑤ Задаём ник бота, юзернейм и реалнейм. Юзернейм виден в хосте (nickname!username@domain.name), а реалнейм пишется в /whois. ⑥ Ирколиба умеет авторизовываться на сервере. Тоже опционально. ⑦ Эта группа выделена для ботоводческих настроек. Но пока там единственная опция — в какие каналы автоматически заходить. ⑧ Здесь задаются настройки исполнения. Опция threaded, по дефолту включённая, запустит бота в отдельном треде. Опция reconnect, также включённая по умолчанию, заставит бота переподключиться к серверу, если отвалится от него. Опция catchErrors перехватит ошибки в пользовательких листнерах; она отключена по умолчанию, чтобы не смущать. ⑨ Бот генерит ивенты для каждого сообщения. Так мы задаём обработчик для ивента. К слову, вместо функции здесь может быть корутина. ⑩ Есть и другие события. Например, irc.events.client.connected означает, что клиент соединился с сервером. А irc.events.client.authenticated говорит, что теперь можно слать сообщения. ⑪ Когда мы закончили конфигурировать бота, собираем через :build(). Если вместо него вызвать :buildAndRun(), бот тут же ещё и запустится. ⑫ Для удобства создадим ещё один тред, где будем работать с чатбоксом и ждать ^C. ⑬ Запускаем бота. Затем ждём завершения любого из двух потоков. ⑭ Когда это произошло, мы выключаем клиент, если он ещё подключен: тот выйдет с сообщением "Quitting." ⑮ Наконец, принудительно останавливаем потоки. На всякий случай. Красота ведь. Репозиторий Репа либы — на нашем гитлабе. Там же есть примеры использования и документация с описанием всего. Наконец, версия 1.0.0 лежит на хеле. Из-за баги в OC хпм крашиться может (фиксить лень), но можно попробовать скачать: $ hpm install libirc
- 2 ответа
-
- 11
-
-
-
-
- opencomputers
- lua
-
(и ещё 1 )
Теги:
-
; — это код, который делает приблизительно ничего. Не абсолютно: об этом статья. Когда я писал crateriform (видяшки в гайде про корутины этим набором прог зарендерены), я отталкивался от Lua-парсера на Lua от @LeshaInc (спасибо ему ещё раз): Lua-часть принимала исходный файл с кодом, парсила его на AST и генерировала по нему обратно код. С костылями. Для рендера нужен был "сценарий" — файл, в котором указаны, какие символы изменились и на какое значение, помимо прочего. Генерируемые костыли как раз этим занимались: они оборачивались вокруг выражений и писали в файл высчитанное значение. Чтобы показать кадр с "n = 10", как на гифке, и следующий за ним, сценарий такой: 5,16 5,16 expr 10 Здесь через пробел: позиция начала в исходном коде, позиция конца, опкод (expr) и значение выражения. Так как генерируемый код делает то же, что и исходный, но ещё рисует сценарий, а выражения могут быть засунуты где угодно и раскрываться сразу в несколько значений, я создаю лямбду (анонимную функцию) и тут же её вызываю. Вот как выглядит часть сгенерированного кода, который занимается строкой выше: highlight({5, 16}, {5, 16}, (function(...) local values = table.pack(...) return function() return table.unpack(values, 1, values.n) end end)((n)), 'expr') Выглядит очень сложно (для сложности есть причины), но сейчас интересует только это: (function(...) <...> end)(...) Эта конструкция присутствует как третий аргумент к highlight. Программисты на JS с этим шаблоном должны быть знакомы: создаётся лямбда и тут же вызывается с некими аргументами. В месте, где синтаксис позволяет указывать только выражение — в списке аргументов вызова в нашем случае, — таким образом размещаем стейтменты. На всякий случай скажу, что стейтмент — любая цельная конструкция, кроме выражений. Если вы берёте часть кода, которая отдельно, вырванная из кода, не выдаёт синтаксическую ошибку (например, цикл for или local x = 3), и её нельзя поместить после x = , это стейтмент. А теперь суть. (function(x) print(x^2) end)(2) (function(y) print(y + 2) end)(2) Этот код задумывался так, чтобы он два раза принтнул четвёрку. Запускаем: $ lua5.3 semicolon.lua 4.0 lua5.3: semicolon.lua:1: attempt to call a nil value stack traceback: semicolon.lua:1: in main chunk [C]: in ? ..? Lua игнорирует пробельные символы. Код вроде такого: func(3) (4)(5) ...эквивалентен такому: func(3)(4)(5) В примере с ошибкой вызывается первая лямбда, возвращающая nil, который мы затем пытаемся вызвать с аргументом — второй лямбдой. Поэтому получаем "attempt to call a nil value". Чиним с помощью ;: (function(x) print(x^2) --> 4.0 end)(2) ; (function(y) print(y + 2) --> 4 end)(2) Кстати, чтобы ещё с толку сбить: комментарий вместо ; ошибку не исправит. Ещё один ошибочный пример: local pi = math.pi (function(r) print(2 * pi * r) end)(3) Как чинить, вы уже знаете. Отдельно упомяну точку с запятой после return. return обязан быть последним стейтментом в блоке. А ; — это стейтмент. Почему тогда можно делать так? local function f(x) return x^2; end print(f(2)) --> 4.0 Ответ: потому что ; — это опциональная часть return, а не отдельный стейтмент. Если же залипает клавиша и получается вот так: local function f(x) return x^2;; end print(f(2)) ...то будет синтаксическая ошибка. Вторая точка с запятой — теперь отдельный стейтмент, которых после return быть не должно. Поэтому с уважением относитесь к этому стейтменту. Точка с запятой делает приблизительно ничего, но с умом.
-
Кто нибудь знает, есть ли интерпретатор вне майнкрафта для lua OpenComputers дабы более удобно проверять и дебажить код ибо в самом майнкрафте это крайне не удобно делать.
-
Эта беспрецедентно короткая запись имеет начало своих ног в запросе @Laine_prikol, как-то спросивший в нашей ирке, можно ли стэктрейс сделать не таким тупым. Меня это заинтересовало, и спустя часик выросла очень короткая программка, которая рисует вот такие стэктрейсы: # 0: C field function yield(...) (defined in [C]) # 1: Lua local function f(f=function: 0x559402b83590, a=42, b=24, vararg test, nil):109 (defined in trace.lua at L108) # 2: Lua local function outer(f=function: 0x5594040b2230, g=function: 0x559402b83590, a=42, b=24, <... (1 arg)>):105 (defined in trace.lua at L103) # 3: Lua function <anon>():113 (defined in trace.lua at L102) Заметили что-то необычное? Наконец-то пишется, какие аргументы имеются у функции, потому что это куда информативнее беглому взгляду, чем описание расположения и строки. Код лежит на гисте: https://gist.github.com/Fingercomp/a688d221356cb371d940b947d0ca90a8. Использованы функции debug.getinfo и debug.getlocal. Аргументы должны писаться даже внутри OC, но уже без значений.
-
Как вы уже видели, программа бесполезная. Просто поставьте комп с видеокартой 2 уровня, большой монитор 2 уровня где нибудь на улице, и установите на него OpenOS. Вы можете редактировать текст, изменяя данные в таблице (она в коде, не зря меня Монстрик учил). Ну что, разбираем. http://pastebin.com/PwhkZTb0
-
Можно ли в чистой Lua (ну или той которая используется в OC) сделать так чтобы две функции выполнялись ДЕЙСТВИТЕЛЬНО одновременно?
- 5 ответов
-
- lua
- multithreading
- (и ещё 1 )
-
Всем привет! В этой теме я расскажу моей программе ---Удалённом рабочем столе на сети OpenNet и моде OpenComputers. Первым делом расскажу как ей пользоваться. Ввод данных: Всё очень просто=) Жмёте на кнопку на клавиатуре, и её нажатие эмитируется на удалённом компьютере. Для обновления экрана --- F5 Для выхода из программы на удалённом компьютере --- F2 Для выхода из программы на локальном компьютере ---F1 Ну....Вроде всё по управлению=) Запуск,настройка и подключение: Подготовка к запуску удалённого терминала: Установить библиотеку thread: local computer = require("computer") computer.SingleThread = computer.pullSignal local thread = {} local mainThread local timeouts local function MultiThread( _timeout ) if coroutine.running()==mainThread then local mintime = _timeout or math.huge local co=next(timeouts) while co do if coroutine.status( co ) == "dead" then timeouts[co],co=nil,next(timeouts,co) else if timeouts[co] < mintime then mintime=timeouts[co] end co=next(timeouts,co) end end if not next(timeouts) then computer.pullSignal=computer.SingleThread computer.pushSignal("AllThreadsDead") end local event={computer.SingleThread(mintime)} local ok, param for co in pairs(timeouts) do ok, param = coroutine.resume( co, table.unpack(event) ) if not ok then timeouts={} error( param ) else timeouts[co] = param or math.huge end end return table.unpack(event) else return coroutine.yield( _timeout ) end end function thread.init() mainThread=coroutine.running() timeouts={} end function thread.create(f,...) computer.pullSignal=MultiThread local co=coroutine.create(f) timeouts[co]=math.huge local ok, param = coroutine.resume( co, ... ) if not ok then timeouts={} error( param ) else timeouts[co] = param or '' end return co end function thread.kill(co) timeouts[co]=nil end function thread.killAll() timeouts={} computer.pullSignal=computer.SingleThread end function thread.waitForAll() repeat until MultiThread()=="AllThreadsDead" end ------------------------------------------------------------------------------- return thread (Только на сервер,на клиенте она не нужна) Установить OpenNet и находится в зоне его покрытия. Установить на сервер его часть: local event= require("event") local thread= require("thread") local opennet= require("opennet") local computer= require("computer") local gpu= require("component").gpu local unicode= require("unicode") local keyboard= require("component").keyboard.address local IP, dis2serv = opennet.getIP() print("Local IP: "..IP) args={...} if args[1]==nil then print("Использование: openviewerS <opennet_ip>") os.exit() end --[[ _, result, reason = opennet.sendrec(args[1], "connecting...") if result==false then print(reason); os.exit() end if args[1]==IP then print("Невозможно инициализировать удалённый доступ со своим устройством.") os.exit() end ]]-- initial=args[1] local function getScreen() screen="" for y=1, 25 do for x=1, 80 do symbol = gpu.get(x, y) screen=screen..symbol end end return screen end local function sendScreen() opennet.send(initial, getScreen()) end function runShell() os.execute("sh") end function reInitial() thread.killAll() thread.init() thread.create(runShell) thread.create(EmulateSignal) thread.waitForAll() end event.listen("Screen", sendScreen) event.listen("Exit", reInitial) function EmulateSignal() while true do opennetIP, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 = opennet.receive() if opennetIP==initial then computer.pushSignal(arg1, keyboard, tonumber(arg3), tonumber(arg4), arg5) end end end thread.init() thread.create(runShell) thread.create(EmulateSignal) thread.waitForAll() Установить на клиент клиентскую часть: local opennet= require("opennet") local term= require("term") local unicode= require("unicode") local event= require("event") args={...} if args[1]==nil then print("Использование: openviewerC <opennet_ip>") os.exit() end initial=args[1] function getScreen() repeat ip, screenRaw=opennet.receive() until ip==initial for sym=1, #screenRaw-160 do io.write(unicode.sub(screenRaw, sym, sym)) end end term.clear() opennet.send(initial, "Screen") getScreen() while true do arg1, arg2, arg3, arg4, arg5 = event.pull() if arg1=="key_down" and arg3==0 and arg4==63 then term.clear() opennet.send(initial, "Screen") getScreen() elseif arg1=="key_down" and arg3==0 and arg4==59 then os.exit() elseif arg1=="key_down" and arg3==0 and arg4==60 then opennet.send(initial, "Exit") else opennet.send(initial, arg1, arg2, arg3, arg4, arg5) end end Для запуска программы надо написать на сервере: openviewerS <IP Адрес клиента> ВНИМАНИЕ!!! Надо ввести именно IP, а не DNS; Единственное поддерживаемое разрешение - 80x25 На клиенте же пишем: openviewerC <IP Адрес сервера> Вот и всё=) Надеюсь,эта программа вам будет полезна ! Неплохо было-бы попасть в вайт-лист
-
Сделал кнопку через библиотеку forms.lua. Врубаю прогу, всё появляется, но программа почему-то не продолжает свою работу, а выключается сразу после отрисовки всех компонентов. addButton делал по инструкции
-
Я предлагаю запилить экспериментальный проект. Кодовое название - "Цитадель". Кавайная заставочка - сверху. Суть вкратце такова. Необходимо полностью развиться в Minecraft, с нуля, используя ТОЛЬКО роботов и дронов из OpenComputers. Делать что либо руками запрещается. (Если кто-то читает мою группу в ВК, там мелькал пост одного чувака, который снимает серию летсплеев с похожей идеей.) Для проекта берём сервер в сингле (например). Ставим несложную сборку - например Minecraft 1.12 + OpenComputers 1.7 + какой-нибудь тех. мод с хорошей OC-интеграцией, например - Mekanism. Далее генерим мир. Игрок будет обитать на спавне - в стартовой базе. У него в наличии будет: * закрытый ангар, в котором он живёт (выходить из него игроку нельзя), * вечный источник энергии, * компьютер третьего тира с беспроводной картой и интернет-платой, * пять доков с роботами (док - это ячейка с зарядником и люком наружу, где стоит робот), * пять доков с дронами, * небольшой запас провизии на первое время. Конфигурация дронов и роботов - тир три, с вайфай-картами и чанклодерами. На компы и роботов установлена OpenOS последней версии. Дроны прошиты нет-флашем. Основные задачи проекта: * наладить поставку провизии игроку * наладить добычу и хранение важных ресурсов * развернуть репликацию роботов и дронов Условие поражения: * потеряны все роботы и не выполнены основные задачи Сюжетный обоснуй: Игрок не совсем удачно десантировался с орбиты. У него мало ресурсов, но сохранился рабочий комплект робототехники и ядерный энергогенератор с ресурсом в тысячу лет бесперебойной работы. Атмосфера планеты непригодна для жизни человека. Что думаете по поводу идеи? Какие моды должны войти в состав сборки? Какие технические препятствия видите? Какие поправки стоит внести в стартовые условия? Какие действия по вашему стоит предпринять игроку первым делом?
- 60 ответов
-
- 2
-
-
- opencomputers
- minecraft
- (и ещё 4 )
-
Кнопки, это самый распространенный элемент интерфейса, и не потому, что их полно в каждой графической программе. Функционал кнопки наследует большинство средство ввода, например: ссылки, переключатели, ползунки, менюшки и т. д. Сейчас, огромные возможности для создания других, более подходящих ситуации способов ввода, но традиционно используются кнопки, которые появились в первых электронных устройствах, т. к. они просты и интуитивно понятны. Внешний вид. Обычная кнопка имеет прямоугольный вид, это позволяет не заморачиваться с алгоритмом взаимодействия, удобно отображать на ней текст/изображения, но если необходимо, ее можно сделать какой угодно формы. Самое главное в кнопке это ее интерактивность, т. е. она должна не только выполнять функцию, для которой назначена, но и сигнализировать свой статус (иметь обратную связь). Например, при нажатии на кнопку, она меняет цвет/визуально проваливается/издает звук, все это вместе или по-отдельности дает пользователю знать, что она активирована, а цветом или звуком можно даже передать состояние выполнения задачи, выполняемой этой кнопкой. А вот если пользователь нажимает на кнопку и ничего не происходит, то он может клацнуть по ней еще много раз, пока кнопка будет выполнять задачу. В большинстве случаев это довольно опасно - накликают беду, а винят программиста. Поэтому, если в текущей ситуации кнопка неактивна, надо это подчеркнуть, например, обесцветив ее или частично слив с фоном, можно дополнить специальным звуком. Все это очевидно, поэтому не стоит об этом забывать. Внутреннее устройство. В графическом интерфейсе, кнопка это определенно обозначенное место на экране, в которое нужно тыкнуть, чтобы получить определенный результат, обозначенный на кнопке в виде текста/изображения или понимаемый из контекста. Как это реализовать в OpenComputers? Нам доступен вывод информации на монитор, посредством компонента GPU. Пока рассмотрим функции назначения цветов и вывода символов. Работа с видеокартой. Список методов видеокарты можно посмотреть на вики. Для назначения цвета текста используется метод setForeground. А чтобы задать цвет фона, есть метод setBackground. Чтобы проверить, как это работает обратимся к компьютеру с установленной OpenOS. Запустим компьютер. Вводим команду edit gpu_test.lua, так мы запускаем текстовый редактор OpenOS, указывая, что нужно редактировать файл gpu_test.lua. Пока этого файла нет, но когда в редакторе нажмем Ctrl+S он сохранится. Чтобы мы могли обратится к компоненту gpu, нам надо загрузить обертку для компонентов, предоставляемую OpenOS, она немного облегчает работу. Для этого, в самом начале программы пишем local component = require('component'), так, что это за письмена? Эта строка создает локальную переменную (указываем словом local перед именем переменной), далее указываем имя переменной. Знак равенства указывает, что в переменной теперь будет хранится то, что дает функция require, в данном случае мы задали этой функции передать переменной component возможности обертки, которая тоже называется component. Так будет удобней понимать, к чему мы обращаемся. На следующей строке пишем local gpu = component.gpu Это мы назначили переменной gpu все методы видеокарты, т. е. теперь можем обращаться к ней через эту переменную. При загрузке, OpenOS сделала несколько скрытых операций: определила основную видеокарту, подключила ее к монитору и добавила их к остальным компонентам, чтобы можно было обратиться по имени компонента и получить готовый интерфейс. Итак, видеокарта готова к работе, теперь опишем, что она должна сделать. Создаем переменные, содержащие информацию о цветах и тексте, с которыми мы будем работать. local color1, color2, text = 0xff00ff, 0x0000ff, 'Hello, OpenComputers!' При помощи параллельного присваивания мы задали две переменные с числовыми значениями цветов и переменную с текстом. Теперь создадим простой цикл, в котором выведем текст на экран, назначая цвет текста и цвет фона. for i = 1, 10 do gpu.setForeground(color1) gpu.setBackground(color2) gpu.set(10, 5, text) color1, color2 = color2, color1 os.sleep(0.5) end Сам код назначает тексту цвет, указанный в color1, а фону color2, затем выводит текст, содержащийся в переменной text на монитор, указывая координаты первого символа (от левого верхнего угла 10 символов в право, 5 символов вниз). Далее, параллельным присваиванием, меняем значения переменных местами, чтобы при следующем выполнении кода, цвета фона и текста поменялись. В конце цикла ставим задержку в пол-секунды, используя системную функцию sleep. Цикл готов, теперь, в конце программы стоит добавить восстановление цветов текста и фона, т. к. по завершению ее работы, цвета останутся такими, которые были назначены в последний раз. Готовый алгоритм будет примерно такой: Нажимаем Ctrl+S, чтобы сохранить файл, затем Ctrl+W, чтобы закрыть редактор. Теперь мы снова попали в шелл. Вызываем только-что созданную программу по имени: gpu_test, и наблюдаем ее выполнение. Так как координаты вывода жестко заданы, мы видим, что текст как-бы мигает. Чтобы увидеть эволюцию работы цикла, можно к координатам вывода добавить значения шага цикла. Для этого откроем файл edit gpu_test.lua, в функции gpu.set к каждому числу прибавим переменную-итератор. Теперь вызов функции gpu.set выглядит вот так: gpu.set(10+i, 5+i, text), сохраним изменения (Ctrl+S), закроем (Ctrl+W), и опять запустим тестовую программу gpu_test Работа с вводом. Со способом вывода информации более-менее разобрались, теперь разберемся с вводом, т. к. мы хотим создать графический интерфейс, хоть и 'псевдо', мы будем использовать возможность сенсорного ввода, клавиатуру поставим для других задач. Монитор I уровня это только средство вывода, а мониторы второго и третьего уровня могут работать и как средство ввода. Когда игрок прикасается к экрану, генерируется сигнал touch, содержащий в себе адрес монитора, координаты касания, код кнопки мыши и ник игрока. Нам остается отследить это событие и соответсвующим образом на него отреагировать. Для демонстрации работы напишем небольшую тестовую программу, которая будет ловить события касания экрана, отображать место и числовые координаты. Создаем файл edit click_test.lua Первым делом подключаем управление видеокартой local gpu = require('component').gpu Затем, подключим мониторинг событий, который предоставляет OpenOS. local pull_e = require('event').pull Общая документация тут, мы воспользуемся только одной функцией. Теперь позаботимся о пользователе, чтобы при завершении программы цвет фона остался такими же, как и перед запуском, мы его сохраним в переменную: local b_color = gpu.getBackground() Эта функция сообщает цвет фона, который сейчас используется, для цвета текста есть getForeground, но в данном тесте мы будем управлять только цветом фона. Так как у мыши две кнопки, в событии touch указывается код кнопки: ЛКМ = 1, ПКМ = 0 Чтобы визуально различать касания, создадим таблицу с цветами для каждой кнопки. В качестве индекса будет использоваться код кнопки. local color = {[0] = 0x00ff00, 0x0000ff} т. е. ЛКМ будет обозначаться синим, ПКМ - зеленым. Теперь создадим цикл, в котором будем ловить и обрабатывать события. while true do Как следует из описания функции event.pull, можно фильтровать ненужное, передав в функцию название интересующего нас события. Так как возвращается довольно много переменных, будем создавать из них таблицу, для большего удобства. local tEvent = {pull_e('touch')} Теперь все события типа touch будут пересоздавать таблицу tEvent, в которой будет заключена информация об этом событии. Обратиться к интересующей информации можно, указав номер, в той же последовательности, как это описано в документации по сигналам Для начала добавим условие выхода из программы, т. к. цикл бесконечный и прервать его можно только грубо нарушив выполнение программы. if tEvent[3] == 1 and tEvent[4] == 1 then Если клик произошел по координатам (1, 1), выполнить следующий код: gpu.setBackground(b_color) - вернем фону его первоначальное значение, полученное при запуске программы. os.exit() - вызовем системную функцию выхода из программы. Закроем условие: end А теперь опишем сам процесс отклика на касание. Присваиваем фону цвет, исходя из полученного кода кнопки мыщи: gpu.setBackground(color[tEvent[5]]) Устанавливаем по полученным координатам символ пробела, чтобы подсветить фон: gpu.set(tEvent[3], tEvent[4], ' ') Затем, по координатм (1, 1) показываем информацию о событии: gpu.set(1, 1, 'x: '..tEvent[3]..' y: '..tEvent[4]..'\t\t') В конце добавляется пустое место, чтобы не заморачиваться с затиранием предыдущих значений. Закрываем цикл end В итоге получается такой код: Сохраним и запустим программу. Кликая мышкой по монитору мы видим, как она оставляет следы и обновляется информация в левом верхнем углу. Кликнув в левый верхний угол мы завершаем работу программы. Значит, мы между делом создали кнопку, хоть и невидимую. Принцип работы очень прост - пользователь кликнул по экрану, а программа сравнила координаты клика с координатами кнопки, если они совпали, то выполняется код, назначенный для этой кнопки. Теперь создадим нормальные кнопки, с более удобной конфигурацией. Все кнопки будут находиться в таблице, при каждом клике будем в цикле обходить таблицу, проверяя координаты. Дополнительно напишем пару функций - одна будет подсвечивать нажатую кнопку, другая переключать видимость. Каждая кнопка будет содержать следующие параметры: статус отображения (т. е. активна кнопка или нет), координаты, размер, цвет фона кнопки, цвет текста, текст и исполняемую функцию. { visible = boolean, X = number, Y = number, W = number, H = number, color = number, textColor = number, text = string, action = function } Загрузим видеокарту и захват событий. local gpu = require('component').gpu local pull_e = require('event').pull Для того, чтобы очистить экран при запуске и поставить кнопку выхода в угол, нам понадобится узнать и сохранить текущее разрешение. local W, H = gpu.getResolution() Сохраняем цвета фона и текста, чтобы вернуть их при завершении программы. local b_color, f_color = gpu.getBackground(), gpu.getForeground() Создаем таблицу tButtons, в ней мы будем хранить все кнопки. Добавляем кнопку выхода из программы: Изначальное состояние кнопки: visible = false, Устанавливаем кнопку в правый верхний угол, задаем размер в один символ: X = W, Y = 1, W = 1, H = 1, Устанавливаем цвета: color = 0xff0000, textColor = 0xffffff, Задаем символ: text = 'X', Функция завершения программы немного изменилась - устанавливаются первоначальные цвета, очищается экран и вызывается функция выхода. action = function() gpu.setBackground(b_color) gpu.setForeground(f_color) gpu.fill(1, 1, W, H, ' ') os.exit() end Опишем функцию рисования кнопки, в которую будет передаваться индекс кнопки. local function drawButton(n) задаем цвет кнопки gpu.setBackground(tButtons[n].color) задаем цвет текста gpu.setForeground(tButtons[n].textColor) заливаем прямоугольник, который занимает кнопка (в данном случае, берем координаты и размер кнопки из ее таблицы) gpu.fill(tButtons[n].X, tButtons[n].Y, tButtons[n].W, tButtons[n].H, ' ') для большей красоты отцентрируем текст по границам кнопки, для этого вычислим половину высоты и половину ширины кнопки, прибавим их к координатам кнопки, а у ширины еще отберем половину длинны текста gpu.set(tButtons[n].X+(tButtons[n].W/2)-(#tButtons[n].text/2), tButtons[n].Y+(tButtons[n].H/2), tButtons[n].text) закрываем функцию end Добавим переключение видимости кнопки. local function toggleVisible(n) if tButtons[n].visible then если кнопка видима, то изменим статус tButtons[n].visible = false установим цвет фона на тот, который был при запуске gpu.setBackground(b_color) зальем прямоугольник фоновым цветом gpu.fill(tButtons[n].X, tButtons[n].Y, tButtons[n].W, tButtons[n].H, ' ') else иначе: изменим статус tButtons[n].visible = true вызовем отрисовку этой кнопки drawButton(n) закроем условие и функцию end end Чтобы кнопка подмигивала при активации, создадим функцию меняющую цвет фона и текста, как в первом примере. Для получения и назначения цветов обратимся к параметрам кнопки по индексу, как и в прошлых функциях. меняем цвета tButtons[n].color, tButtons[n].textColor = tButtons[n].textColor, tButtons[n].color рисуем кнопку drawButton(n) делаем задержку os.sleep(0.09) возвращаем цвета tButtons[n].color, tButtons[n].textColor = tButtons[n].textColor, tButtons[n].color заново рисуем кнопку, с номальными цветами drawButton(n) Функции описаны, теперь напишем саму программу. При запуске очистим экран gpu.fill(1, 1, W, H, ' ') Можно вынести ее в отдельную функцию, но в данном примере очистка вызвается только два раза - при запуске и при выходе. Теперь активируем все нужные кнопки. В данном примере можно запустить все кнопки, поэтому пройдем в цикле по таблице с кнопками и для каждой вызовем переключатель видимости. for i = 1, #tButtons do toggleVisible(i) end И опишем главный цикл. while true do ловим событие в таблицу tEvent local tEvent = {pull_e('touch')} перебираем все кнопки for i = 1, #tButtons do если кнопка видима if tButtons.visible then сравниваем координаты клика с прямоугольником кнопки if tEvent[3] >= tButtons.X and tEvent[3] <= tButtons.X+tButtons.W and tEvent[4] >= tButtons.Y and tEvent[4] <= tButtons.Y+tButtons.H then если клик попал по этой кнопке, заставляем ее мигнуть blink(i) выполняем функцию, которая назначена для нее tButtons.action() прерываем цикл проверки кнопок break закрываем циклы и условия end end end end На этом все, программа готова, в готовом примере я добавил три кнопки - 'set' выводит строку, а 'del' стирает и бибикает спикером, 'reboot' перезагружает компьютер.
-
Недавно видел в какой-то теме про сворачивание блоков кода, которые завернуты в do ... end Попробовал то же в своем sublime и увидел как оно работает. Захотелось бОльшего Немого поковырявшись в гугле разобрался как в sublime 3 добавить подобную свертку для любого синтаксиса. Включая Lua С помощью PackageControl устанавливаем SyntaxFold Идём в Preferences -> Package Settings -> SyntaxFold -> Settings - User Добавляем такую запись для сворачивания функций и таблиц: { "scope": "source.lua", "startMarker": "local function, function, {", "endMarker":"end, end, }" }, По аналогии можно добавить более специфичные маркеры после чего перезапустить редактор Теперь по Control+Shift+[ , Control+Shift+] , Control+K, Control+Цифра а также командами в меню Edit -> Code Folding можно сворачивать и разворачивать блоки внутри назначенных маркеров. Если тут есть еще любители саблайма кроме меня, новые полезности и удобности для луа - приветствуются
-
Вопрос такой можно ли перехватывать сообщения из чата? Пример: Человек написал слово в чат, если оно совпадает с переменной то сообщение в чат не отправляется и пишет что он к примеру победил, а если не совпадает то сообщение отправляется в чат.
-
Я вас категорически приветствую! Сегодня я хочу представить вам новый формат для изображений для OpenComputers! Данный формат был придумал в соавторстве с @@Alexc. Начну я с того, как устроен процесс конвертации картинки (ну и самого формата тоже): Определяются базовые цвета картинки (пара цветов -baseFore, baseBack - которые чаще всего встречаются на исходном изображении), преобразуются в цвета opencomputers и записываются в файл вместе с размерами картинки. Сканируется картинка по паре пикселей по координатам x y * 2 - 1 и x y * 2, чтобы получилась пара цветов (fore и back). Из них формируются "цепочки" вида : { [back] = { [fore] = {x,y,str} } где back и fore - цвета "верхнего" и "нижнего" пикселей, а {x,y,str} - сама цепочка. Пример из 1 картинки: [6712704]={ -- Преобразованный в целочисленное значение цвет для background [7895160]={ -- Преобразованный в целочисленное значение цвет для foreground {70,31,"▄"} -- Сама цепочка, которая будет отрисована. } ,[13816530]={ {65,41,"▄▄"} } ,[2960685]={ {95,43,"▄"} },[12829635]={ {95,42,"▄"} } } (Разумеется все это хранится в байткоде, а не в таком виде ) Плюсы и минусы: Плюсы: Достаточно быстрая скорость отрисовки картинок. Достаточно небольшой размер конечных файлов (По сравнению с оригиналом в .png - .pix занимает в разы меньше места, а по сравнению с .jpg - больше ) Минусы: При конвертации и отрисовке используются только 4 символа Юникода: "▄" , "▀" , "█" , " ". Максимальное разрешение исходной картинки 160х100 пикселей в форматах: .png, .jpg, .bmp. Нет поддержки шрифтов Брайля (см. пункт 1 ). Установка: Скачать сам конвертор, написанный на Kotlin (Спасибо @@Totoro =) ) https://github.com/cc-ru/pix/releases Или же скачать lua версию : pastebin get SYfcHuhr PIXconv.lua Запускать таким образом: PIXconv file Файл будет сохранен в ту же папку, с тем же названием, но с расширением .pix Так же вместе с конвертором будет скачана программа для отрисовки под названием PIXdraw.lua. Если же вы хотите ее скачать отдельно, то: pastebin get Bm0JUJnj PIXdraw.lua Запускать таким образом: PIXdraw file.pix Скриншоты (как это выглядит в OCEmu и майнкрафте): https://clip2net.com/s/3Ug8qrb https://clip2net.com/s/3Ug88vV
- 1 ответ
-
- 10
-
-
Всем привет Есть 16 МФСУ, к ним подключены адаптеры В системе видно 16 адаптеров с МФСУ Как получить заряд конкретного МФСУ ? Если ввести =component.mfsu.getCapacity() , то отображается заряд первого МФСУ 1.А как получить заряд любого МФСУ по его UUID? 2.И как можно получать его заряд по сокращенному UUID? (не вводя весь адрес целиком)
- 5 ответов
-
- lua
- open computers
-
(и ещё 2 )
Теги:
-
Привет ComputerCraft! В программировании я полный ноль и наверное моя ошибка банальна, но прошу помочь. Ругается на 34 строчку. Что и на что нужно исправить чтобы всё завелось? Код Вылет -- разработчик dases print("LOADING... ENERGY INFO v1.1") --загружаем библиотеки local computer = require("computer") local component = require("component") local term = require("term") local os = require("os") local gpu = component.gpu --работаем с экраном gpu.setBackground(0x109910) --задаём цвет фона gpu.setForeground(0x000000) --задаём цвет текста --gpu.setResolution(28, 14) --задаём разрешение экрана --начальный экран term.clear() --чистим экран от мусора print(" ENERGY INFO v1.1") print("____________________________") print(" www.computercraft.ru") os.sleep(2.7) --задержка начального экрана local maxenergy = computer.maxEnergy local energy = computer.energy local procent = energy()/maxenergy()*100 --экран с информацией о энергии while true do term.clear() --чистим экран от старого текста print(" ENERGY INFO v1.1") print("____________________________") print(" ") print(" Energy :"..energy()) --показывает сколько сейчас энергии в сети print(" Procen energy:"..procent()) print(" Max energy:"..maxenergy()) --показывает сколько всего можно залить энергии в сеть print("________________________________________________________") print(" DANGER!!! High Voltage!!!") print("________________________________________________________") os.sleep(3) --задержка перед следующим обновлением текста на экране end
