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

Лидеры


Популярный контент

Показан контент с высокой репутацией 24.03.2021 во всех областях

  1. 6 баллов
    Описание Данная программа позволяет видеть местоположение руды вокруг игрока. Работает следующим образом: Планшет с геосканером и сетевой картой сканирует область вокруг игрока и отправляет на стационарный компьютер информацию о найденных блоках Компьютер с терминалом OpenGlasses2 и сетевой картой принимает информацию о блоках и рисует этим блокам подсветку. Фичи и особенности Используется методика из исследования Дуба, которая позволяет весьма точно определять руду Настраиваемые параметры сканирования c валидацией и коррекцией сохраняются в конфиг при выходе из программы Понятный ui Подсветка границ области сканирования Отображение на очках с использованием всего 2 виджетов фпс снижается меньше Это программа работает на версии игры 1.12.2 с аддоном OpenGlasses2 теоретически можно портировать на 1.7.10 Скриншоты Видео Установка Требуемое железо Планшет, минимальное Планшет, рекомендуемое Стационарный компьютер Вместо системного блока 3 тира можно юзать серверную стойку с сервером 2 тира. Также вместо связанной карты можно юзать беспроводную сетевую, однако, радиус действия в этом случае будет ограничен. Все процессоры нужно переключить на Lua 5.3(шифт+пкм). На планшет и компьютер устанавливаем OpenOS. На планшет устанавливаем программу и ее либы wget https://raw.githubusercontent.com/hohserg1/OpenComputersPrograms/master/oresense/oresense_tablet.lua wget https://raw.githubusercontent.com/hohserg1/OpenComputersPrograms/master/simple_libs/bit_array.lua lib/bit_array.lua pastebin get iKzRve2g lib/forms.lua На комп устанавливаем программу и ее либы wget https://raw.githubusercontent.com/hohserg1/OpenComputersPrograms/master/oresense/oresense_server.lua wget https://raw.githubusercontent.com/hohserg1/OpenComputersPrograms/master/simple_libs/bit_array.lua lib/bit_array.lua Использование Привязываем очки к терминалу и надеваем. Запускаем на компе oresense_server. Программа будет работать в фоновом режиме, поэтому комп можно юзать для чего-нибудь еще. Запускаем на планшете oresense_tablet. Синие поля позволяют настроить параметры. Большая красная кнопка запускает сканирование. Во время этого процесса лучше не сдвигаться с места. По окончанию сканирования оглядитесь вокруг - руда будет подсвечена красными каркасными кубами. Благодарности Спасибо @Doob и всем, кто ему помогал, за исследование принципов работы геолайзера и статью об этом Спасибо @Zer0Galaxy за либу гуи forms Спасибо @BrightYC за реью гуи и идею мэйн-картинки Спасибо @Sainthozier за реью гуи Спасибо @Fingercomp за функцию индексации координат, к сожалению, она не понадобилась Спасибо людям из irc-чата за саппорт по ОС и Lua Ссылки Гитхаб: https://github.com/hohserg1/OpenComputersPrograms/tree/master/oresense
  2. 2 балла
    В моде OpenComputers есть интересное устройство, которое позволяет определить плотность блока на расстоянии. Но вот беда, данные он выдает довольно шумные и чем больше расстояние, тем больше шума. Чтобы определить подлинную плотность блока, можно просканировать его несколько раз, а результат усреднить. Шум, мешающий сканированию, имеет вероятностную природу. И после нескольких сканирований можно статистически найти, какая вероятней всего плотность у блока. За один тик мы можем просканировать 64 блока. Чтобы проанализировать всю доступную область (65 x 65 x 64) сотней итераций, нам понадобится 422500 тиков, что равно 21125 секунд или 352 минуты, то есть без малого 6 часов. Но сколько раз надо сканировать? Сто? Тысячу? Нам открыто тайное знание и есть точный ответ. Один. Всего за одно сканирование мы можем найти руду среди любых других блоков. Если хочется абсолютной уверенности, придется сделать пару магических пассов и просканировать повторно. Начнем с теории. Для начала откроем код мода и найдем функцию geolyzer.scan, она располагается [здесь] src/main/scala/li/cil/oc/integration/vanilla/EventHandlerVanilla.scala и называется onGeolyzerScan() Просмотрев код, мы можем понять, что функция принимает параметры, по этим параметрам сканирует блоки в мире. Делает разные проверки вроде world.blockExists(x, y, z) && !world.isAirBlock(x, y, z), чтобы убедится, что блок есть. Потом получает информацию о блоке по координатам, делает еще несколько проверок (опять проверить, что блок все-таки есть block != null, проверяет дополнительные параметры: includeReplaceable, isFluid(block), block.isReplaceable(world, blockPos.x, blockPos.y, blockPos.z)) Потом происходит измерение расстояния до блока. И в конце берется плотность, смешивается с шумом и расстоянием. Результат добавляется к таблице блоков и отправляется игроку. Вроде-бы ничего необычного. Шум, расстояние, плотность. Нам и так известна зависимость силы шума от расстояния. И вот тут начинается волшебство. Рассмотрим поподробнее код вычисления итоговой плотности блока. e.data(index) = e.data(index) * distance * Settings.get.geolyzerNoise + block.getBlockHardness(world, x, y, z) Коротко можно это записать в виде формулы: R = G * D * N + H G - это сгенерированный шум. D - расстояние до блока. N - множитель шума из конфига (стандартно - 2). H - настоящая плотность. R - результат работы геосканера. Если мы попробуем в качестве эксперимента отнять от результата предполагаемую плотность, то ничего нового не узнаем. Если обратим все операции с известными значениями, то получим только шум. А можем ли мы так же разобрать формулу шума? Давайте попробуем. Несколькими строками выше [ссылка]. Можно наблюдать получение массива случайных байт. val noise = new Array[Byte](e.data.length) world.rand.nextBytes(noise) Далее следует нормализация значений. noise.map(_ / 128f / 33f).copyToArray(e.data) Хм. Так-так-так. Если мы это все обьеденим с предыдущей формулой, то получится что-то вроде такого: R = G(RANDOM_BYTE / 128 / 33) * D * N + H И что это нам дает? А то, что исходное псевдослучайное число имеет жесткую дискретность. ГПСЧ дает случайные числа типа byte, а это только 256 значений (-128, +127). Нам известны все значения, кроме H и RANDOM_BYTE, что нам это дает? Мы можем предположить значение H и обратить всю формулу. (R - H) / D / N * 128 * 33 Для стандартного конфига можно сократить до: 2112 * (R - H) / D А теперь тайное знание для тех, кто не понял самостоятельно. Мы взяли желаемую плотность блока (например 3 для руды). Подставили вместо H. Получили случайное значение. Можем легко определить, угадали ли плотность или нет. Из-за дискретности случайных значений генератора, распределение вероятностей для блоков с разной плотностью не одинаковое. Перейдем к практике. Вот код простого скрипта, который в заданном радиусе ищет блоки с нужной плотностью. Результат выводится на голопроектор. local sqrt = math.sqrt local component = require('component') local geolyzer = component.geolyzer local hologram = component.hologram local function distance(x, y, z) return sqrt(x^2 + y^2 + z^2) end local function magic(R, H, D) return 2112 * (R - H) / D % 1 end local function visualize(hardness, elevation, size) hologram.clear() hologram.setScale(9) local blocks, result for x = -size, size do for z = -size, size do blocks = geolyzer.scan(x, z, elevation, 1, 1, 32) for i_y = 1, 32 do result = magic(blocks[i_y], hardness, distance(x, i_y+elevation-1, z)) if blocks[i_y] ~= 0 and (result > 0.9998 or result < 0.00005) then hologram.set(x+24, i_y, z+24, true) end end end end end local hrd, ele, siz = table.unpack({...}) hrd = hrd or 3 ele = ele or -32 siz = siz or 16 visualize(hrd, ele, siz) А вот результат: При сканировании заметны артефакты. Когда разные плотности близки на целочисленных расстояниях, позникают коллизии. Это можно частично компенсировать, если есть блок кандидат на ошибку. На любом расстоянии можно рассчитать абсолютный минимальный и максимальный уровень шума. С расстоянием, у близких плотностей пересечение значений увеличивается, но если плотность блока не в области пересечений, то можно точно определить к какой области он относится. Пересечение плотностей руды (3) и камня (1.5), точками обозначены три сканирования блока руды. Результаты обратного вычисления для разных плотностей хорошо это демонстрируют. Для компенсации артефактов надо ввести дополнительное условие: полученный RANDOM_BYTE должен быть в диапазоне -128:127. Вот финальный скрипт и результат. local sqrt = math.sqrt local component = require('component') local geolyzer = component.geolyzer local hologram = component.hologram local function distance(x, y, z) return sqrt(x^2 + y^2 + z^2) end local function magic(R, H, D) return 2112 * (R - H) / D end local function visualize(hardness, elevation, size) hologram.clear() hologram.setScale(9) local blocks, result for x = -size, size do for z = -size, size do blocks = geolyzer.scan(x, z, elevation, 1, 1, 32) for i_y = 1, 32 do result = magic(blocks[i_y], hardness, distance(x, i_y+elevation-1, z)) if blocks[i_y] ~= 0 and result > -128 and result < 127 and (result%1 > 0.9998 or result%1 < 0.0002) then hologram.set(x+24, i_y, z+24, true) end end end end end local hrd, ele, siz = table.unpack({...}) hrd = hrd or 3 ele = ele or -32 siz = siz or 16 visualize(hrd, ele, siz) Для более точного определения плотности можно сделать два сканирования. Одно сместить относительно другого так, чтобы расстояния с артефактами не совпадали. Чтобы не выполнять тяжелую операцию sqrt, можно создать словарь, где [x^2 + y^2 + z^2] = sqrt(x^2 + y^2 + z^2), всего понадобится 1742 уникальных значений. P.S. Пост является компиляцией знаний из [этой] темы. Собрал, чтобы перевести и опубликовать на официальном форуме. Автор идеи хакнуть геосканер - @eu_tomat
  3. 2 балла
    @hohserg , на гитхаб, в ветку indev залил новую версию библиотеки с разбивкой больших пакетов. Там же лежит пример для работы с сетью из eeprom.
  4. 1 балл
    Апдейт. Я уже перешёл на плагинописание и как-то даже забыл про этот мод. В первом сообщении хоть я и преувеличил свои способности, но задумка объективно отличная и интересная, как дойдут руки - начну писать, всё равно я от скуки просто летаю по миру майна без цели, так хоть интересным делом займусь. Скорее всего это будет ОС для планшетов, которая будет похожа на андроид и не будет требовать клавиатуры. По ходу разработки я буду выкладывать некоторые интересные луа скрипты, которые вскоре, скорее всего, будут использованы в моей оболочке. Всем спасибо за советы и поддержку.
  5. 1 балл
    Кажется понял о чем ты. Нужно дать возможность получать доступ к родительскому объекту. В принципе, этот доступ есть через метатаблицу: getmetatable(self).draw(self) -- вызываем родительский метод Коряво, конечно. Нужно будет подумать над чем-то вроде: self.inherited:draw()
  6. 1 балл
    Разумеется, оригинальная OpenOS не предусматривает такого трюка. Требуется серьёзная переработка всей системы. Но если отвечать по существу вопроса, то да, можно. И тому есть реалистичный пример.
  7. 0 баллов
    На форуме в последнее время начали появляться темы с сетевыми библиотеками и браузерами. Продолжу это движение (да, скоро и мой браузер будет). Итак, представляю вам 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 родительского компьютера
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...