Skip to content

Commit

Permalink
Merge pull request #470 from besteon/dev
Browse files Browse the repository at this point in the history
8.5.4 Patch Release
  • Loading branch information
UTDZac authored May 17, 2024
2 parents 90d9b21 + 33893a3 commit d6a1ac4
Show file tree
Hide file tree
Showing 21 changed files with 372 additions and 155 deletions.
5 changes: 3 additions & 2 deletions ironmon_tracker/Drawing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -747,8 +747,9 @@ function Drawing.setAnimatedPokemon(pokemonID)
ExternalUI.BizForms.setProperty(Drawing.AnimatedPokemon.addonMissing, ExternalUI.BizForms.Properties.VISIBLE, not fileExists)
elseif fileExists then
-- For mGBA, duplicate the image file so it can be rendered by external programs
local animatedImageFile = FileManager.prependDir(FileManager.Files.Other.ANIMATED_POKEMON)
FileManager.CopyFile(imagePath, animatedImageFile, "overwrite")
local folderpath = FileManager.getPathOverride("Animated Pokemon") or FileManager.dir
local filepath = folderpath .. FileManager.Files.Other.ANIMATED_POKEMON
FileManager.CopyFile(imagePath, filepath, "overwrite")
end
end

Expand Down
204 changes: 129 additions & 75 deletions ironmon_tracker/FileManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ FileManager.Files = {
RANDOMIZER_ERROR_LOG = "RandomizerErrorLog.txt",
TRACKER_CORE = "Ironmon-Tracker.lua",
UPDATE_OR_INSTALL = "UpdateOrInstall.lua",
REQUESTS_DATA = FileManager.Folders.TrackerCode .. FileManager.slash .. FileManager.Folders.Network .. FileManager.slash .. "Requests.json",
REQUESTS_DATA = "Requests.json", -- Located in the `network` folder
STREAMERBOT_CODE = FileManager.Folders.TrackerCode .. FileManager.slash .. FileManager.Folders.Network .. FileManager.slash .. "StreamerbotCodeImport.txt",
JSON_LIBRARY = FileManager.Folders.TrackerCode .. FileManager.slash .. "Json.lua",
OSEXECUTE_OUTPUT = FileManager.Folders.TrackerCode .. FileManager.slash .. "osexecute-output.txt",
ERROR_LOG = FileManager.Folders.TrackerCode .. FileManager.slash .. "errorlog.txt",
CRASH_REPORT = FileManager.Folders.TrackerCode .. FileManager.slash .. "crashreport.txt",
KNOWN_WORKING_DIR = FileManager.Folders.TrackerCode .. FileManager.slash .. "knownworkingdir.txt",
LanguageCode = {
SpainData = "SpainData.lua",
ItalyData = "ItalyData.lua",
Expand Down Expand Up @@ -163,9 +164,7 @@ end

function FileManager.folderExists(folderpath)
if folderpath == nil then return false end
if folderpath:sub(-1) ~= "/" and folderpath:sub(-1) ~= "\\" then
folderpath = folderpath .. FileManager.slash
end
folderpath = FileManager.tryAppendSlash(folderpath)

-- Hacky but simply way to check if a folder exists: try to rename it
-- The "code" return value only exists in Lua 5.2+, but not required to use here
Expand Down Expand Up @@ -210,42 +209,44 @@ function FileManager.getPathIfExists(filepath)
return nil
end

-- Returns the absolute file path using a local filename/path and the working directory of the Tracker
---@return string filepath
function FileManager.prependDir(filenameOrPath)
return FileManager.dir .. (filenameOrPath or "")
---Returns the absolute file path using a local filename/path and the working directory of the Tracker
---@param filenameOrPath string
---@param includeTrailingSlash? boolean (Optional) If true, appends the system's path separator (slash)
---@return string
function FileManager.prependDir(filenameOrPath, includeTrailingSlash)
local suffix = includeTrailingSlash and FileManager.slash or ""
return FileManager.dir .. (filenameOrPath or "") .. suffix
end

-- An absolute path working directory is required for Bizhawk (Windows or Linux)
function FileManager.setupWorkingDirectory()
FileManager.dir = IronmonTracker.workingDir or ""
FileManager.dir = ""
local dir = tostring(IronmonTracker.workingDir or "")

-- First check if the working directory has been looked up before
local knownDirPath = FileManager.Folders.TrackerCode .. FileManager.slash .. "knownworkingdir.txt"
local knownDirPath = FileManager.Files.KNOWN_WORKING_DIR
local knownDirFile = io.open(knownDirPath, "r")
-- If the file doesn't exist, try another path
if knownDirFile == nil then
knownDirPath = FileManager.dir .. knownDirPath
knownDirPath = dir .. knownDirPath
knownDirFile = io.open(knownDirPath, "r")
end

-- If the working directory is known (used in the past), then load that instead of running an os execute
if knownDirFile ~= nil then
FileManager.dir = knownDirFile:read("*a") or ""
dir = knownDirFile:read("*a") or ""
knownDirFile:close()
FileManager.dir = FileManager.dir:gsub("^%s*(.-)%s*$", "%1") -- trim whitespace
dir = tostring(dir:gsub("^%s*(.-)%s*$", "%1"))
-- Then verify that this saved working directory is correct and usable (user might have moved files/folders)
if not FileManager.fileExists(FileManager.prependDir(FileManager.Files.TRACKER_CORE)) then
FileManager.dir = ""
if not FileManager.fileExists(dir .. FileManager.Files.TRACKER_CORE) then
dir = ""
end
end

-- Properly format the path
local function formatPath(filepath)
filepath = FileManager.formatPathForOS(filepath)
if filepath:sub(-1) ~= FileManager.slash then
filepath = filepath .. FileManager.slash
end
filepath = FileManager.tryAppendSlash(filepath)
-- Linux Bizhawk 2.8 doesn't support popen or working dir absolute path
if Main.emulator == Main.EMU.BIZHAWK28 and filepath == FileManager.slash then
filepath = ""
Expand All @@ -254,10 +255,10 @@ function FileManager.setupWorkingDirectory()
end

-- Otherwise, if no known working directory was found, look it up the hard way
if knownDirFile == nil or FileManager.dir == "" then
if knownDirFile == nil or dir == "" then
-- For Bizhawk, use luaconsole script list as a quick backup solution
if Main.IsOnBizhawk() then
local pathCheckFile = io.open(FileManager.prependDir(FileManager.Files.TRACKER_CORE), "r")
local pathCheckFile = io.open(dir .. FileManager.Files.TRACKER_CORE, "r")
if pathCheckFile then
pathCheckFile:close()
else
Expand All @@ -268,38 +269,39 @@ function FileManager.setupWorkingDirectory()
local scriptPath = scriptList[i].Path or scriptList[i].path or ""
local index = scriptPath:find(FileManager.Files.TRACKER_CORE, 1, true)
if index then
FileManager.dir = scriptPath:sub(1, index - 1)
dir = scriptPath:sub(1, index - 1)
break
end
end
FileManager.dir = formatPath(FileManager.dir)
dir = formatPath(dir)
end
end
-- If still can't find the filepath, use a command to get it
if FileManager.dir == "" then
if dir == "" then
-- Windows: "cd", Linux: "pwd"
local getDirCommand = FileManager.slash == "\\" and "cd" or "pwd"
-- Bizhawk handles current working directory differently, this is the only way to get it
local success, fileLines = FileManager.tryOsExecute(getDirCommand)
if success and #fileLines > 0 and Main.IsOnBizhawk() and FileManager.dir == "" then
FileManager.dir = fileLines[1]
if success and #fileLines > 0 and Main.IsOnBizhawk() then
dir = fileLines[1]
end
FileManager.dir = formatPath(FileManager.dir)
dir = formatPath(dir)
end

-- Save known working directory to file to load for future startups
if FileManager.dir ~= "" then
if dir ~= "" then
knownDirFile = io.open(knownDirPath, "w")
if knownDirFile then
knownDirFile:write(FileManager.dir)
knownDirFile:write(dir)
knownDirFile:flush()
knownDirFile:close()
end
end
end

-- Required so UpdateOrInstall works regardless of standalone execution
IronmonTracker.workingDir = FileManager.dir
-- The current known working directory of the Tracker
FileManager.dir = dir
IronmonTracker.workingDir = dir
end

-- Attempts to execute the command, returning two results: success, outputTable
Expand Down Expand Up @@ -364,6 +366,26 @@ function FileManager.executeEachFile(functionName)
end
end

---Removes the system's path separator (slash) from the end of the path, or returns the path unchanged
---@param path string
---@return string
function FileManager.trimSlash(path)
if (path or "") == "" or not path:find("[/\\]$") then
return path
end
return path:sub(1, -2)
end

---Appends the system's path separator (slash) to the path if it's not already present
---@param path string
---@return string
function FileManager.tryAppendSlash(path)
if (path or "") == "" or path:find("[/\\]$") then
return path
end
return path .. FileManager.slash
end

-- Returns a properly formatted path that contains only the correct path-separators based on the OS
function FileManager.formatPathForOS(path)
path = path or ""
Expand All @@ -378,6 +400,7 @@ end
-- Returns true if it creates the folder, false if it already exists (I think)
function FileManager.createFolder(folderpath)
if folderpath == nil then return end
folderpath = FileManager.trimSlash(folderpath)
local command
if Main.OS == "Windows" then
command = string.format('mkdir "%s"', folderpath)
Expand Down Expand Up @@ -457,6 +480,17 @@ function FileManager.logError(errorMessage)
end
end

---Checks if there is an override available and returns that path; or nil if no override exists
---@param key string A table key for Options.Overrides
---@return string|nil folderpath Path includes trailing slash
function FileManager.getPathOverride(key)
local folderpath = Options.Overrides[key or false] or ""
if Utils.isNilOrEmpty(folderpath) then
return nil
end
return FileManager.tryAppendSlash(folderpath)
end

function FileManager.buildImagePath(imageFolder, imageName, imageExtension)
local listOfPaths = {
FileManager.Folders.TrackerCode,
Expand Down Expand Up @@ -489,6 +523,16 @@ function FileManager.getRandomizerSettingsPath()
return FileManager.prependDir(table.concat(listOfPaths, FileManager.slash))
end

-- Returns a properly formatted folder path where network files are located; includes trailing slash
function FileManager.getNetworkPath()
local listOfPaths = {
FileManager.Folders.TrackerCode,
FileManager.Folders.Network,
"", -- Necessary to include a trailing slash, helps with appending a filename
}
return FileManager.prependDir(table.concat(listOfPaths, FileManager.slash))
end

-- Returns a properly formatted folder path where custom code files are located; includes trailing slash
function FileManager.getCustomFolderPath()
local listOfPaths = {
Expand All @@ -501,9 +545,7 @@ end
function FileManager.extractFolderNameFromPath(path)
if path == nil or path == "" then return "" end

if path:sub(-1) == FileManager.slash then
path = path:sub(1, -2)
end
path = FileManager.trimSlash(path)

local folderStartIndex = path:match("^.*()[\\/]") -- path to folder
if folderStartIndex ~= nil then
Expand All @@ -519,7 +561,7 @@ end
function FileManager.extractFileNameFromPath(path, includeExtension)
if path == nil or path == "" then return "" end

local folder, filename, extension = FileManager.getPathParts(path)
local _, filename, extension = FileManager.getPathParts(path)
if includeExtension and filename then
return filename .. (extension or "")
else
Expand All @@ -530,7 +572,7 @@ end
function FileManager.extractFileExtensionFromPath(path)
if path == nil or path == "" then return "" end

local folder, filename, extension = FileManager.getPathParts(path)
local _, _, extension = FileManager.getPathParts(path)
if extension and #extension > 1 then
return extension:sub(2) -- remove the leading '.'
else
Expand Down Expand Up @@ -595,37 +637,47 @@ function FileManager.CopyFile(filepath, filepathCopy, overwriteOrAppend)
return true
end

-- 'filename' is a local name of a file
function FileManager.writeTableToFile(table, filename)
local filepath = FileManager.prependDir(filename)
---Writes the contents of `table` to the file at `filepath`
---@param table table
---@param filepath string
function FileManager.writeTableToFile(table, filepath)
if type(table) ~= "table" or (filepath or "") == "" then
return
end
local file = io.open(filepath, "w")

if file ~= nil then
local dataString = Pickle.pickle(table)
--append a trailing \n if one is absent
if dataString:sub(-1) ~= "\n" then dataString = dataString .. "\n" end
for dataLine in dataString:gmatch("(.-)\n") do
file:write(dataLine .. "\n")
end
file:flush()
file:close()
if not file then
return
end
local dataString = Pickle.pickle(table)
--append a trailing \n if one is absent
if dataString:sub(-1) ~= "\n" then
dataString = dataString .. "\n"
end
for dataLine in dataString:gmatch("(.-)\n") do
file:write(dataLine .. "\n")
end
file:flush()
file:close()
end

-- 'filepath' is must contain the absolute path to the file
---Returns the contents of the file at `filepath` as a luatable
---@param filepath string
---@return table|nil
function FileManager.readTableFromFile(filepath)
local tableData = nil
if (filepath or "") == "" then
return nil
end
local file = io.open(filepath, "r")

if file ~= nil then
local dataString = file:read("*a")
if dataString ~= nil and dataString ~= "" then
tableData = Pickle.unpickle(dataString)
end
file:close()
if not file then
return nil
end

return tableData
local dataString = file:read("*a")
file:close()
if (dataString or "") == "" then
return nil
end
return Pickle.unpickle(dataString)
end

-- Returns a table that contains an entry for each line from a filename/filepath
Expand Down Expand Up @@ -704,31 +756,34 @@ function FileManager.addCustomThemeToFile(themeName, themeCode)
return
end

local themeFilePath = FileManager.prependDir(FileManager.Files.THEME_PRESETS)
local file = io.open(themeFilePath, "a")

if file ~= nil then
file:write(string.format("%s %s", themeName, themeCode))
file:write("\n")
file:close()
else
print(string.format('> ERROR: Unable to save custom Theme "%s" to file: %s', themeName, FileManager.Files.THEME_PRESETS))
local folderpath = FileManager.getPathOverride("Theme Presets") or FileManager.dir
local filepath = folderpath .. FileManager.Files.THEME_PRESETS
local file = io.open(filepath, "a")
if not file then
-- Don't really want to flood the console with error messages; if important, use Main.DisplayError()
-- print(string.format('> ERROR: Unable to save custom Theme "%s" to file: %s', themeName, FileManager.Files.THEME_PRESETS))
return
end

file:write(string.format("%s %s\n", themeName, themeCode))
file:close()
end

-- Removes a saved Theme preset by rewriting the file with all presets, but excluding the one that is being removed
function FileManager.removeCustomThemeFromFile(themeName, themeCode)
local themeFilePath = FileManager.prependDir(FileManager.Files.THEME_PRESETS)
local folderpath = FileManager.getPathOverride("Theme Presets") or FileManager.dir
local filepath = folderpath .. FileManager.Files.THEME_PRESETS

if themeName == nil or themeCode == nil or not FileManager.fileExists(themeFilePath) then
if themeName == nil or themeCode == nil or not FileManager.fileExists(filepath) then
return false
end

local existingThemePresets = FileManager.readLinesFromFile(FileManager.Files.THEME_PRESETS)
local existingThemePresets = FileManager.readLinesFromFile(filepath)

local file = io.open(themeFilePath, "w")
if file == nil then
print(string.format('> ERROR: Unable to remove custom Theme "%s" from file: %s', themeName, FileManager.Files.THEME_PRESETS))
local file = io.open(filepath, "w")
if not file then
-- Don't really want to flood the console with error messages; if important, use Main.DisplayError()
-- print(string.format('> ERROR: Unable to remove custom Theme "%s" from file: %s', themeName, FileManager.Files.THEME_PRESETS))
return false
end

Expand All @@ -744,8 +799,7 @@ function FileManager.removeCustomThemeFromFile(themeName, themeCode)
end

if themeLineName ~= themeName and themeLineCode ~= themeCode then
file:write(line)
file:write("\n")
file:write(line .. "\n")
end
end
end
Expand Down
Loading

0 comments on commit d6a1ac4

Please sign in to comment.