Ticket #4027: 4027_mod_installation.patch
File 4027_mod_installation.patch, 7.1 KB (added by , 7 years ago) |
---|
-
source/main.cpp
49 49 #include "ps/Globals.h" 50 50 #include "ps/Hotkey.h" 51 51 #include "ps/Loader.h" 52 #include "ps/ModInstaller.h" 52 53 #include "ps/Profile.h" 53 54 #include "ps/Profiler2.h" 54 55 #include "ps/Pyrogenesis.h" … … 443 444 return; 444 445 } 445 446 } 447 448 const bool isModInstallation = args.Has("install-mod"); 449 const OsPath modPath(isModInstallation ? args.Get("install-mod") : ""); 446 450 451 if (isModInstallation) 452 { 453 if (!FileExists(modPath)) 454 { 455 debug_printf("ERROR: The mod file '%s' does not exist!\n", modPath.string8().c_str()); 456 return; 457 } 458 if (DirectoryExists(modPath)) 459 { 460 debug_printf("ERROR: The mod file '%s' is a directory!\n", modPath.string8().c_str()); 461 return; 462 } 463 if (modPath.Basename().empty()) 464 { 465 debug_printf("ERROR: The name of the mod file '%s' is empty!\n", modPath.string8().c_str()); 466 return; 467 } 468 } 469 447 470 // We need to initialize SpiderMonkey and libxml2 in the main thread before 448 471 // any thread uses them. So initialize them here before we might run Atlas. 449 472 ScriptEngine scriptEngine; … … 483 506 CXeromyces::Terminate(); 484 507 return; 485 508 } 509 510 if (isModInstallation) 511 { 512 Paths paths(args); 513 514 CModInstaller installer(paths.UserData() / "mods", paths.Cache()); 486 515 516 // Creates a directory with the name extracted from a `mod.json` 517 installer.Install(modPath); 518 519 CXeromyces::Terminate(); 520 return; 521 } 522 487 523 // run in archive-building mode if requested 488 524 if (args.Has("archivebuild")) 489 525 { -
source/ps/ModInstaller.cpp
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "ModInstaller.h" 21 22 #include "lib/file/vfs/vfs_util.h" 23 #include "ps/Filesystem.h" 24 #include "ps/XML/Xeromyces.h" 25 26 #include <boost/filesystem/operations.hpp> 27 #include <fstream> 28 29 CModInstaller::CModInstaller(const OsPath& modsdir, const OsPath& tempdir) : 30 m_ModsDir(modsdir), m_TempDir(tempdir / "_modscache"), m_CacheDir("cache/") 31 { 32 m_VFS = CreateVfs(16 * MiB); 33 34 CreateDirectories(m_TempDir, 0700); 35 36 const int runtimeSize = 8 * MiB; 37 const int heapGrowthBytesGCTrigger = 1 * MiB; 38 m_ScriptRuntime = ScriptInterface::CreateRuntime(std::shared_ptr<ScriptRuntime>(), runtimeSize, heapGrowthBytesGCTrigger); 39 } 40 41 CModInstaller::~CModInstaller() 42 { 43 m_VFS.reset(); 44 45 m_ScriptRuntime.reset(); 46 47 DeleteDirectory(m_TempDir); 48 } 49 50 void CModInstaller::Install(const OsPath& mod) 51 { 52 #define BOOST_WARN_IF_FAIL(expression) try { (expression); } catch (boost::filesystem::filesystem_error& ex) { debug_printf("%s", ex.what()); } 53 54 const OsPath modTemp = m_TempDir / mod.Basename() / mod.Filename().ChangeExtension(L".zip"); 55 CreateDirectories(modTemp.Parent(), 0700); 56 57 BOOST_WARN_IF_FAIL(boost::filesystem::copy_file(mod.string8(), modTemp.string8(), boost::filesystem::copy_option::overwrite_if_exists)); 58 59 // Load the mod to VFS 60 if (m_VFS->Mount(m_CacheDir, m_TempDir / "") != INFO::OK) 61 return; 62 CVFSFile modinfo; 63 PSRETURN modinfo_status = modinfo.Load(m_VFS, m_CacheDir / modTemp.Basename() / "mod.json", false); 64 m_VFS->Clear(); 65 if (modinfo_status != PSRETURN_OK) 66 return; 67 68 // Extract the name of the mod 69 ScriptInterface scriptInterface("Engine", "ModInstaller", m_ScriptRuntime); 70 JSContext* cx = scriptInterface.GetContext(); 71 JS::RootedValue json_val(cx); 72 if (!scriptInterface.ParseJSON(modinfo.GetAsString(), &json_val)) 73 return; 74 JS::RootedObject json_obj(cx, json_val.toObjectOrNull()); 75 JS::RootedValue name_val(cx); 76 if (!JS_GetProperty(cx, json_obj, "name", &name_val)) 77 return; 78 std::string modName; 79 ScriptInterface::FromJSVal(cx, name_val, modName); 80 if (modName.empty()) 81 return; 82 83 const OsPath modDir = m_ModsDir / modName; 84 const OsPath modPath = modDir / (modName + ".zip"); 85 86 // Create a directory with the next structure: 87 // mod-name/ 88 // +mod-name.zip 89 CreateDirectories(modDir, 0700); 90 BOOST_WARN_IF_FAIL(boost::filesystem::rename(modTemp.string8(), modPath.string8())); 91 DeleteDirectory(modTemp.Parent()); 92 93 #ifdef OS_WIN 94 std::ofstream mod_json((modDir / "mod.json").string8()); 95 if (mod_json.good()) 96 { 97 mod_json << modinfo.GetAsString(); 98 mod_json.close(); 99 } 100 #endif 101 102 // Remove the original file 103 BOOST_WARN_IF_FAIL(boost::filesystem::remove(mod.string8())); 104 #undef BOOST_WARN_IF_FAIL 105 } -
source/ps/ModInstaller.h
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_MODINSTALLER 19 #define INCLUDED_MODINSTALLER 20 21 #include "lib/file/vfs/vfs.h" 22 #include "scriptinterface/ScriptInterface.h" 23 24 /** 25 * Install a mod into the mods directory. 26 */ 27 class CModInstaller 28 { 29 public: 30 /** 31 * Initialise the mod installer for processing the given mod. 32 * 33 * @param modsdir path to the data directory, containing mods 34 * @param tempdir path to a writable directory for temporary files 35 */ 36 CModInstaller(const OsPath& modsdir, const OsPath& tempdir); 37 38 ~CModInstaller(); 39 40 /** 41 * Do all the processing and unpacking. 42 * @param mod path of .pyromod file of mod 43 */ 44 void Install(const OsPath& mod); 45 46 private: 47 48 PIVFS m_VFS; 49 OsPath m_ModsDir; 50 OsPath m_TempDir; 51 VfsPath m_CacheDir; 52 53 std::shared_ptr<ScriptRuntime> m_ScriptRuntime; 54 }; 55 56 #endif // INCLUDED_MODINSTALLER