mirror of
https://github.com/Garux/netradiant-custom.git
synced 2026-09-28 00:00:03 +02:00
unvanquished filesystem
This commit is contained in:
+1
-9
@@ -124,6 +124,7 @@ struct _QERFuncTable_1
|
||||
const char* ( *getSettingsPath )( );
|
||||
const char* ( *getMapsPath )( );
|
||||
|
||||
const char* ( *getGameFile )( );
|
||||
const char* ( *getGameName )( );
|
||||
const char* ( *getGameMode )( );
|
||||
|
||||
@@ -134,15 +135,6 @@ struct _QERFuncTable_1
|
||||
const char* ( *getGameDescriptionKeyValue )(const char* key);
|
||||
const char* ( *getRequiredGameDescriptionKeyValue )(const char* key);
|
||||
|
||||
void ( *attachGameToolsPathObserver )( ModuleObserver& observer );
|
||||
void ( *detachGameToolsPathObserver )( ModuleObserver& observer );
|
||||
void ( *attachEnginePathObserver )( ModuleObserver& observer );
|
||||
void ( *detachEnginePathObserver )( ModuleObserver& observer );
|
||||
void ( *attachGameNameObserver )( ModuleObserver& observer );
|
||||
void ( *detachGameNameObserver )( ModuleObserver& observer );
|
||||
void ( *attachGameModeObserver )( ModuleObserver& observer );
|
||||
void ( *detachGameModeObserver )( ModuleObserver& observer );
|
||||
|
||||
SignalHandlerId ( *XYWindowDestroyed_connect )( const SignalHandler& handler );
|
||||
void ( *XYWindowDestroyed_disconnect )( SignalHandlerId id );
|
||||
MouseEventHandlerId ( *XYWindowMouseDown_connect )( const MouseEventHandler& handler );
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/// \brief Text-output-formatting.
|
||||
|
||||
#include "itextstream.h"
|
||||
#include "string/string.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
@@ -33,6 +34,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "generic/arrayrange.h"
|
||||
|
||||
@@ -396,6 +398,48 @@ std::size_t write( const char* buffer, std::size_t length ){
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief A wrapper for a TextInputStream used for reading one text line at a time.
|
||||
template<typename TextInputStreamType, int SIZE = 1024>
|
||||
class TextLinesInputStream
|
||||
{
|
||||
TextInputStreamType& m_inputStream;
|
||||
char m_buffer[SIZE + 1];
|
||||
char* m_cur;
|
||||
char* m_end;
|
||||
|
||||
int fillBuffer(){
|
||||
m_end = m_buffer + m_inputStream.read( m_buffer, SIZE );
|
||||
m_cur = m_buffer;
|
||||
m_buffer[SIZE] = '\0';
|
||||
*m_end = '\0';
|
||||
return m_end - m_cur;
|
||||
}
|
||||
public:
|
||||
|
||||
TextLinesInputStream( TextInputStreamType& inputStream ) : m_inputStream( inputStream ), m_cur( m_buffer ), m_end( m_buffer ){
|
||||
m_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
CopiedString readLine(){
|
||||
std::string s;
|
||||
char* m_fin;
|
||||
|
||||
while ( (m_fin = strchr( m_cur, '\n' )) == 0 )
|
||||
{
|
||||
s.append( m_cur, m_end - m_cur );
|
||||
if ( fillBuffer() <= 0 ) break;
|
||||
}
|
||||
if ( m_fin != 0 ) {
|
||||
s.append( m_cur, m_fin - m_cur + 1 );
|
||||
m_cur = m_fin + 1;
|
||||
}
|
||||
|
||||
return CopiedString( s.c_str() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief A wrapper for a TextOutputStream, optimised for writing a few characters at a time.
|
||||
template<typename TextOutputStreamType, int SIZE = 1024>
|
||||
class BufferedTextOutputStream : public TextOutputStream
|
||||
|
||||
@@ -194,6 +194,14 @@ inline char* string_new( std::size_t length ){
|
||||
return string_new( length, allocator );
|
||||
}
|
||||
|
||||
/// \brief Allocates a new buffer large enough to hold two concatenated strings and fills it with strings.
|
||||
inline char* string_new_concat( const char* a, const char* b ){
|
||||
char* str = string_new( string_length( a ) + string_length( b ) );
|
||||
strcpy( str, a );
|
||||
strcat( str, b );
|
||||
return str;
|
||||
}
|
||||
|
||||
/// \brief Deallocates the \p buffer large enough to hold \p length characters.
|
||||
inline void string_release( char* string, std::size_t length ){
|
||||
DefaultAllocator<char> allocator;
|
||||
|
||||
+289
-34
@@ -84,6 +84,7 @@ struct archive_entry_t
|
||||
};
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
typedef std::list<archive_entry_t> archives_t;
|
||||
|
||||
@@ -132,7 +133,7 @@ const _QERArchiveTable* GetArchiveTable( ArchiveModules& archiveModules, const c
|
||||
tmp << LowerCase( ext );
|
||||
return archiveModules.findModule( tmp.c_str() );
|
||||
}
|
||||
static void InitPakFile( ArchiveModules& archiveModules, const char *filename ){
|
||||
static Archive* InitPakFile( ArchiveModules& archiveModules, const char *filename ){
|
||||
const _QERArchiveTable* table = GetArchiveTable( archiveModules, path_get_extension( filename ) );
|
||||
|
||||
if ( table != 0 ) {
|
||||
@@ -143,7 +144,11 @@ static void InitPakFile( ArchiveModules& archiveModules, const char *filename ){
|
||||
entry.is_pakfile = true;
|
||||
g_archives.push_back( entry );
|
||||
globalOutputStream() << " pak file: " << filename << "\n";
|
||||
|
||||
return entry.archive;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void pathlist_prepend_unique( GSList*& pathlist, char* path ){
|
||||
@@ -276,6 +281,219 @@ bool operator()( const CopiedString& self, const CopiedString& other ) const {
|
||||
|
||||
typedef std::set<CopiedString, PakLess> Archives;
|
||||
|
||||
Archive* AddPk3Dir( const char* fullpath ){
|
||||
if ( g_numDirs == VFS_MAXDIRS ) return 0;
|
||||
|
||||
strncpy( g_strDirs[g_numDirs], fullpath, PATH_MAX );
|
||||
g_strDirs[g_numDirs][PATH_MAX] = '\0';
|
||||
g_numDirs++;
|
||||
|
||||
{
|
||||
archive_entry_t entry;
|
||||
entry.name = fullpath;
|
||||
entry.archive = OpenArchive( fullpath );
|
||||
entry.is_pakfile = false;
|
||||
g_archives.push_back( entry );
|
||||
|
||||
return entry.archive;
|
||||
}
|
||||
}
|
||||
|
||||
// for unvanquished
|
||||
|
||||
bool IsUnvanquished(){
|
||||
return strncmp( GlobalRadiant().getGameFile(), "unvanquished", 12 ) == 0;
|
||||
}
|
||||
|
||||
struct pakfile_path_t
|
||||
{
|
||||
CopiedString fullpath; // full pak dir or pk3dir name
|
||||
bool is_pakfile; // defines is it .pk3dir or .pk3 file
|
||||
};
|
||||
|
||||
typedef std::pair<CopiedString, pakfile_path_t> PakfilePathsKV;
|
||||
typedef std::map<CopiedString, pakfile_path_t> PakfilePaths; // key must have no extension, only name
|
||||
|
||||
static PakfilePaths g_pakfile_paths;
|
||||
|
||||
void AddUnvPak( const char* name, const char* fullpath, bool is_pakfile ){
|
||||
pakfile_path_t pakfile_path;
|
||||
pakfile_path.fullpath = fullpath;
|
||||
pakfile_path.is_pakfile = is_pakfile;
|
||||
g_pakfile_paths.insert( PakfilePathsKV( name, pakfile_path ) );
|
||||
}
|
||||
|
||||
// Comparaison function for version numbers
|
||||
// Implementation is based on dpkg's version comparison code (verrevcmp() and order())
|
||||
// http://anonscm.debian.org/gitweb/?p=dpkg/dpkg.git;a=blob;f=lib/dpkg/version.c;hb=74946af470550a3295e00cf57eca1747215b9311
|
||||
static int char_weight(char c){
|
||||
if (std::isdigit(c))
|
||||
return 0;
|
||||
else if (std::isalpha(c))
|
||||
return c;
|
||||
else if (c == '~')
|
||||
return -1;
|
||||
else if (c)
|
||||
return c + 256;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int VersionCmp(const char* a, const char* b){
|
||||
while (*a || *b) {
|
||||
int firstDiff = 0;
|
||||
|
||||
while ((*a && !std::isdigit(*a)) || (*b && !std::isdigit(*b))) {
|
||||
int ac = char_weight(*a);
|
||||
int bc = char_weight(*b);
|
||||
|
||||
if (ac != bc)
|
||||
return ac - bc;
|
||||
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
while (*a == '0')
|
||||
a++;
|
||||
while (*b == '0')
|
||||
b++;
|
||||
|
||||
while (std::isdigit(*a) && std::isdigit(*b)) {
|
||||
if (firstDiff == 0)
|
||||
firstDiff = *a - *b;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
if (std::isdigit(*a))
|
||||
return 1;
|
||||
if (std::isdigit(*b))
|
||||
return -1;
|
||||
if (firstDiff)
|
||||
return firstDiff;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// takes name without ext, returns without ext
|
||||
static const char* GetLatestVersionOfUnvPak( const char* name ){
|
||||
const char* maxversion = 0;
|
||||
const char* result = 0;
|
||||
const char* pakname;
|
||||
const char* pakversion;
|
||||
int namelen = string_length( name );
|
||||
|
||||
for ( PakfilePaths::iterator i = g_pakfile_paths.begin(); i != g_pakfile_paths.end(); ++i )
|
||||
{
|
||||
pakname = i->first.c_str();
|
||||
if ( strncmp( pakname, name, namelen ) != 0 || pakname[namelen] != '_' ) continue;
|
||||
pakversion = pakname + (namelen + 1);
|
||||
if ( maxversion == 0 || VersionCmp( pakversion, maxversion ) > 0 ){
|
||||
maxversion = pakversion;
|
||||
result = pakname;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// release string after using
|
||||
static char* GetCurrentMapPakName(){
|
||||
char* mapdir;
|
||||
char* mapname;
|
||||
int mapnamelen;
|
||||
char* result = 0;
|
||||
|
||||
mapname = string_clone( GlobalRadiant().getMapName() );
|
||||
mapnamelen = string_length( mapname );
|
||||
|
||||
mapdir = strrchr( mapname, '/' );
|
||||
if ( mapdir ) {
|
||||
mapdir -= 12;
|
||||
if ( strncmp( mapdir, ".pk3dir/maps/", 13 ) == 0 ) {
|
||||
*mapdir = '\0';
|
||||
mapdir = strrchr( mapname, '/' );
|
||||
if ( mapdir ) mapdir++;
|
||||
else mapdir = mapname;
|
||||
result = string_clone( mapdir );
|
||||
}
|
||||
}
|
||||
|
||||
string_release( mapname, mapnamelen );
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
// prevent loading duplicates or circular references
|
||||
static Archives g_loaded_unv_paks;
|
||||
|
||||
// actual pak adding on initialise, deferred from InitDirectory
|
||||
// Unvanquished filesystem doesn't need load all paks it finds
|
||||
static void LoadPakWithDeps( const char* pakname ){
|
||||
const char* und = strrchr( pakname, '_' );
|
||||
if ( !und ) pakname = GetLatestVersionOfUnvPak( pakname );
|
||||
if ( !pakname || g_loaded_unv_paks.find( pakname ) != g_loaded_unv_paks.end() ) return;
|
||||
|
||||
PakfilePaths::iterator i = g_pakfile_paths.find( pakname );
|
||||
if ( i == g_pakfile_paths.end() ) return;
|
||||
|
||||
Archive* arc;
|
||||
if ( i->second.is_pakfile ){
|
||||
arc = InitPakFile( FileSystemQ3API_getArchiveModules(), i->second.fullpath.c_str() );
|
||||
} else {
|
||||
arc = AddPk3Dir( i->second.fullpath.c_str() );
|
||||
}
|
||||
g_loaded_unv_paks.insert( pakname );
|
||||
|
||||
ArchiveTextFile* depsFile = arc->openTextFile( "DEPS" );
|
||||
if ( !depsFile ) return;
|
||||
|
||||
{
|
||||
TextLinesInputStream<TextInputStream> istream = depsFile->getInputStream();
|
||||
|
||||
CopiedString line;
|
||||
const char* c;
|
||||
const char* p_name;
|
||||
const char* p_name_end;
|
||||
const char* p_version;
|
||||
const char* p_version_end;
|
||||
while ( line = istream.readLine(), string_length( line.c_str() ) ) {
|
||||
c = line.c_str();
|
||||
while ( std::isspace( *c ) && *c != '\0' ) ++c;
|
||||
p_name = c;
|
||||
while ( !std::isspace( *c ) && *c != '\0' ) ++c;
|
||||
p_name_end = c;
|
||||
while ( std::isspace( *c ) && *c != '\0' ) ++c;
|
||||
p_version = c;
|
||||
while ( !std::isspace( *c ) && *c != '\0' ) ++c;
|
||||
p_version_end = c;
|
||||
|
||||
if ( p_name_end - p_name == 0 ) continue;
|
||||
if ( p_version_end - p_version == 0 ) {
|
||||
const char* p_pakname;
|
||||
CopiedString name_final = CopiedString( StringRange( p_name, p_name_end ) );
|
||||
p_pakname = GetLatestVersionOfUnvPak( name_final.c_str() );
|
||||
if ( !p_pakname ) continue;
|
||||
LoadPakWithDeps( p_pakname );
|
||||
} else {
|
||||
int len = ( p_name_end - p_name ) + ( p_version_end - p_version ) + 1;
|
||||
char* p_pakname = string_new( len );
|
||||
strncpy( p_pakname, p_name, p_name_end - p_name );
|
||||
p_pakname[ p_name_end - p_name ] = '\0';
|
||||
strcat( p_pakname, "_" );
|
||||
strncat( p_pakname, p_version, p_version_end - p_version );
|
||||
LoadPakWithDeps( p_pakname );
|
||||
string_release( p_pakname, len );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
depsFile->release();
|
||||
}
|
||||
|
||||
// end for unvanquished
|
||||
|
||||
// =============================================================================
|
||||
// Global functions
|
||||
|
||||
@@ -337,15 +555,19 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
|
||||
}
|
||||
|
||||
if ( g_bUsePak ) {
|
||||
|
||||
GDir* dir = g_dir_open( path, 0, 0 );
|
||||
|
||||
if ( dir != 0 ) {
|
||||
globalOutputStream() << "vfs directory: " << path << "\n";
|
||||
|
||||
bool unv;
|
||||
unv = IsUnvanquished();
|
||||
|
||||
const char* ignore_prefix = "";
|
||||
const char* override_prefix = "";
|
||||
|
||||
{
|
||||
if ( !unv ) {
|
||||
// See if we are in "sp" or "mp" mapping mode
|
||||
const char* gamemode = gamemode_get();
|
||||
|
||||
@@ -381,23 +603,19 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
|
||||
}
|
||||
|
||||
const char *ext = strrchr( name, '.' );
|
||||
char tmppath[PATH_MAX];
|
||||
|
||||
if ( ext && !string_compare_nocase_upper( ext, ".pk3dir" ) ) {
|
||||
if ( g_numDirs == VFS_MAXDIRS ) {
|
||||
continue;
|
||||
}
|
||||
snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s%s/", path, name );
|
||||
g_strDirs[g_numDirs][PATH_MAX] = '\0';
|
||||
FixDOSName( g_strDirs[g_numDirs] );
|
||||
AddSlash( g_strDirs[g_numDirs] );
|
||||
g_numDirs++;
|
||||
|
||||
{
|
||||
archive_entry_t entry;
|
||||
entry.name = g_strDirs[g_numDirs - 1];
|
||||
entry.archive = OpenArchive( g_strDirs[g_numDirs - 1] );
|
||||
entry.is_pakfile = false;
|
||||
g_archives.push_back( entry );
|
||||
snprintf( tmppath, PATH_MAX, "%s%s/", path, name );
|
||||
tmppath[PATH_MAX] = '\0';
|
||||
FixDOSName( tmppath );
|
||||
AddSlash( tmppath );
|
||||
|
||||
if ( unv ) {
|
||||
AddUnvPak( CopiedString( StringRange( name, ext ) ).c_str(), tmppath, false );
|
||||
} else {
|
||||
AddPk3Dir( tmppath );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +628,11 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
|
||||
continue;
|
||||
}
|
||||
if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) {
|
||||
archivesOverride.insert( name );
|
||||
if ( unv ) {
|
||||
archives.insert( name );
|
||||
} else {
|
||||
archivesOverride.insert( name );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -420,19 +642,29 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
|
||||
g_dir_close( dir );
|
||||
|
||||
// add the entries to the vfs
|
||||
for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i )
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
strcpy( filename, path );
|
||||
strcat( filename, ( *i ).c_str() );
|
||||
InitPakFile( archiveModules, filename );
|
||||
}
|
||||
for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i )
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
strcpy( filename, path );
|
||||
strcat( filename, ( *i ).c_str() );
|
||||
InitPakFile( archiveModules, filename );
|
||||
char* fullpath;
|
||||
if ( unv ) {
|
||||
for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i ) {
|
||||
const char* name = i->c_str();
|
||||
const char* ext = strrchr( name, '.' );
|
||||
CopiedString name_final = CopiedString( StringRange( name, ext ) );
|
||||
fullpath = string_new_concat( path, name );
|
||||
AddUnvPak( name_final.c_str(), fullpath, true );
|
||||
string_release( fullpath, string_length( fullpath ) );
|
||||
}
|
||||
} else {
|
||||
for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i )
|
||||
{
|
||||
fullpath = string_new_concat( path, i->c_str() );
|
||||
InitPakFile( archiveModules, fullpath );
|
||||
string_release( fullpath, string_length( fullpath ) );
|
||||
}
|
||||
for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i )
|
||||
{
|
||||
fullpath = string_new_concat( path, i->c_str() );
|
||||
InitPakFile( archiveModules, fullpath );
|
||||
string_release( fullpath, string_length( fullpath ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -454,6 +686,9 @@ void Shutdown(){
|
||||
|
||||
g_numDirs = 0;
|
||||
g_numForbiddenDirs = 0;
|
||||
|
||||
g_pakfile_paths.clear();
|
||||
g_loaded_unv_paks.clear();
|
||||
}
|
||||
|
||||
#define VFS_SEARCH_PAK 0x1
|
||||
@@ -587,6 +822,25 @@ void initDirectory( const char *path ){
|
||||
InitDirectory( path, FileSystemQ3API_getArchiveModules() );
|
||||
}
|
||||
void initialise(){
|
||||
if ( IsUnvanquished() ) {
|
||||
const char* pakname;
|
||||
g_loaded_unv_paks.clear();
|
||||
|
||||
pakname = GetLatestVersionOfUnvPak( "tex-common" );
|
||||
if ( pakname ) LoadPakWithDeps( pakname );
|
||||
|
||||
pakname = GetLatestVersionOfUnvPak( "radiant" );
|
||||
if ( pakname ) LoadPakWithDeps( pakname );
|
||||
|
||||
pakname = GetCurrentMapPakName();
|
||||
if ( pakname && !string_empty( pakname ) ) {
|
||||
LoadPakWithDeps( pakname );
|
||||
}
|
||||
|
||||
g_pakfile_paths.clear();
|
||||
g_loaded_unv_paks.clear();
|
||||
}
|
||||
|
||||
globalOutputStream() << "filesystem initialised\n";
|
||||
g_observers.realise();
|
||||
}
|
||||
@@ -692,14 +946,15 @@ void forEachArchive( const ArchiveNameCallback& callback, bool pakonly, bool rev
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Quake3FileSystem g_Quake3FileSystem;
|
||||
|
||||
VirtualFileSystem& GetFileSystem(){
|
||||
return g_Quake3FileSystem;
|
||||
}
|
||||
|
||||
void FileSystem_Init(){
|
||||
}
|
||||
|
||||
void FileSystem_Shutdown(){
|
||||
}
|
||||
|
||||
VirtualFileSystem& GetFileSystem(){
|
||||
return g_Quake3FileSystem;
|
||||
}
|
||||
|
||||
+6
-6
@@ -336,14 +336,14 @@ EclassManagerAPI(){
|
||||
m_eclassmanager.realise = &EntityClass_realise;
|
||||
m_eclassmanager.unrealise = &EntityClass_unrealise;
|
||||
|
||||
GlobalRadiant().attachGameToolsPathObserver( g_EntityClassQuake3 );
|
||||
GlobalRadiant().attachGameModeObserver( g_EntityClassQuake3 );
|
||||
GlobalRadiant().attachGameNameObserver( g_EntityClassQuake3 );
|
||||
Radiant_attachGameToolsPathObserver( g_EntityClassQuake3 );
|
||||
Radiant_attachGameModeObserver( g_EntityClassQuake3 );
|
||||
Radiant_attachGameNameObserver( g_EntityClassQuake3 );
|
||||
}
|
||||
~EclassManagerAPI(){
|
||||
GlobalRadiant().detachGameNameObserver( g_EntityClassQuake3 );
|
||||
GlobalRadiant().detachGameModeObserver( g_EntityClassQuake3 );
|
||||
GlobalRadiant().detachGameToolsPathObserver( g_EntityClassQuake3 );
|
||||
Radiant_detachGameNameObserver( g_EntityClassQuake3 );
|
||||
Radiant_detachGameModeObserver( g_EntityClassQuake3 );
|
||||
Radiant_detachGameToolsPathObserver( g_EntityClassQuake3 );
|
||||
|
||||
EntityClassQuake3_destroy();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "ifilesystem.h"
|
||||
#include "iscriplib.h"
|
||||
#include "qerplugin.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
#include "string/string.h"
|
||||
#include "eclasslib.h"
|
||||
@@ -699,12 +700,12 @@ EntityClassFGDAPI(){
|
||||
m_eclassmanager.realise = &EntityClassFGD_realise;
|
||||
m_eclassmanager.unrealise = &EntityClassFGD_unrealise;
|
||||
|
||||
GlobalRadiant().attachGameToolsPathObserver( g_EntityClassFGD );
|
||||
GlobalRadiant().attachGameNameObserver( g_EntityClassFGD );
|
||||
Radiant_attachGameToolsPathObserver( g_EntityClassFGD );
|
||||
Radiant_attachGameNameObserver( g_EntityClassFGD );
|
||||
}
|
||||
~EntityClassFGDAPI(){
|
||||
GlobalRadiant().detachGameNameObserver( g_EntityClassFGD );
|
||||
GlobalRadiant().detachGameToolsPathObserver( g_EntityClassFGD );
|
||||
Radiant_detachGameNameObserver( g_EntityClassFGD );
|
||||
Radiant_detachGameToolsPathObserver( g_EntityClassFGD );
|
||||
|
||||
EntityClassFGD_destroy();
|
||||
}
|
||||
|
||||
+22
-10
@@ -146,22 +146,33 @@ glwindow_globals_t g_glwindow_globals;
|
||||
|
||||
|
||||
// VFS
|
||||
|
||||
bool g_vfsInitialized = false;
|
||||
|
||||
void VFS_Init(){
|
||||
if ( g_vfsInitialized ) return;
|
||||
QE_InitVFS();
|
||||
GlobalFileSystem().initialise();
|
||||
g_vfsInitialized = true;
|
||||
}
|
||||
void VFS_Shutdown(){
|
||||
if ( !g_vfsInitialized ) return;
|
||||
GlobalFileSystem().shutdown();
|
||||
g_vfsInitialized = false;
|
||||
}
|
||||
void VFS_Restart(){
|
||||
VFS_Shutdown();
|
||||
VFS_Init();
|
||||
}
|
||||
|
||||
class VFSModuleObserver : public ModuleObserver
|
||||
{
|
||||
std::size_t m_unrealised;
|
||||
public:
|
||||
VFSModuleObserver() : m_unrealised( 1 ){
|
||||
}
|
||||
void realise(){
|
||||
if ( --m_unrealised == 0 ) {
|
||||
QE_InitVFS();
|
||||
GlobalFileSystem().initialise();
|
||||
}
|
||||
VFS_Init();
|
||||
}
|
||||
void unrealise(){
|
||||
if ( ++m_unrealised == 1 ) {
|
||||
GlobalFileSystem().shutdown();
|
||||
}
|
||||
VFS_Shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -513,6 +524,7 @@ void gamemode_set( const char* gamemode ){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "os/dir.h"
|
||||
|
||||
class CLoadModule
|
||||
|
||||
+1
-2
@@ -245,8 +245,7 @@ void gamemode_set( const char* gamemode );
|
||||
void Radiant_attachGameModeObserver( ModuleObserver& observer );
|
||||
void Radiant_detachGameModeObserver( ModuleObserver& observer );
|
||||
|
||||
|
||||
|
||||
void VFS_Restart();
|
||||
void VFS_Construct();
|
||||
void VFS_Destroy();
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ MapModules& ReferenceAPI_getMapModules();
|
||||
#include "ifilesystem.h"
|
||||
#include "namespace.h"
|
||||
#include "moduleobserver.h"
|
||||
#include "moduleobservers.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -404,6 +405,31 @@ float g_MinWorldCoord = -64 * 1024;
|
||||
void AddRegionBrushes( void );
|
||||
void RemoveRegionBrushes( void );
|
||||
|
||||
/* Map open/close observers */
|
||||
|
||||
ModuleObservers g_mapPathObservers;
|
||||
|
||||
class UnvanquishedMapFileObserver : public ModuleObserver
|
||||
{
|
||||
void realise() {
|
||||
if ( strncmp( GlobalRadiant().getGameFile(), "unvanquished", 12 ) == 0 ) {
|
||||
// Restart VFS to apply new pak filtering based on mapname
|
||||
VFS_Restart();
|
||||
}
|
||||
}
|
||||
void unrealise() { }
|
||||
};
|
||||
|
||||
UnvanquishedMapFileObserver g_unvanquishedMapFileObserver;
|
||||
|
||||
void BindMapFileObservers(){
|
||||
g_mapPathObservers.attach( g_unvanquishedMapFileObserver );
|
||||
}
|
||||
|
||||
void UnBindMapFileObservers(){
|
||||
g_mapPathObservers.detach( g_unvanquishedMapFileObserver );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
@@ -422,6 +448,7 @@ void Map_Free(){
|
||||
|
||||
g_currentMap = 0;
|
||||
Brush_unlatchPreferences();
|
||||
g_mapPathObservers.unrealise();
|
||||
}
|
||||
|
||||
class EntityFindByClassname : public scene::Graph::Walker
|
||||
@@ -946,6 +973,7 @@ void Map_LoadFile( const char *filename ){
|
||||
}
|
||||
Brush_toggleFormat( i );
|
||||
g_map.m_name = filename;
|
||||
g_mapPathObservers.realise();
|
||||
Map_UpdateTitle( g_map );
|
||||
g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() );
|
||||
if ( format ) {
|
||||
@@ -1177,10 +1205,12 @@ void Map_RenameAbsolute( const char* absolute ){
|
||||
|
||||
g_map.m_resource->detach( g_map );
|
||||
GlobalReferenceCache().release( g_map.m_name.c_str() );
|
||||
g_mapPathObservers.unrealise();
|
||||
|
||||
g_map.m_resource = resource;
|
||||
|
||||
g_map.m_name = absolute;
|
||||
g_mapPathObservers.realise();
|
||||
Map_UpdateTitle( g_map );
|
||||
|
||||
g_map.m_resource->attach( g_map );
|
||||
@@ -1218,6 +1248,7 @@ void Map_New(){
|
||||
//globalOutputStream() << "Map_New\n";
|
||||
|
||||
g_map.m_name = "unnamed.map";
|
||||
g_mapPathObservers.realise();
|
||||
Map_UpdateTitle( g_map );
|
||||
|
||||
{
|
||||
|
||||
@@ -162,4 +162,7 @@ void Map_mergeClonedNames();
|
||||
|
||||
const char* getMapsPath();
|
||||
|
||||
void BindMapFileObservers();
|
||||
void UnBindMapFileObservers();
|
||||
|
||||
#endif
|
||||
|
||||
+7
-9
@@ -113,6 +113,10 @@ const char* TextureBrowser_getSelectedShader(){
|
||||
return TextureBrowser_GetSelectedShader( GlobalTextureBrowser() );
|
||||
}
|
||||
|
||||
const char* getGameFile(){
|
||||
return g_GamesDialog.m_sGameFile.c_str();
|
||||
}
|
||||
|
||||
class RadiantCoreAPI
|
||||
{
|
||||
_QERFuncTable_1 m_radiantcore;
|
||||
@@ -128,6 +132,7 @@ RadiantCoreAPI(){
|
||||
m_radiantcore.getSettingsPath = &SettingsPath_get;
|
||||
m_radiantcore.getMapsPath = &getMapsPath;
|
||||
|
||||
m_radiantcore.getGameFile = &getGameFile;
|
||||
m_radiantcore.getGameName = &gamename_get;
|
||||
m_radiantcore.getGameMode = &gamemode_get;
|
||||
|
||||
@@ -138,15 +143,6 @@ RadiantCoreAPI(){
|
||||
m_radiantcore.getGameDescriptionKeyValue = &GameDescription_getKeyValue;
|
||||
m_radiantcore.getRequiredGameDescriptionKeyValue = &GameDescription_getRequiredKeyValue;
|
||||
|
||||
m_radiantcore.attachGameToolsPathObserver = Radiant_attachGameToolsPathObserver;
|
||||
m_radiantcore.detachGameToolsPathObserver = Radiant_detachGameToolsPathObserver;
|
||||
m_radiantcore.attachEnginePathObserver = Radiant_attachEnginePathObserver;
|
||||
m_radiantcore.detachEnginePathObserver = Radiant_detachEnginePathObserver;
|
||||
m_radiantcore.attachGameNameObserver = Radiant_attachGameNameObserver;
|
||||
m_radiantcore.detachGameNameObserver = Radiant_detachGameNameObserver;
|
||||
m_radiantcore.attachGameModeObserver = Radiant_attachGameModeObserver;
|
||||
m_radiantcore.detachGameModeObserver = Radiant_detachGameModeObserver;
|
||||
|
||||
m_radiantcore.XYWindowDestroyed_connect = XYWindowDestroyed_connect;
|
||||
m_radiantcore.XYWindowDestroyed_disconnect = XYWindowDestroyed_disconnect;
|
||||
m_radiantcore.XYWindowMouseDown_connect = XYWindowMouseDown_connect;
|
||||
@@ -254,10 +250,12 @@ Radiant(){
|
||||
MapRoot_construct();
|
||||
|
||||
EnginePath_verify();
|
||||
BindMapFileObservers();
|
||||
EnginePath_Realise();
|
||||
}
|
||||
~Radiant(){
|
||||
EnginePath_Unrealise();
|
||||
UnBindMapFileObservers();
|
||||
|
||||
MapRoot_destroy();
|
||||
NullModel_destroy();
|
||||
|
||||
Reference in New Issue
Block a user