Перейти к публикации
Форум - ComputerCraft

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


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

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

  1. 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 — вставить строку. Процессы закрывают файлы при завершении. Ссылочка на гитхаб, откуда можно скачать мод.
  2. 2 балла
    Меня тут попросили что-нибудь написать в блог. Например про мои заброшенные проекты. Честно перелопатил свои репозитории, но не нашел ничего интересного. Ни одного интересного заброшенного проекта. Просто беда какая-то. Даже на секунду померещился нимб над головой (такой наверняка есть у любого программиста, который всегда дописывает все свои проекты до единого). Но потом я пошел посмотрел в зеркало и морок пропал. Поэтому вот скриншотик из пинг-понга, который я начал было писать, чтобы потренироваться в работе с сетью (хотел приделать туда мультиплеер). Но дальше фотошопа (точнее гимпа) меню у меня дело не ушло, писать одному было скучно, и быстро нашлись дела по-прикольнее. Сохранился даже репозиторий: https://github.com/MoonlightOwl/Upong
  3. 1 балл
    Потоки — очень полезные штуки, позволяющие исполнять несколько кусков кода. Раньше для их использования приходилось скачивать отдельную библиотеку, работающую через костыли. Начиная с 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
  • Рассылка

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

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