Files
2025-03-31 13:19:47 +02:00

310 lines
13 KiB
Lua

if SERVER then return end
local resolution = blue_prints.getScreenResolution()
local run_once_at_start = false
local folder_states = {} -- Track collapsed state of folders
local button_height = 45
-- Function to move blueprints from a folder to root
local function moveFilesToRoot(folderPath)
if folderPath == "[Root Directory]" then return true end
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
local rootPath = blue_prints.normalizePath(blue_prints.save_path)
local files = File.GetFiles(fullFolderPath)
local success = true
if files then
for _, filepath in ipairs(files) do
if string.match(filepath, "%.txt$") then
-- Read file content
local content = blue_prints.readFileContents(filepath)
if content then
-- Get just the filename
local filename = filepath:match("([^/\\]+)$")
-- Create new path in root
local newPath = blue_prints.normalizePath(rootPath .. "/" .. filename)
-- Write to new location
if not blue_prints.writeFile(newPath, content) then
success = false
end
end
end
end
end
return success
end
-- Function to delete a folder and its contents
local function deleteFolder(folderPath)
if folderPath == "[Root Directory]" then return false end
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
-- Move all files to root first
if not moveFilesToRoot(folderPath) then
return false
end
-- Try to delete the folder
local success = pcall(function()
File.DeleteDirectory(fullFolderPath)
end)
-- If first attempt fails, try alternate path
if not success then
local altPath = fullFolderPath:gsub("LocalMods/", "local_mods/")
success = pcall(function()
File.DeleteDirectory(altPath)
end)
end
return success
end
local function count_blueprints_in_folder(folderPath)
local files = File.GetFiles(folderPath)
local count = 0
if files then
for _, filepath in ipairs(files) do
if string.match(filepath, "%.txt$") then
count = count + 1
end
end
end
return count
end
local function formatFolderHeaderText(folderName, isExpanded, blueprintCount)
return string.format("%s %s (%d blueprints)",
isExpanded and "" or "",
folderName,
blueprintCount)
end
local function generate_load_gui()
blue_prints.current_gui_page = GUI.Frame(GUI.RectTransform(Vector2(1, 1), blue_prints.gui_button_frame.RectTransform, GUI.Anchor.Center),
nil)
blue_prints.current_gui_page.CanBeFocused = false
blue_prints.current_gui_page.Visible = false
-- Background close button
local closeButton = GUI.Button(
GUI.RectTransform(Vector2(1, 1), blue_prints.current_gui_page.RectTransform, GUI.Anchor.Center), "",
GUI.Alignment.Center, nil)
closeButton.OnClicked = function()
blue_prints.current_gui_page.Visible = not blue_prints.current_gui_page.Visible
end
local menuContent = GUI.Frame(GUI.RectTransform(Vector2(0.4, 0.6), blue_prints.current_gui_page.RectTransform,
GUI.Anchor.Center))
local mainList = GUI.ListBox(GUI.RectTransform(Vector2(1, 1), menuContent.RectTransform, GUI.Anchor.BottomCenter))
-- Title
local title_text = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.08), mainList.Content.RectTransform),
"LOAD BLUEPRINT", nil, nil, GUI.Alignment.Center)
title_text.TextScale = 1.5
title_text.TextColor = Color(200, 200, 200)
-- Instructions
local instruction_text = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.25), mainList.Content.RectTransform),
'Click a button to load. Hover over the button to see its description. Click folder headers to expand/collapse.\n\n' ..
'If the base component is not available, FPGAs will be used instead. These components must be in your main inventory, not a toolbelt/backpack etc.\n\n' ..
'Click anywhere outside this box to cancel.',
nil, nil, GUI.Alignment.TopLeft)
instruction_text.Wrap = true
instruction_text.TextColor = Color(200, 200, 200)
instruction_text.Padding = Vector4(10, 5, 10, 5)
local function createBlueprintButton(filename, filepath, description, componentCount, contentList)
local buttonContainer = GUI.Frame(GUI.RectTransform(Vector2(1, 0.10), contentList.Content.RectTransform,
GUI.Anchor.TopCenter))
buttonContainer.RectTransform.MinSize = Point(0, button_height)
buttonContainer.RectTransform.MaxSize = Point(9999, button_height)
local button_label = filename .. " - " .. tostring(componentCount) .. " FPGAs"
local leftButton = GUI.Button(
GUI.RectTransform(Vector2(0.90, 1), buttonContainer.RectTransform, GUI.Anchor.CenterLeft),
button_label, GUI.Alignment.CenterLeft, "GUIButtonSmall")
leftButton.TextBlock.Padding = Vector4(80, 0, 0, 0)
if description then
description = description:gsub("
", "\n"):gsub("
", "\n")
leftButton.ToolTip = description
else
leftButton.ToolTip = "No description available"
end
leftButton.OnClicked = function()
blue_prints.construct_blueprint(filepath)
blue_prints.current_gui_page.Visible = false
end
local rightButton = GUI.Button(
GUI.RectTransform(Vector2(0.10, 1), buttonContainer.RectTransform, GUI.Anchor.CenterRight),
"Delete", GUI.Alignment.Center, "GUIButtonSmall")
rightButton.ToolTip = "Delete " .. filename
rightButton.Color = Color(255, 80, 80)
rightButton.HoverColor = Color(255, 120, 120)
rightButton.OnClicked = function()
local message_box = GUI.MessageBox('Delete Blueprint?',
'Are you sure you want to delete "' .. filename .. '"?',
{ 'Cancel', 'Delete' })
local cancel_button = nil
local delete_button = nil
if message_box.Buttons[0] == nil then
cancel_button = message_box.Buttons[1]
delete_button = message_box.Buttons[2]
else
cancel_button = message_box.Buttons[0]
delete_button = message_box.Buttons[1]
end
delete_button.Color = Color(255, 80, 80)
delete_button.HoverColor = Color(255, 120, 120)
cancel_button.OnClicked = function() message_box.Close() end
delete_button.OnClicked = function()
blue_prints.delete_blueprint(filepath)
blue_prints.current_gui_page.Visible = false
GUI.AddMessage('Blueprint Deleted', Color.White)
message_box.Close()
end
end
end
-- Process folders
local folders = blue_prints.getFolderList()
for _, folderName in ipairs(folders) do
local folderPath = folderName == "[Root Directory]" and "" or folderName
local fullFolderPath = blue_prints.normalizePath(blue_prints.save_path .. "/" .. folderPath)
local blueprintCount = count_blueprints_in_folder(fullFolderPath)
folder_states[folderName] = folder_states[folderName] or false
-- Create folder container
local folderContainer = GUI.Frame(GUI.RectTransform(Vector2(1, 0.10), mainList.Content.RectTransform,
GUI.Anchor.TopCenter))
folderContainer.RectTransform.MinSize = Point(0, button_height)
folderContainer.RectTransform.MaxSize = Point(9999, button_height)
-- Create folder button with 90% width
local headerButton = GUI.Button(
GUI.RectTransform(Vector2(0.90, 1), folderContainer.RectTransform, GUI.Anchor.CenterLeft),
formatFolderHeaderText(folderName, folder_states[folderName], blueprintCount),
GUI.Alignment.CenterLeft, "GUIButtonSmall")
headerButton.TextColor = Color(150, 150, 255)
headerButton.HoverColor = Color(180, 180, 255, 0.5)
headerButton.ForceUpperCase = 1
headerButton.TextBlock.Padding = Vector4(0, 0, 0, 0)
-- Add delete button for folder (except root)
if folderName ~= "[Root Directory]" then
local deleteButton = GUI.Button(
GUI.RectTransform(Vector2(0.10, 1), folderContainer.RectTransform, GUI.Anchor.CenterRight),
"Delete", GUI.Alignment.Center, "GUIButtonSmall")
deleteButton.ToolTip = "Delete folder and move contents to root"
deleteButton.Color = Color(255, 80, 80)
deleteButton.HoverColor = Color(255, 120, 120)
deleteButton.OnClicked = function()
local message_box = GUI.MessageBox('Delete Folder?',
'Are you sure you want to delete "' ..
folderName .. '"?\nAll blueprints will be moved to the root folder.',
{ 'Cancel', 'Delete' })
local cancel_button = nil
local delete_button = nil
if message_box.Buttons[0] == nil then
cancel_button = message_box.Buttons[1]
delete_button = message_box.Buttons[2]
else
cancel_button = message_box.Buttons[0]
delete_button = message_box.Buttons[1]
end
delete_button.Color = Color(255, 80, 80)
delete_button.HoverColor = Color(255, 120, 120)
cancel_button.OnClicked = function() message_box.Close() end
delete_button.OnClicked = function()
if deleteFolder(folderName) then
blue_prints.current_gui_page.Visible = false
GUI.AddMessage('Folder Deleted', Color.White)
message_box.Close()
-- Regenerate GUI to show updated folder structure
Timer.Wait(function()
blue_prints.current_gui_page = generate_load_gui()
blue_prints.current_gui_page.Visible = true
end, 100)
else
GUI.AddMessage('Failed to delete folder', Color(255, 0, 0))
message_box.Close()
end
end
end
end
local files = File.GetFiles(fullFolderPath)
local size_of_listbox = #files * button_height + 20
local contentList = GUI.ListBox(GUI.RectTransform(Vector2(1, 0.1), mainList.Content.RectTransform))
contentList.RectTransform.MinSize = Point(0, size_of_listbox)
contentList.RectTransform.MaxSize = Point(999999, size_of_listbox)
contentList.Visible = folder_states[folderName]
-- Process files
if files then
for _, filepath in ipairs(files) do
if string.match(filepath, "%.txt$") then
local filename = filepath:match("([^/\\]+)%.txt$")
local xmlContent = blue_prints.readFileContents(filepath)
local description = blue_prints.get_description_from_xml(xmlContent)
local componentCount = blue_prints.get_component_count_from_xml(xmlContent)
createBlueprintButton(filename, folderPath .. "/" .. filename, description, componentCount,
contentList)
end
end
end
headerButton.OnClicked = function()
folder_states[folderName] = not folder_states[folderName]
contentList.Visible = folder_states[folderName]
headerButton.Text = formatFolderHeaderText(folderName, folder_states[folderName], blueprintCount)
end
end
return blue_prints.current_gui_page
end
local function check_and_rebuild_frame()
local new_resolution = blue_prints.getScreenResolution()
if new_resolution ~= resolution or run_once_at_start == false then
local spacer = GUI.TextBlock(GUI.RectTransform(Vector2(1, 0.04), blue_prints.gui_button_frame_list.Content.RectTransform), "", nil, nil, GUI.Alignment.Center)
local button = GUI.Button(GUI.RectTransform(Vector2(1, 0.1), blue_prints.gui_button_frame_list.Content.RectTransform), "Load Blueprint", GUI.Alignment.Center, "GUIButtonSmall")
button.OnClicked = function()
if blue_prints.current_gui_page then
blue_prints.current_gui_page.Visible = false
end
blue_prints.current_gui_page = generate_load_gui()
blue_prints.current_gui_page.Visible = true
end
resolution = new_resolution
run_once_at_start = true
end
end
Hook.Patch("Barotrauma.Items.Components.CircuitBox", "AddToGUIUpdateList", function()
check_and_rebuild_frame()
end, Hook.HookMethodType.After)