Перейти к публикации

Таблица лидеров


Популярные публикации

Отображаются публикации с наибольшей репутацией начиная с 20.03.2018 во всех областях

  1. 8 баллов
    Всем привет! Накануне я решил создать свой полноценный Банк, но пока я его делал, решил, что это будет карта на прохождение и специально допустил пару уязвимостей. (На самом деле я решил сделать карту на прохождение потому, что мне было лень их фиксить :d). Суть карты в том, что необходимо взломать банк и получить 10000$ на банковской карте. Уязвимости довольно скрыты и предстоит помучаться чтобы их найти, уязвимостей всего две. Первая - глобальная, средней сложности. Вторая - очень скрытая, высокая сложность. На карте так же реализовано подобие вышки, которое позволяет отправлять пакеты друг другу не напрямую, а через эту вышку. Так-же эта вышка помогает покрыть этим "интернетом" всю карту (необходимо поставить много вышек по всей карте) и преодолеть ограничение радиуса отправления пакетов. Банковская карта реализована RFID меткой. На карте присутствует банкомат, сервера, ваш домик и немного налички в сундуке. Правила карты (На вашу совесть, чтобы было интересно): Запрещается использовать компьютеры, кроме своего. (Просматривать логи сервера банка и сервера вышки на экране разрешено). Запрещается просмотр исходников серверов. Запрещается ломать блоки. (Карта в режиме приключения, но читы включены) Так-же имеется библиотека на вашем компьютере для работы с внутренним интернетом, находится она по пути: /lib/gsm.lua Строения на карте: 1. Вышка интернета. 2. ДЦ Сбербанк. 3. Офис Сбербанк. (Компьютер не трогать в нём) 4. Банкомат. 5. Домик кулхацкера. Подсказки по прохождению карты можно попросить у меня во ВКонтакте: https://vk.com/superrolan51 Ссылка на небольшой ролик по карте: Клик Ссылка на сборку: Клик Ссылка на портативную сборку от @Asior: Клик (Для версии Forge 1.7.10) Удачи в взломе! P.S. Не пишите в комментариях подсказки к карте
  2. 8 баллов
    Помните мост Рида? Ну так вот. Я тут изучаю Rust на досуге, и пишу мини проекты. Так и получился у меня... Stem Это интернет мост для OpenComputers. Что такое мост Для тех кто не знает что такое мост, и для чего он нужен: мост дает примерно такие же возможности как и linked карта. Он позволяет связать между собой компьютеры OpenComputers, где бы они не находились. Только мост реализует это через интернет карту. Однако по сравнению с linked картой есть один очень крутой плюс. Вы можете подключиться к своему OpenComputers компу не только с другого OpenComputers компа из Майнкрафта, но и из реального мира. Например с телефона. Или с вашего домашнего компьютера. Отличие от моста Рида Я немного по другому подошел к архитектуре проекта. Вместо попарного соединения, Stem реализует систему каналов. Работает это очень просто. Вы можете: 1) послать сообщение в канал X 2) подписаться на сообщения из канала X Количество подписчиков не ограничено. Количество клиентов которые могут посылать сообщения в канал тоже не ограничено. ID канала (по которому происходит подписка и отправка сообщений) служит заодно и паролем к нему. Поэтому если вы хотите создать публично доступный канал - просто опубликуйте его ID. А если хотите создать свой, приватный, канал - просто возьмите ID подлиннее и никому его не открывайте. ID - это последовательность любых байт длиной до 256. Число комбинаций (256 в степени 256) это огромное число, так что уникальных ключей хватит надолго. Пример local event = require('event') -- подключаем STEM local stem = require('stem') -- присоединяемся к серверу STEM local server = stem.connect('stem.fomalhaut.me') -- просим сервер присылать нам сообщения с канала 'my-channel-id' server:subscribe('my-channel-id') -- слушаем эвент 'stem_message' в цикле while true do local name, channel_id, message = event.pull('stem_message') if name ~= nil then print(channel_id, message) end end -- ...или регистрируем листенер event.listen('stem_message', function(_, channel_id, message) print(channel_id, message) end) -- мы можем посылать сообщение в канал -- (причем не обязательно быть подписанным на этот канал -- достаточно просто его ID) server:send('my-channel-id', 'hello there') -- просим сервер перестать присылать сообщение с канала server:unsubscribe('my-channel-id') -- полностью отключаемся от сервера STEM server:disconnect() Одновременно можно работать с несколькими серверами Stem и с любым количеством каналов. Библиотека stem.lua Библиотечку можно скачать напрямую по этой ссылке: https://gitlab.com/UnicornFreedom/stem/raw/master/stem.lua Либо установить через HPM: hpm install stem Сервер STEM Дефолтный сервер STEM запущен у меня на VPS по адресу: https://stem.fomalhaut.me/ Можете смело его использовать. Единственное, что это тестовый сервер пока. Может пропадать или менять протокол. Новости постараюсь писать сюда. Исходный код проекта находится тут: https://gitlab.com/UnicornFreedom/stem Вы можете скомпилировать его под свою систему и запустить где угодно. Настраивается сервер файлом stem.toml в корневой папке. Дефолтный конфиг может выглядеть так: [tcp] host = '127.0.0.1' port = 5733 [web] host = '127.0.0.1' port = 5780 Чтобы получить полностью свой отдельный и независимый сервер STEM, достаточно будет просто запустить бинарник, получившийся после компиляции. Не забудьте также положить в папку с бинарником папки static и templates. Они нужны для веб-интерфейса. Сервер мультипоточный, и очень производительный. Должен тянуть довольно большие объемы трафика. Но точных бенчмарков я не проводил. Если есть желающие - пишите в IRC, скооперируемся и померяем. 😃 Веб-интерфейс Если перейти по ссылке на сервер STEM то вы увидите... какую-то хрень. Веб интерфейс еще не доделан, и пока просто показывает счетчик активных каналов и сессий в стиле Web 1.0. Доделать его и дополнить фишками - задача на будущее. Ну вот и все Мост в принципе уже полностью работоспособен. Что я хочу добавить в будущем: Клиент для Java / Rust (чтобы можно было подключаться к компу с телефонов на Android и с десктопов / серверов). Веб-интерфейс. Все идеи, пожелания, отчеты о багах пишите сюда, либо на issue трекер в репозитории. Enjoy! 😃
  3. 7 баллов
    По этой теме уже существует отлаженный софт, успешно используемый многими игроками. Однако на днях я заметил забавную особенность местных видеокарт, позволяющую выставлять разрешение большее, нежели получаемое через gpu.maxResolution(). К примеру, если maxResolution для видеокарты третьего уровня вернет числа 160 и 50, то никто не мешает установить разрешение, скажем, в 20x158 пикселей. При этом при проверке валидности устанавливаемого разрешения соблюдается два правила: Результирующее разрешение по числу пикселей не должно превышать результат умножения чисел, возвращаемых maxResolution. То есть для T3 GPU не более 160 * 50 = 8000. Каждый параметр разрешения, будь то ширина или высота, не должен численно превышать значение возвращаемой ширины. То есть для T3 GPU не более 160. Не знаю, баг это или фича, однако подобное грех не использовать в своих целях. К примеру, старая версия программы при вертикально-удлиненном расположении мониторов позволяла выставить разрешение лишь в 30х50 (1500 пикселей в итоге), заполняя тем самым "черные полосы". В то же время обновленная софтина, учитывающая описанные выше особенности, выдает 69x114 (7866 пикселей), максимально приближаясь к предельной отметке в 8000: Согласитесь, лишние пиксели на дороге не валяются, и, думаю, кому-то будет интересно узнать про реализацию подобного софта. Прежде всего нам требуется определить точную пропорцию мультиблочного монитора: то, как относится его ширина к высоте. Взглянем на текстуру блока: она явно состоит из мелких "квадратиков" в количестве 16 штук, причем лицевая часть монитора имеет рамку толщиной в 2 "квадратика" с каждой стороны: Эти "квадратики" мы и будем использовать для расчета пропорции, так как они позволяют идеально точно получить размеры отображающей части монитора в игровом мире. А размеры "в квадратиках" можно посчитать по формуле: число_блоков_монитора * 16 - 4 Следовательно, пропорция монитора будет считается следующим образом: local gpu = component.gpu local screen = component.proxy(gpu.getScreen()) local blockCountByWidth, blockCountByHeight = component.screen.getAspectRatio() local proportion = (blockCountByWidth * 16 - 4) / (blockCountByHeight * 16 - 4) Также не забываем, что высота каждого псевдографического пикселя при отображении в 2 раза больше его ширины, поэтому формула пропорции слегка меняется. Заодно произведем некоторые сокращения, чтобы избавиться от лишних математических операций. Все три варианта эквивалентны: local proportion = 2 * (blockCountByWidth * 16 - 4) / (blockCountByHeight * 16 - 4) local proportion = (blockCountByWidth * 16 - 4) / (blockCountByHeight * 8 - 2) local proportion = (blockCountByWidth * 2 - 0.5) / (blockCountByHeight - 0.25) После вычисления пропорции монитора можно приступить к написанию программной логики. Для начала получим максимальное разрешение видеокарты: local maxWidth, maxHeight = gpu.maxResolution() Обладая этими данными, а также взглянув на условия, описанные в начале поста, мы можем составить систему неравенств для получения итогового идеального разрешения: Помним также, что ширину мы вполне можем выразить через высоту и пропорцию монитора: width = proportion * height Подставим этот вариант в систему: Оставим высоту в левой части неравенств: Подставляем имеющиеся переменные в каждое неравенство, рисуем числовую прямую и выбираем высоту, удовлетворяющую условиям неравенства для конкретного случая. Разумеется, в программировании никаких числовых прямых нет, зато есть любимые math.min() и math.max(): local height = math.min( maxWidth / proportion, maxWidth, math.sqrt(maxWidth * maxHeight / proportion) ) -- Выражаем ширину через пропорцию local width = height * proportion Все. Разумеется, полученные значения ширины и высоты нужно округлить в меньшую сторону, дабы не кормить видеокарту дробями. Заодно добавим поддержку масштабирования, чтобы выставлять половинное или, скажем, четвертичное от идеального разрешение. Сократив код, избавившись от лишних переменных, мы получаем следующее: local component = require("component") -- Получаем масштаб в качестве первого аргумента скрипта и корректируем его значение local scale = tonumber(select(1, ...) or 1) if not scale or scale > 1 then scale = 1 elseif scale < 0.1 then scale = 0.1 end local gpu = component.gpu local blockCountByWidth, blockCountByHeight = component.proxy(gpu.getScreen()).getAspectRatio() local maxWidth, maxHeight = gpu.maxResolution() local proportion = (blockCountByWidth * 2 - 0.5) / (blockCountByHeight - 0.25) local height = scale * math.min( maxWidth / proportion, maxWidth, math.sqrt(maxWidth * maxHeight / proportion) ) -- Выставляем полученное разрешение gpu.setResolution(math.floor(height * proportion), math.floor(height)) Надеюсь, это микро-знание кому-то было полезно. Лично я очень доволен, что могу наконец запилить графонистый интерфейс для контроля реакторов на вертикальных мониках без осваивания профессии "глиномес", да и соответствующая либа для автопобора разрешения в оське пригодится.
  4. 7 баллов
    Дело было вечером, делать было нечего... И тут я случайно зажал горячую клавишу калькулятора, и меня осенило! А ведь калькулятора то для ОС никто не писал еще! Так появилась идея создания этого калькулятора. Что можно про него сказать? Базовый калькулятор который умеет выполнять стандартные математические операции. Требования к ОС: Видеокарта 2 уровня и выше Монитор 2 уровня и выше Компьютер/сервер любого уровня с установленной OpenOS Управление самое простое - мышкой. При создании программы была взята статья Псевдографические интерфейсы в OpenComputers и на основе кода из неё был создан калькулятор. Установка: version 0.2 pastebin -get PaVaRGcd Calculator.lua version 0.3 pastebin -get ZjCTrj5a Calculator.lua P.S. Выражаю благодарность @Doob за статью. Если найдете какие-то баги, недочеты, или возникнут идеи по улучшению, я всех с радостью выслушаю.
  5. 7 баллов
    С переменным успехом работа продолжается: Перенес основную логику на сангаровский JNLua вместо LuaJ, добавил лимитирование оперативки Переосмыслил систему виртуализации: теперь каждая машина - это отдельное окошко со своими параметрами, сохраняемыми в конфиге Запилил опцию изменения пропорций виртуального экрана для screen.getAspectRatio(), а то эмуляторы обычно выдают 1, 1 по дефолту Реализовал компонент tunnel, который, в общем-то, ничем не отличается от модема. Возможно, если нервы не сдадут, в будущем добавлю систему энергозатрат - и тогда связанная карта будет жрать овердофигища ресурсов Сделал выбор имени игрока, от лица которого осуществляется управление компом Добавил фичу скрытия тулбара справа, чтоб ничто не отвлекало взор, так сказать Багов, конечно, жопой жуй: не всегда корректно читаются файлы в бинарном режиме, многие фичи по типу computer.addUser() являются не более чем функциями-заглушками, а еще странно читаются экранные события при вертикальной ориентации. Ну, по крайней мере, опенось уже запускается. И гляньте, какой чудный FPS:
  6. 6 баллов
    Еще мой дед говаривал, что каждый кодер на ОС просто обязан начать писать собственный эмуль для самоутверждения. Не желая изменять семейным ценностям, я тоже окунулся с головой в эту клоаку. Вообще в существующих эмуляторах лично меня люто бесит возня с ручной компиляцией, докачиванием всяческих либ по типу openssl, а также отсутствие возможности запуска нескольких виртуальных компиков в едином пространстве с масштабированием экранов, не говоря уже про пересылку данных между ними посредством не менее виртуальных модемов. Поэтому почесав репу, собрав JavaFX + LuaJ, накатав несколько компонентов, на данный момент я заимел следующие зачатки проекта: Библиотеки computer, component, unicode Компоненты computer, eeprom, filesystem, gpu, modem, screen, keyboard Имитация системных сигналов по типу touch/drag/drop/key_down/key_up/scroll/modem_message с поддержкой pullSignal/pushSignal Пересылка сетевых пакетов между имеющимися машинами в рабочем пространстве через modem.send/broadcast BSOD для "unrecoverable error" Звуковая система а-ля "комп в мире кубача", имитирующая звуки доступа к диску, и прикольно шумящая на фоне для антуража Создание/сохранение/загрузка виртуальных машин с сериализацией данных имеющихся компонентов. Ну, всяких там адресов, разрешений видях, размеров, координат и т.п. Кнопочка включения (!) Разумеется, компоненты имеют далеко не все методы, их написание - дело долгосрочное. Но поскольку этот раздел называется блогом, то, кажется, никто не мешает мне писать о запланированном. В идеале хочу замутить компоненты internet, tunnel и data, позволить юзерам выбирать пути к прошивке виртуального EEPROM и содержимому жесткого диска. Также остается открытым вопрос о лимитировании памяти: я понятия не имею, как это реализовать на LuaJ и ублюдочной Яве без обожаемого sizeof(). Городить костыли в виде JavaAgent + Instrumentation.getObjectSize не хочется, но, видимо, придется. Ну, и если у кого-то имеются занятные предложения по функционалу софтины - буду рад. Сырцы: https://github.com/IgorTimofeev/OpenComputersVM Скриншотик:
  7. 6 баллов
    Давненько не было автокрафтеров тут. Может, кому-то пригодится моя версия. Предназначена в первую очередь для крафта всяких часто необходимых мелочей со сложными крафтами (например, компоненты OpenComputers) из примитивных исходных ресурсов (например, процессор из слитков золота и железа, тростника и редстоуна), которые у пользователя отнимают кучу времени на поиск всех транзисторов и крафт недостающих. Рассчитана на использовании робота и двух сундуков, один из которых - основное хранилище (может быть покрупнее), а другой предназначен для резервирования компонентов при крафте. Ссылка: https://pastebin.com/1gqtWLub Необходимая конфигурация робота: Проверялась работа на компонентах (корпус, память, процессор, жёсткий диск) второго уровня. Screen, Keyboard Crafting Upgrade Inventory Upgrade и Inventory Controller Видеокарта и экран первого уровня Для дальнейших потенциальных расширений: Беспроводная карта Upgrade Container Конфигурация установки: Перед роботом - контейнер ресурсов (любой из возможных инвентарей достаточного размера) Под роботом - контейнер-буфер (можно обычный сундук) Рядом желательно поставить зарядник Возможности: Рекурсивный крафт сложных рецептов. Ресурсов расходуется, по результатам практических испытаний, ровно столько, сколько необходимо. Каталог рецептов для крафта, разбитый на страницы по 10 предметов для более удобного пролистывания на маленьком экране робота. Портативность - требуется только робот, два сундука и исходные ресурсы. Желателен также источник энергии Сообщения о том, каких конкретно исходных ресурсов не хватает для крафта (исходные ресурсы - те, для которых не найдено рецепта) Процесс крафта подробно отображается на экране, чтоб за ним было не так скучно и одиноко следить (см. недостатки) Об окончании крафта робот сообщит приветливым писком. Равно как и о неудаче. Недостатки и известные недочёты: Скорость..... Крафт занимает значительное время. Например, изготовление процессора 3го уровня из примитивных ресурсов (тростник, красный камень, алмазы, дерево для резаков, слитки золота, железа) занимает около 5 минут. Стоит отметить что количество изготавливаемых предметов не сильно влияет на время (2 процессора, скорее всего, будут делаться те же примерно 5 минут). Не умеет работать с альтернативными ресурсами. Возможно, когда-нибудь исправлю. Не умеет работать с инструментами (имеются ввиду многоразовые, как молот ИК2). Возможно, так же когда-нибудь исправлю. Не умеет работать с количествами предметов более стака, а также не гарантируется корректная работа с предметами, не складывающимися в стак. Постараюсь исправить в ближайшее время. Нет поиска по именам компонентов (то есть, либо задаёте название компонента целиком, либо задаёте крафт через каталог). Когда-нибудь поправлю Проверок на наличие контейнеров не делается, так как программа писалась "для себя" и находится в разработке. В дальнейшем будут введены. Также не везде гарантируется наличие защиты от "Количество предметов: Привет". Особенности: Шаблоны содержатся в одном файле, что облегчает переносимость, но приносит определённые неудобства всвязи с размерами файла (12 строк на предмет). Буду думать, как лучше сделать (разбить на разные файлы?). Файл имеющихся шаблонов могу выложить при необходимости (на разных сборках эти шаблоны могут отличаться) Дальнейшее развитие (no promises!): Исправление имеющихся недочётов Поддержка работы по сети (заказ компонентов, сообщение о готовности - дистанционно). Работа с более сложными инвентарями - сборщики, и т.д. Работа с машинами-обработчиками ресурсов - когда-нибудь в отдалённом будущем, скорее всего. Управление: Интерфейс текстовый. Посмотреть команды главного меню можно, нажав "Enter" (оставив поле ввода пустым).
  8. 6 баллов
    Эм, здрассьте. Предлагаю поглядеть на новое обновление мода. Очень толстого обновления. Отрегулировали частоту выполнения хука, который шлёт этот ненавистный "too long without yielding", так что теперь и скорость исполнения кода должна гораздо возрасти, и с ошибкой этой код падать реже. Мы проверяли: некая гуи-либа с 1.6 fps до 2.5 fps только благодаря этому работать стала. Оптимизировали производительность ещё и записи на диск. Пошустрее будет — обещают, что в 5–500 раз. Сетевой разделитель (сплиттер) стал компонентом. Можно программно теперь отключать куски сети. Жёсткие диски стало возможным делать Read-Only. Компьютеры CC могут читать сигналы бандлед-редстоуна OC. И наоборот. Функции [il]debug.getlocal[/il] и [il]debug.getupvalue[/il]: возвращают они лишь только имя переменной, но не значение её. И мне кажется, что это уже давно было завезено. Геолайзеры получили методы [il]isSunVisible[/il], [il]canSeeSky[/il] и [il]detect[/il]. Неплохо. В [il]computer.beep[/il] можно писать морзянку. [il]computer.beep("---.---")[/il]. [il]redstone.setOutput[/il] научился ставить значения больше 15. Клавиатуру можно цеплять к монитору, если ещё поставить к непередней стороне блока. Наконец-то. [1.12] Вернули поддержку Project Red. Через адаптер можно теперь работать с камерой реактора IC2. У серверных дисководов тоже есть теперь гуишка (пкм в мире или внутри интерфейса стойки). Торговый апгрейд обзавёлся методом [il]getMerchantId[/il]. Полезно, если жителей куча. [1.12] Вернули поддержку энергии AE2. В конце-то концов: дебаг-карте добавили [il]scanContentsAt[/il]. Больше инфы возвращается для предметов из Draconic Evolution. Вейпоинты стало можно ставить вверх или вниз. Это действительно было слишком контринтуитивным. Связанные карты можно скрафчивать вместе (повяжет на новый канал их). Плюс получать адрес канала при скане стэка. Можно теперь менять цветовой код сундуков Ender Storage. Связанные карты также научились будить компьютер по сигналу, как модемы. Белый и чёрный списки измерений для чанклоадера. Метод [il]disk_drive.media[/il], которым можно получить адрес дискеты внутри дисковода. Поддержка Forge Energy для зарядки предметов вроде батареек и планшетов. Анализатор показывать будет по клику на адаптер ещё и содержащийся в нём компонент. Событие [il]redstone_changed[/il] показывает, какой цвет поменялся на бандлед-кабеле. По шифт-клику компоненты закидываются в соответствии с их уровнями. Подрезали немного шум в логе от OC. Методы вроде [il]robot.suck[/il], [il]robot.suchFromSlot[/il] и [il]transpoer.transferItem[/il] теперь возвращают вместо [il]true[/il] число перемещённых предметов. Немного уменьшили назойливость частиц наномашинок. Жёсткий диск 3 уровня в режиме без ФС стал иметь по умолчанию не 6, а 8 пластин. Улучшили рендер кабелей как-то. Такие же "как-то" улучшения произошли с инвентарём роботов, апгрейдом крафта, методами [il]swing[/il] и [il]use[/il], взаимодействием с жидкостными баками. С модами получше работать должны. Чанклодыри можно ставить в микроконтроллер теперь. Расширили покрытие юникода шрифтом. Стандартный биос стал есть меньше памяти. Мониторы глючить должны поменьше. Пофиксили обнуление содержимого инвентарей блоков мода при крашах. Ещё некий краш при установке микроконтроллеров починили. Команду [il]/oc_nm[/il] вправили в место и заставили работать. Дюп роботов убран. Команды перемещения теперь говорят, успешно или безуспешно вызов завершился. Форсирование [il]LuaJ[/il] не форсировало эту архитектуру. [il]transferItem[/il] проверял не ту сторону. Починили Unknown error при попытке залить чего-то в некие машинки. Дюп дронов тоже починили. Выкорчевали возможную ошибку при запуске вместе с IC2. Роботы перестали потреблять ингредиенты при крафте, которые не потребляются. Апгрейд ангельский стал работать. Пофиксили торговый апгрейд. Его прямая задача исполнялась кривовато. Роботы не перемещались, когда нужно было. Дюп предметов дронами и роботами. Дискету network тоже можно ставить через install теперь. Дюп жидкостей, конечно, тоже был и тоже пофикшен. Дроны не реинициализировались после включения по сообщению модема. И вели себя очень странно. Всякие фиксы в интеграции с AE2. Опять некий дюп EEPROM. Удалён. Краши при загрузке с Applied Llamagistics. Краши при нетрадиионной установке компьютеров. Краши (но на клиенте), связанные как-то с кабелями и загрузкой чанков. [il]enableNanomachinePfx[/il] не имела эффекта. Роботы стали вызывать обработчики модов при получении опыта. Вводящие в заблуждение сообщения анализатора о выключенных компьютерах стали вводить в заблуждение в меньшей степени. Микроконтроллеры свою начинку теперь тоже выключают вместе с собою. Всякие ошибки кидал апгрейд поводка вместе с некоторыми модами. Фиксед. [1.10+] Починен рецепт крафта карточки с мировым датчиком. Экран планшетов теперь не зависает. Терминальные серверы ненормально цепляли удалённых терминалов на себя. Ошибки освещения с шейдерами. В OpenOS ещё отметить можно: Команда [il]reset[/il], которая ресетит разрешение. Ошибки сервисов пишутся в /tmp/event.log. Можно теперь ловить ошибки по Ctrl-Alt-C (жёсткие прерывания) путём переопределения функции в [il]process.info().data.signal[/il]. Копипаст в [il]edit[/il]: Ctrl-K — вырезать, Ctrl-U — вставить строку. Процессы закрывают файлы при завершении. Ссылочка на гитхаб, откуда можно скачать мод.
  9. 6 баллов
    В маркете появился ВК-клиент местного разлива. Поскольку VK API с недавних пор стало зашибенно удобным в плане уменьшения количества веб-запросов, то болтать с посонами и посонихами можно с комфортом без ожидания загрузки тонны инфы. На данный момент имеются следующие фичи: • Динамическая подгрузка свежего контента при достижении конца имеющегося • Отображение информации профилей • Просмотр списка друзей с имеющимися тегами • Просмотр новостной ленты • Просмотр списка диалогов, истории переписки, отправки сообщений и файлов (к примеру, можно закинуть какой-нибудь скрипт прямо себе на аккаунт) • Индикатор сетевой занятости, чтобы никто ничо там не подумал, мол, "говнософт завис!!1" • Рекурсивное отображение всех медиавложений, репостов и прочей атрибутики • Раздел настроек с кастомизацией количества загружаемой инфы по категориям Планирую сделать поддержку двухфакторной авторизации, раздел документов и скачивание присланных доков. Пока что софтина чуть сыровата, но вполне себе юзабельна. Напоследок немножечко скринов:
  10. 5 баллов
    Робот может двигаться, пора добавить функцию сканирования породы и калибровки компаса. (Пока тестировал, обнаружил баг работы с зачарованными инструментами, пришлось немного переделать функцию step() - теперь после неудачного свинга, робот дополнительно проверяет наличие блока. Можно будет оставить, даже когда разрабы это исправят) Чтобы отфильтровать блоки по плотности, надо получить плотность нужных блоков с учетом шумов. На расстоянии x8 z8 y1 от геосканера, максимальная плотность бедрока равна -0.317, внесем в фильтр -0.31. Для руды 3.683, но это ванильная руда, в модах бывает и больше. Минимальная плотность обсидиана 49.312, значит, eсли он не нужен, установим для полезных блоков максимальную плотность 40. C минимальной плотностью не все так гладко. Свинцовая руда из индастриала имеет плотность 2.5 это как у деревянных предметов, разброс с учетом шума от 1.3 до 2.7, это пересекается с камнем, у которого 0.8 - 2.2. Вот таблица некоторых блоков с минимальной и максимальной плотностью: Руда 2.312 - 3.683 Стекло -0.388 - 0.983 Камень 0.812 - 2.183 Грязь -0.188 - 1.183 Сундук 1.312 - 2.683 Обсидиан 49.312 - 50.683 Видно, что плотность стекла пересекается с плотностью коренной породы, но у бедрока приоритет выше, поэтому лучше лишний раз обойти. Исходя из этих данных, полезные блоки будут отмечаться с минимальной плотностью 2.3 и максимальной 40 Теперь опишем функцию сканирования. Заглянем в подсказку. Чтобы получить сырые данные, зададим координаты и размеры квадрата, относительно сканера. geolyzer.scan(позиция_х, позиция_z, позиция_y, ширина, длина, высота) Так как один раз можно отканировать только 64 блока, будем делать 4 подхода, получая координаты квадрата по горизонтали из вызывающей функции. Преобразовываем данные в координаты, попутно анализируя плотность условным оператором и устанавливаем метки. При обнаружении бедрока устанавливаем соответсвующий флаг во внешней для всех функций переменной. Получаем функцию scan(), выглядеть она будет примерно так: local function scan(xx, zz) -- сканирование квадрата x8 относительно робота local raw, index = geolyzer.scan(xx, zz, -1, 8, 8, 1), 1 -- получить сырые данные, установить индекс в начало таблицы for z = zz, zz+7 do -- развертка данных по z for x = xx, xx+7 do -- развертка данных по х if raw[index] >= 2.3 and raw[index] <= 40 then -- если обнаружен блок с плотностью от 2.3 до 40 table.insert(WORLD.x, X+x) --| записать метку в список table.insert(WORLD.y, Y-1) --| с коррекцией локальных table.insert(WORLD.z, Z+z) --| координат геосканера elseif raw[index] < -0.31 then -- если обнаружен блок с отрицательной плотностью border = true -- сделать отметку end index = index + 1 -- переход к следующему индексу сырых даннх end end end Раз уже взялись за геосканер, напишем и компас. Чтобы определить стороны света, надо сломать блок перед носом, просканировать его, затем установить обратно и, если есть разница - выдать результат. Для большей надежности добавим вращение вокруг своей оси, т. к. блока перед носом может и не быть или быть, но не тот. Координаты блоков задаем в таблице, сбрасываем текущее направление, определяем заново, вот и вся функция. Назовем ее compass() local function compass() -- определение сторон света local sides = {{-1,0}, {0,-1}, {1,0}, [0]={0,1}} -- привязка значений сторон света к смежным блокам D = nil -- обнуление текущего направления while not D do -- пока направление не найдено for n = 0, 3 do -- перебор сторон света robot.swing(3) -- разрушение блока if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] == 0 and robot.place(3) then -- тестовое сканирование и установка блока if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] > 0 then -- если обнаружена разница в сканах D = n -- установить новое направление break -- выйти из цикла end end end turn() -- задействовать простой поворот end end Самые важные функции готовы, можно приступить к тестированию.
  11. 5 баллов
    Ядро копателя готово, теперь можно и пощупать. Напишем пробную функцию сканирования и добычи одного слоя. Сначала откалибруем компас и зададим таблицу с координатами сканируемых квадратов. Затем, отсканируем квадрат 16 на 16 блоков, выведем количество обнаруженных блоков. И в цикле обойдем все метки. Вроде бы все просто. Ах, да... будем искать ближайший блок к текущей позиции, чтобы быстрее закончить работу. Есть много подходов к определению расстояний. Например квадрат гипотенузы равен сумме квадратов катетов, формула для нашего случая будет math.sqrt((X-x)^2+(Z-z)^2), где X,Z - координаты робота, x,z - координаты метки, можно выкинуть квадратный корень, в нашем случае бесполезный и даже вредный. Но тут есть одно "но", мы получили гипотенузу, а это наименьшее расстояние между точками, а роботы по диагонали не ходят. Я буду вычислять дельту между точками, суммируя реальное расстояние, которое пройдет робот по формуле math.abs(X-x)+math.abs(Z-z) Эта операция в сферическом вакууме потребляет на 5% больше процессорного времени, чем предыдущая, но с лихвой окупается сэкономленными шагами. В цикле будем обходить таблицу с метками, до каждой вычисляя расстояние, самый лучший результат с индексом будем хранить в отдельных переменных. По окончании работы цикла, будем посылать робота в ближайшую точку. Код всей тестовой программы под спойлером. А вот и видео с демонстрацией. Можно добавить штрафы на повороты, тогда он будет меньше крутиться и собирать кучи линейкой, а не змейкой.
  12. 5 баллов
    Предлагаю своё решение. local f = io.open("/etc/program.cfg", "r") local content = f:read("*a") f:close() local cfg = {} assert(load(content, "=program.cfg", "t", cfg))() print(cfg.player) Соответствующий конфиг будет выглядеть тогда так: player = "Robot" robot = "Player" age = 39 alive = false С синтаксисом Луа. Что, согласитесь, выглядит приятно. И не надо запятые ставить, как в таблице сериализованной.
  13. 5 баллов
    во первых, чтобы была конкуретность, а во вторых MineOS это не ось, а граф.оболочка. Эта фраза уже бичом нервов стала, а чертовы доморощенные эксперты-казуисты продолжают лезть изо всех дыр. Элементарная ОСь на платформе опенкомпов состоит буквально из нескольких сот строк кода, реализующих методы работы с файловой системой, позволяющих монтировать физические дисковые носители, грузить библиотеки по предустановленным путям, обрабатывать события и имитировать многозадачность. Все остальное - это графическая оболочка, в моем случае состоящая из десятка тысяч строк кода, вылизанных до предела, чтобы уложиться в строгие рамки ресурсов, выделенных под каждую виртуальную машину в кубаче. Интерфейс майноси с базовым прикладным софтом по типу проводника/настроек/пикчредакторов/магазинов/IDE мы писали с большой командой товарищей около четырех с фигом лет, постоянно его совершенствуя. Эксперимента ради я решил отвязать майнось от опеноси, сделав ее полностью независимой. Это заняло несколько часов. Ценой нескольких, мать их, часов, а также нескольких написанных либ суммарным объемом в две сотни строк майнось стала полностью удовлетворять определению "операционная система", загружаясь с очищенного от скверны жесткого диска и собственного EEPROM. Результат лежит на отдельном репозитории, законсервированный до лучших дней: https://github.com/IgorTimofeev/MineOSStandalone А теперь скажи мне, умник, не кажется ли тебе странным, что вся "ось" пишется на коленке за несколько часов, а "граф. оболочка" - пускай и не годами, но в значительно большие сроки? Может быть, термин "ось" переоценен, и основу современной интерфейсной операционной системы составляет все же графическая оболочка c прикладным софтом? Эх, мяу
  14. 5 баллов
    Кстати о майноси: тут несколько занятных софтин подъехало. Например, YobaКалькулатрон9000, как его окрестил товарищ-шестиклассник. Умеет почти все: от работы с различными системами счисления и побитового редактирования чисел до базовых бинарно-тригонометрических операций с отображением символа по его коду. Во-вторых, слегка обновился местный проводник, заимев удобную панель навигации по текущему пути с кликабельными подпунктами а-ля Винда. Ну, и всякие кнопочки для ручного ввода пути появились, а также фича ресайза тулбара: Ну, и наконец не шибко сложная, однако довольно полезная в быту возможность интерфейсного привата компа по аналогии с useradd:
  15. 5 баллов
    Программка почти не изменилась, просто использует другой тип графика. Конечно тут речи никакой не идет о тонкой линии которая будет чертить график, я использовал то что есть в уже готовой библиотеке. Для работы программы все так-же требуется адаптер. К требованиям компьютера изменений нет, все так-же что запихаешь то и будет работать. Единственное что поменял, это теперь график не имеет никаких ограничений по размерам экрана. Да и вообще никакая информация кроме графика больше не рисуется. Проверка на изменения количества ресурсов в бочке проводится раз в секунду, если изменений нет, график не отрисовывается. График показывается следующим образом: Берется максимально допустимое количество ресурсов, что можно запихать в бочку, и делится пополам. Все что выше половины то отрисовывается зеленым, если уровень ресурсов падает ниже середины, то отрисовка проходит красным. Установка программы в 2 шага: Загрузка библиотеки: pastebin get -f wchQZtZB /lib/charts.lua Загрузка программы: pastebin get -f zjiKv5F0 Graf_drawer.lua
  16. 5 баллов
    Ну, собственно, 40 минут назад фичу запилили. В 1.7.3 будет метод component.disk_drive.media(), который будет возвращать адрес дискеты. Пока что можно скачать билд с ci.cil.li.
  17. 4 балла
    И так, наконец-то возвращаюсь к роботу-копателю. Да будут новые баги и новые фичи! Краткий план внедряемых фич: Улучшенное сканирование руд. Робот сканирует под собой квадрат 16x16 блоков, опускаясь блок за блоком. При обнаружении бедрока запускается функция добычи. При добыче робот поднимается и в цикле ищет ближайшие по горизонтали блоки руды, захватывая три слоя - Y+1, Y, Y-1 Определение энергопотребления сборки при запуске. На старте, робот запоминает количество потребленной энергии на один шаг + прочность инструмента. Это будет служить константой при проверке статуса, чтобы была возможность гарантированно вернуться на точку старта. Умная упаковка добычи. Перед обработкой рассыпухи, теперь будет точнее анализироваться свободное место, упаковка не будет происходить механическим перебором, из-за которого бывали внезапные сбои. При наличии генератора, робот всегда будет с собой таскать уголь, при разгрузке на точке старта будет забирать стак угля или угольных блоков. Текущие константа энергопотребления и координаты будут записываться в EEPROM. Следовательно, при наличии сетевой/связанной карты, робота можно будет будить и не бояться выгрузки чанков, лагов, космических лучей. Скорее всего, добавлю функцию аварийного крафта кирок из булыги, в случае работы с ванильными инструментами. Планируется утилита, собирающая программу по параметрам, заданным пользователем. ...Или не планируется, скорее всего все возможности копалки не получится впихнуть на EEPROM, поэтому на EEPROM будет загрузчик с main функцией, а дополнительные модули придется записывать на жесткий диск. Планируется поддержка модов, например, возможность возить с собой и разворачивать заправочную станцию в виде генератора и зарядника. Или скидывать предметы в межпространственные сундуки. Тут надо будет смотреть, как будут развиваться моды. В блоге буду описывать каждую функцию, чтобы отследить создание программы шаг за шагом, надеюсь, кому-то это поможет.
  18. 4 балла
    Часто необходимо писать программы для серверов. Это могут быть сервера для чатов, или файловые облака или что то еще, но всегда приходится писать велосипеды. Подумав об этом я решил написать программу для сервера. Программа работает просто. Подгружает модули из папки проекта, а потом начинает слушать все event'ы и обрабатывать. Представляю вам саму программу: Servercore v0.2.1 Исходный код: http://pastebin.com/NASX9sX0 Использование: Создаем папку проекта Создаем в этой папке файл .servercore Запускаем servercore указывая первым аргументом папку которую мы создали. Если не указывать аргумент то servercore запустится в рабочей директории. Наслаждаемся рабочим сервером, который пока ничего не делает. Любые файлы (кроме .servercore) которые находятся в папке проекта будут загружены как модули. Если модуль содержит ошибку наш сервер не полетит, а просто выведет тест ошибки на экран. При создании модулей можно использовать специальные функции, которые находятся в _G.sc. Описание этих функций: sc.info(info_type:string, message:string) - выводит информацию со временем и раскрашивает как на скринах. Принимает тип информации и само сообщение. Типов информации всего 4: ok,err,warn и info. sc.getTime() - возвращает время в формате unix timestamp. sc.on(event_name:string,handler:function) - добавляет слушателя на сигнал. Циклом слушаются все сигналы а потом запускают функцию обработчик для того сигнала который пришел. Пример простейшего модуля: sc.on("touch",function (e) sc.info("info","you touched!")end) Изменения в версии: Патч 1: убрана обязательная поддержка модемов. Старые версии: Произведение «Servercore» созданное автором по имени LeshaInc, публикуется на условиях лицензии Creative Commons «Attribution-NonCommercial-NoDerivatives» («Атрибуция — Некоммерческое использование — Без производных произведений») 4.0 Всемирная. PS: Название проги звучит как поджанр метала)))
  19. 4 балла
    Так, программка готова. Рекомендую размер экрана 3х2. Хотя вроде должно нормально работать и на экранах большего размера. Рядом (сверху/снизу/неважно короче) с бочкой надо поставить адаптер. Его подключить к компьютеру. По устройству компьютера требований вообще никаких, что запихаешь то и будет. Установка программы в 2 шага: Загрузка библиотеки: pastebin get -f wchQZtZB /lib/charts.lua Загрузка программы: pastebin get -f mSRmMS72 Graf_drawer.lua Рекомендую вручную вбивать команды, а то при копировании лезет дополнительная информация в буфер обмена и ОС начинает глючить. Ну и скрин, как это выглядит: Обновляется программа каждую 1 секунду, но график меняется только при изменении количества предметов, что там заложены. Название предмета, если ты играешь на сервере может выводиться на каком-то другом языке (зависит от настроек сервера)
  20. 4 балла
    Ну просто это актуально только если ты уже знаешь Делфи, и тебе нужно найти работу. А начинать изучение программирования с Делфи - мне кажется - не самая лучшая идея. Это как запрыгнуть в списанный тепловоз стоящий на запасных путях. Там может быть комфортно, но далеко ты уже не уедешь. Руби - такой же уходящий язык как и Делфи. Луа - это очень нишевый скриптовый язык, который не все любят, почему-то. Scala - тоже язык который занял очень маленькую нишу - в основном интерпрайз / биг дата. В этой области 90% занято Java, и Scala удержалась за счет того, что под нее, на пике популярности, было создано несколько очень крутых фреймворков. ну а Rust - это новый язык, который только набирает темпы. У него довольно много конкуренции - тот же Go, поддерживаемый со спины корпорацией Google. Rust пользуется популярностью у программистов, и я думаю будет постепенно подниматься в рейтинге. (В этом году он занял Тор-1 позицию как "самый любимый язык" в опросе StackOverflow.) Delphi - это язык который держится в топе за счет большого объема кода, который был на нем написан в годы его расцвета. Но как несложно заметить, позиции он постепенно теряет. Основной плюс Делфи, который обычно называют - очень быстрая и удобная разработка десктопных приложений - стал относительно неактуален в последние годы, а больше нигде особенно Делфи не применим, так как есть конкуренты, которые делают это лучше и быстрее. В том же опросе от StackOverflow он попал в топ языков, которых программисты "боятся". Наряду с Visual Basic, Assembler, Perl, Cobol (и, почему-то, C и Lua =)). Какого черта в топе делает Visual Basic.NET - я вот не понимаю. Наверное черное шаманство Microsoft играет какую-то роль в этом загадочном факте.
  21. 4 балла
    Я поражён, если честно, выдержке, которая потребовалась для написания такого. Я бы уже на втором энде запилил строку вроде [il]"#${}<>*?$!':@+`|="[/il], а потом делал бы [il]characters:find(gpu.get(4 + i, 3))[/il]. По скриншотам выглядит неплохо. Вообще, круто, что проект до релиза доведён. Некоторые (глазами упираюсь в @LeshaInc) и такого не достигают. P. S. К слову — я, наверное, этим разочарую — но даже с таким крупным текстом, как в первых постах, без очков я не разгляжу толком что-либо, к сожалению. Укатились старания в вену.
  22. 4 балла
  23. 4 балла
    А что предлагаешь ты? Переквалифицироваться в серьёзный ресурс для бородатых мужиков, или же окуклиться в Майнкрафте? Программирование внутри игры – это просто и весело. Порог вхождения низкий, а результаты труда наглядны. Приятно видеть, как десяток строк кода оживляют робота, заставляя его делать полезную (в игровом смысле) работу. Прокачавшие навык ищут задачи посложнее. До сих пор кто-то находит в Майнкрафте новые задачи, а кто-то находит новые решения старых задач. Кто-то ушёл в другие игры, а кто-то хочет написать свою игру. Почему нет? Сам я пока отношусь к тем, как выразился NEO, которые до сих пор не наигрались в Майнкрафт. Ну, да, бывает, я экспериментирую с другими играми, но Майнкрафт, как поставщик игровых задач для роботов, до сих пор лучший, как по мне. Тем не менее, на этом форуме я одобряю любые начинания, связанные с игровым программированием. Сейчас критика в этой теме не имеет смысла. Подождём годик, а потом уже и покритикуем. Сейчас надо накидать будущим авторам каких-то идей, которые их заинтересуют. А заинтересует ли результат игроков, предугадать сложно. Нотч, помнится, тоже не ожидал такого успеха Майнкрафта. Не исключаю даже, что ему кто-то так же предлагал заняться чем-то более осмысленным. Если находятся желающие запрограммировать игру, в которой требуется программировать, то зачем их отговаривать? Пусть пишут. Форуму это точно не повредит.
  24. 4 балла
    Скриншотов накопилось много P.S фух 3 месяца скринов обработал с 1 февраля до 1 мая P.S.S позже ещё добавлю
  25. 4 балла
    Потоки — очень полезные штуки, позволяющие исполнять несколько кусков кода. Раньше для их использования приходилось скачивать отдельную библиотеку, работающую через костыли. Начиная с OpenOS 1.6.4, они есть в стандартной поставке ОС — в модуле thread. Давайте посмотрим, из чего она состоит — и в чём её преимущество перед любыми другим библиотеками. Начнём с версий. OpenOS 1.6.4 — версия, включённая в OpenComputers 1.7.0. Если не хотите возиться с обновлением системы вручную, требуется иметь версию выше или равную 1.7.0. Сразу обращаю внимание на самую важную вещь: потоки не могут исполняться одновременно. В один момент времени только один поток может работать. В чём тогда красота тредов? Они автономны, то есть: Начинают исполнение сразу же после создания. Передают исполнение в другие потоки в местах, указанных использователем, — при том или ином вызове computer.pullSignal (os.sleep, event.pull и т. д.). Автоматически продолжают своё исполнение без необходимости самостоятельно их стартовать. Потоки можно убить и приостановить. Они неблокирующие: Вызов computer.pullSignal не блокирует исполнение других потоков. Они отцепляемые: Процесс, в котором был создан поток, называется родительским. При завершении родительского процесса все потоки останавливаются. Поток может отсоединиться от родительского процесса и работать полностью автономно — например, как слушатели событий. Поток может сменить родителя на другого. Поток сам является процессом и потому может создавать дочерние потоки. Работающий поток не даёт завершиться своему родителю. Они независимы при обработке событий: Потоки не наследуют и не передают дочерним свой набор слушателей событий. Все слушатели событий и таймеры принадлежат только конкретному потоку. Как следствие, поток не может изменять их набор в другом. Слушатели и таймеры автоматически удаляются при завершении потока, даже если завершение вызвано ошибкой. Приостановленные потоки игнорирует события. Если несколько потоков вызвали event.pull на одно и то же событие, они оба его получат. Этот набор фич в таком объёме присутствует только в этой библиотеке, и ни одна другая и не даёт столько простоты в работе с ними. Пожалуй, приступим к использованию. Потоки создаются функцией thread.create: первым аргументом передаётся функция, дальше идут аргументы к ней. local thread = require("thread")local t = thread.create(function(a, b) print("В потоке получены аргументы:", a, b)end, 21, 42) Функция возвращает объект потока. Его же может получить сам поток вызовом thread.current() — однако если вызвана не в потоке, то возвращает nil. На всякий случай, основной процесс не является потоком. Объект потока позволяет чудить различные вещи с потоком. t:suspend() приостанавливает поток. Как уже сказано, такой поток не будет получать события и обрабатывать тики таймера. Забавно, что если приостановить поток, когда он ждёт события, то неизвестно, что он получит после его возобновления. t:resume() возобновляет работу ранее приостановленного потока. Так как созданные потоки сразу начинают работу, то обычно этот метод вызывать не придётся. t:kill() убивает поток, то есть завершает его, удаляя всех слушателей и таймеры. Возобновить работу потока после того, как он убит, нельзя. t:status() возвращает строку со статусом потока: "running" — поток работает или блокирован другим. Такой поток не даёт завершиться своему родителю. "suspended" — поток приостановлен. Его дочерние потоки также будут приостановлены. Когда родительский процесс завершается, такой поток автоматически убивается. "dead" — поток мёртв. t:attach() позволяет сменить родителя у потока. Без аргумента поток будет присоединён к текущему процессу. Переданное как аргумент число позволяет указать, к кому присоединить: 0 — текущий процесс, 1 — родитель текущего и т. д. t:detach() отцепляет поток от родителя. Такой поток будет работать до его остановки или перезагрузки компьютера. t:join() останавливает процесс, в котором была вызвана это функция, до завершения потока t. local thread = require("thread")local t = thread.create(function() os.sleep(10)end)t:join() -- остановится на 10 секунд Можно передать первым аргументом этой функции число, которое будет служит таймаутом (в секундах). Тогда, если не успеет завершиться поток за это время, join завершится досрочно. t:join ждёт только одного потока. Для групп потоков есть функции thread.waitForAny и thread.waitForAll — обратите внимание, что это функции библиотеки, а не методы объекта потока. Обе функции первым аргументом требуют таблицу с потоками, а вторым опционально можно задать таймаут. thread.waitForAll ждёт, пока завершатся все потоки из списка. local thread = require("thread")local t1 = thread.create(function() os.sleep(10)end)local t2 = thread.create(function() os.sleep(15)end)thread.waitForAll({t1, t2})print("Это сообщение будет написано через 15 секунд") thread.waitForAny ждёт, пока завершится хотя бы один поток из списка. local thread = require("thread")local t1 = thread.create(function() os.sleep(10)end)local t2 = thread.create(function() os.sleep(15)end)thread.waitForAny({t1, t2})print("Это сообщение будет написано через 10 секунд") Что будет, если поток бросает ошибку? При ошибке в потоке она не будет проброшена в родительский процесс. Как и со слушателями, она будет записана в файл /tmp/event.log, но родитель не сможет узнать причину ошибки — и, вообще, успешно ли завершился поток. local thread = require("thread")local t = thread.create(function() os.sleep(3) error("test")end)print(t:status())--> runningt:join()print(t:status())--> dead Кроме того, событие жёстокого прерывания (Ctrl+Alt+C) не передаётся всем процессам — только одному; причём неизвестно, какому именно: родителю или одному из его потоков. Если вы используете потоки, первым делом сделайте один, который будет ждать события interrupted и подчищать ресурсы. local thread = require("thread")local cleanupThread = thread.create(function() event.pull("interrupted") print("Принял ^C, чищу всякие ресурсы")end)local mainThread = thread.create(function() while true do local input = io.read() if input == "exit" then break end endend)thread.waitForAny({cleanupThread, mainThread})os.exit(0) Обратите внимание, что в конце программы стоит os.exit. Где-то я уже упоминал не раз, что родительский процесс, достигнув конца программы, не завершится до тех пор, пока работает хотя бы один из его дочерних потоков. Вызов os.exit() позволяет выйти из программы, закрыв все дочерние потоки. Что, безусловно, достаточно удобно. Есть ещё один момент. Допустим, данная программа запускается в роботе: local robot = require("robot")local thread = require("thread")local moveThread = thread.create(function() while true do robot.forward() endend)local inputThread = thread.create(function() while true do local input = io.read() if input == "exit" then break end endend)thread.waitForAny({inputThread, moveThread})os.exit(0) Если вы запустите эту программу, то должны заметить, что вы ничего не сможете написать в роботе, хотя работает io.read. Дело в том, что функция robot.forward вызывает метод компонента, который блокирует исполнение компьютера. Пока робот двигается, на компьютере не может выполняться ни одна команда. Чтобы хоть что-то можно было вставить в строку, то поставьте после robot.forward какой-нибудь os.sleep(0) — он позволит соседнему потоку принять и обработать события. Тем не менее, строка ввода всё равно будет работать с тормозами. В подобном случае задумайтесь над тем, чтобы использовать вместо строки ввода иное средство коммуникации: редстоун, сеть, интернет-сокет. Несмотря на всё, библиотека действительно облегчает работу с потоками в OpenOS. Кроме того, очень удобно поместить все слушатели событий в один поток, чтобы они все автоматически были удалены после убийства потока. local event = require("event")local thread = require("thread")local mainThread = thread.create(function() event.listen("key_down", function(evt, addr, key, code, user) print("A key has been pressed!") end) while true do print("do something") os.sleep(0.5) endend)-- событие interrupted не ловится обработчикамиlocal intThread = thread.create(function() event.pull("interrupted")end)thread.waitForAny({mainThread, intThread})os.exit(0) Не нужно функции сохранять в переменные и помнить, что нужно ставить event.ignore в конце программы; не требуется ребутать компьютер, если программа завершилась с ошибкой, а до отключения слушателей дело не дошло. В общем, красота.
Таблица лидеров находится в часовом поясе Москва/GMT+03:00
  • Рассылка

    Хотите узнавать о наших последних новостях и информации?

    Подписаться
×