Fix node graph code incorrectly flagging node graphs as out of date if an outdated graph exists in a search path other than the mod directory
This commit is contained in:
parent
f3810c7107
commit
04c63d0aa9
4 changed files with 196 additions and 1 deletions
|
@ -29,6 +29,7 @@
|
||||||
* Fixed scientists crashing when speaking fear dialogue when enemy has been removed
|
* Fixed scientists crashing when speaking fear dialogue when enemy has been removed
|
||||||
* Disabled fall think function for weapons when the player picks it up to prevent possible double-pickup which removes the weapon and crashes the game
|
* Disabled fall think function for weapons when the player picks it up to prevent possible double-pickup which removes the weapon and crashes the game
|
||||||
* Disabled jump sounds while player is frozen (e.g. trigger_camera, trigger_playerfreeze)
|
* Disabled jump sounds while player is frozen (e.g. trigger_camera, trigger_playerfreeze)
|
||||||
|
* Fixed node graph code incorrectly flagging node graphs as out of date if an outdated graph exists in a search path other than the mod directory (e.g. a graph in `halflife_updated_addon/map/graphs`)
|
||||||
|
|
||||||
## Changes in V1.0.0 Beta 014
|
## Changes in V1.0.0 Beta 014
|
||||||
|
|
||||||
|
|
|
@ -2612,7 +2612,7 @@ bool CGraph::CheckNODFile(const char* szMapName)
|
||||||
bool retValue = true;
|
bool retValue = true;
|
||||||
|
|
||||||
int iCompare;
|
int iCompare;
|
||||||
if (COMPARE_FILE_TIME(bspFileName.c_str(), graphFileName.c_str(), &iCompare))
|
if (FileSystem_CompareFileTime(bspFileName.c_str(), graphFileName.c_str(), &iCompare))
|
||||||
{
|
{
|
||||||
if (iCompare > 0)
|
if (iCompare > 0)
|
||||||
{ // BSP file is newer.
|
{ // BSP file is newer.
|
||||||
|
|
|
@ -13,20 +13,106 @@
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
#include "PlatformHeaders.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "extdll.h"
|
#include "extdll.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifdef CLIENT_DLL
|
||||||
|
#include "hud.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
#include "filesystem_utils.h"
|
#include "filesystem_utils.h"
|
||||||
|
|
||||||
static CSysModule* g_pFileSystemModule = nullptr;
|
static CSysModule* g_pFileSystemModule = nullptr;
|
||||||
|
|
||||||
|
// Some methods used to launch the game don't set the working directory.
|
||||||
|
// This makes using relative paths that point to the game and/or mod directory difficult
|
||||||
|
// since C and C++ runtime APIs don't know to use the game directory as a base.
|
||||||
|
// As a workaround we look up the executable directory and use that as a base.
|
||||||
|
// See https://stackoverflow.com/a/1024937/1306648 for more platform-specific workarounds.
|
||||||
|
// The engine's filesystem doesn't provide functions to do this so we have to work around it.
|
||||||
|
static std::string g_GameDirectory;
|
||||||
|
static std::string g_ModDirectory;
|
||||||
|
|
||||||
|
static bool FileSystem_InitializeGameDirectory()
|
||||||
|
{
|
||||||
|
std::string gameDirectory;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
const std::size_t BufferSize = MAX_PATH + 1;
|
||||||
|
gameDirectory.resize(BufferSize);
|
||||||
|
|
||||||
|
const DWORD charactersWritten = GetModuleFileNameA(NULL, gameDirectory.data(), BufferSize);
|
||||||
|
|
||||||
|
if (charactersWritten == BufferSize)
|
||||||
|
{
|
||||||
|
// Path was truncated. Game is installed in the wrong location (Steam shouldn't allow this).
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const std::size_t BufferSize = PATH_MAX + 1;
|
||||||
|
directory.resize(BufferSize);
|
||||||
|
|
||||||
|
const ssize_t charactersWritten = readlink("/proc/self/exe", directory.data(), BufferSize);
|
||||||
|
|
||||||
|
if (charactersWritten < 0 || charactersWritten == BufferSize)
|
||||||
|
{
|
||||||
|
// Path was truncated. Game is installed in the wrong location (Steam shouldn't allow this).
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Resize buffer to actual size.
|
||||||
|
gameDirectory.resize(std::strlen(gameDirectory.c_str()));
|
||||||
|
|
||||||
|
// Truncate to directory name.
|
||||||
|
const std::size_t directoryEnd = gameDirectory.find_last_of(DefaultPathSeparatorChar);
|
||||||
|
|
||||||
|
if (directoryEnd == std::string::npos)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameDirectory.resize(directoryEnd);
|
||||||
|
|
||||||
|
gameDirectory.shrink_to_fit();
|
||||||
|
|
||||||
|
std::string modDirectory;
|
||||||
|
modDirectory.resize(BufferSize);
|
||||||
|
|
||||||
|
#ifdef CLIENT_DLL
|
||||||
|
modDirectory = gEngfuncs.pfnGetGameDirectory();
|
||||||
|
#else
|
||||||
|
g_engfuncs.pfnGetGameDir(modDirectory.data());
|
||||||
|
modDirectory.resize(std::strlen(modDirectory.c_str()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_GameDirectory = std::move(gameDirectory);
|
||||||
|
g_ModDirectory = g_GameDirectory + DefaultPathSeparatorChar + modDirectory;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileSystem_LoadFileSystem()
|
bool FileSystem_LoadFileSystem()
|
||||||
{
|
{
|
||||||
if (nullptr != g_pFileSystem)
|
if (nullptr != g_pFileSystem)
|
||||||
|
@ -73,6 +159,11 @@ bool FileSystem_LoadFileSystem()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FileSystem_InitializeGameDirectory())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +181,75 @@ void FileSystem_FreeFileSystem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystem_FixSlashes(std::string& fileName)
|
||||||
|
{
|
||||||
|
std::replace(fileName.begin(), fileName.end(), AlternatePathSeparatorChar, DefaultPathSeparatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t FileSystem_GetFileTime(const char* fileName)
|
||||||
|
{
|
||||||
|
if (nullptr == fileName)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string absoluteFileName = g_ModDirectory + DefaultPathSeparatorChar + fileName;
|
||||||
|
|
||||||
|
FileSystem_FixSlashes(absoluteFileName);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct _stat64i32 buf;
|
||||||
|
|
||||||
|
const int result = _stat64i32(absoluteFileName.c_str(), &buf);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time_t value = std::max(buf.st_ctime, buf.st_mtime);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
const int result = stat(absoluteFileName.c_str(), &buf);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time_t value = std::max(buf.st_ctim.tv_sec, buf.st_mtim.tv_sec);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSystem_CompareFileTime(const char* filename1, const char* filename2, int* iCompare)
|
||||||
|
{
|
||||||
|
*iCompare = 0;
|
||||||
|
|
||||||
|
if (!filename1 || !filename2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time_t time1 = FileSystem_GetFileTime(filename1);
|
||||||
|
const time_t time2 = FileSystem_GetFileTime(filename2);
|
||||||
|
|
||||||
|
if (time1 < time2)
|
||||||
|
{
|
||||||
|
*iCompare = -1;
|
||||||
|
}
|
||||||
|
else if (time1 > time2)
|
||||||
|
{
|
||||||
|
*iCompare = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::byte> FileSystem_LoadFileIntoBuffer(const char* fileName, FileContentFormat format, const char* pathID)
|
std::vector<std::byte> FileSystem_LoadFileIntoBuffer(const char* fileName, FileContentFormat format, const char* pathID)
|
||||||
{
|
{
|
||||||
assert(nullptr != g_pFileSystem);
|
assert(nullptr != g_pFileSystem);
|
||||||
|
|
|
@ -24,16 +24,50 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
constexpr char DefaultPathSeparatorChar = '\\';
|
||||||
|
constexpr char AlternatePathSeparatorChar = '/';
|
||||||
|
#else
|
||||||
|
constexpr char DefaultPathSeparatorChar = '/';
|
||||||
|
constexpr char AlternatePathSeparatorChar = '\\';
|
||||||
|
#endif
|
||||||
|
|
||||||
inline IFileSystem* g_pFileSystem = nullptr;
|
inline IFileSystem* g_pFileSystem = nullptr;
|
||||||
|
|
||||||
bool FileSystem_LoadFileSystem();
|
bool FileSystem_LoadFileSystem();
|
||||||
void FileSystem_FreeFileSystem();
|
void FileSystem_FreeFileSystem();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Replaces occurrences of ::AlternatePathSeparatorChar with ::DefaultPathSeparatorChar.
|
||||||
|
*/
|
||||||
|
void FileSystem_FixSlashes(std::string& fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the last modification time of the given file.
|
||||||
|
* Filenames are relative to the game directory.
|
||||||
|
*/
|
||||||
|
time_t FileSystem_GetFileTime(const char* fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares the file time of the given files located in the mod directory.
|
||||||
|
* @details Needed because IFileSystem::GetFileTime() does not provide a path ID parameter.
|
||||||
|
* @param filename1 First file to compare.
|
||||||
|
* @param filename2 Second file to compare.
|
||||||
|
* @param[out] iCompare Stores the result of the comparison.
|
||||||
|
* -@c 0 if equal
|
||||||
|
* -@c -1 if @p filename2 is newer than @p filename1
|
||||||
|
* -@c 1 if @p filename1 is newer than @p filename2
|
||||||
|
* @return @c true if filetimes were retrieved, false otherwise.
|
||||||
|
*/
|
||||||
|
bool FileSystem_CompareFileTime(const char* filename1, const char* filename2, int* iCompare);
|
||||||
|
|
||||||
enum class FileContentFormat
|
enum class FileContentFormat
|
||||||
{
|
{
|
||||||
Binary = 0,
|
Binary = 0,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue