{"id":18425843,"url":"https://github.com/faforever/ncoop","last_synced_at":"2025-09-12T10:33:25.525Z","repository":{"id":75007046,"uuid":"123134403","full_name":"FAForever/NCoop","owner":"FAForever","description":"Repository containing the mod for Nomads Coop.","archived":false,"fork":false,"pushed_at":"2018-10-22T08:43:15.000Z","size":434,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-02-16T08:17:17.470Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FAForever.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-27T13:40:20.000Z","updated_at":"2018-10-22T08:43:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"d223928f-de45-497a-bf2c-05f04042d925","html_url":"https://github.com/FAForever/NCoop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FAForever%2FNCoop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FAForever%2FNCoop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FAForever%2FNCoop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FAForever%2FNCoop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FAForever","download_url":"https://codeload.github.com/FAForever/NCoop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248758424,"owners_count":21156959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T05:06:05.173Z","updated_at":"2025-04-13T18:18:37.630Z","avatar_url":"https://github.com/FAForever.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nomads Coop\nA mod that's required to run the Nomads coop missions in the Forged Alliance Forever Client.\n\nIt's supposed to be run as a featured mod, similarly to the coop mod.\n\n# Setting up for testing\nThis is how to be able to run the mod with the nomads coop campaign, its good for testing the missions. To develop the mod itself see *Setting up for development*\n\n1. Download this repository, and pack its contents into a .zip file\n2. Rename the zip file to `nomads_coop.nmd`\n3. Place the file into your gamedata folder at `C:\\ProgramData\\FAForever\\gamedata`\n4. Get a modified version of the `init_coop.lua` file - see below\n5. Place that into `C:\\ProgramData\\FAForever\\bin`, overwriting anything already present\n6. Set the `init_coop.lua` file to read-only\n7. Ensure you have a nomads coop campaign mission to test, they can be downloaded from the [nomads missions repository]: https://github.com/FAForever/NomadMissions or elsewhere.\n8. Host a coop game through FAF - if everything has been done correctly, an error that a file could not be downloaded should appear. This is because you set the modified `init_coop.lua` to read only.\n9. Change the map to a nomads supported map in the lobby. Currently only the nomads campaign is supported.\n10. This _will_ cause desyncs if not everyone in your game has done this procedure.\n11. To disable the mod, rename `init_coop.lua` to something else or clear the read only flag, so the next game it will be updated and not load the nomads mod anymore.\n\n\n## Modifying init_coop.lua for testing\n1. Create or open `init_coop.lua` inside `C:\\ProgramData\\FAForever\\bin`\nPaste the following:\n```lua\nsc_path = \"\"\ndofile(InitFileDir .. '\\\\..\\\\fa_path.lua')\n\npath = {}\n\nwhitelist =\n{\n    \"effects.nx2\",\n    \"env.nx2\",\n    \"etc.nx2\",\n    \"loc.nx2\",\n    \"lua.nx2\",\n    \"meshes.nx2\",\n    \"mods.nx2\",\n    \"modules.nx2\",\n    \"projectiles.nx2\",\n    \"schook.nx2\",\n    \"textures.nx2\",\n    \"units.nx2\",\n    \"murderparty.nxt\",\n    \"labwars.nxt\",\n    \"units.scd\",\n    \"textures.scd\",\n    \"skins.scd\",\n    \"schook.scd\",\n    \"props.scd\",\n    \"projectiles.scd\",\n    \"objects.scd\",\n    \"moholua.scd\",\n    \"mohodata.scd\",\n    \"mods.scd\",\n    \"meshes.scd\",\n    \"lua.scd\",\n    \"loc_us.scd\",\n    \"loc_es.scd\",\n    \"loc_fr.scd\",\n    \"loc_it.scd\",\n    \"loc_de.scd\",\n    \"loc_ru.scd\",\n    \"env.scd\",\n    \"effects.scd\",\n    \"editor.scd\",\n    \"ambience.scd\",\n    \"advanced strategic icons.nxt\",\n    \"lobbymanager.scd\",\n    \"texturepack.nxt\",\n    \"sc_music.scd\"\n}\n\nlocal function mount_dir(dir, mountpoint)\n    table.insert(path, { dir = dir, mountpoint = mountpoint } )\nend\n\n\nlocal function mount_contents(dir, mountpoint)\n    LOG('checking ' .. dir)\n    for _,entry in io.dir(dir .. '\\\\*') do\n        if entry != '.' and entry != '..' then\n        local mp = string.lower(entry)\n        local safe = true\n        mp = string.gsub(mp, '[.]scd$', '')\n        mp = string.gsub(mp, '[.]zip$', '')\n        mount_dir(dir .. '\\\\' .. entry, mountpoint .. '/' .. mp)\n        end\n    end\nend\n\nlocal function mount_dir_with_glob(dir, glob, mountpoint)\n    sorted = {}\n    LOG('checking ' .. dir .. glob)\n    for _,entry in io.dir(dir .. glob) do\n        if entry != '.' and entry != '..' then\n            table.insert(sorted, dir .. entry)\n        end\n    end\n    table.sort(sorted)\n    table.foreach(sorted, function(k,v) mount_dir(v, mountpoint) end)\nend\n\nlocal function mount_dir_with_whitelist(dir, glob, mountpoint)\n    sorted = {}\n    LOG('checking ' .. dir .. glob)\n    for _,entry in io.dir(dir .. glob) do\n        if entry != '.' and entry != '..' then\n            local mp = string.lower(entry)\n            local notsafe = true\n            for i, white in whitelist do\n                notsafe = notsafe and (string.find(mp, white, 1) == nil)\n            end\n            if notsafe then\n                LOG('not safe ' .. dir .. entry)\n            else\n                table.insert(sorted, dir .. entry)\n            end\n        end\n    end\n    table.sort(sorted)\n    table.foreach(sorted, function(k,v) mount_dir(v, mountpoint) end)\nend\n\nlocal function mount_dir_with_blacklist(dir, glob, mountpoint)\n    sorted = {}\n    LOG('checking ' .. dir .. glob)\n    for _,entry in io.dir(dir .. glob) do\n        if entry != '.' and entry != '..' then\n            local mp = string.lower(entry)\n            local safe = true\n            for i, black in blacklist do\n                safe = safe and (string.find(mp, black, 1) == nil)\n            end\n            if safe then\n                table.insert(sorted, dir .. entry)\n            else\n                LOG('not safe ' .. dir .. entry)\n            end\n        end\n    end\n    table.sort(sorted)\n    table.foreach(sorted, function(k,v) mount_dir(v, mountpoint) end)\nend\n\nlocal function mount_map_dir(dir, glob, mountpoint)\n    LOG('mounting maps from: '..dir)\n    mount_contents(dir, mountpoint)\n\n    for _, map in io.dir(dir..glob) do\n        for _, folder in io.dir(dir..'\\\\'..map..'\\\\**') do\n            if folder == 'movies' then\n                LOG('Found map movies in: '..map)\n                mount_dir(dir..map..'\\\\movies', '/movies')\n            elseif folder == 'sounds' then\n                LOG('Found map sounds in: '..map)\n                mount_dir(dir..map..'\\\\sounds', '/sounds')\n            end\n        end\n    end\nend\n\nlocal function clear_cache()\n    local dir = SHGetFolderPath('LOCAL_APPDATA') .. 'Gas Powered Games\\\\Supreme Commander Forged Alliance\\\\cache\\\\'\n    LOG('Clearing cached shader files in: ' .. dir)\n    for _,file in io.dir(dir .. '**') do\n        if string.find(file, 'mesh') then\n            os.remove(dir .. file)\n        end\n    end\nend\n\n-- Clear the shader\nclear_cache()\n\n-- mount maps\nmount_map_dir(SHGetFolderPath('PERSONAL') .. 'My Games\\\\Gas Powered Games\\\\Supreme Commander Forged Alliance\\\\maps\\\\', '**', '/maps')\nmount_map_dir(InitFileDir .. '\\\\..\\\\user\\\\My Games\\\\Gas Powered Games\\\\Supreme Commander Forged Alliance\\\\maps\\\\', '**', '/maps')\n\n-- mount mods\nmount_contents(SHGetFolderPath('PERSONAL') .. 'My Games\\\\Gas Powered Games\\\\Supreme Commander Forged Alliance\\\\mods', '/mods')\nmount_contents(InitFileDir .. '\\\\..\\\\user\\\\My Games\\\\Gas Powered Games\\\\Supreme Commander Forged Alliance\\\\mods', '/mods')\n\nmount_dir(InitFileDir .. '\\\\..\\\\gamedata\\\\nomads_coop.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\units.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\textures.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\sounds.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\effects.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\env.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\nomadhook.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\lua.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\projectiles.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\loc.nmd', '/')\nmount_dir(InitFileDir..'\\\\..\\\\gamedata\\\\meshes.nmd', '/')\n\nmount_dir(InitFileDir .. '\\\\..\\\\gamedata\\\\*.cop', '/')\nmount_dir_with_whitelist(InitFileDir .. '\\\\..\\\\gamedata\\\\', '*.nxt', '/')\nmount_dir_with_whitelist(InitFileDir .. '\\\\..\\\\gamedata\\\\', '*.nx2', '/')\n\nmount_dir_with_whitelist(fa_path .. '\\\\gamedata\\\\', '*.scd', '/')\nmount_dir(fa_path, '/')\nmount_dir(InitFileDir .. '\\\\..\\\\movies', '/movies')\n\nmount_dir_with_glob(InitFileDir .. '\\\\..\\\\gamedata\\\\', '*_VO.nx2', '/')\n\n\n\nhook = {\n    '/schook',\n    '/mods/coop/hook',\n    '/sounds',\n    '/nomadhook',\n}\n\n\n\nprotocols = {\n    'http',\n    'https',\n    'mailto',\n    'ventrilo',\n    'teamspeak',\n    'daap',\n    'im',\n}\n```\n\n# Setting up for development\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaforever%2Fncoop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaforever%2Fncoop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaforever%2Fncoop/lists"}