Skip to content

Commit

Permalink
Fix icon loading (#3450)
Browse files Browse the repository at this point in the history
* Refactor / update init_faf.lua

Improves overall code style and removes directly loading in of
ui-related textures.

* Load preference file during initialisation

This allows us to send data to blueprints.lua

* Add a todo

* Load icon config from mod_icons.lua and send it to preferences

* Make sure all blueprint ids are lower case

* Finish pipeline for custom icon loading - they're not working however

* Load in only custom strategic icons from active mods

* Finalize icon loading

* Broadcast the launch event again

* Update init_faf.lua for custom icon support

* remove dev files

* Allows a script-based approach to determine id -> icon table

* Pass list of icons in the ui mod for backwards compatibility

* Update changelog

* Update changelog

* Add space in changelog

* Find custom strategic icons after all blueprints have been loaded

* Small change for performance

* Add fail safe in case people use capitalized blueprint ids

* Add speed2 as contributor for another PR

* Update init files for dev and other features branches

* Add more extensive error handling

In particular, a lua parsing error does not appear to stop
executing and therefore it not caught by the pcall we used.

Instead, we're now checking if either values that we expect are
set and if none of them are then we expect something to be at
odds.

* de-capitalize speed2

* Add functions on suggestion by Balthazar
  • Loading branch information
Garanas authored Oct 3, 2021
1 parent a5c958d commit cca5e78
Show file tree
Hide file tree
Showing 6 changed files with 516 additions and 163 deletions.
8 changes: 7 additions & 1 deletion changelog-3724.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ Patch 3721 (19 September, 2021)
### Lobby

### Gameplay
- (#3450) An alternative approach to loading in custom strategic icons
- (#3458) Fix UEF Triad and UEF Destroyer projectile on impact animation

### Bugs
- (#3442) Fix scathis packing animation time
- (#3439) Fix Cybran drone visibility for other players than the owner
- (#3450) Fix UI textures being overridden by mods that are not enabled
- (#3457) Fix Cybran drone being interactable and other small issues (with thanks to Archsimkat)
- (#3453) Fix units being gifted to the same player causing a crash for the shared army mod (co-op campaign)

### Stability
- (#3436) Prevent fetching blueprints for potential entities with no blueprints
Expand All @@ -23,5 +26,8 @@ Patch 3721 (19 September, 2021)
### Other

### Contributors
- Jip (#3442, #3439, #3449, #3458, #3457, #3460)
- Jip (#3442, #3439, #3449, #3458, #3457, #3460, #3450)
- KionX (#3449)
- Crotalus (#3436)
- Balthazar (#3450)
- speed2 (#3453)
145 changes: 89 additions & 56 deletions init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

-- This imports a path file that is written by Forged Alliance Forever right before it starts the game.
dofile(InitFileDir .. '\\..\\fa_path.lua')

Expand All @@ -21,18 +22,17 @@ blacklist = {
}

whitelist = {
"effects.nx5",
"env.nx5",
"etc.nx5",
"loc.nx5",
"lua.nx5",
"meshes.nx5",
"mods.nx5",
"projectiles.nx5",
"schook.nx5",
"textures.nx5",
"units.nx5",
"props.nx5",
"effects.nx2",
"env.nx2",
"etc.nx2",
"loc.nx2",
"lua.nx2",
"meshes.nx2",
"mods.nx2",
"projectiles.nx2",
"schook.nx2",
"textures.nx2",
"units.nx2",
"murderparty.nxt",
"labwars.nxt",
"units.scd",
Expand Down Expand Up @@ -129,73 +129,105 @@ local function mount_dir_with_blacklist(dir, glob, mountpoint)
table.foreach(sorted, function(k,v) mount_dir(v,'/') end)
end

-- Begin map mounting section
-- This section mounts movies and sounds from maps, essential for custom missions and scripted maps
local function mount_map_dir(dir, glob, mountpoint)
--- A helper function that loads in additional content for maps.
-- @param mountpoint The root folder to look for content in.
local function mount_map_content(dir, glob, mountpoint)
LOG('mounting maps from: '..dir)
mount_contents(dir, mountpoint)

-- look for all directories / maps at the mount point
for _, map in io.dir(dir..glob) do
for _, folder in io.dir(dir..'\\'..map..'\\**') do
if folder == 'movies' then
LOG('Found map movies in: '..map)
mount_dir(dir..map..'\\movies', '/movies')
elseif folder == 'sounds' then
LOG('Found map sounds in: '..map)
mount_dir(dir..map..'\\sounds', '/sounds')

-- make sure we're not retrieving the current / previous directory
if map != '.' and map != '..' then

-- look at each directory inside this map
for _, folder in io.dir(dir..'\\'..map..'\\**') do

-- if we found a directory named 'movies' then we mount its content
if folder == 'movies' then
LOG('Found map movies in: '..map)
mount_dir(dir..map..'\\movies', '/movies')
end

-- if we found a directory named 'sounds' then we mount its content
if folder == 'sounds' then
LOG('Found map sounds in: '..map)
mount_dir(dir..map..'\\sounds', '/sounds')
end
end
end
end
end
mount_map_dir(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\maps\\', '**', '/maps')
mount_map_dir(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\maps\\', '**', '/maps')

-- Begin mod mounting section
-- This section mounts sounds and ui textures from the mods directory to allow mods to add custom sounds and textures to the game
function mount_mod_content(MODFOLDER)
-- searching for mods inside the modfolder
for _,mod in io.dir(MODFOLDER..'\\*.*') do
-- do we have a true directory ?

--- A helper function that loads in additional content for mods.
-- @param mountpoint The root folder to look for content in.
function mount_mod_content(mountpoint)
-- get all directories / mods at the mount point
for _, mod in io.dir(mountpoint..'\\*.*') do

-- make sure we're not retrieving the current / previous directory
if mod != '.' and mod != '..' then
-- searching for sounds inside mod folder
for _,folder in io.dir(MODFOLDER..'\\'..mod..'\\*.*') do
-- if we found a folder named sounds then mount it

-- look at each directory inside this mod
for _, folder in io.dir(mountpoint..'\\'..mod..'\\*.*') do

-- if we found a directory named 'sounds' then we mount its content
if folder == 'sounds' then
LOG('Found mod sounds in: '..mod)
mount_dir(MODFOLDER..'\\'..mod..'\\sounds', '/sounds')
-- mount ui textures if there are any
elseif folder == 'textures' then
for _,folder in io.dir(MODFOLDER..'\\'..mod..'\\textures\\*.*') do
if folder == 'ui' then
LOG('Found mod icons in: '..mod)
mount_dir(MODFOLDER..'\\'..mod..'\\textures\\ui', '/textures/ui')
break
end
end
mount_dir(mountpoint..'\\'..mod..'\\sounds', '/sounds')
end

-- if we found a directory named 'custom-strategic-icons' then we mount its content
if folder == 'custom-strategic-icons' then
local mountLocation = '/textures/ui/common/game/strategicicons/' .. string.lower(mod)
LOG('Found mod icons in ' .. mod .. ', mounted at: ' .. mountLocation)
mount_dir(mountpoint..'\\'..mod..'\\custom-strategic-icons', mountLocation)
end
end
end
end
end
mount_mod_content(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\mods')
mount_mod_content(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\mods')

-- These are the classic supcom directories. They don't work with accents or other foreign characters in usernames
mount_contents(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\mods', '/mods')
mount_contents(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\maps', '/maps')
--- A helper function to load in all maps and mods on a given location.
-- @param path The root folder for the maps and mods
local function load_content(path)
-- load in additional things, like sounds and
mount_map_content(path .. '\\maps\\', '**', '/maps')
mount_mod_content(path .. '\\mods')

mount_contents(path .. '\\mods', '/mods')
mount_contents(path .. '\\maps', '/maps')
end

-- load maps / mods from custom vault location, if set by client
if custom_vault_path then
LOG('Loading custom vault path' .. custom_vault_path)
load_content(custom_vault_path)
else
LOG("No custom vault path defined.")
end

-- load maps / mods from backup vault location location
load_content(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')

-- These are the local FAF directories. The My Games ones are only there for people with usernames that don't work in the uppder ones.
mount_contents(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\mods', '/mods')
mount_contents(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\maps', '/maps')
-- load maps / mods from my documents vault location
load_content(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')

-- load in any .nxt that matches the whitelist / blacklist in FAF gamedata
mount_dir_with_whitelist(InitFileDir .. '\\..\\gamedata\\', '*.nxt', '/')
mount_dir_with_whitelist(InitFileDir .. '\\..\\gamedata\\', '*.nx5', '/')
mount_dir_with_whitelist(InitFileDir .. '\\..\\gamedata\\', '*.nx2', '/')

-- These are using the newly generated path from the dofile() statement at the beginning of this script
-- load in any .nxt that matches the whitelist / blacklist in FA gamedata
mount_dir_with_whitelist(fa_path .. '\\gamedata\\', '*.scd', '/')
mount_dir(fa_path, '/')

--load preferences into the game as well, letting us have much more control over their contents. This also includes cache and similar.
-- TODO: should we limit this?
-- load preferences into the game as well, letting us have much more control over their contents. This also includes cache and similar.
mount_dir(SHGetFolderPath('LOCAL_APPDATA') .. 'Gas Powered Games\\Supreme Commander Forged Alliance', '/preferences')

-- TODO: ?
mount_dir(fa_path, '/')

hook = {
'/schook'
}
Expand All @@ -209,3 +241,4 @@ protocols = {
'daap',
'im',
}

108 changes: 66 additions & 42 deletions init_faf.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

-- This imports a path file that is written by Forged Alliance Forever right before it starts the game.
dofile(InitFileDir .. '\\..\\fa_path.lua')

Expand Down Expand Up @@ -128,80 +129,103 @@ local function mount_dir_with_blacklist(dir, glob, mountpoint)
table.foreach(sorted, function(k,v) mount_dir(v,'/') end)
end

-- Begin map mounting section
-- This section mounts movies and sounds from maps, essential for custom missions and scripted maps
local function mount_map_dir(dir, glob, mountpoint)
--- A helper function that loads in additional content for maps.
-- @param mountpoint The root folder to look for content in.
local function mount_map_content(dir, glob, mountpoint)
LOG('mounting maps from: '..dir)
mount_contents(dir, mountpoint)

-- look for all directories / maps at the mount point
for _, map in io.dir(dir..glob) do
for _, folder in io.dir(dir..'\\'..map..'\\**') do
if folder == 'movies' then
LOG('Found map movies in: '..map)
mount_dir(dir..map..'\\movies', '/movies')
elseif folder == 'sounds' then
LOG('Found map sounds in: '..map)
mount_dir(dir..map..'\\sounds', '/sounds')

-- make sure we're not retrieving the current / previous directory
if map != '.' and map != '..' then

-- look at each directory inside this map
for _, folder in io.dir(dir..'\\'..map..'\\**') do

-- if we found a directory named 'movies' then we mount its content
if folder == 'movies' then
LOG('Found map movies in: '..map)
mount_dir(dir..map..'\\movies', '/movies')
end

-- if we found a directory named 'sounds' then we mount its content
if folder == 'sounds' then
LOG('Found map sounds in: '..map)
mount_dir(dir..map..'\\sounds', '/sounds')
end
end
end
end
end

-- Begin mod mounting section
-- This section mounts sounds and ui textures from the mods directory to allow mods to add custom sounds and textures to the game
function mount_mod_content(MODFOLDER)
-- searching for mods inside the modfolder
for _,mod in io.dir(MODFOLDER..'\\*.*') do
-- do we have a true directory ?
--- A helper function that loads in additional content for mods.
-- @param mountpoint The root folder to look for content in.
function mount_mod_content(mountpoint)
-- get all directories / mods at the mount point
for _, mod in io.dir(mountpoint..'\\*.*') do

-- make sure we're not retrieving the current / previous directory
if mod != '.' and mod != '..' then
-- searching for sounds inside mod folder
for _,folder in io.dir(MODFOLDER..'\\'..mod..'\\*.*') do
-- if we found a folder named sounds then mount it

-- look at each directory inside this mod
for _, folder in io.dir(mountpoint..'\\'..mod..'\\*.*') do

-- if we found a directory named 'sounds' then we mount its content
if folder == 'sounds' then
LOG('Found mod sounds in: '..mod)
mount_dir(MODFOLDER..'\\'..mod..'\\sounds', '/sounds')
-- mount ui textures if there are any
elseif folder == 'textures' then
for _,folder in io.dir(MODFOLDER..'\\'..mod..'\\textures\\*.*') do
if folder == 'ui' then
LOG('Found mod icons in: '..mod)
mount_dir(MODFOLDER..'\\'..mod..'\\textures\\ui', '/textures/ui')
break
end
end
mount_dir(mountpoint..'\\'..mod..'\\sounds', '/sounds')
end

-- if we found a directory named 'custom-strategic-icons' then we mount its content
if folder == 'custom-strategic-icons' then
local mountLocation = '/textures/ui/common/game/strategicicons/' .. string.lower(mod)
LOG('Found mod icons in ' .. mod .. ', mounted at: ' .. mountLocation)
mount_dir(mountpoint..'\\'..mod..'\\custom-strategic-icons', mountLocation)
end
end
end
end
end

-- adds maps / mods to keep track of for the game
local function load_vault(vault_path)
mount_map_dir(vault_path .. '\\maps\\', '**', '/maps')
mount_mod_content(vault_path .. '\\mods')
--- A helper function to load in all maps and mods on a given location.
-- @param path The root folder for the maps and mods
local function load_content(path)
-- load in additional things, like sounds and
mount_map_content(path .. '\\maps\\', '**', '/maps')
mount_mod_content(path .. '\\mods')

mount_contents(vault_path .. '\\mods', '/mods')
mount_contents(vault_path .. '\\maps', '/maps')
mount_contents(path .. '\\mods', '/mods')
mount_contents(path .. '\\maps', '/maps')
end

-- load in custom vault location first so that it takes precendence
-- load maps / mods from custom vault location, if set by client
if custom_vault_path then
LOG('Loading custom vault path' .. custom_vault_path)
load_vault(custom_vault_path)
load_content(custom_vault_path)
else
LOG("No custom vault path defined.")
end

-- load in files from backup vault location
load_vault(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')
-- load maps / mods from backup vault location location
load_content(InitFileDir .. '\\..\\user\\My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')

-- load in files from default vault location
load_vault(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')
-- load maps / mods from my documents vault location
load_content(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance')

-- load in any .nxt that matches the whitelist / blacklist in FAF gamedata
mount_dir_with_whitelist(InitFileDir .. '\\..\\gamedata\\', '*.nxt', '/')
mount_dir_with_whitelist(InitFileDir .. '\\..\\gamedata\\', '*.nx2', '/')

-- these are using the newly generated path from the dofile() statement at the beginning of this script
-- load in any .nxt that matches the whitelist / blacklist in FA gamedata
mount_dir_with_whitelist(fa_path .. '\\gamedata\\', '*.scd', '/')

-- TODO: should we limit this?
-- load preferences into the game as well, letting us have much more control over their contents. This also includes cache and similar.
mount_dir(SHGetFolderPath('LOCAL_APPDATA') .. 'Gas Powered Games\\Supreme Commander Forged Alliance', '/preferences')

-- TODO: ?
mount_dir(fa_path, '/')

hook = {
Expand Down
Loading

0 comments on commit cca5e78

Please sign in to comment.