diff --git a/Sources/Plasma/CoreLib/hsThread.h b/Sources/Plasma/CoreLib/hsThread.h index 49d0da2c..ae5e35f0 100644 --- a/Sources/Plasma/CoreLib/hsThread.h +++ b/Sources/Plasma/CoreLib/hsThread.h @@ -96,6 +96,7 @@ public: virtual hsError Run() = 0; // override this to do your work virtual void Start(); // initializes stuff and calls your Run() method virtual void Stop(); // sets fQuit = true and the waits for the thread to stop + virtual void OnQuit() { } // Static functions static void* Alloc(size_t size); // does not call operator::new(), may return nil diff --git a/Sources/Plasma/CoreLib/hsThread_Unix.cpp b/Sources/Plasma/CoreLib/hsThread_Unix.cpp index 4c3deb54..7ac17a66 100644 --- a/Sources/Plasma/CoreLib/hsThread_Unix.cpp +++ b/Sources/Plasma/CoreLib/hsThread_Unix.cpp @@ -76,6 +76,7 @@ extern "C" { pthread_mutex_lock(((hsThread*)param)->GetStartupMutex()); void* ret = (void*)(uintptr_t)((hsThread*)param)->Run(); pthread_mutex_unlock(((hsThread*)param)->GetStartupMutex()); + ((hsThread*)param)->OnQuit(); pthread_exit(ret); return ret; } diff --git a/Sources/Plasma/CoreLib/hsThread_Win.cpp b/Sources/Plasma/CoreLib/hsThread_Win.cpp index 31646497..4fb4e3c8 100644 --- a/Sources/Plasma/CoreLib/hsThread_Win.cpp +++ b/Sources/Plasma/CoreLib/hsThread_Win.cpp @@ -68,6 +68,7 @@ static unsigned int __stdcall gEntryPointBT(void* param) WinThreadParam* wtp = (WinThreadParam*)param; unsigned int result = wtp->fThread->Run(); ::ReleaseSemaphore(wtp->fQuitSemaH, 1, nil); // signal that we've quit + wtp->fThread->OnQuit(); delete param; return result; } diff --git a/Sources/Plasma/CoreLib/plFileSystem.cpp b/Sources/Plasma/CoreLib/plFileSystem.cpp index 59fd4c73..51aa3dc2 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.cpp +++ b/Sources/Plasma/CoreLib/plFileSystem.cpp @@ -570,3 +570,27 @@ plFileName plFileSystem::GetTempFilename(const char *prefix, const plFileName &p return result; #endif } + +plString plFileSystem::ConvertFileSize(uint64_t size) +{ + const char* labels[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" }; + if (size < 1024) + return plString::Format("%i B"); + + uint64_t last_div = size; + for (size_t i = 0; i < arrsize(labels); ++i) { + uint64_t my_div = last_div / 1024; + if (my_div < 1024) { + float decimal = static_cast(last_div) / 1024.f; + // Kilobytes are so small that we only care about whole numbers + if (i < 1) + return plString::Format("%.0f %s", decimal, labels[i]); + else + return plString::Format("%.2f %s", decimal, labels[i]); + } + last_div = my_div; + } + + // this should never happen + return plString::Format("%i %s", last_div, labels[arrsize(labels) - 1]); +} diff --git a/Sources/Plasma/CoreLib/plFileSystem.h b/Sources/Plasma/CoreLib/plFileSystem.h index 1b0bcb32..317e8a03 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.h +++ b/Sources/Plasma/CoreLib/plFileSystem.h @@ -338,6 +338,9 @@ namespace plFileSystem * system temp path is used. */ plFileName GetTempFilename(const char *prefix = "tmp", const plFileName &path = ""); + + /** Convert a file size from bytes to a human readable size. */ + plString ConvertFileSize(uint64_t size); } #endif // plFileSystem_Defined diff --git a/Sources/Plasma/FeatureLib/CMakeLists.txt b/Sources/Plasma/FeatureLib/CMakeLists.txt index 8b2b13a5..07552faa 100644 --- a/Sources/Plasma/FeatureLib/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/CMakeLists.txt @@ -17,6 +17,7 @@ add_subdirectory(pfJournalBook) # add_subdirectory(pfKI) add_subdirectory(pfLocalizationMgr) add_subdirectory(pfMessage) +add_subdirectory(pfPatcher) add_subdirectory(pfPython) add_subdirectory(pfSecurePreloader) add_subdirectory(pfSurface) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPatcher/CMakeLists.txt new file mode 100644 index 00000000..71a2e8dc --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPatcher/CMakeLists.txt @@ -0,0 +1,19 @@ +include_directories("../../CoreLib") +include_directories("../../NucleusLib") +include_directories("../../NucleusLib/inc") +include_directories("../../PubUtilLib") + +set(pfPatcher_SOURCES + plManifests.cpp + pfPatcher.cpp +) + +set(pfPatcher_HEADERS + plManifests.h + pfPatcher.h +) + +add_library(pfPatcher STATIC ${pfPatcher_SOURCES} ${pfPatcher_HEADERS}) + +source_group("Source Files" FILES ${pfPatcher_SOURCES}) +source_group("Header Files" FILES ${pfPatcher_HEADERS}) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp new file mode 100644 index 00000000..080b9c01 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp @@ -0,0 +1,450 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include +#include + +#include "pfPatcher.h" + +#include "HeadSpin.h" +#include "plCompression/plZlibStream.h" +#include "pnEncryption/plChecksum.h" +#include "plFileSystem.h" +#include "pnNetBase/pnNbError.h" +#include "plNetGameLib/plNetGameLib.h" +#include "plStatusLog/plStatusLog.h" +#include "hsStream.h" +#include "hsThread.h" +#include "hsTimer.h" + +// Some log helper defines +#define PatcherLogGreen(...) pfPatcher::GetLog()->AddLineF(plStatusLog::kGreen, __VA_ARGS__) +#define PatcherLogRed(...) pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, __VA_ARGS__) +#define PatcherLogWhite(...) pfPatcher::GetLog()->AddLineF(plStatusLog::kWhite, __VA_ARGS__) +#define PatcherLogYellow(...) pfPatcher::GetLog()->AddLineF(plStatusLog::kYellow, __VA_ARGS__) + +/** Patcher grunt work thread */ +struct pfPatcherWorker : public hsThread +{ + /** Represents a File/Auth download request */ + struct Request + { + enum { kFile, kManifest }; + + plString fName; + uint8_t fType; + class pfPatcherStream* fStream; + + Request(const plString& name, uint8_t type, class pfPatcherStream* s=nullptr) : + fName(name), fType(type), fStream(s) + { } + }; + + /** Human readable file flags */ + enum FileFlags + { + // Sound files only + kSndFlagCacheSplit = 1<<0, + kSndFlagStreamCompressed = 1<<1, + kSndFlagCacheStereo = 1<<2, + + // Any file + kFlagZipped = 1<<3, + }; + + std::deque fRequests; + std::deque fQueuedFiles; + + hsMutex fRequestMut; + hsMutex fFileMut; + hsSemaphore fFileSignal; + + pfPatcher::CompletionFunc fOnComplete; + pfPatcher::FileDownloadFunc fFileBeginDownload; + pfPatcher::FileDownloadFunc fFileDownloaded; + pfPatcher::ProgressTickFunc fProgressTick; + + pfPatcher* fParent; + volatile bool fStarted; + volatile bool fRequestActive; + + uint64_t fCurrBytes; + uint64_t fTotalBytes; + + pfPatcherWorker(); + ~pfPatcherWorker(); + + void OnQuit(); + + void EndPatch(ENetError result, const plString& msg=plString::Null); + bool IssueRequest(); + virtual hsError Run(); + void ProcessFile(); +}; + +// =================================================== + +class pfPatcherStream : public plZlibStream +{ + pfPatcherWorker* fParent; + plFileName fFilename; + uint32_t fFlags; + + uint64_t fBytesWritten; + float fDLStartTime; + + plString IMakeStatusMsg() const + { + float secs = hsTimer::GetSysSeconds() - fDLStartTime; + float bytesPerSec = fBytesWritten / secs; + return plFileSystem::ConvertFileSize(bytesPerSec) + "/s"; + } + + void IUpdateProgress(uint32_t count) + { + fBytesWritten += count; // just this file + fParent->fCurrBytes += count; // the entire everything + + // tick-tick-tick, tick-tick-tock + if (fParent->fProgressTick) + fParent->fProgressTick(fParent->fCurrBytes, fParent->fTotalBytes, IMakeStatusMsg()); + } + +public: + pfPatcherStream(pfPatcherWorker* parent, const plFileName& filename, const NetCliFileManifestEntry& entry) + : fParent(parent), fFlags(entry.flags), fBytesWritten(0) + { + // ugh. eap removed the compressed flag in his fail manifests + if (filename.GetFileExt().CompareI("gz") == 0) { + fFlags |= pfPatcherWorker::kFlagZipped; + parent->fTotalBytes += entry.zipSize; + } else + parent->fTotalBytes += entry.fileSize; + } + + virtual bool Open(const plFileName& filename, const char* mode) + { + fFilename = filename; + return plZlibStream::Open(filename, mode); + } + + virtual uint32_t Write(uint32_t count, const void* buf) + { + // tick whatever progress bar we have + IUpdateProgress(count); + + // write the appropriate blargs + if (hsCheckBits(fFlags, pfPatcherWorker::kFlagZipped)) + return plZlibStream::Write(count, buf); + else + return fOutput->Write(count, buf); + } + + void Begin() { fDLStartTime = hsTimer::GetSysSeconds(); } + plFileName GetFileName() const { return fFilename; } + void Unlink() const { plFileSystem::Unlink(fFilename); } +}; + +// =================================================== + +static void IFileManifestDownloadCB(ENetError result, void* param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount) +{ + pfPatcherWorker* patcher = static_cast(param); + + if (IS_NET_SUCCESS(result)) { + PatcherLogGreen("\tDownloaded Manifest '%S'", group); + { + hsTempMutexLock lock(patcher->fFileMut); + for (unsigned i = 0; i < entryCount; ++i) + patcher->fQueuedFiles.push_back(manifest[i]); + patcher->fFileSignal.Signal(); + } + patcher->IssueRequest(); + } else { + PatcherLogRed("\tDownload Failed: Manifest '%S'", group); + patcher->EndPatch(result, plString::FromWchar(group)); + } +} + +static void IFileThingDownloadCB(ENetError result, void* param, const plFileName& filename, hsStream* writer) +{ + pfPatcherWorker* patcher = static_cast(param); + pfPatcherStream* stream = static_cast(writer); + stream->Close(); + + if (IS_NET_SUCCESS(result)) { + PatcherLogGreen("\tDownloaded File '%s'", stream->GetFileName().AsString().c_str()); + if (patcher->fFileDownloaded) + patcher->fFileDownloaded(stream->GetFileName()); + patcher->IssueRequest(); + } else { + PatcherLogRed("\tDownloaded Failed: File '%s'", stream->GetFileName().AsString().c_str()); + stream->Unlink(); + patcher->EndPatch(result, filename.AsString()); + } + + delete stream; +} + +// =================================================== + +pfPatcherWorker::pfPatcherWorker() : + fStarted(false), fCurrBytes(0), fTotalBytes(0), fRequestActive(true) +{ } + +pfPatcherWorker::~pfPatcherWorker() +{ + { + hsTempMutexLock lock(fRequestMut); + std::for_each(fRequests.begin(), fRequests.end(), + [] (const Request& req) { + if (req.fStream) req.fStream->Close(); + delete req.fStream; + } + ); + fRequests.clear(); + } + + { + hsTempMutexLock lock(fFileMut); + fQueuedFiles.clear(); + } +} + +void pfPatcherWorker::OnQuit() +{ + // the thread's Run() has exited sanely... now we can commit hara-kiri + delete fParent; +} + +void pfPatcherWorker::EndPatch(ENetError result, const plString& msg) +{ + // Guard against multiple calls + if (fStarted) { + // Send end status + if (fOnComplete) + fOnComplete(result, msg); + + // yay log hax + if (IS_NET_SUCCESS(result)) + PatcherLogWhite("--- Patch Complete ---"); + else { + PatcherLogRed("\tNetwork Error: %S", NetErrorToString(result)); + PatcherLogWhite("--- Patch Killed by Error ---"); + } + } + + fStarted = false; + fFileSignal.Signal(); +} + +bool pfPatcherWorker::IssueRequest() +{ + hsTempMutexLock lock(fRequestMut); + if (fRequests.empty()) { + fRequestActive = false; + fFileSignal.Signal(); // make sure the patch thread doesn't deadlock! + return false; + } else + fRequestActive = true; + + const Request& req = fRequests.front(); + switch (req.fType) { + case Request::kFile: + req.fStream->Begin(); + if (fFileBeginDownload) + fFileBeginDownload(req.fStream->GetFileName()); + + NetCliFileDownloadRequest(req.fName, req.fStream, IFileThingDownloadCB, this); + break; + case Request::kManifest: + NetCliFileManifestRequest(IFileManifestDownloadCB, this, req.fName.ToWchar()); + break; + DEFAULT_FATAL(req.fType); + } + + fRequests.pop_front(); + return true; +} + +hsError pfPatcherWorker::Run() +{ + // So here's the rub: + // We have one or many manifests in the fRequests deque. We begin issuing those requests one-by one, starting here. + // As we receive the answer, the NetCli thread populates fQueuedFiles and pings the fFileSignal semaphore, then issues the next request... + // In this non-UI/non-Net thread, we do the stutter-prone/time-consuming IO/hashing operations. (Typically, the UI thread == Net thread) + // As we find files that need updating, we add them to fRequests. + // If there is no net request from ME when we find a file, we issue the request + // Once a file is downloaded, the next request is issued. + // When there are no files in my deque and no requests in my deque, we exit without errors. + + PatcherLogWhite("--- Patch Started (%i requests) ---", fRequests.size()); + fStarted = true; + IssueRequest(); + + // Now, work until we're done processing files + do { + fFileSignal.Wait(); + + hsTempMutexLock fileLock(fFileMut); + if (!fQueuedFiles.empty()) { + ProcessFile(); + continue; + } + + // This makes sure both queues are empty before exiting. + if (!fRequestActive) + if(!IssueRequest()) + break; + } while (fStarted); + + EndPatch(kNetSuccess); + return hsOK; +} + +void pfPatcherWorker::ProcessFile() +{ + do { + const NetCliFileManifestEntry& entry = fQueuedFiles.front(); + + // eap sucks + plString clName = plString::FromWchar(entry.clientName); + plString dlName = plString::FromWchar(entry.downloadName); + + // Check to see if ours matches + plFileInfo mine(clName); + if (mine.FileSize() == entry.fileSize) { + plMD5Checksum cliMD5(clName); + plMD5Checksum srvMD5; + srvMD5.SetFromHexString(plString::FromWchar(entry.md5, 32).c_str()); + + if (cliMD5 == srvMD5) { + fQueuedFiles.pop_front(); + continue; + } + } + + // If you got here, they're different. + PatcherLogYellow("\tEnqueuing '%S'", entry.clientName); + plFileSystem::CreateDir(plFileName(clName).StripFileName()); + + pfPatcherStream* s = new pfPatcherStream(this, dlName, entry); + s->Open(clName, "wb"); + + hsTempMutexLock lock(fRequestMut); + fRequests.push_back(Request(dlName, Request::kFile, s)); + fQueuedFiles.pop_front(); + + if (!fRequestActive) + IssueRequest(); + } while (!fQueuedFiles.empty()); +} + +// =================================================== + +plStatusLog* pfPatcher::GetLog() +{ + static plStatusLog* log = nullptr; + if (!log) + { + log = plStatusLogMgr::GetInstance().CreateStatusLog( + 20, + "patcher.log", + plStatusLog::kFilledBackground | plStatusLog::kAlignToTop | plStatusLog::kDeleteForMe); + } + return log; +} + +pfPatcher::pfPatcher() : fWorker(new pfPatcherWorker) { } +pfPatcher::~pfPatcher() { } + +// =================================================== + +void pfPatcher::OnCompletion(CompletionFunc cb) +{ + fWorker->fOnComplete = cb; +} + +void pfPatcher::OnFileDownloadBegin(FileDownloadFunc cb) +{ + fWorker->fFileBeginDownload = cb; +} + +void pfPatcher::OnFileDownloaded(FileDownloadFunc cb) +{ + fWorker->fFileDownloaded = cb; +} + +void pfPatcher::OnProgressTick(ProgressTickFunc cb) +{ + fWorker->fProgressTick = cb; +} + +// =================================================== + +void pfPatcher::RequestManifest(const plString& mfs) +{ + hsTempMutexLock lock(fWorker->fRequestMut); + fWorker->fRequests.push_back(pfPatcherWorker::Request(mfs, pfPatcherWorker::Request::kManifest)); +} + +void pfPatcher::RequestManifest(const std::vector& mfs) +{ + hsTempMutexLock lock(fWorker->fRequestMut); + std::for_each(mfs.begin(), mfs.end(), + [&] (const plString& name) { + fWorker->fRequests.push_back(pfPatcherWorker::Request(name, pfPatcherWorker::Request::kManifest)); + } + ); +} + +bool pfPatcher::Start() +{ + hsAssert(!fWorker->fStarted, "pfPatcher is one-use only. kthx."); + if (!fWorker->fStarted) { + fWorker->fParent = this; // wheeeee circular + fWorker->Start(); + return true; + } + return false; +} + diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h new file mode 100644 index 00000000..5262a1ec --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h @@ -0,0 +1,112 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#ifndef _pfPatcher_inc_ +#define _pfPatcher_inc_ + +#include +#include +#include + +#include "plString.h" +#include "pnNetBase/pnNbError.h" + +class plFileName; +class plStatusLog; + +/** Plasma File Patcher + * This is used to patch the client with one or many manifests at once. It assumes that + * we have permission to modify the game files, so be sure that you do! We memory manage + * ourselves, so allocate a new pfPatcher, add your manifests, and Start! + */ +class pfPatcher +{ + std::unique_ptr fWorker; + +public: + static plStatusLog* GetLog(); + +public: + /** Represents a function that takes the status and an optional message on completion. */ + typedef std::function CompletionFunc; + + /** Represents a function that takes (const plFileName&) on an interesting file operation. */ + typedef std::function FileDownloadFunc; + + /** Represents a function that takes (bytesDLed, totalBytes, statsStr) as a progress indicator. */ + typedef std::function ProgressTickFunc; + + pfPatcher(); + ~pfPatcher(); + + /** Set a callback that will be fired when the patcher finishes its dirty work. + * \remarks This may be called from any thread, so make sure your callback is + * thread safe! + */ + void OnCompletion(CompletionFunc cb); + + /** Set a callback that will be fired when the patcher issues a download request to the server. + * \remarks This will be called from the network thread. + */ + void OnFileDownloadBegin(FileDownloadFunc cb); + + /** Set a callback that will be fired when the patcher has finished downloading a file from the server. + * \remarks This will be called from the network thread. + */ + void OnFileDownloaded(FileDownloadFunc cb); + + /** Set a callback that will be fired when the patcher receives a chunk from the server. The status string + * will contain the current download speed. + * \remarks This will be called from the network thread. + */ + void OnProgressTick(ProgressTickFunc cb); + + void RequestManifest(const plString& mfs); + void RequestManifest(const std::vector& mfs); + + /** Start patching the requested manifests. Please note that after calling this, you should + * discard your pointer to this object as it will memory-manage itself. + */ + bool Start(); +}; + +#endif // _pfPatcher_inc_ diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp new file mode 100644 index 00000000..d368c2db --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp @@ -0,0 +1,90 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com +or by snail mail at: +Cyan Worlds, Inc. +14617 N Newport Hwy +Mead, WA 99021 + +*==LICENSE==*/ + +#include "plManifests.h" +#include "plFileSystem.h" + +// Helper that returns the appropriate string per build +#ifdef PLASMA_EXTERNAL_RELEASE +# define MANIFEST(in, ex) ex +#else +# define MANIFEST(in, ex) in +#endif // PLASMA_EXTERNAL_RELEASE + +plFileName plManifest::ClientExecutable() +{ + return MANIFEST("plClient.exe", "UruExplorer.exe"); +} + +plFileName plManifest::PatcherExecutable() +{ + return MANIFEST("plUruLauncher.exe", "UruLauncher.exe"); +} + +plString plManifest::ClientManifest() +{ + return MANIFEST("ThinInternal", "ThinExternal"); +} + +plString plManifest::ClientImageManifest() +{ + return MANIFEST("Internal", "External"); +} + +plString plManifest::PatcherManifest() +{ + return MANIFEST("InternalPatcher", "ExternalPatcher"); +} + +std::vector plManifest::EssentialGameManifests() +{ + std::vector mfs; + mfs.push_back("CustomAvatars"); + mfs.push_back("GlobalAnimations"); + mfs.push_back("GlobalAvatars"); + mfs.push_back("GlobalClothing"); + mfs.push_back("GlobalMarkers"); + mfs.push_back("GUI"); + + return mfs; +} + diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.h b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.h new file mode 100644 index 00000000..f21d039a --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.h @@ -0,0 +1,73 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#ifndef _plManifests_inc_ +#define _plManifests_inc_ + +#include + +class plFileName; +class plString; + +namespace plManifest +{ + /** Get the name of the client executable for this build type.*/ + plFileName ClientExecutable(); + + /** Get the name of the patcher executable for this build type.*/ + plFileName PatcherExecutable(); + + /** Get the name of the baseline client manifest for this build type. */ + plString ClientManifest(); + + /** Get the name of the full game manifest for this build type. */ + plString ClientImageManifest(); + + /** Get the name of the patcher manifest for this build type. */ + plString PatcherManifest(); + + /** Get a vector containing all manifests the game requires to initialize. */ + std::vector EssentialGameManifests(); + +} + +#endif // _plManifests_inc_