Esempio n. 1
1
static void OutputExceptionDetails(MonoObject* exc)
{
	MonoClass* eclass = mono_object_get_class(exc);

	if (eclass)
	{
		MonoObject* toStringExc = nullptr;
		MonoString* msg = mono_object_to_string(exc, &toStringExc);

		MonoProperty* prop = mono_class_get_property_from_name(eclass, "StackTrace");
		MonoMethod* getter = mono_property_get_get_method(prop);
		MonoString* msg2 = (MonoString*)mono_runtime_invoke(getter, exc, NULL, NULL);

		if (toStringExc)
		{
			MonoProperty* prop = mono_class_get_property_from_name(eclass, "Message");
			MonoMethod* getter = mono_property_get_get_method(prop);
			msg = (MonoString*)mono_runtime_invoke(getter, exc, NULL, NULL);
		}

		GlobalError("Unhandled exception in Mono script environment: %s %s", mono_string_to_utf8(msg), mono_string_to_utf8(msg2));
	}
}
Esempio n. 2
0
				streaming::AddMetaToLoadList(true, resourceRoot + meta.second);
			}

			for (auto& meta : metaData->GetEntries("after_level_meta"))
			{
				streaming::AddMetaToLoadList(false, resourceRoot + meta.second);
			}

			for (auto& meta : metaData->GetEntries("replace_level_meta"))
			{
				streaming::SetNextLevelPath(resourceRoot + meta.second);
			}

			if (!RangeLengthMatches(metaData->GetEntries("data_file"), metaData->GetEntries("data_file_extra")))
			{
				GlobalError("data_file entry count mismatch in resource %s", resource->GetName());
				return;
			}

			auto entryListComponent = resource->GetComponent<ResourceEntryListComponent>();

			auto view1 = metaData->GetEntries("data_file");
			auto view2 = metaData->GetEntries("data_file_extra");

			for (auto it1 = view1.begin(), end1 = view1.end(), it2 = view2.begin(), end2 = view2.end(); it1 != end1 && it2 != end2; ++it1, ++it2)
			{
				const std::string& type = it1->second;
				const std::string& name = it2->second;

				rapidjson::Document document;
				document.Parse(name.c_str(), name.length());
Esempio n. 3
0
bool DownloadManager::Process()
{
    switch (m_downloadState)
    {
    case DS_IDLE:
    {
        m_downloadState = DS_FETCHING_CONFIG;

        m_httpClient = new HttpClient();

        std::wstring hostname = m_gameServer.GetWAddress();

        std::map<std::string, std::string> postMap;
        postMap["method"] = "getConfiguration";

        bool isUpdate = false;

        if (!m_updateQueue.empty())
        {
            std::string resourceString;

            while (!m_updateQueue.empty())
            {
                resourceString += m_updateQueue.front();

                m_updateQueue.pop();

                if (!m_updateQueue.empty())
                {
                    resourceString += ";";
                }
            }

            postMap["resources"] = resourceString;

            isUpdate = true;
        }

        m_httpClient->DoPostRequest(hostname, m_gameServer.GetPort(), L"/client", postMap, [=] (bool result, std::string connData)
        {
            if (!result)
            {
                // TODO: make this a non-fatal error leading back to UI
                GlobalError("Obtaining configuration from server failed.");

                return;
            }

            if (!isUpdate)
            {
                m_requiredResources.clear();
            }

            std::string serverHost = m_gameServer.GetAddress();
            serverHost += va(":%d", m_gameServer.GetPort());

            // parse the received YAML file
            //try
            //{
            //auto node = YAML::Load(connData);
            rapidjson::Document node;
            node.Parse(connData.c_str());

            if (node.HasParseError())
            {
                auto err = node.GetParseError();

                GlobalError("parse error %d", err);
            }

            if (node.HasMember("loadScreen"))
            {
                m_serverLoadScreen = node["loadScreen"].GetString();
            }

            auto& resources = node["resources"];

            std::string origBaseUrl = node["fileServer"].GetString();

            for (auto it = resources.Begin(); it != resources.End(); it++)
            {
                auto& resource = *it;

                std::string baseUrl = origBaseUrl;

                if (it->HasMember("fileServer"))
                {
                    baseUrl = (*it)["fileServer"].GetString();
                }

                ResourceData resData(resource["name"].GetString(), va(baseUrl.c_str(), serverHost.c_str()));

                //for (auto& file : resource["files"])
                auto& files = resource["files"];
                for (auto i = files.MemberBegin(); i != files.MemberEnd(); i++)
                {
                    std::string filename = i->name.GetString();
                    std::string hash = i->value.GetString();

                    resData.AddFile(filename, hash);
                }

                if (resource.HasMember("streamFiles"))
                {
                    auto& streamFiles = resource["streamFiles"];

                    //for (auto& file : resource["streamFiles"])
                    for (auto i = streamFiles.MemberBegin(); i != streamFiles.MemberEnd(); i++)
                    {
                        std::string filename = i->name.GetString();
                        std::string hash = i->value["hash"].GetString();
                        uint32_t rscFlags = i->value["rscFlags"].GetUint();
                        uint32_t rscVersion = i->value["rscVersion"].GetUint();
                        uint32_t size = i->value["size"].GetUint();

                        AddStreamingFile(resData, filename, hash, rscFlags, rscVersion, size);
                    }
                }

                if (isUpdate)
                {
                    for (auto ite = m_requiredResources.begin(); ite != m_requiredResources.end(); ite++)
                    {
                        if (ite->GetName() == resData.GetName())
                        {
                            m_requiredResources.erase(ite);
                            break;
                        }
                    }
                }

                trace("%s\n", resData.GetName().c_str());

                m_isUpdate = isUpdate;

                m_requiredResources.push_back(resData);
            }
            /*}
            catch (std::exception& e)
            {
            	GlobalError("YAML parsing error in server configuration (%s)", e.msg);

            	return;
            }*/

            if (isUpdate)
            {
                assert(m_isUpdate);
            }

            m_downloadState = DS_CONFIG_FETCHED;
        });

        break;
    }

    case DS_CONFIG_FETCHED:
    {
        // check cache existence (TODO: and integrity?)
        auto resourceCache = TheResources.GetCache();

        auto downloadList = resourceCache->GetDownloadsFromList(m_requiredResources);

        resourceCache->ClearMark();
        resourceCache->MarkList(m_requiredResources);
        resourceCache->MarkStreamingList(m_streamingFiles);

        m_downloadList = std::queue<ResourceDownload>();

        for (auto& download : downloadList)
        {
            m_downloadList.push(download);
        }

        if (m_downloadList.empty())
        {
            m_downloadState = DS_DOWNLOADED_SINGLE;
        }
        else
        {
            m_downloadState = DS_DOWNLOADING;
        }

        break;
    }

    case DS_DOWNLOADING:
    {
        if (!m_currentDownload.get())
        {
            m_currentDownload = std::make_shared<ResourceDownload>(m_downloadList.front());
            m_downloadList.pop();

            std::wstring hostname, path;
            uint16_t port;

            m_httpClient->CrackUrl(m_currentDownload->sourceUrl, hostname, path, port);

            m_httpClient->DoFileGetRequest(hostname, port, path, TheResources.GetCache()->GetCacheDevice(), m_currentDownload->targetFilename, [=] (bool result, std::string connData)
            {
                m_downloadState = DS_DOWNLOADED_SINGLE;
            });
        }

        break;
    }

    case DS_DOWNLOADED_SINGLE:
    {
        if (m_currentDownload.get())
        {
            TheResources.GetCache()->AddFile(m_currentDownload->targetFilename, m_currentDownload->filename, m_currentDownload->resname);

            m_currentDownload = nullptr;
        }

        if (!m_downloadList.empty())
        {
            m_downloadState = DS_DOWNLOADING;
        }
        else
        {
            if (!m_isUpdate)
            {
                TheResources.Reset();
            }
            else
            {
                // unload any resources we already know that are currently unprocessed
                for (auto& resource : m_requiredResources)
                {
                    // this is one we just got from the configuration redownload
                    if (!resource.IsProcessed())
                    {
                        auto resourceData = TheResources.GetResource(resource.GetName());

                        if (!resourceData.get())
                        {
                            continue;
                        }

                        // sanity check: is the resource not running?
                        if (resourceData->GetState() == ResourceStateRunning)
                        {
                            FatalError("Tried to unload a running resource in DownloadMgr. (%s)", resource.GetName().c_str());
                        }

                        // remove all packfiles related to this old resource
                        auto packfiles = resourceData->GetPackFiles();

                        for (auto& packfile : packfiles)
                        {
                            // FIXME: implementation detail from same class
                            fiDevice::Unmount(va("resources:/%s/", resourceData->GetName().c_str()));

                            packfile->closeArchive();

                            // remove from the to-close list (!)
                            for (auto it = m_packFiles.begin(); it != m_packFiles.end(); it++)
                            {
                                if (it->second == packfile)
                                {
                                    m_packFiles.erase(it);
                                    break;
                                }
                            }
                        }

                        // and delete the resource (hope nobody kept a reference to that sucker, ha!)
                        TheResources.DeleteResource(resourceData);
                    }
                }
            }

            //std::string resourcePath = "citizen:/resources/";
            //TheResources.ScanResources(fiDevice::GetDevice("citizen:/setup2.xml", true), resourcePath);

            std::list<std::shared_ptr<Resource>> loadedResources;

            // mount any RPF files that we include
            for (auto& resource : m_requiredResources)
            {
                if (m_isUpdate && resource.IsProcessed())
                {
                    continue;
                }

                std::vector<rage::fiPackfile*> packFiles;

                for (auto& file : resource.GetFiles())
                {
                    if (file.filename.find(".rpf") != std::string::npos)
                    {
                        // get the path of the RPF
                        std::string markedFile = TheResources.GetCache()->GetMarkedFilenameFor(resource.GetName(), file.filename);

                        rage::fiPackfile* packFile = new rage::fiPackfile();
                        packFile->openArchive(markedFile.c_str(), true, false, 0);
                        packFile->mount(va("resources:/%s/", resource.GetName().c_str()));

                        packFiles.push_back(packFile);
                        m_packFiles.push_back(std::make_pair(va("resources:/%s/", resource.GetName().c_str()), packFile));
                    }
                }

                // load the resource
                auto resourceLoad = TheResources.AddResource(resource.GetName(), va("resources:/%s/", resource.GetName().c_str()));

                if (resourceLoad.get())
                {
                    resourceLoad->AddPackFiles(packFiles);

                    loadedResources.push_back(resourceLoad);
                }

                resource.SetProcessed();
            }

            if (m_isUpdate)
            {
                for (auto& resource : loadedResources)
                {
                    resource->Start();
                }
            }

            m_loadedResources = loadedResources;

            m_downloadState = DS_DONE;
        }

        break;
    }

    case DS_DONE:
        m_downloadState = DS_IDLE;

        if (m_isUpdate && !m_updateQueue.empty())
        {
            ProcessQueuedUpdates();
        }

        if (!m_serverLoadScreen.empty() && !m_isUpdate)
        {
            CustomLoadScreens::PrepareSwitchTo(m_serverLoadScreen);
        }

        m_isUpdate = false;

        g_netLibrary->DownloadsComplete();

        while (!g_netLibrary->ProcessPreGameTick())
        {
            HANDLE hThread = GetCurrentThread();

            MsgWaitForMultipleObjects(1, &hThread, TRUE, 15, 0);
        }

        return true;
    }

    return false;
}