crococrystal

3d.lua

Jun 21st, 2024 (edited)
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.99 KB | None | 0 0
  1. local component = require("component")
  2. local fs = require("filesystem")
  3. local shell = require("shell")
  4. local term = require("term")
  5. local serialization = require("serialization")
  6.  
  7. local function setTextColor(color)
  8.     term.gpu().setForeground(color)
  9. end
  10.  
  11. local function resetTextColor()
  12.     term.gpu().setForeground(0xFFFFFF)
  13. end
  14.  
  15. local function clearScreen()
  16.     term.clear()
  17. end
  18.  
  19. local function listModels()
  20.     local models = {}
  21.     for file in fs.list("/home/shape3d/") do
  22.         if file:match("%.3d$") then
  23.             local filePath = "/home/shape3d/" .. file
  24.             local fileContent = io.open(filePath, "r")
  25.             if fileContent then
  26.                 local content = fileContent:read("*a")
  27.                 fileContent:close()
  28.                 local model = serialization.unserialize(content)
  29.                 if model and model.label then
  30.                     table.insert(models, {label = model.label, file = filePath})
  31.                 end
  32.             end
  33.         end
  34.     end
  35.     table.sort(models, function(a, b) return a.label < b.label end)
  36.     return models
  37. end
  38.  
  39. local function parseColorCodes(text)
  40.     local colorCodes = {
  41.         ["§0"] = 0x000000, ["§1"] = 0x0000AA, ["§2"] = 0x00AA00, ["§3"] = 0x00AAAA,
  42.         ["§4"] = 0xAA0000, ["§5"] = 0xAA00AA, ["§6"] = 0xFFAA00, ["§7"] = 0xAAAAAA,
  43.         ["§8"] = 0x555555, ["§9"] = 0x5555FF, ["§a"] = 0x55FF55, ["§b"] = 0x55FFFF,
  44.         ["§c"] = 0xFF5555, ["§d"] = 0xFF55FF, ["§e"] = 0xFFFF55, ["§f"] = 0xFFFFFF
  45.     }
  46.  
  47.     local textWithoutCodes = text:gsub("§.", "")
  48.     local coloredTextParts = {}
  49.     local lastColor = 0xFFFFFF
  50.  
  51.     for code, subText in text:gmatch("(§.)([^§]*)") do
  52.         if colorCodes[code] then
  53.             lastColor = colorCodes[code]
  54.         end
  55.         table.insert(coloredTextParts, {color = lastColor, text = subText})
  56.     end
  57.  
  58.     if #coloredTextParts == 0 then
  59.         table.insert(coloredTextParts, {color = lastColor, text = textWithoutCodes})
  60.     end
  61.  
  62.     return textWithoutCodes, coloredTextParts
  63. end
  64.  
  65. local function displayModelInfo(model, texture, colorMode, color, vertical, horizontal)
  66.     clearScreen()
  67.     local label = model.label or "Без имени"
  68.     local tooltip = model.tooltip or "Оригинальное"
  69.     local _, labelParts = parseColorCodes(label)
  70.     local tooltipLines = {}
  71.     for line in tooltip:gmatch("[^\n]+") do
  72.         table.insert(tooltipLines, line)
  73.     end
  74.  
  75.     setTextColor(0xFFFFFF)
  76.     io.write("Выбранная модель: \"")
  77.     for _, part in ipairs(labelParts) do
  78.         setTextColor(part.color)
  79.         io.write(part.text)
  80.     end
  81.     setTextColor(0xFFFFFF)
  82.     print("\"")
  83.     resetTextColor()
  84.     print()
  85.  
  86.     setTextColor(0xAAAAAA)  -- Серый цвет
  87.     print("- Описание:")
  88.     for _, line in ipairs(tooltipLines) do
  89.         local _, parts = parseColorCodes(line)
  90.         for _, part in ipairs(parts) do
  91.             setTextColor(part.color)
  92.             io.write(part.text)
  93.         end
  94.         print()  -- Перенос строки
  95.     end
  96.     print()
  97.     resetTextColor()
  98.  
  99.     print("Найденные текстуры: " .. (model.texture or "Оригинальная"))
  100.     print("Найденные цвета: " .. (model.color or "Оригинальный"))
  101.     print("Поворот по вертикали: " .. vertical)
  102.     print("Поворот по горизонтали: " .. horizontal)
  103.     print()
  104.  
  105.     setTextColor(0xAAAAAA)  -- Серый цвет
  106.     print("Нажмите Enter чтобы вернуться в главное меню")
  107.     resetTextColor()
  108. end
  109.  
  110. local function selectModel(models)
  111.     clearScreen()
  112.     setTextColor(0xFF00FF)  -- Ярко фиолетовый цвет
  113.     print("Доступные модели:")
  114.     resetTextColor()
  115.     print()
  116.     for i, model in ipairs(models) do
  117.         setTextColor(0xFFFFFF)  -- Белый цвет для номеров
  118.         io.write(i .. ". ")
  119.         resetTextColor()
  120.         local _, parts = parseColorCodes(model.label)
  121.         for _, part in ipairs(parts) do
  122.             setTextColor(part.color)
  123.             io.write(part.text)
  124.         end
  125.         setTextColor(0xAAAAAA)  -- Серый цвет для имени файла
  126.         print(" - " .. model.file:match("/home/(.+)$"))
  127.         resetTextColor()
  128.     end
  129.     print()
  130.     print()
  131.     setTextColor(0xAAAAAA)  -- Серый цвет
  132.     print("Введите Enter чтобы выйти из программы")
  133.     resetTextColor()
  134.     print()
  135.     setTextColor(0xFFFF00)  -- Желтый цвет
  136.     print("Выберите номер модели:")
  137.     resetTextColor()
  138.     local choice = tonumber(term.read())
  139.     if choice and choice >= 1 and choice <= #models then
  140.         return models[choice]
  141.     elseif choice == nil then
  142.         return "exit"
  143.     else
  144.         return nil
  145.     end
  146. end
  147.  
  148. local function readTexture(model)
  149.     setTextColor(0xFFFF00)
  150.     print("Найденные текстуры которые вы можете изменить:")
  151.     resetTextColor()
  152.     print()
  153.     local textures = model.textures or {}
  154.     for i, texture in ipairs(textures) do
  155.         print(i .. ". " .. texture)
  156.     end
  157.     print()
  158.     print("Введите номер текстуры для замены:")
  159.     local choice = tonumber(term.read())
  160.     if choice and choice >= 1 and choice <= #textures then
  161.         setTextColor(0xFFFF00)
  162.         print("Введите текстуру которая заменит \"" .. textures[choice] .. "\"")
  163.         resetTextColor()
  164.         local newTexture = term.read():gsub("\n", "")
  165.         if newTexture == "" then
  166.             return
  167.         else
  168.             model.textures[choice] = newTexture
  169.             setTextColor(0x00FF00)
  170.             print("Текстура \"" .. textures[choice] .. "\" была заменена на \"" .. newTexture .. "\"")
  171.             resetTextColor()
  172.         end
  173.     else
  174.         setTextColor(0xFF0000)
  175.         print("Неверный выбор")
  176.         resetTextColor()
  177.     end
  178. end
  179.  
  180. local function readColorMode()
  181.     setTextColor(0xFFFF00)
  182.     print("Режим выбора цвета:")
  183.     setTextColor(0xFFFFFF)
  184.     print("1. Сохранить оригинальные цвета из файла модели")
  185.     print("2. Очистить цвета модели")
  186.     print("3. Установить HEX цвет")
  187.     resetTextColor()
  188.     local choice = tonumber(term.read())
  189.     if choice and (choice == 1 or choice == 2 or choice == 3) then
  190.         return choice
  191.     else
  192.         print("Неверный выбор")
  193.         return nil
  194.     end
  195. end
  196.  
  197. local function readColor()
  198.     setTextColor(0xFFFF00)
  199.     print("Введите цвет текстуры:")
  200.     print()
  201.     setTextColor(0xAAAAAA)  -- Серый цвет
  202.     print("Введите номер цвета без #. Например \"E23737\"")
  203.     print("Нажмите Enter чтобы выйти без изменений")
  204.     resetTextColor()
  205.     local color = term.read():gsub("\n", "")
  206.     if color == "" then
  207.         return nil
  208.     else
  209.         return tonumber(color, 16)
  210.     end
  211. end
  212.  
  213. local function readRotation(prompt)
  214.     setTextColor(0xFFFF00)
  215.     print(prompt)
  216.     resetTextColor()
  217.     local rotation = tonumber(term.read())
  218.     if rotation == 0 or rotation == 90 or rotation == 180 or rotation == 270 or rotation == 360 then
  219.         return rotation
  220.     else
  221.         print("Неверный выбор")
  222.         return nil
  223.     end
  224. end
  225.  
  226. local function transformShape(shape, vertical, horizontal, texture, colorMode, color)
  227.     local x1, y1, z1, x2, y2, z2 = shape[1], shape[2], shape[3], shape[4], shape[5], shape[6]
  228.  
  229.     -- Vertical rotation
  230.     if vertical == 90 then
  231.         y1, z1 = z1, 16 - y1
  232.         y2, z2 = z2, 16 - y2
  233.     elseif vertical == 180 then
  234.         y1, z1 = 16 - y1, 16 - z1
  235.         y2, z2 = 16 - y2, 16 - z2
  236.     elseif vertical == 270 then
  237.         y1, z1 = 16 - z1, y1
  238.         y2, z2 = 16 - z2, y2
  239.     elseif vertical == 360 then
  240.         -- No change for 360 degrees as it is same as 0 degrees
  241.     end
  242.  
  243.     -- Horizontal rotation
  244.     if horizontal == 90 then
  245.         x1, z1 = z1, 16 - x1
  246.         x2, z2 = z2, 16 - x2
  247.     elseif horizontal == 180 then
  248.         x1, z1 = 16 - x1, 16 - z1
  249.         x2, z2 = 16 - x2, 16 - z2
  250.     elseif horizontal == 270 then
  251.         x1, z1 = 16 - z1, x1
  252.         x2, z2 = 16 - z2, x2
  253.     elseif horizontal == 360 then
  254.         -- No change for 360 degrees as it is same as 0 degrees
  255.     end
  256.  
  257.     if texture then
  258.         shape.texture = texture
  259.     end
  260.  
  261.     if colorMode == 2 then
  262.         shape.tint = nil
  263.     elseif colorMode == 3 and color then
  264.         shape.tint = color
  265.     end
  266.  
  267.     return {x1, y1, z1, x2, y2, z2, texture = shape.texture, tint = shape.tint, state = shape.state}
  268. end
  269.  
  270. local function modifyModel(model, texture, colorMode, color, vertical, horizontal)
  271.     for i, shape in ipairs(model.shapes) do
  272.         model.shapes[i] = transformShape(shape, vertical, horizontal, texture, colorMode, color)
  273.     end
  274.     return model
  275. end
  276.  
  277. local function changeLabel(model)
  278.     while true do
  279.         clearScreen()
  280.         setTextColor(0xFFFF00)
  281.         print("Введите название модели:")
  282.         resetTextColor()
  283.         print()
  284.         setTextColor(0xFFFFFF)
  285.         print("Максимум 30 символов с учетом цветовых кодов")
  286.         print("Используйте цветовые коды с помощью &")
  287.         resetTextColor()
  288.         print()
  289.         setTextColor(0xAAAAAA)
  290.         print("Нажмите Enter чтобы выйти без изменений")
  291.         resetTextColor()
  292.         print()
  293.  
  294.         local newLabel = term.read():gsub("\n", "")
  295.         if newLabel == "" then
  296.             return model.label
  297.         else
  298.             -- Подсчет количества символов без учета цветовых кодов
  299.             local textOnly = newLabel:gsub("&.", "")  -- Удаление цветовых кодов для проверки длины
  300.             if #textOnly > 30 then
  301.                 setTextColor(0xFF6363)  -- Красный цвет
  302.                 print("Название превышает количество символов, попробуйте снова")
  303.                 resetTextColor()
  304.                 os.sleep(2)  -- Задержка для отображения сообщения
  305.             else
  306.                 newLabel = newLabel:gsub("&", "§")
  307.                 model.label = newLabel
  308.                 setTextColor(0x66FF63)  -- Зеленый цвет
  309.                 print("Название установлено!")
  310.                 resetTextColor()
  311.                 os.sleep(2)  -- Задержка для отображения сообщения
  312.                 return model.label
  313.             end
  314.         end
  315.     end
  316. end
  317.  
  318. local function changeTooltip(model)
  319.     clearScreen()
  320.     setTextColor(0xFFFF00)
  321.     print("Введите описание модели:")
  322.     resetTextColor()
  323.     local newTooltip = term.read():gsub("\n", "")
  324.     if newTooltip == "" then
  325.         return model.tooltip
  326.     else
  327.         -- Заменяем & на § для цветовых кодов
  328.         newTooltip = newTooltip:gsub("&", "§")
  329.         -- Обрабатываем перенос строки с указанием цвета
  330.         newTooltip = newTooltip:gsub("#§", "\n§")
  331.         -- Обрабатываем просто перенос строки
  332.         newTooltip = newTooltip:gsub("#", "\n")
  333.         model.tooltip = newTooltip
  334.     end
  335.     return model.tooltip
  336. end
  337.  
  338. local function handleModelSave(model, modelPath)
  339.     clearScreen()
  340.     setTextColor(0xFFFF00)
  341.     print("Будет напечатана модель: \"" .. model.label .. "\"")
  342.     resetTextColor()
  343.     print()
  344.     print("Описание:")
  345.     print(model.tooltip or "Оригинальное")
  346.     print()
  347.     print("Текстура: " .. (model.texture or "Оригинальная"))
  348.     print("Цвет: " .. (model.color or "Оригинальный"))
  349.     print("Поворот по вертикали: 0")
  350.     print("Поворот по горизонтали: 0")
  351.     print()
  352.     print("Что делать с внесенными изменениями?")
  353.     print("1. Создать как новый файл модели")
  354.     print("2. Создать копию как copy-" .. fs.name(modelPath))
  355.     setTextColor(0xFFFF00)
  356.     print("3. Обновить оригинальный файл модели")
  357.     resetTextColor()
  358.     print("4. Отменить печать")
  359.     local choice = tonumber(term.read())
  360.     if choice == 1 then
  361.         setTextColor(0xFFFF00)
  362.         print("Введите только название новой модели без указания формата")
  363.         resetTextColor()
  364.         local newName = term.read():gsub("\n", "")
  365.         local newModelPath = "/home/shape3d/" .. newName .. ".3d"
  366.         local file = io.open(newModelPath, "w")
  367.         if not file then
  368.             print("Не удалось создать новый файл модели")
  369.             return
  370.         end
  371.         file:write(serialization.serialize(model))
  372.         file:close()
  373.         setTextColor(0x00FF00)
  374.         print("Модель была сохранена как " .. newModelPath)
  375.         resetTextColor()
  376.     elseif choice == 2 then
  377.         local newModelPath = "/home/shape3d/copy-" .. fs.name(modelPath)
  378.         local file = io.open(newModelPath, "w")
  379.         if not file then
  380.             print("Не удалось создать копию модели")
  381.             return
  382.         end
  383.         file:write(serialization.serialize(model))
  384.         file:close()
  385.     elseif choice == 3 then
  386.         local file = io.open(modelPath, "w")
  387.         if not file then
  388.             print("Не удалось обновить файл модели")
  389.             return
  390.         end
  391.         file:write(serialization.serialize(model))
  392.         file:close()
  393.     elseif choice == 4 then
  394.         return
  395.     else
  396.         print("Неверный выбор")
  397.         return
  398.     end
  399. end
  400.  
  401. local function displayMenu(model, texture, colorMode, color, vertical, horizontal)
  402.     displayModelInfo(model, texture, colorMode, color, vertical, horizontal)
  403.     print()
  404.     setTextColor(0xAAAAAA)  -- Серый цвет
  405.     print("0. Выбрать другую модель")
  406.     resetTextColor()
  407.     print("1. Найти и изменить текстуры")
  408.     print("2. Найти и изменить цвета")
  409.     print("3. Изменить название модели")
  410.     print("4. Изменить описание модели")
  411.     print("5. Повернуть по вертикали")
  412.     print("6. Повернуть по горизонтали")
  413.     setTextColor(0xFFFF00)  -- Желтый цвет
  414.     print("7. Начать печать модели")
  415.     resetTextColor()
  416.     setTextColor(0xAAAAAA)  -- Серый цвет
  417.     print("Введите Enter чтобы выйти из программы")
  418.     resetTextColor()
  419. end
  420.  
  421. local function main()
  422.     local models = listModels()
  423.     if #models == 0 then
  424.         print("Нет доступных моделей в формате .3d")
  425.         return
  426.     end
  427.  
  428.     local modelChoice = selectModel(models)
  429.     if modelChoice == "exit" then
  430.         return
  431.     elseif not modelChoice then
  432.         return
  433.     end
  434.  
  435.     local modelName = modelChoice.label
  436.     local modelPath = modelChoice.file
  437.     local file = io.open(modelPath, "r")
  438.     if not file then
  439.         print("Не удалось открыть файл модели")
  440.         return
  441.     end
  442.     local modelData = file:read("*a")
  443.     file:close()
  444.  
  445.     local model = serialization.unserialize(modelData)
  446.     if model == nil then
  447.         print("Ошибка при загрузке модели")
  448.         return
  449.     end
  450.  
  451.     local texture = nil
  452.     local colorMode = 1
  453.     local color = nil
  454.     local vertical = 0
  455.     local horizontal = 0
  456.  
  457.     while true do
  458.         displayMenu(model, texture, colorMode, color, vertical, horizontal)
  459.         local choice = tonumber(term.read())
  460.         if choice == nil then
  461.             return
  462.         elseif choice == 0 then
  463.             modelChoice = selectModel(models)
  464.             if modelChoice == "exit" then
  465.                 return
  466.             elseif not modelChoice then
  467.                 return
  468.             end
  469.             modelName = modelChoice.label
  470.             modelPath = modelChoice.file
  471.             file = io.open(modelPath, "r")
  472.             if not file then
  473.                 print("Не удалось открыть файл модели")
  474.                 return
  475.             end
  476.             modelData = file:read("*a")
  477.             file:close()
  478.             model = serialization.unserialize(modelData)
  479.             if model == nil then
  480.                 print("Ошибка при загрузке модели")
  481.                 return
  482.             end
  483.             texture = nil
  484.             colorMode = 1
  485.             color = nil
  486.             vertical = 0
  487.             horizontal = 0
  488.         elseif choice == 1 then
  489.             texture = readTexture()
  490.         elseif choice == 2 then
  491.             colorMode = readColorMode()
  492.             if colorMode == 3 then
  493.                 color = readColor()
  494.             end
  495.         elseif choice == 3 then
  496.             model.label = changeLabel(model)
  497.         elseif choice == 4 then
  498.             model.tooltip = changeTooltip(model)
  499.         elseif choice == 5 then
  500.             vertical = readRotation("Введите градус поворота по Вертикали (0, 90, 180, 270, 360):")
  501.             if vertical == nil then
  502.                 vertical = 0
  503.             end
  504.         elseif choice == 6 then
  505.             horizontal = readRotation("Введите градус поворота по Горизонтали (0, 90, 180, 270, 360):")
  506.             if horizontal == nil then
  507.                 horizontal = 0
  508.             end
  509.         elseif choice == 7 then
  510.             local newModel = modifyModel(model, texture, colorMode, color, vertical, horizontal)
  511.             fs.makeDirectory("/home/modified-3d")
  512.             local newModelPath = "/home/modified-3d/modified_" .. fs.name(modelPath)
  513.             file = io.open(newModelPath, "w")
  514.             if not file then
  515.                 print("Не удалось создать новый файл модели")
  516.                 return
  517.             end
  518.             file:write(serialization.serialize(newModel))
  519.             file:close()
  520.             setTextColor(0x00FF00)
  521.             print("Модифицированная модель сохранена как: " .. newModelPath)
  522.             resetTextColor()
  523.             handleModelSave(newModel, modelPath)
  524.             print("Запуск печати...")
  525.             os.execute("/home/3d " .. newModelPath)
  526.             break
  527.         else
  528.             print("Неверный выбор")
  529.         end
  530.     end
  531. end
  532.  
  533. main()
  534.  
Add Comment
Please, Sign In to add comment