ECS
Гуру-
Публикации
533 -
Зарегистрирован
-
Посещение
-
Победитель дней
203
Тип публикации
Блоги
Профили
Форум
Багтрекер
Магазин
Все публикации пользователя ECS
-
Доброго времени суток. Захотелось написать клиент для работы с гитхабом через API, однако для заливки файлов на репозиторий требуется отправка PUT-запроса с соответствующим содержимым: Вопрос: это вообще реализуемо через интернет-карту? Если тут имеются эксперты в области веб-запросов, то подскажите, как познать сию магию. Наиболее логичным мне показалось решение ниже, однако увы: local handle = require("component").internet.request( "https://api.github.com/repos/IgorTimofeev/Test/contents/Meow.cpp", '{"path":"meow.cpp","message":"lol","content":"aGVsbG8gd29ybGQ="}', { ["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0", ["Authorization"] = "Basic base64encoded login:pass pair", ["Content-Type"] = "application/application/json", } ) for i = 1, 30 do print(handle.read(math.huge)) end handle.close() В то же время через специализированный софт все прекрасно заливается: И, разумеется, вариант с консольным curl также вполне себе рабочий: curl -ivX PUT -u login:pass -d '{"path": "meow.cpp", "message": "lol", "content": "aGVsbG8gd29ybGQ="}' https://api.github.com/repos/IgorTimofeev/Test/contents/meow.cpp { "content": { "name": "meow.cpp", "path": "meow.cpp", "sha": "95d09f2b10159347eece71399a7e2e907ea3df4f", "size": 11, "url": "https://api.github.com/repos/IgorTimofeev/Test/contents/meow.cpp?ref=master", "html_url": "https://github.com/IgorTimofeev/Test/blob/master/meow.cpp", "git_url": "https://api.github.com/repos/IgorTimofeev/Test/git/blobs/95d09f2b10159347eece71399a7e2e907ea3df4f", "download_url": "https://raw.githubusercontent.com/IgorTimofeev/Test/master/meow.cpp", "type": "file", "_links": { "self": "https://api.github.com/repos/IgorTimofeev/Test/contents/meow.cpp?ref=master", "git": "https://api.github.com/repos/IgorTimofeev/Test/git/blobs/95d09f2b10159347eece71399a7e2e907ea3df4f", "html": "https://github.com/IgorTimofeev/Test/blob/master/meow.cpp" } }, "commit": { "sha": "38e198640380a061ec9357677fa275ed2a450202", "node_id": "MDY6Q29tbWl0MTQ3ODczMzQzOjM4ZTE5ODY0MDM4MGEwNjFlYzkzNTc2NzdmYTI3NWVkMmE0NTAyMDI=", "url": "https://api.github.com/repos/IgorTimofeev/Test/git/commits/38e198640380a061ec9357677fa275ed2a450202", "html_url": "https://github.com/IgorTimofeev/Test/commit/38e198640380a061ec9357677fa275ed2a450202", "author": { "name": "Igor", "email": "sosi@mail.ru", "date": "2018-09-07T22:37:07Z" }, "committer": { "name": "Igor", "email": "sosi@mail.ru", "date": "2018-09-07T22:37:07Z" }, "tree": { "sha": "86d1529b4193d66705cc2272715009166deb16b2", "url": "https://api.github.com/repos/IgorTimofeev/Test/git/trees/86d1529b4193d66705cc2272715009166deb16b2" }, "message": "lol", "parents": [ { "sha": "db4b95734315298cad0e733421051524b4e32fc1", "url": "https://api.github.com/repos/IgorTimofeev/Test/git/commits/db4b95734315298cad0e733421051524b4e32fc1", "html_url": "https://github.com/IgorTimofeev/Test/commit/db4b95734315298cad0e733421051524b4e32fc1" } ], "verification": { "verified": false, "reason": "unsigned", "signature": null, "payload": null } } }
-
Раз уж речь зашла об идеях и медалях, то у нас была мыслишка накатать мод, рендерящий полученные награды в виде оверлея в дополнение к надетой броне, чтобы деды-ветераны форума имели возможность блеснуть ими не только на сайте. Единственной проблемой стало отсутствие личного форума и, разумеется, сервера
-
Нашел среди старых коммитов русскую версию. Для ознакомления сойдет, но учти, что в последних версиях либы очень многое изменилось, поэтому претензий никаких не предъявлять: https://github.com/IgorTimofeev/MineOS/blob/00f19b2c460bc82a4ae5fc593c367f0fbfd5ccdd/Documentation/GUI.md
-
Если приложение уже создано, то пкм - показать содержимое пакета - двойной клик по пикче - рисуешь - сохраняешь - пкм в пустоту - обновить - профит. Если приложения нет, то открываешь Picture Edit и вручную создаешь пикчу размером 8х4 пикселя. Это ж вообще элементарно, ты чо
-
Ты не обновляешь контейнер раз в секунду, а отрисовываешь его содержимое раз в секунду - это большая разница. Пожалуйста, читай документацию более вдумчиво: в ней подробно описана концепция либы. Для твоей задачи логичнее всего было бы создать пустой GUI.object вместо GUI.label и присвоить ему метод отрисовки, выводящий os.time на экран: -- Создаем главный контейнер и добавляем в него темно-серую фоновую панель local mainContainer = GUI.fullScreenContainer() mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D)) -- Добавляем объект, выводящее в экранный буфер системное время каждую операцию отрисовки mainContainer:addChild(GUI.object(3, 2, 1, 1)).draw = function(object) local text = os.date("%d %b %Y %H:%M:%S", os.time()) object.width = #text buffer.drawText(object.x, object.y, 0xFFFFFF, text) end -- Разово отрисовываем содержимое главного контейнера и запускаем обработку событий с интервалом 0 mainContainer:drawOnScreen(true) mainContainer:startEventHandling(0) Однако если по каким-то причинам тебе требуется использовать именно GUI.label, то можно использовать обработчик событий, обновляющий текст лейбла при каждом событии: -- Создаем главный контейнер и добавляем в него темно-серую фоновую панел local mainContainer = GUI.fullScreenContainer() mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D)) -- Добавляем лейбл и создаем функцию-обработчик событий, которая при каждом событии (даже отсутствующем) будет обновлять текст лейбла и отрисовывать изменения на экране local label = mainContainer:addChild(GUI.label(3, 2, 10, 1, 0xFFFFFF, "")) mainContainer.eventHandler = function() label.text = os.date("%d %b %Y %H:%M:%S", os.time()) mainContainer:drawOnScreen() end -- Разово вызываем созданную функцию для обновления текста mainContainer.eventHandler() -- Запускаем обработку событий с интервалом 0 mainContainer:startEventHandling(0) Старая версия либы была лютым калом: она отрисовывала изменения в экранный буфер во время клика на вкладку, затем вызывала метод .onTouch, а после вновь отрисовывала изменения. Я счел этот подход неразумным, т.к. незачем нагружать компьютер без четких на то указаний. Короче, добавь строку mainContainer:drawOnScreen() в конец метода .onTouch для каждой вкладки - и все будет шоколадно Как говорится, ложь, говнокод и провокация. Скорее всего, ты сначала создаешь объекты под жирное разрешение экрана, затем изменяешь его на меньшее, позабыв изменить размеры объектов. Пруфскрипт: -- Изменяем разрешение экрана на требуемое buffer.setResolution(80, 50) local mainContainer = GUI.fullScreenContainer() mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D)) -- Добавляем селектор цвета local colorSelector = mainContainer:addChild(GUI.colorSelector(3, 2, 30, 3, 0xFF00FF, "Цвет")) colorSelector.onColorSelected = function() GUI.alert("Ты выбрал новый цвет") end mainContainer:drawOnScreen(true) mainContainer:startEventHandling(0) Результат:
-
Берешь FOV камеры, а также ее текущий поворот, например, по горизонтали. Через цикл изменяешь угол будущего луча в диапазоне [поворот камеры - FOV / 2; поворот камеры + FOV / 2] с заранее рассчитанными шагом, равным ширина экрана / FOV (чтобы число лучей было равным ширине экрана). Далее необходимо прокастовать луч, следующий вдоль полученного угла вплоть до желаемой дистанции прорисовки. Поскольку рейкастинг всегда выполняется с определенной точностью, то разумнее всего будет разово высчитать итеративное смещение кусочка луча по оси X через sin(угол луча) * точность и по оси Y через cos. Полученные значения необходимо раз за разом прибавлять к точке старта луча, чтобы усмешно достигнуть конца. Ну, а далее проще простого: пробегаешься циклом по всей длине луча, попутно вычисляя мировые координаты вокселя по горизонтали. А затем повторяешь вышеописанное для вертикальной ориентации, проверяя наличие вокселя в обоих плоскостях и делая с ним все, что только заблагорассудится. Соль подобного подхода в том, что число тригонометрических операций будет эквивалентно ширина * высота экрана: и никаких тебе векторных вращений и бессмысленных расчетов. Цветами выделил инфу из этой пикчи: Значит, ищи ошибку. Я твой софт не кодил, и дебажить его не намерен. Формулы выше я скопипастил с собственного 3D-движка для опенкомпов, который с удовольствием их кушает. К слову, несмотря на наличие динамического освещения с полной перспективной коррекции, реализован он безо всяких углов Эйлера, матриц, кватернионов и прочей чуши на чистой линейной математике уровня 9 класса Зачем, заче-е-ем? К чему этот геморрой, когда сам алгоритм проще пареной репы? Подобное еще на Сегу во времена Вульфа кодили, слухом не слыхивая о подобной терминологии в компьютерной графике. Ты точно рейкастинг имеешь в виду, а не полноценное трехмерное проецирование со всеми вытекающими?
- 3 ответа
-
- 3
-
-
Интересно, для чего тебе вращение трехмерных векторов при написании рейкастера, если соль алгоритма именно в минимизации векторных расчетов и статичной производительности? Но хозяин - барин. Во-первых, на кой дьявол постоянно использовать конверсию из градусов в радианы? Сожрет же львиную долю ресурсов ЦП, а толку ноль. Юзай сразу радианы, а в человекопонятный градусный формат выводи лишь в интерфейсе. Во-вторых, очень много локальных переменных - рендерер загнется от "out of memory" на сценах с удаленной от точки каста геометрией, т.к. GC не успеет подтереть кучки локального навоза. В-третьих, незачем столь часто обращаться к таблице math и вычислять значения синусов: достаточно разово передать их в расчетную функцию. Также разумнее использовать векторные координаты в качестве последних аргументов функций, чтобы более эффективно передавать результат расчетов из одной функции в другую, хотя лично я бы вообще ограничился тремя локальными переменными для всех векторов и работал бы только с ними. В-четвертых, в нормализации углов особого смысла нет, т.к. тригонометрические функции автоматом работают с углами любого формата. Разве что если ты захочешь сделать заранее вычисленную таблицу косинусов/синусов и получать значения углов уже из нее - вот тогда да, приводить углы к диапазону [-2π; +2π] уже разумно, хотя на практике прирост производительности толком не заметен.
- 3 ответа
-
- 4
-
-
Вставлю свои пять копеек, чтобы правильность была еще более правильной. Ох уж эта правильность... В общем, так как время, затрачиваемое на вызов функций в Lua значительно превышает время осуществления иных операций, следует использовать итеративный метод расчетов вместо рекурсивного. Кроме того, как вполне грамотно заметил товарищ с e-maxx.ru, для определения четности числа имеет смысл заменить "n % 2 == 0" на "n & 1 == 0". В итоге времечко сократится еще втрое. Собсна, пруф: https://ideone.com/t9Yv5F
- 72 ответа
-
- 1
-
-
- цифровая подпись
- шифрование
- (и ещё 1 )
-
Ни для кого не секрет, что существует множество занятных софтин для работы с геосканером и вывода результата на голопроектор, очки из OpenGlasses или просто в виде сечения на экран. Мне захотелось пополнить их коллекцию программой для просмотра результата сканирования от первого лица в трехмерном пространстве. Работает детище по принципу рейкастинга и на данный момент имеет следующие фичи: Сканирование местности по указанному радиусу (до 32 блоков), сохранение и загрузка результата Примитивная мини-карта для упрощения ориентации в пространстве Кастомизация дистанции прорисовки, полей зрения игрока и уровня детализации Выбор палитры (оттенки серого или спектральная) Изменение размеров окна курсором Разумеется, оперативку оно жрет быстрее, чем репликаторы поглощали флот Гоа'Улдов, а также требует топовый ПК для работы, т.к. хранит безумное количество данных о результатах сканирования. Изначально я хотел замутить софтину для управления дроном-грифером, делающего снимки местности для упрощения воровства картошки с полей, однако по факту получилась просто занятная игрушка без какого-либо практически полезного с точки зрения выживания функционала. Поэтому хотелось бы услышать предложения по использованию подобных технологий именно в сурве. Команда для установки, чтобы пощупать ручками: pastebin run Gm8t26kd
-
Файл либы должен возвращать таблицу с созданными функциями: local liba = {} function liba.menu() ... end function liba.test() ... end return liba
- 2 ответа
-
- 2
-
-
Пробежимся по твоему скрипту: во-первых, что за странный бесконечный цикл в начале программы? while true do local adresses = { ... Метод :startEventHandling() автоматически обрабатывает все события бесконечно вплоть до завершения программы. Зачем нужен while true do? Нипанятна. Во-вторых, почему ты заносишь адреса компонентов реакторов вручную, да еще и по их аббревиатурам? Почему бы не использовать автоматическое получение proxy? local reactors = {} for address in component.list("reactor") do table.insert(reactors, component.proxy(address)) end Если это сделано с какой-то определенной целью, например, ради работы с небольшой группой реакторов из большого множества, то прошу прощения. В-третьих, почему бы не использовать циклы для создания виджетов? Неужели самому не лень копипастить тонну однотипного кода? -- Разметка layout:setCellPosition(1, 1, layout:addChild(GUI.text(1, 1, clr_main, "№"))) for i = 2, 7 do layout:setCellPosition(i, 1, layout:addChild(GUI.text(1, 1, clr_main, "№" .. (i - 1)))) end -- Заполняем Layout начиная со 2 колонки и 2 столбца local column, row, counter = 2, 2, 1 for address in component.list("reactor") do -- Добавляем виджет local widget = layout:setCellPosition(column, row, layout:addChild(GUI.text(1, 1, 0x0, "Реактор " .. counter))) -- Присваиваем виджету ссылку на proxy компонента реактора widget.reactorProxy = component.proxy(address) row, counter = row + 1, counter + 1 if row > 10 then column, row, counter = column + 1, 2, 1 end end В-четвертых, разумеется, изменений на экране у тебя нет. Как программа поймет, что состояние реакторов изменилось? Откуда она знает, что ты от нее хочешь? Накодь соответствующий функционал и наслаждайся. А если требуется обновлять температуру реакторов периодически, то используй нечто подобное: -- Создаем обработчик событий главного контейнера mainContainer.eventHandler = function(mainContainer, object, eventData) -- Если события нет, то следует обновить состояние реакторов и отрисовать изменения на экране if not eventData[1] then -- Перебираем все виджеты Layout начиная с 9 (все предыдущие - это чисто информация) for i = 9, #layout.children do -- Задаем им нужный цвет layout.children[i].color = layout.children[i].reactorProxy.producesEnergy() and 0xFF0000 or 0x00FF00 end -- Отрисовываем изменения на экране mainContainer:drawOnScreen() end end -- События пуллятся раз в 1 секунду по аналогии с computer.pullSignal(timeout) mainContainer:startEventHandling(1) Насчет отрисовки содержимого контейнера на экран - тут вообще все просто. Это основа основ, присутствующая в каждом примере кода в документации к либе: mainContainer:drawOnScreen() И наконец, где отступы? Ну рили, 2018 год на дворе, эпоха Sublime/Atom/Notepad++, где отступыЫыЫыЫ?
-
@@vlad1vv1 Этой либе сто лет в обед, и использовать ее нет особого смысла ввиду наличия более продвинутых аналогов. Возьми GUI, меньше геморроя будет. Там тебе и примеры, и картиночки, и вообще до мелочей все расписано: https://github.com/IgorTimofeev/OpenComputers/blob/master/Documentation/GUI.md А для создания вертикального меню из кнопок воспользуйся одним из примеров в доке: local GUI = require("GUI") ------------------------------------------------- local mainContainer = GUI.fullScreenContainer() mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D)) -- Создаем вертикально ориентированный список local verticalList = mainContainer:addChild(GUI.list(3, 2, 25, 30, 3, 0, 0xE1E1E1, 0x4B4B4B, 0xD2D2D2, 0x4B4B4B, 0x3366CC, 0xFFFFFF, false)) verticalList:addItem("Hello world") verticalList:addItem("This is test").onTouch = function() -- Сделать что-то при нажатии end verticalList:addItem("Beautiful") verticalList:addItem("Like a shit") ------------------------------------------------- mainContainer:drawOnScreen(true) mainContainer:startEventHandling()
-
Давно хотел, однако побаивался делать "слабую" линковку из-за возможного упарывания опеносовских либ. Потестирую денек-другой с различным софтом как для опеноси, так и для майноси, и если все будет в порядке - то без проблем добавлю эту фичу с возможностью отключения.
-
Переписан системный графический редактор. Каждый инструмент реализован в виде отдельного скрипта-модуля для удобства написания кастомных. Имеется возможность назначения инструменту горячей клавиши, краткого описания и создания меню с параметрами. Среди дефолтных инструментов стоит отдельно отметить редактор шрифта Брайля, заливку и выделение областей:
-
Да, безусловно. Надо было как-то схитрить и уместить эту фиговину в обещанные "10-20 строк", сэкономив одну на присваивание. Однако факта говнокодистости это не отменяет, нет-нет
-
Любую автоматизацию виджетов, потенциально ведущую к уменьшению производительности, я реализую в качестве опциональной и отключенной по умолчанию фичи. Надо - активируй по требованию, всего 12 буковок в аргументы написать, ерунда. А если оч оч лень писать или чем-то не устраивают стандартные виджеты - создай собственный, это буквально 10-20 строк кода: local function myTextBox(x, y, width, color, text) local lines = string.wrap({text}, width) local object = GUI.object(x, y, width, #lines) object.draw = function() for i = 1, #lines do buffer.text(objext.x, object.y + i - 1, color, lines[i]) end end return object end
-
Написал, что не подходит, а причину не указал. Почему не подходит-то? Лично я для тех же целей использую именно GUI.textBox с параметром autoWrap = true и autoHeight = true
-
В магазин приложений добавлена возможность отправки личных сообщений. Это позволит не только обмениваться взаимными оскорблениями, но и предоставлять информацию разработчиками об работоспособности их говнокода не отходя от кассы:
-
Не-а, обычный статичный IPшник под маскировкой анти-дудоса от Cloudflare. Сервачок в твоем случае можно открыть через DDNS, хотя геморроя будет чуть побольше
-
Собсна, предложение о поддержке подключения к реальному FTP-серверу на уровне ОС реализовано. В проводнике появилась опция ввода адреса/порта/пользователя/пароля, после чего вы сможете взаимодействовать с удаленной машиной так же, как и с любой файловой системой из мода. Поддержка внутриигровых модемов для обмена файлами по сети также осталась:
- 218 ответов
-
- 11
-
-
Все он правильно сделал, гипотетически четвертый вариант возможен:
-
@@eu_tomat, плюсую, хотелось бы глянуть и потестировать исходник без минификации. Еще интересует возможность практического применении подобной методики: безусловно, упор на экономию памяти - дело благородное, однако, к примеру, для отрисовки изображений и буферизации экрана идея не сгодится ввиду необходимости постоянной распаковки/упаковки чисел, что катастрофически снизит производительность. Это не претензия к либе, а вопрос о ее применении "не на бумажке"
-
Замена текста подойдет? Пример из php'шного мануала: local text = "<p>Параграф.</p><!-- Комментарий --> <a href=\"#fragment\">Еще текст</a>" print(text:gsub("<[^<>]+>", "")) > Параграф. Еще текст
-
Захотелось написать очередную прошивку для EEPROM с интересным функционалом. Чтобы запихать этого монстра (в масштабах прошивок, разумеется) в 4-килобайтный лимит, пришлось пройти семь кругов ада, сожрать пуд соли и пролить ведро крови. Из фич отмечу следующие: • Поддержка всех уровней видеокарт и мониторов • Отображение подробной информации об имеющихся дисках • Форматирование / переименование / выбор файловой системы в качестве загрузочного тома • Аналог Internet Recovery, позволяющий запустить скрипт по указанной URL в качестве нативного кода для EEPROM Исходник без минификации: https://github.com/IgorTimofeev/MineOS/blob/master/EFI/Full.lua Команды для прошивки: wget https://raw.githubusercontent.com/IgorTimofeev/MineOS/master/EFI/Minified.lua /EFI.lua -f flash /EFI.lua
