Ticket #4027: 4027_proposed.patch

File 4027_proposed.patch, 6.2 KB (added by Vladislav Belov, 7 years ago)

How a mod installation could work

  • source/main.cpp

     
    4949#include "ps/Globals.h"
    5050#include "ps/Hotkey.h"
    5151#include "ps/Loader.h"
     52#include "ps/ModInstaller.h"
    5253#include "ps/Profile.h"
    5354#include "ps/Profiler2.h"
    5455#include "ps/Pyrogenesis.h"
     
    443444            return;
    444445        }
    445446    }
     447   
     448    const bool isModInstallation = args.Has("install-mod");
     449    const CStr modPath = isModInstallation ? args.Get("install-mod") : "";
    446450
     451    if (isModInstallation)
     452    {
     453        if (!FileExists(OsPath(modPath)))
     454        {
     455            debug_printf("ERROR: The mod file '%s' does not exist!\n", modPath.c_str());
     456            return;
     457        }
     458        if (DirectoryExists(OsPath(modPath)))
     459        {
     460            debug_printf("ERROR: The mod file '%s' is a directory!\n", modPath.c_str());
     461            return;
     462        }
     463    }
     464
    447465    // We need to initialize SpiderMonkey and libxml2 in the main thread before
    448466    // any thread uses them. So initialize them here before we might run Atlas.
    449467    ScriptEngine scriptEngine;
     
    483501        CXeromyces::Terminate();
    484502        return;
    485503    }
     504   
     505    if (isModInstallation)
     506    {
     507        Paths paths(args);
     508       
     509        CModInstaller installer(paths.UserData() / "mods", paths.Cache());
    486510
     511        // Creates a directory with the name extracted from a `mod.json`
     512        installer.Install(modPath);
     513
     514        CXeromyces::Terminate();
     515        return;
     516    }
     517
    487518    // run in archive-building mode if requested
    488519    if (args.Has("archivebuild"))
    489520    {
  • 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 "lib/sysdep/sysdep.h"
     24#include "ps/Filesystem.h"
     25#include "ps/XML/Xeromyces.h"
     26
     27#include <boost/filesystem/operations.hpp>
     28
     29CModInstaller::CModInstaller(const OsPath& modsdir, const OsPath& tempdir) :
     30    m_ModsDir(modsdir), m_TempDir(tempdir / "_modscache"), m_CacheDir("cache/")
     31{
     32    m_VFS = CreateVfs(20 * MiB);
     33
     34    CreateDirectories(m_TempDir, 0700);
     35
     36    const int runtimeSize = 64 * MiB;
     37    const int heapGrowthBytesGCTrigger = 16 * MiB;
     38    m_ScriptRuntime = ScriptInterface::CreateRuntime(std::shared_ptr<ScriptRuntime>(), runtimeSize, heapGrowthBytesGCTrigger);
     39}
     40
     41CModInstaller::~CModInstaller()
     42{
     43    m_VFS.reset();
     44
     45    m_ScriptRuntime.reset();
     46
     47    DeleteDirectory(m_TempDir);
     48}
     49
     50void CModInstaller::Install(const OsPath& mod)
     51{
     52    const OsPath modTemp = m_TempDir / mod.Filename().ChangeExtension(L".zip");
     53    // TODO: move the file, not copy
     54    boost::filesystem::copy_file(
     55        mod.string8(),
     56        modTemp.string8(),
     57        boost::filesystem::copy_option::overwrite_if_exists
     58    );
     59
     60    m_VFS->Mount(m_CacheDir, m_TempDir / "");
     61    CVFSFile modinfo;
     62    if (modinfo.Load(m_VFS, m_CacheDir / "mod.json", false) != PSRETURN_OK)
     63        return;
     64    m_VFS->Clear();
     65
     66    ScriptInterface scriptInterface("Engine", "ModInstaller", m_ScriptRuntime);
     67    JSContext* cx = scriptInterface.GetContext();
     68    JS::RootedValue json_val(cx);
     69    if (!scriptInterface.ParseJSON(modinfo.GetAsString(), &json_val))
     70        return;
     71    JS::RootedObject json_obj(cx, json_val.toObjectOrNull());
     72    JS::RootedValue name_val(cx);
     73    JS_GetProperty(cx, json_obj, "name", &name_val);
     74    std::string modName;
     75    ScriptInterface::FromJSVal(cx, name_val, modName);
     76
     77    const OsPath modDir = m_ModsDir / modName;
     78    const OsPath modPath = modDir / (modName + ".zip");
     79   
     80    DeleteDirectory(modDir);
     81    CreateDirectories(modDir, 0700);
     82
     83    boost::filesystem::rename(modTemp.string8(), modPath.string8());
     84
     85#ifdef OS_WIN
     86    // TODO: copy mod.json to the path
     87#endif
     88}
  • 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 */
     27class CModInstaller
     28{
     29public:
     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
     46private:
     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