Лидеры
Популярный контент
Показан контент с высокой репутацией 01.01.2022 во всех областях
-
1 баллЕсли вы когда нибудь сталкивались с созданием серверов под OpenOS, вам знакома проблема блокирования всего компьютера. Его нельзя использовать, пока сервер не выключится. Некоторые придумывали свои велосипеды, которые запускали event.listen или event.ignore. Но не то это! Для таких вещей существует rc, в OpenOS. Сейчас я расскажу вам, что это за зверь, где он живет и зачем он нам. Немного теории Итак, все скрипты для rc хранятся в папочке /etc/rc.d/. Любой файл с расширением .lua, который находится там, является rc-скриптом. У такого скрипта все глобальные функции это команды. Запустить такую команду можно командой rc <имя скрипта, без расширения> <имя команды>. Например если мы создадим глобальную функцию start в файлике /etc/rc.d/test.lua, то запустив команду rc test start эта команда выполнится. Все просто. Получить список команд определенного скрипта можно при помощи команды rc <имя скрипта, без расширения>. Например так: rc test. RC сам создает некоторые команды, хотя мы их можем переопределить: enable/disable. Соответственно включают/выключают скрипт. Все включенные скрипты получат команду start при запуске компьютера. restart если есть start и stop. Перезапускает скрипт, то есть поочередно запускает stop и start. Каждый скрипт можно конфигурировать. Конфиг находится в /etc/rc.cfg. Формат файла прост: <имя скрипта> = <конфиг: все что угодно, таблица, текст, число> По сути это обычный луа-файл, все глобальные значения из которого считаются полями. Каждый скрипт может получить доступ к своему конфигу. Конфиг записывается в переменную args. С теорией покончено, приступим к практике! Практика Я предлагаю написать простой эхо-сервер. Он будет слушать определенный порт (из конфига), и отвечать на любое сообщение эхом. Начнем! Создадим файл /etc/rc,d/echo.lua, и начнем писать в нем код. Нам понадобятся некоторые переменные -- нам понадобятся библиотека event -- что бы установить свой обработчик событий local event = require("event") -- еще нам нужна библиотека computer -- что бы подключить компонент `modem` local component = require("component") -- будем считать количество ответов -- зачем? для диванных аналитиков конечно! local count = 0 -- будем хранить текущее положение -- что б никто не запустил случайно сервер два раза local started = false -- сюда запишем прокси модема, когда убедимся что он есть local modem -- а сюда запишем рабочий порт local port Создадим обработчик события modem_message. Он будет вызываться при каждом сообщении по сетевой карте. -- функция ниже будет запускаться -- при каждом сообщении по сетевой плате local function onModemMessage(_, _, snd, prt, _, ...) -- `_` в нашем понимании - неиспользуемый аргумент -- если порт сообщения не совпадает с портом -- из конфига, выходим print(prt) if prt ~= port then return end -- добавим еденицу к счетчику count = count + 1 -- здесь мы уверены, что modem существует -- так как обработчик поставится только если у нас есть модем modem.send(snd, prt, ...) -- / | \ -- получатель, порт, данные -- просто напросто пересылаем отправителю то что он -- отправил нам =) end Теперь мы добавим команду start, которая запустит наш сервер. -- функция ниже глобальная, `local` нет. -- потому _rc_ ее будет смело считать командой -- а команда эта будет запускать наш сервер function start() -- мы должны проверить, есть ли у нашего сервера -- сетевая карта if not component.isAvailable("modem") then -- если ее нет, мы выводим ошибку и выходим io.stderr:write("Сетевая карта не найдена!") return end -- еще нам нужно проверить, выключены ли мы -- если это не так, снова ошибка if started then io.stderr:write("Сервер уже запущен!") return end count = 0 -- сбросим счетчик started = true -- теперь мы знаем, что с этого момента -- сервер включен. port = args or 666 -- args это переменная, в которую _rc_ запишет данные из конфига -- конфиг находится в /etc/rc.cfg -- но если в конфиге порт не настроен, используем дефолтный modem = component.modem -- мы проверили, что модем существует, -- поэтому смело его подключаем -- откроем порт modem.open(port) -- нам нужно сделать так, что бы все сообщения -- по сетевой карте обслуживались нашей функцией event.listen("modem_message", onModemMessage) -- ну а теперь мы точно включились! end Куда без команды stop? Добавим ее! -- эта функция тоже глобальная, поэтому считаем ее командой -- эта команда остановит сервер function stop() -- мы должны проверить, включен ли вообще сервер -- если он не включен, какой толк его выключать, верно? if not started then -- если он не включен, выводим ошибку и выходим io.stderr:write("Сервер уже выключен!") return end count = 0 -- опять же сбрасываем счетчик started = false -- запоминаем, что теперь -- сервер выключен -- теперь нам нужно по-настоящему выключить сервер event.ignore("modem_message", onModemMessage) -- все! с этого момента сервер выключен, и не принимает сообщение end Еще самая малость, добавим команду printCount, которая будет отображать количество полученных сообщений. -- и это тоже команда, думаю вы понимаете -- а эта команда напишет количество отправленных сообщений function printCount() -- выводить информацию будем только если сервер не запущен -- поэтому выведем ошибку, если он не включен if not started then io.stderr:write("Сервер выключен!") return end print(count) -- пишем количество подключений -- диванные аналитики ликуют! end Ну вот и все, программа сделана, диванные аналитики ликуют, инженеры недоумевают. Полный код: Время QA! Симулируем Васю Пупкина... А вот уже на другом компьютере отправлено сообщение на работающий сервер. Счетчик тоже работает. Установим значение в конфиге. Проверим... Все работает, инженеры ликуют! Такую систему очень удобно использовать для всяческих серверов. Сервер может спокойно работать в фоне, а в главном потоке спокойно можно запускать консоль сервера, интерпретатор луа, rm -rf / ... Enjoy!
-
1 баллПрогулка с экскурсоводом по обновлённой части парка "OpenComputers". Глянем на новые вещи и попытаемся разобраться. Начнём с самого значительного изменения. Серверные Стойки. Ну тут всё интересно. Пугающая штука теперь — интерфейс стойки. А на хотбаре у меня лежат орудия пыток. Думаю, предпоследний предмет опознали — это сервер T3. По нажатию ПКМ этим предметом всё так же открывается интерфейс подобный компьютерному, куда можно вставить компоненты. Заменил я его на креативный, так как я играю в креативе, но уровень не так важен. Кладём три предпоследних предмета в стойку. Видим эту страшную картину. Но у нас же вроде гайд, поэтому добавим стрелочек. (2) — это сервер креативного уровня. В нём стандартный набор компонентов + инет- и беспроводная сетевая карты. (1) — это Server Terminal. Об его функции я расскажу позже. (3) — специальный дисководик для серверов. Вместо отдельного чукчёмного блока. Функции абсолютно те же. Сразу скажу, что (6) — это та же кнопка, что и [internal/External] в прошлых версиях, а так как её практическое использование нулевое, я промолчу про её функцию. Справа от слотов для серверов и модулей есть 6 линий разноцветных (7). Под каждой линией есть изображение стороны игральной кости (4), символически обозначающее эту линию. Их расшифровка — (5). Получается, для каждой из пяти сторон стойки (передняя не считается) в интерфейсе отдельная линия. Напротив слотов с предметами на линиях образуются точки (9), (10), .... Они требуются для соединения компонентов для серверов . То есть, подключив сервер (2) и компоненты к нижней стороне в интерфейсе, кликнув по большим точкам на линиях, для сервера (2) становятся доступны Server Terminal (1), Rack Disk Drive (3) и компоненты с нижней стороны. Неожиданно просто. А что же за маленькая точечка (8) напротив сервера? Оказывается, она служит для подключения сетевой карты в сервере к какой-либо стороне. Действует так же, как и в прошлых версиях. Теперь про (1), как и обещал. Если раньше всё было очень просто — берём Remote Terminal, подключаем и просто работаем, то теперь всё плохо. Эта штука позволяет подключённому к этой же стороне сервер у работать с удалёнными терминалами. Для этого берём Remote Terminal и делаем им ПКМ по компоненту в серверной стойке. Думаю, опознаете. Если загорится лампочка на компоненте в стойке — всё ОК. Если же тратить ресурсы на эту штуку не хочется, достаточно просто от указанной стороны компонентов провести кабель к монитору и клавиатуре. "Эм, а как включить сервер?" Теперь всё управление ими ведётся через ПКМ по серверу в стойке. Щёлкаем и можем включить сервер, потушить его и даже сменить компоненты во время работы! Кстати, о дисководах. В него и в дисковод обычный можно вставлять и изымать дискеты через Шифт-ПКМ. Очень удобно. Теперь сходим к роботу, так как в OpenComputers появился новый апгрейд: торговый. Торговый апгрейд для робота — апгрейд второго уровня, при подключении предоставляет компонент "trading" . У него всего одна функция — trading.getTrades() , возвращающая таблицу предложений жителей в радиусе 8 блоков от робота. Каждый элемент представляет собою одну сделку одного из жителей. Структура: {getInput = function():table, table, getOutput = function():table, isEnabled = function():boolean, trade = function():boolean[, string]} Функция getInput() возвращает таблицы с описанием необходимых предметов. По сути, это то же описание, что возвращает контроллер инвентаря — метаданные, имеет ли нбт-теги, имя предмета, его айдишник, максимальное повреждение, размер стэка и количество предметов, необходимых для торговли. Если второй предмет не требуется для торговли — вторая таблица будет равняться nil . Функция getOutput() действует по схожему с предыдущим принципу, только возвращает таблицу с описанием выходного предмета. Функция isEnabled() возвращает, интересна ли эта сделка на текущий момент жителю. Как известно, после 7 сделок она блокируется. Для разблокирования надо совершить другую сделку с этим же торговцем. Функция trade() , наконец, совершает сделку. Её условия: в инвентаре робота должно быть достаточное количество предметов для сделки, а предложение должно быть активно. Если всё верно, предметы обмениваются в инвентарь робота. Ошибки: false, "not enough items to trade" — в инвентаре робота недостаточно предметов для торговли. false, "trade is disabled" — житель более не заинтересован в этом предложении (было совершено 7 сделок). Кроме того, ещё одно мелкое изменение — для дисковода появился собственный компонент "disk_drive". Он есть только у Rack Disk Drive и Disk Drive, но не во встроенных в компьютер. Функция isEmpty() возвратит статус дисковода — есть ли в нём диск. Функция eject([velocity]) выплюнет диск из дисковода. Если дать как аргумент число (числа более 1 смысла не имеют, так как эффект тот же), диску передастся определённая скорость. Вот пример для максимальной скорости: Ещё из изменений — интернет-карта. Функция request() принимает третьим опциональным аргументом таблицу хедеров. Например, {["Accept-Encoding"] = "application/json"} . Это очень крутое изменение — так, для работы с чатом форума с OpenComputers теперь нет никаких технических преград. А ещё можно наконец-то запилить логин на сайты... Ах, применений много. Для модняков. Если дронотапки совместить с красителями, как кожанку, то неон на них покрасится. Для смытия краски достаточно кинуть тапки в ванильный котёл с водой, как кожаную броню. Если у меня хватит духу написать вторую часть, то, скорее всего, я начну рассказывать об изменениях в OpenOS 1.6. Ибо материала там тонны. Пока что не забудьте проголосовать в опросике сверху. Порадуйте диванных аналитиков.
Эта таблица лидеров рассчитана в Москва/GMT+03:00
