Перейти к содержанию

Doob

Гуру
  • Публикаций

    776
  • Зарегистрирован

  • Посещение

  • Победитель дней

    78

Doob стал победителем дня 8 апреля

Doob имел наиболее популярный контент!

Репутация

1 510 Очень хороший

8 Подписчиков

Информация

  • Пол
    Не определился

Посетители профиля

1 460 просмотров профиля
  1. Да, с 1.7.3 можно ЧЛ засунуть в микроконтроллер и в конфиге можно добавить ид измерения в черный или белый список (dimBlacklist, dimWhitelist). Загрузка чанка не зависит от онлайна игрока.
  2. Было бы здорово в некоторых бункерах запилить квесты/ловушки с опенкомпами, но для этого надо будет игрокам возле бункера включать режим приключения или делать спецприваты, иначе они тупо все перелопатят в поисках квестовых наград. И кстати, лут только ванильный или можно еще опенкомповский? Если да, то какой версии? Вообще не знал про этот мод, с ним можно наделать таких вундервафель в генерации, что MC 1.14 со своими структурами выглядит совсем невзрачно.
  3. По всяким голосовалкам вряд-ли кто-то кликает. Знаю пару лончеров, где в основном окне висят новости сервера, информация об ивентах, ссылки на последние активные темы форума. Очень удобно - запускаешь игру и сразу в курсе событий. Но этим контентом опять-таки кто-то должен заниматься, да и сервер у нас не на тыщу ролеплееров, можно и на форум сходить-посмотреть.
  4. Ну я и говорю, скайблок, там тоже вся игра сводится к прокликиванию того, что сказала книжка. Надо больше хаоса. И поделить всех мух, котлет и изюм, чтобы каждый мог найти что-то для себя и отыгрывать то, что нравится. То есть без всеобщей принудиловки к надраиванию единорогов или орбитальной бомбежке.
  5. Идея хард-мира с эвилом была норм, а это какой-то скайблок без скайблока.
  6. Может кто-то придумает смысл игры? А то голая болванка болтается. В Duskers, например, интересно подается взаимодействие с миром. Сделать что-то похожее и какую-от соревновательную механику сделать, чтобы игроки могли программировать дронов на лету или управлять вручную.
  7. Для майна тоже есть шейдер, осталось придумать мод, который будет сворачивать пространство.
  8. Это просто набросок, готовый результат буду делать в 3D и крутить постэффекты рендера, чтобы получить приятственную гамму. Рисовал в Krita.
  9. Для шапки был набросок. Там за компом стив сидел, сзади эндермен и зомби на слизне заглядывали через плечо, а рядом скелет сидел перед потухшим экраном. Как обычно где-то потерялся. Вот с другого ракурса сляпал.
  10. Ну да, в основном на главной новости, сверху какое-то слайдшоу со скринами и кнопки переключения разделов. Большинство подкроватных серверов вообще на одном шаблоне с разными вариациями крутятся. Сейчас у нас не хватает информации, о чем этот сайт. Для постороннего человека вряд-ли сразу дойдет, что тут в майн играют, а про наличие каких-то компов только название туманно намекает.
  11. На старой версии светлая тема была норм. Кнопки в шапке норм, но немного сливаются с фоном, можно было бы их оживить цветом. Или вообще стиль переделать. Блок чата вообще расползается, я долго не мог понять, как в него писать. Обе темы вырвиглазные, но светлая еще и кислотная. Все блоки слишком массивно смотрятся, на oc.cil.li визуально тоже самое, но выглядит аккуратней. Надо глядеть на другие игровые проекты, сделать такой дизайн, какой ожидают увидеть потенциальные игроки. А то сейчас человек попадает сюда, а тут какой-то потусторонний даркнет. Могу нарисовать картинку на шапку, вектор или пихель-стайл, но надо определится с палитрой, чтобы потом не переделывать. Или текстуры для контента, чтобы не платить $30 за новую тему, а проапгрейдить текущую.
  12. Чтобы отобразить иконки файлов и папок, а затем использовать их как кнопки, нужно разработать удобную в управлении структуру данных. При помощи filesystem API можно получить контент текущей директории, что с этим делать? Для начала разметим экран. В верхней части, на всю ширину экрана будет что-то вроде статус-бара высотой в 4 строки, там будет состояние памяти, батареи, может быть адресная и поисковая строка. Иконки 10x5 символов, с именем снизу, будут располагаться по сетке, через 1 символ. Загруженные иконки уже хранятся в таблице, осталось назначить их файлам и нарисовать. При загрузке программы надобно рассчитать, сколько иконок войдет по горизонтали и вертикали, создать таблицу для хранения сетки. Иконка начинает рисоваться от левого верхнего угла, поэтому в таблицу будем заносить именно эти начальные координаты. Обзовем таблицу, например, grid. В этой же таблице сделаем буфер для хранения имен иконок, чтобы при переходе из папки в папку не рисовать иконки, которые уже есть. Кстати, все содержимое может не влезть на экран, поэтому будем его разбивать на страницы. Для этого создадим таблицу pages и при сканировании директории будем добавлять в нее таблицы с содержимым страницы, если количество файлов больше размерности #grid. Сами страницы будут с такими же индексами, что и grid, по индексам будут хранится: имя файла или папки, назначенная иконка и флаг, директория это или нет. Приступим к описанию функции обновления информации о содержимом. Для начала обнулим страницы. Получим текущую директорию при помощи filesystem.realPath(os.getenv('PWD')) или shell.getWorkingDirectory(). Для того, чтобы в результате получить привычный вид, надо будет отсортировать файлы отдельно от папок по алфавиту. Для этого создадим две временные таблицы, просканируем директорию через filesystem.list(), если имя оканчивается символом '/', то кидаем его к папкам, иначе к файлам, затем сортируем обе таблицы обычным table.sort(). Добавляем имена папок к именам файлов в том же порядке, но в начало таблицы и начинаем обработку результата. Обходим таблицу с именами файлов, если это папка, то назначаем иконку 'folder', если это ссылка, то 'link', во всех остальных случаях получаем расширение файла паттерном ([^%.]+)$ и пробуем назначить иконку с таким же названием. Как-то лень было изучить работу lua-patterns, по идее он должен захватывать одно и больше вхождений, но захватывает от нуля, поэтому файлы с именем расширения, получают иконки. Если расширения нет, назначается иконка 'unknown'. Далее, в таблицу pages записываем имя файлв, имя иконки и флаг. Потом обновляем индекс, по условию индекс == размерность сетки сбрасываем индекс и обновляем счетчик страниц. local W, H = gpu.getResolution() -- получить разрешение экрана local grid, pages = {buffer = {}}, {{}} -- создать таблицу для сетки и страниц local wm = math.floor(W/11) -- вычислить, сколько иконок войдет по горизонтали local index = 1 -- создать счетчик for Y = 1, math.floor((H*2-5)/14) do -- пройти цикл по вертикали for X = 1, wm do -- пройти цикл по горизонтали grid[index] = {x = X*11-9+(W-wm*11-1)/2, y = Y*7-2, z = Y*7+3} -- рассчитать и задать координаты для текущего индекса index = index + 1 end end local function update() pages = {{}} -- обнулить страницы local index, page, pwd = 1, 1, os.getenv('PWD') -- создать счетчики и получить текущую директорию local names, folders = {}, {} -- создать таблицы для имен if fs.realPath(pwd) ~= '' then -- если текущая директория не корневая folders[1] = '..' -- добавить папку для перехода на верхний уровень end for name in fs.list(fs.realPath(pwd)) do -- получить имена в текущей папке if name:sub(-1) == '/' then -- если в конце слэш table.insert(folders, name) -- добавить к папкам else -- иначе table.insert(names, name) -- к файлам end end table.sort(folders) -- отсортировать имена папок table.sort(names) -- отсортировать имена файлов for i = #folders, 1, -1 do -- в цикле объеденить имена в одну таблицу table.insert(names, 1, folders[i]) end folders = nil -- удалить таблицу для папок for n, name in pairs(names) do -- пройти по всем именам local icon, isDir -- создать переменные для имени иконки и флага if fs.isDirectory(pwd..'/'..name) then -- назначить иконку для папки icon, isDir = 'folder', true elseif fs.isLink(pwd..'/'..name) then -- назначить для ссылки icon = 'link' elseif icons[name:match('([^%.]+)$')] then -- если есть иконка для этого расширения icon = name:match('([^%.]+)$') -- назначить по имени else icon = 'unknown' -- для всех остальных назначить стандартную иконку end pages[page][index] = {name = name:gsub('/', ''), icon = icon, dir = isDir} -- записать имя, имя иконки и флаг в текущую страницу if index == #grid then -- если текущая страница заполнена index, page = 1, page + 1 -- обновить индекс и номер страницы pages[page] = {} -- создать страницу else index = index + 1 -- обновить индекс end end end Теперь надо отрисовать иконки по сетке. В цикле пройдем по индексам сетки, из координат получим индекс для буфера, для быстрого обращения. Если на текущей странице и с текущим индексом что-то есть, а в буфере по этим координатам другая иконка. Берем имя иконки и координаты сетки, вызываем функцию draw_icon(), записываем в буфер имя новой иконки. Сбрасываем цвета, стираем зону, где будет имя файла. Пишем имя файла, со смещением, чтобы оно было примерно по центру иконки. Не забывая обрезать имя до 10 символов. Если по текущему индексу на странице ничего нет, но в буфере осталось имя иконки. Стираем его из буфера. Устанавливаем фоновый цвет и заливаем иконку вместе с именем по текущему индексу пустотой. local function draw(page) page = page or 1 -- если страница не указана, назначить первую for index = 1, #grid do -- пройти по индексам сетки local hash = grid[index].x*W+grid[index].y -- получить хеш if pages[page][index] then -- если на странице по этому индексу есть запись if pages[page][index].icon ~= grid.buffer[hash] then -- если новая иконка отличается draw_icon(pages[page][index].icon, grid[index].x, grid[index].y) -- нарисовать иконку grid.buffer[hash] = pages[page][index].icon -- обновить буфер end local name = pages[page][index].name gpu.setBackground(0) -- задать фоновый цвет local color = 0xffffff -- задать цвет текста if pages[page][index].dir then -- если это папка color = 0xffff00 -- задать другой end gpu.setForeground(color) -- установить цвет gpu.fill(grid[index].x, grid[index].z, 10, 1, ' ') -- очистить место gpu.set(grid[index].x+5-#name:sub(1, 10)/2, grid[index].z, name:sub(1, 10)) -- написать имя else -- если страница кончилась if grid.buffer[hash] then -- если в буфере что-то есть grid.buffer[hash] = nil -- обновить буфер gpu.setBackground(0) -- задать фоновый цвет gpu.fill(grid[index].x, grid[index].y, 10, 6, ' ') -- очистить место end end end end Теперь можно добавить слушателей из части #0, очистить экран, вызвать update() и draw() По событию 'click' запускать следующую конструкцию: for index = 1, #grid do if grid[index].x <= e[3] and grid[index].x+10 >= e[3] and grid[index].y <= e[4] and grid[index].y+5 >= e[4] then if pages[1][index] then if pages[1][index].dir then shell.setWorkingDirectory(shell.getWorkingDirectory()..'/'..pages[1][index].name) update() draw() break end end end end Теперь можно ползать по диску.
  13. Doob

    Файловый менеджер. Часть #1 [иконки]

    Чтобы было куда кликать, надо на экране разметить места для иконок, еще и иконки нарисовать. Для иконок возьмем формат PPM, а конкретно, цветную бинарную версию P6. Формат ультра-примитивный, иконки можно будет без лишних заморочек рисовать в любом нормальном растровом редакторе, в опенкомпах, а при наличии нужного скрипта - прямо в консоли. Но в этом формате будем хранить иконки на диске. Внутри программы они будут преобразовываться в таблицу, хранящую цвет каждого пикселя. Например, создадим иконку, которая будет рисоваться для всех типов файлов по умолчанию. (Будет отображаться, если подходящая иконка не загружена) local icons = {} -- создать массив с иконками local icons.unknown = {x = 10} -- создать таблицу для иконки, указать ширину в пикселях for i = 1, 100 do -- цикл заполнения таблицы 10x10 if i%3 == 0 then -- если номер пикселя делится на 3 icons.unknown[i] = 3394611 -- сделать пиксель зеленым else -- иначе icons.unknown[i] = 3355443 -- сделать серым end end С внутренним представлением определились, теперь напишем функцию отрисовки. Создадим счетчики для индексов, горизонтальной и вертикальной координаты. Запустим цикл, с условием: пока индекс меньше или равен (количество пикселей - ширина изображения). Установим для символа цвет текущего пикселя, а для фона получим пиксель через текущий индекс + ширина изображения. И выведем полученные пиксели одним символом u+2580. Если счетчик по горизонтали досчитал до ширины изображения - сбросить в начало, к счетчику по вертикали добавить 1, а к индексу прибавить ширину. Получим пропуск строки, т. к. она уже была отрисована в текущей итерации. local function draw_icon(name, X, Y) -- получить название и координаты if not icons[name] then return false end -- прервать, если нет такой иконки local x, y, index = 1, 1, 1 -- создать счетчики while index <= #icons[name]-icons[name].x do -- пройти по индексам gpu.setForeground(icons[name][index]) -- установить цвет верхнего пикселя gpu.setBackground(icons[name][index+icons[name].x]) -- цвет нижнего gpu.set(x+X-1, y+Y-1, quad) -- вывести на экран if x == icons[name].x then -- если достигнута ширина изображения x, y, index = 1, y + 1, index + icons[name].x+1 -- обновить все счетчики else -- простая итерация x, index = x + 1, index + 1 -- обновить счетчик горизонтали и индекса end end end Одна иконка уже сгенерирована, чтобы вывести ее в углу экрана, вызовем ее по имени - draw_icon('unknown', 1, 1) В итоге, на экране получим такое изображение: Чтобы загрузить иконки и конвертировать в удобный вид, создадим такую функцию: Перебрать все файлы в папке, получив их список через filesystem API. Прочитать файл построчно в таблицу, попутно удалив строки с комментариями. Если заголовок файла равен , получить ширину картинки, информацию о пикселях объединить в одну строку. В цикле пройти по пикселям, конвертируя бинарное значение пикселя в число. Тут надо помнить, что значение одного пикселя хранится в трех символах (по одному на канал), поэтому цикл будет скакать через 3. Первый символ конвертируем в число, умножаем на 65536, второй на 256 и складываем. Полученное число добавляем в массив пикселей текущей иконки. Получаем примерно такую реализацию: local function load_icons(path) -- получить путь к папке с иконками local multiplier, path = {65536, 256, 1}, path or '' -- создать таблицу множителей for name in fs.list(path) do -- получить имя файла в папке local file = io.open(path..name, 'r') -- открыть файл if not file then break end -- если файла нет, прервать цикл name = name:gsub('%..+', '') -- обрезать название файла до первой точки local raw_img = {} -- создать массив для сырых данных for line in file:lines() do -- в цикле пройти по строкам if line and line:sub(1,1) ~= '#' then -- если строка не закоментированна table.insert(raw_img, line) -- добавить в таблицу end end file:close() -- закрыть файл if raw_img[1] == 'P6' then -- если заголовок совпадает local _ = raw_img[2]:find(' ') -- проверить наличие пробела на второй строке if _ then -- если размеры на одной строке _, raw_img[2] = raw_img[2]:sub(_+1), raw_img[2]:sub(1,_-1) -- разделить table.insert(raw_img, 3, _) -- перенести высоту на другую строку end raw_img[2] = tonumber(raw_img[2]) -- преобразовать ширину изображения в число icons[name] = {x = raw_img[2]} -- создать пустую таблицу для пикселей local current = '' -- создать переменную с сырой информацией о пикселях for i = 5, #raw_img do -- пройти до конца файла current = current..raw_img[i]..'\n' -- объединить данные в одну строку end local color, n for i = 1, #current-1, 3 do -- пройти по каждому третьему символу, исключая последний перевод строки n, color = 1, 0 -- сбросить счетчик для таблицы множителей и цвет for j = i, i+2 do -- перебрать три символа color = color+current:sub(j,j):byte()*multiplier[n] -- преобразовать символ в число и добавить к значению цвета n = n + 1 -- обновить счетчик end table.insert(icons[name], color) -- добавить цвет пикселя к остальным end end end end Реализация очень примитивная, но главное, что иконки будут загружаться. Можно было бы сотворить свой формат, который быстрей распаковывается и занимает меньше места, но плодить сущностей очень вредно. Для проверки, осталось нарисовать иконки, сложить их в папку /home/icons/, например. И запустить весь код: local fs = require('filesystem') local gpu = require('component').gpu local quad = require('unicode').char(0x2580) local icons = {unknown = {x = 10}} for i = 1, 100 do if i%3 == 0 then icons.unknown[i] = 3394611 else icons.unknown[i] = 3355443 end end local function load_icons(path) local multiplier, path = {65536, 256, 1}, path or '' for name in fs.list(path) do local file = io.open(path..name, 'r') if not file then break end name = name:gsub('%..+', '') local raw_img = {} for line in file:lines() do if line and line:sub(1,1) ~= '#' then table.insert(raw_img, line) end end file:close() if raw_img[1] == 'P6' then local _ = raw_img[2]:find(' ') if _ then _, raw_img[2] = raw_img[2]:sub(_+1), raw_img[2]:sub(1,_-1) table.insert(raw_img, 3, _) end raw_img[2] = tonumber(raw_img[2]) icons[name] = {x = raw_img[2]} local current = '' for i = 5, #raw_img do current = current..raw_img[i]..'\n' end local n, color for i = 1, #current-1, 3 do n, color = 1, 0 for j = i, i+2 do color = color+current:sub(j,j):byte()*multiplier[n] n = n+1 end table.insert(icons[name], color) end end end end local function draw_icon(name, X, Y) if not icons[name] then return false end local x, y, index = 1, 1, 1 while index <= #icons[name]-icons[name].x do gpu.setForeground(icons[name][index]) gpu.setBackground(icons[name][index+icons[name].x]) gpu.set(x+X-1, y+Y-1, quad) if x == icons[name].x then x, y, index = 1, y + 1, index + icons[name].x+1 else x, index = x + 1, index + 1 end end end load_icons('/home/icons/') local n = 1 for name in pairs(icons) do draw_icon(name, (n*11)-10, 1) n = n + 1 end Получаем:
  14. Опечатка тут: gpu.setForeground(cf) аргумент приходит cF Вообще, при ошибке выводится название проблемной функции, а на скрине только аргумент. Но это тоже может помочь - рассмотреть или переписать строку, указанную в ошибке.
×
×
  • Создать...