mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-23 03:58:59 +00:00
3426 lines
91 KiB
C++
3426 lines
91 KiB
C++
/*
|
|
* $Logfile: /DescentIII/Main/manage/manage.cpp $
|
|
* $Revision: 103 $
|
|
* $Date: 10/10/01 11:32a $
|
|
* $Author: Matt $
|
|
*
|
|
* Jason should put something here
|
|
*
|
|
* $Log: /DescentIII/Main/manage/manage.cpp $
|
|
*
|
|
* 103 10/10/01 11:32a Matt
|
|
* Added system to check for errors when reading in add-on data.
|
|
*
|
|
* 102 10/08/01 1:50p Matt
|
|
* Added a case for gamefile pagetype to avoid int3
|
|
*
|
|
* 101 4/19/00 5:07p Matt
|
|
* From Duane for 1.4
|
|
* Added checks, asserts, and fixes for bad return values
|
|
*
|
|
* 100 3/20/00 12:27p Matt
|
|
* Merge of Duane's post-1.3 changes.
|
|
* Mac pilot directory stuff.
|
|
*
|
|
* 99 10/26/99 3:30p Jeff
|
|
* handle extra.gam addon tablefile
|
|
*
|
|
* 98 10/20/99 6:27p Jeff
|
|
* sped up addon page popping (by saving page offsets)
|
|
*
|
|
* 97 10/19/99 9:14p Chris
|
|
* Fixed a memory free bug
|
|
*
|
|
* 96 8/11/99 5:32p Jeff
|
|
* changes to fix addon tablefile support so it works correctly
|
|
*
|
|
* 95 7/28/99 2:29p Kevin
|
|
* Added macintosh DLL extentions (msl)
|
|
*
|
|
* 94 5/14/99 12:45p Matt
|
|
* Removed yet more static data
|
|
*
|
|
* 93 5/14/99 12:33p Matt
|
|
* Fixed another case of too much local data for the Mac.
|
|
*
|
|
* 92 5/13/99 8:36p Matt
|
|
* Made some local variables global to get around the 32K local variable
|
|
* limit on the Mac.
|
|
*
|
|
* 91 5/12/99 3:01p Matt
|
|
* Declared one texpage structure statically for all the functions that
|
|
* need it, because the Mac limits local data to 32K.
|
|
*
|
|
* 90 4/30/99 8:53p Matt
|
|
* Added a "voice" directory for gamefiles.
|
|
*
|
|
* 89 4/22/99 3:26p Jason
|
|
* added transferring of pagelocks
|
|
*
|
|
* 88 4/20/99 12:06a Jeff
|
|
* added so files to data/scripts search path
|
|
*
|
|
* 87 4/15/99 5:21p Jason
|
|
* sped up table file loading
|
|
*
|
|
* 86 4/14/99 10:46a Kevin
|
|
* Removed OutrageMessageBox from release builds
|
|
*
|
|
* 85 4/14/99 1:33a Jeff
|
|
* fixed case mismatched #includes
|
|
*
|
|
* 84 4/12/99 3:05p Jason
|
|
* changes for 256 textures
|
|
*
|
|
* 83 3/05/99 10:42a Jason
|
|
* more deletion of pagelocls
|
|
*
|
|
* 82 3/04/99 1:46p Jason
|
|
* fixed some manage problems
|
|
*
|
|
* 81 2/27/99 5:15p Jason
|
|
* fixed search path bug
|
|
*
|
|
* 80 2/17/99 12:11p Jason
|
|
* added music directory to searchable list
|
|
*
|
|
* 79 2/16/99 11:35a Samir
|
|
* added art directory.
|
|
*
|
|
* 78 2/10/99 3:47p Jason
|
|
* before doing a backup, makes sure that the tablefile version is the
|
|
* same on the net and on the local machine
|
|
*
|
|
* 77 1/29/99 6:29p Jason
|
|
* first pass at adding bumpmaps
|
|
*
|
|
* 76 1/21/99 11:16p Jeff
|
|
* pulled out some structs and defines from header files and moved them
|
|
* into seperate header files so that multiplayer dlls don't require major
|
|
* game headers, just those new headers. Side effect is a shorter build
|
|
* time. Also cleaned up some header file #includes that weren't needed.
|
|
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
|
|
* manage.h and multi.h
|
|
*
|
|
* 75 1/13/99 2:49p Jeff
|
|
* added .msg to the search path for data\scripts
|
|
*
|
|
* 74 1/13/99 7:08a Jeff
|
|
* put some #ifdef's around some window's specific code (really only used
|
|
* in the editor, but EDITOR is never defined when building manage) so it
|
|
* builds in linux
|
|
*
|
|
* 73 12/30/98 6:52p Matt
|
|
* Fixed compile warnings
|
|
*
|
|
* 72 12/29/98 4:30p Jason
|
|
* added add-on data functionality
|
|
*
|
|
* 71 12/13/98 7:51p Jeff
|
|
* only check the script directory for cpp,dll and def files
|
|
*
|
|
* 70 12/11/98 5:50p Jeff
|
|
* implemented and added changes regarding Level&Scripting manage system
|
|
* and compiler interface
|
|
*
|
|
* 69 11/28/98 2:19p Jason
|
|
* fixed stupid filecopy bug
|
|
*
|
|
* 68 11/18/98 11:02a Jason
|
|
* temp fix for table problems
|
|
*
|
|
* 67 11/16/98 3:49p Jason
|
|
* changes for manage system
|
|
*
|
|
* 66 11/16/98 2:43p Jason
|
|
* better file checking for old files
|
|
*
|
|
* 65 11/13/98 12:30p Jason
|
|
* fixed reordered pages bug
|
|
*
|
|
* 64 11/13/98 12:30p Jason
|
|
* changes for weapons
|
|
*
|
|
* 63 11/06/98 6:00p Josh
|
|
* fixed dumb bug
|
|
*
|
|
* 62 11/06/98 5:28p Josh
|
|
* FROM JASON:upped tracklock limit
|
|
*
|
|
* 61 11/06/98 12:35p Jason
|
|
* more speedups for manage system
|
|
*
|
|
* 60 11/05/98 7:55p Jason
|
|
* changes for new manage system
|
|
*
|
|
* 59 11/04/98 11:02a Jason
|
|
* added levels and briefing directories to new "old files" update method
|
|
*
|
|
* 58 11/02/98 6:35p Jason
|
|
* changes for filter
|
|
*
|
|
* 57 11/02/98 6:02p Jason
|
|
* made yes network updates much faster
|
|
*
|
|
* 56 10/15/98 8:48a Matt
|
|
* Changed some errors to use Error() instead of OutrageMessageBox()
|
|
*
|
|
* 55 10/14/98 5:15p Jason
|
|
* added version checking to the table file
|
|
*
|
|
* 54 10/12/98 11:38p Jeff
|
|
* wrapped all the Object_info[].description whenever freed...trying to
|
|
* find an obscure bug. Added icon_name to manage page of Generic
|
|
*
|
|
* 53 10/12/98 10:31a Jason
|
|
* don't seach data directories if release
|
|
*
|
|
* 52 10/09/98 4:39p Jason
|
|
* fixed local table file message
|
|
*
|
|
* 51 10/09/98 2:27p Jason
|
|
* reorganized table file system
|
|
*
|
|
* 50 10/09/98 2:40a Jason
|
|
* fixed table file issues with demo
|
|
*
|
|
* 49 10/08/98 10:03p Jason
|
|
* more filtered table file stuff
|
|
*
|
|
* 48 10/08/98 7:05p Jason
|
|
* added file filter support
|
|
*
|
|
* 47 9/28/98 6:53p Kevin
|
|
* localized some multiplayer menus
|
|
*
|
|
* 46 9/25/98 4:37p Jason
|
|
* fixed dedicated server printing out progress messages
|
|
*
|
|
* 45 9/25/98 2:53p Jason
|
|
* added progress bar
|
|
*
|
|
* 44 9/25/98 12:24p Samir
|
|
* fixed bugs for release version.
|
|
*
|
|
* 43 9/24/98 6:22p Jason
|
|
* fixed RELEASE version asking to update network files
|
|
*
|
|
* 42 9/18/98 3:58p Jason
|
|
* change weapon reordering to do countermeasure weapons after generics
|
|
*
|
|
* 41 9/15/98 4:31p Jason
|
|
* added more functionality for the dedicated server
|
|
*
|
|
* 40 9/14/98 6:28p Jason
|
|
* first pass at getting dedicated server working
|
|
*
|
|
* 39 8/25/98 3:42p Jason
|
|
* fixed generic object problems
|
|
*
|
|
* 38 8/25/98 3:25p Jason
|
|
* turned off fast load trick
|
|
*
|
|
* 37 8/17/98 4:00p Jason
|
|
* Added mprintf
|
|
*
|
|
* 36 8/15/98 5:17p Matt
|
|
* Added new Base_directory variable. Got rid of D3_LOCAL check and
|
|
* 'local directory' registry variable.
|
|
*
|
|
* 35 8/13/98 6:34p Jason
|
|
* made table file loading much faster
|
|
*
|
|
* 34 8/10/98 1:49p Samir
|
|
* added music directory.
|
|
*
|
|
* 33 8/03/98 6:44p Jason
|
|
* set custom graphics in the search path
|
|
*
|
|
* 32 7/27/98 6:25p Jeff
|
|
* added creation of custom directories
|
|
*
|
|
* 31 6/23/98 2:43p Matt
|
|
* Changed calls to OutrageMessageBox() & Debug_MessageBox() to deal with
|
|
* int return value (instead of bool).
|
|
*
|
|
* 30 6/12/98 1:06p Jason
|
|
* added smart loading from local table file
|
|
*
|
|
* 29 5/04/98 5:00p Keneta
|
|
* FROM JASON:Fixed copyfile bug
|
|
*
|
|
* 28 5/04/98 4:42p Jason
|
|
* even better error checking
|
|
*
|
|
* 26 5/04/98 4:24p Jason
|
|
* upped MAX_TRIES
|
|
*
|
|
* 25 5/04/98 4:18p Jason
|
|
* added assert to prevent table file problems
|
|
*
|
|
* 24 3/31/98 3:49p Jason
|
|
* added memory lib
|
|
*
|
|
* 23 3/19/98 3:51p Samir
|
|
* added misc data directory.
|
|
*
|
|
* 22 2/23/98 2:00p Jason
|
|
* Pop up a message box when table file couldn't be opened
|
|
*
|
|
* 21 2/06/98 12:15p Jason
|
|
* upped max times program will try to delete the table file before
|
|
* bailing
|
|
*
|
|
* 20 2/04/98 11:47a Jason
|
|
* added dynamic description field to generic pages
|
|
*
|
|
* 19 1/26/98 11:32a Jason
|
|
* upped the number of times the system will try to delete a table file
|
|
*
|
|
* 18 1/22/98 2:49p Samir
|
|
* Added D3 Local Dir to the search path.
|
|
*
|
|
* 17 1/15/98 6:22p Jason
|
|
* added safety checks so the network won't copy over a primitive you have
|
|
* held locally
|
|
*
|
|
* 16 1/15/98 4:54p Mark
|
|
* FROM JASON:Do switcheroo a few times before giving up
|
|
*
|
|
* 15 12/22/97 3:50p Chris
|
|
*
|
|
* 14 11/17/97 4:16p Jason
|
|
* added briefings directory
|
|
*
|
|
* 13 9/09/97 4:07p Matt
|
|
* Added mprintf()
|
|
*
|
|
* 12 9/04/97 2:53p Samir
|
|
* Added gamefile and generic page strings to PageNames array.
|
|
*
|
|
* 11 8/12/97 12:47p Matt
|
|
* Only copy pagefile from net if different from local copy.
|
|
* When loading pages, print different char for each type
|
|
* Show how long it took to load the pagefile
|
|
*
|
|
* 10 8/11/97 1:54p Matt
|
|
* Ripped out robot & powerup pages, and added generic page
|
|
*
|
|
* 9 8/08/97 5:17p Jason
|
|
* made it so that when you update from the network it doesn't halt other
|
|
* users
|
|
*
|
|
* 8 8/08/97 3:44p Jason
|
|
* added code to support new generic page
|
|
*
|
|
* 7 8/08/97 1:57p Matt
|
|
* Took out error message now handled by mng_MakeLocker()
|
|
*
|
|
* 6 7/29/97 12:07p Jason
|
|
* added gamefile page for auto retrieval of non-standard page types
|
|
*
|
|
* 50 6/27/97 3:11p Jason
|
|
* added room directories
|
|
*
|
|
*
|
|
* 49 6/11/97 1:07p Samir
|
|
* The removal of gameos and replaced with oeApplication, oeDatabase
|
|
*
|
|
* 48 6/10/97 5:08p Jason
|
|
* added reorderpages menu item
|
|
*
|
|
* 47 6/05/97 2:52p Jason
|
|
* added megacell functions
|
|
*
|
|
* 46 5/30/97 11:41a Jason
|
|
* made a better error message if someone already has the table file
|
|
* locked upon startup
|
|
*
|
|
* 45 5/22/97 3:08p Jason
|
|
* added the ReorderPage function
|
|
*
|
|
* 44 5/16/97 3:53p Jason
|
|
* added filepage dialog
|
|
*
|
|
* 43 5/15/97 5:56 PM Jeremy
|
|
* made initlocaltable files check if the file exists by using cfexist
|
|
* rather than trying to open the file and checking the error code
|
|
*
|
|
* 42 5/14/97 6:38p Jason
|
|
* fixed a plethora of potential problems by locking the table file when
|
|
* someone is starting up.
|
|
*
|
|
* 41 5/14/97 6:44 PM Jeremy
|
|
* fixed a bug where local dir backup directory was not being set
|
|
* correctly in init local table files
|
|
*
|
|
* 40 5/13/97 3:41p Jason
|
|
* made all manage code work with the new device independant database
|
|
*
|
|
* 39 5/08/97 12:41p Jason
|
|
* made manage system work with device dependant path names
|
|
*
|
|
* 38 4/29/97 5:07p Samir
|
|
* Added levels directory to search path
|
|
*
|
|
* 37 4/25/97 6:16p Jason
|
|
* added switcheroo function
|
|
*
|
|
* 36 4/01/97 2:13p Jason
|
|
* changes for sound page functionality
|
|
*
|
|
* 35 3/31/97 4:35p Jason
|
|
* added player ship and weapon pages
|
|
*
|
|
* 34 3/25/97 3:10p Jason
|
|
* added robots and robot page functionality
|
|
*
|
|
* 33 3/17/97 4:27p Jason
|
|
* added sounds directory to path list
|
|
*
|
|
* 32 3/14/97 7:18p Matt
|
|
* Added missing include
|
|
*
|
|
* 31 3/14/97 6:13 PM Jeremy
|
|
* changed calls to windows "MessageBox" to OutrageMessageBox, changed
|
|
* call of GetUserName to os_database->get_user_name, #included descent.h
|
|
* in order to refer to the OS_database object, unincluded <windows.h> and
|
|
* <direct.h>
|
|
*
|
|
* 30 3/13/97 7:39p Matt
|
|
* Changed code to use getenv() (ANSI-standard) instead of
|
|
* GetEnvironmentVariable()
|
|
*
|
|
* 29 3/13/97 12:34p Matt
|
|
* Changed code to not leave directory changed after checking for presence
|
|
* of a directory.
|
|
*
|
|
* 28 3/13/97 11:37a Samir
|
|
* Changed os file functions to ddio file functions
|
|
*
|
|
* 27 3/10/97 2:23p Jason
|
|
* added auto creation of models directory
|
|
*
|
|
* 26 3/07/97 1:02p Jason
|
|
* Now uses Samir's OS specific directory functions
|
|
*
|
|
* 25 3/05/97 3:10p Jason
|
|
* added more door functionality
|
|
*
|
|
* 24 3/05/97 12:16p Jason
|
|
* added code to support our new 3d doors
|
|
*
|
|
* 23 3/03/97 6:21p Matt
|
|
* Changed cfile functions to use D3 naming convention
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#if defined(WIN32)
|
|
#include <windows.h>
|
|
#elif defined(__LINUX__)
|
|
#include "linux/linux_fix.h"
|
|
#endif
|
|
#include "descent.h"
|
|
#include "manage.h"
|
|
#include "pserror.h"
|
|
#include "gametexture.h"
|
|
#include "texpage.h"
|
|
#include "doorpage.h"
|
|
#include "soundpage.h"
|
|
#include "megapage.h"
|
|
#include "shippage.h"
|
|
#include "weaponpage.h"
|
|
#include "gamefilepage.h"
|
|
#include "mono.h"
|
|
#include "object.h"
|
|
#include "ddio.h"
|
|
#include "CFILE.H"
|
|
#include "appdatabase.h"
|
|
#include "genericpage.h"
|
|
#include "mem.h"
|
|
#include "dedicated_server.h"
|
|
#include "AppConsole.h"
|
|
#include "init.h"
|
|
#include "stringtable.h"
|
|
#include "args.h"
|
|
#include "vclip.h"
|
|
#include "polymodel.h"
|
|
int Old_table_method=0;
|
|
void mng_WriteNewUnknownPage (CFILE *outfile);
|
|
// This is for levels
|
|
char LocalLevelsDir[TABLE_NAME_LEN];
|
|
#ifdef MACINTOSH
|
|
char LocalPilotsDir[TABLE_NAME_LEN];
|
|
#endif
|
|
// This is for pages
|
|
char TableLockFilename[TABLE_NAME_LEN],TableFilename[TABLE_NAME_LEN];
|
|
char TempTableLockFilename[TABLE_NAME_LEN],TempTableFilename[TABLE_NAME_LEN];
|
|
char LocalTableFilename[TABLE_NAME_LEN],LocalTempTableFilename[TABLE_NAME_LEN];
|
|
char BackupTableFilename[TABLE_NAME_LEN],BackupLockFilename[TABLE_NAME_LEN];
|
|
char ManageGraphicsDir[TABLE_NAME_LEN],LocalManageGraphicsDir[TABLE_NAME_LEN];
|
|
char LocalModelsDir[TABLE_NAME_LEN],NetModelsDir[TABLE_NAME_LEN];
|
|
char LocalSoundsDir[TABLE_NAME_LEN],NetSoundsDir[TABLE_NAME_LEN];
|
|
char LocalRoomsDir[TABLE_NAME_LEN],NetRoomsDir[TABLE_NAME_LEN];
|
|
char LocalBriefingDir[TABLE_NAME_LEN],NetBriefingDir[TABLE_NAME_LEN];
|
|
char LocalScriptDir[TABLE_NAME_LEN],NetScriptDir[TABLE_NAME_LEN];
|
|
char LocalMiscDir[TABLE_NAME_LEN],NetMiscDir[TABLE_NAME_LEN];
|
|
char LocalArtDir[TABLE_NAME_LEN],NetArtDir[TABLE_NAME_LEN];
|
|
char LocalMusicDir[TABLE_NAME_LEN],NetMusicDir[TABLE_NAME_LEN];
|
|
char LocalVoiceDir[TABLE_NAME_LEN],NetVoiceDir[TABLE_NAME_LEN];
|
|
char NetTableDir[TABLE_NAME_LEN],LocalTableDir[TABLE_NAME_LEN];
|
|
char LocalD3Dir[TABLE_NAME_LEN],NetD3Dir[TABLE_NAME_LEN];
|
|
char LocalCustomGraphicsDir[TABLE_NAME_LEN];
|
|
char LocalCustomSoundsDir[TABLE_NAME_LEN];
|
|
char LockerFile [TABLE_NAME_LEN];
|
|
char VersionFile [TABLE_NAME_LEN];
|
|
char TableUser[TABLE_NAME_LEN];
|
|
char ErrorString[INFO_STRING_LEN],InfoString[INFO_STRING_LEN];
|
|
mngs_track_lock GlobalTrackLocks[MAX_TRACKLOCKS];
|
|
bool Use_old_update_method=false;
|
|
char *TablefileNameOverride = NULL;
|
|
// Only valid when first starting the editor
|
|
#define MAX_LOCKLIST_ELEMENTS 1000
|
|
mngs_Pagelock *LockList;
|
|
int Num_locklist,Starting_editor=0,Loading_locals=0,Fast_load_trick=0;
|
|
#define PRIMTYPE_OOF 0
|
|
#define PRIMTYPE_OGF 1
|
|
#define PRIMTYPE_WAV 2
|
|
#define PRIMTYPE_OAF 3
|
|
#define PRIMTYPE_FILE 4
|
|
#if defined(WIN32)
|
|
FILETIME TableTimeThreshold;
|
|
// Builds a list of old files so we know which ones to update
|
|
// Searches through all our netdirectories for old files
|
|
void BuildOldFileList (FILETIME threshold);
|
|
#endif
|
|
typedef struct
|
|
{
|
|
ubyte type;
|
|
char name[PAGENAME_LEN];
|
|
} old_file;
|
|
#define MAX_OLDFILE_ELEMENTS 10000
|
|
int Num_old_files=0;
|
|
old_file *OldFiles;
|
|
char *PageNames[]={"Unknown","Texture","Weapon","Robot","Powerup","Door","Player ship","Sound","Megacell", "Files", "Generic objects"};
|
|
#ifndef RELEASE
|
|
int Network_up=1;
|
|
int Stand_alone=0;
|
|
#else
|
|
int Network_up=0;
|
|
int Stand_alone=1;
|
|
#endif
|
|
void mng_BackupTableFile();
|
|
// returns 1 if network is up, 0 if down
|
|
int mng_IsNetworkUp()
|
|
{
|
|
char dir[100];
|
|
int ret;
|
|
if (Stand_alone)
|
|
return 0;
|
|
|
|
char net_dir[255]={0};
|
|
int dirlen=255;
|
|
Database->read("net directory", net_dir, &dirlen);
|
|
if (net_dir[0]==0)
|
|
return 0;
|
|
ddio_MakePath (dir,net_dir,"data",NULL);
|
|
|
|
ret=ddio_CreateDir (dir);
|
|
if (!ret)
|
|
{
|
|
char old_dir[100];
|
|
ddio_GetWorkingDir(old_dir,100);
|
|
if (!ddio_SetWorkingDir(dir))
|
|
return 0; // network down
|
|
else {
|
|
ddio_SetWorkingDir(old_dir); //restore directory
|
|
return 1; // directory is already there
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
void ReorderPages (int);
|
|
//#define JASONS_REORDERING
|
|
void Read256TextureNames ();
|
|
// Sets up our table files, get their filenames, etc.
|
|
// Returns 1 on success, zero on error
|
|
int mng_InitTableFiles()
|
|
{
|
|
ulong size=TABLE_NAME_LEN;
|
|
int answer;
|
|
Database->get_user_name(TableUser, &size);
|
|
if (FindArg("-filter"))
|
|
Use_old_update_method=true;
|
|
//Read256TextureNames ();
|
|
|
|
if (FindArg("-oldmethod"))
|
|
Use_old_update_method=true;
|
|
if (mng_IsNetworkUp())
|
|
{
|
|
#ifndef RELEASE
|
|
answer=OutrageMessageBox (MBOX_YESNO, "Do you wish to update your data files from the network?\n(If NO is selected then you will have to restart to use networking functions)");
|
|
#else
|
|
answer = IDNO;
|
|
#endif
|
|
if (answer == IDNO)
|
|
Network_up=0;
|
|
else
|
|
{
|
|
Network_up=1;
|
|
#ifndef RELEASE
|
|
#if defined(WIN32)
|
|
if (cfexist("c:\\edload"))
|
|
Use_old_update_method=true;
|
|
else
|
|
{
|
|
CFILE *fp=cfopen("c:\\edload","wt");
|
|
cfclose (fp);
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mprintf ((0,"Network is down...\n"));
|
|
Network_up=0;
|
|
}
|
|
|
|
if (Network_up==0)
|
|
{
|
|
mng_InitLocalTables();
|
|
mng_InitLocalDirectories();
|
|
mng_CheckToCreateLocalTables();
|
|
mng_InitTrackLocks();
|
|
}
|
|
else
|
|
{
|
|
// Do locals
|
|
mng_InitLocalTables ();
|
|
mng_InitLocalDirectories();
|
|
mng_CheckToCreateLocalTables();
|
|
|
|
// Do network
|
|
mng_InitNetTables();
|
|
mng_InitNetDirectories ();
|
|
mng_CheckToCreateNetTables();
|
|
mng_BackupTableFile();
|
|
mng_InitPagelocks ();
|
|
mng_InitTrackLocks();
|
|
#ifdef JASONS_REORDERING
|
|
ReorderPages(0);
|
|
return 0;
|
|
#endif
|
|
}
|
|
return 1;
|
|
}
|
|
// Loads our tables
|
|
int mng_LoadTableFiles (int show_progress)
|
|
{
|
|
if (Network_up)
|
|
{
|
|
LockList=(mngs_Pagelock *)mem_malloc (MAX_LOCKLIST_ELEMENTS*sizeof(mngs_Pagelock));
|
|
Num_locklist=mng_GetListOfLocks (LockList,MAX_LOCKLIST_ELEMENTS,TableUser);
|
|
OldFiles=(old_file *)mem_malloc (MAX_OLDFILE_ELEMENTS*sizeof(old_file));
|
|
Num_old_files=0;
|
|
ASSERT (OldFiles);
|
|
#if defined (WIN32)
|
|
if (TableTimeThreshold.dwHighDateTime!=-1)
|
|
BuildOldFileList (TableTimeThreshold);
|
|
#endif
|
|
|
|
Starting_editor=1;
|
|
}
|
|
int ret1,ret2;
|
|
if (Fast_load_trick && !FindArg ("-filter"))
|
|
Network_up=0;
|
|
|
|
ret1=mng_LoadNetPages(show_progress);
|
|
if (Fast_load_trick)
|
|
{
|
|
Network_up=1;
|
|
Fast_load_trick=0;
|
|
}
|
|
ret2=mng_LoadLocalPages();
|
|
if (Network_up)
|
|
{
|
|
Starting_editor=0;
|
|
Num_locklist=0;
|
|
Num_old_files=0;
|
|
mem_free (OldFiles);
|
|
mem_free (LockList);
|
|
#ifndef RELEASE
|
|
#if defined(WIN32)
|
|
remove ("c:\\edload");
|
|
#endif
|
|
#endif
|
|
}
|
|
RemapEverything();
|
|
|
|
|
|
if (!ret1 || !ret2)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
// This is for initting tables on STAND_ALONE, if the network is down, or if
|
|
// the user doesn't want network support
|
|
int mng_InitLocalTables ()
|
|
{
|
|
//Set the local table directory from the base directory
|
|
strcpy(LocalD3Dir,Base_directory);
|
|
mprintf ((1,"Local dir:%s\n",LocalD3Dir));
|
|
|
|
// Make the CFILE system first look at our local directories. If the goods aren't
|
|
// found there, try out on the network
|
|
ddio_MakePath (LocalTableDir,LocalD3Dir,"data","tables",NULL);
|
|
ddio_MakePath (LocalManageGraphicsDir,LocalD3Dir,"data","graphics",NULL);
|
|
ddio_MakePath (LocalModelsDir,LocalD3Dir,"data","models",NULL);
|
|
ddio_MakePath (LocalSoundsDir,LocalD3Dir,"data","sounds",NULL);
|
|
ddio_MakePath (LocalCustomSoundsDir,LocalD3Dir,"custom","sounds",NULL);
|
|
ddio_MakePath (LocalCustomGraphicsDir,LocalD3Dir,"custom","graphics",NULL);
|
|
ddio_MakePath (LocalRoomsDir,LocalD3Dir,"data","rooms",NULL);
|
|
ddio_MakePath (LocalBriefingDir,LocalD3Dir,"data","briefings",NULL);
|
|
ddio_MakePath (LocalScriptDir,LocalD3Dir,"data","scripts",NULL);
|
|
ddio_MakePath (LocalMiscDir,LocalD3Dir,"data","misc",NULL);
|
|
ddio_MakePath (LocalArtDir, LocalD3Dir,"data", "art", NULL);
|
|
ddio_MakePath (LocalMusicDir, LocalD3Dir, "data", "music", NULL);
|
|
ddio_MakePath (LocalVoiceDir, LocalD3Dir, "data", "voice", NULL);
|
|
ddio_MakePath (LocalLevelsDir,LocalD3Dir,"data","levels",NULL);
|
|
cf_SetSearchPath (LocalD3Dir, NULL);
|
|
#ifdef MACINTOSH
|
|
ddio_MakePath (LocalPilotsDir,LocalD3Dir,"pilots",NULL);
|
|
cf_SetSearchPath (LocalPilotsDir, "plt", NULL);
|
|
#endif
|
|
#ifndef RELEASE
|
|
cf_SetSearchPath (LocalLevelsDir, NULL);
|
|
cf_SetSearchPath (LocalTableDir,NULL); // Local table directory
|
|
|
|
cf_SetSearchPath (LocalManageGraphicsDir,NULL);
|
|
cf_SetSearchPath (LocalModelsDir,NULL);
|
|
cf_SetSearchPath (LocalSoundsDir,NULL);
|
|
cf_SetSearchPath (LocalRoomsDir,NULL);
|
|
cf_SetSearchPath (LocalBriefingDir,NULL);
|
|
cf_SetSearchPath (LocalScriptDir,"cpp","dll","def","msg","so","msl","dylib",NULL);
|
|
cf_SetSearchPath (LocalMiscDir, NULL);
|
|
cf_SetSearchPath (LocalArtDir, NULL);
|
|
cf_SetSearchPath (LocalMusicDir, NULL);
|
|
cf_SetSearchPath (LocalVoiceDir, NULL);
|
|
#endif
|
|
|
|
if (Network_up)
|
|
{
|
|
ddio_MakePath (LocalTableFilename,LocalTableDir,LOCAL_TABLE,NULL);
|
|
ddio_MakePath (LocalTempTableFilename,LocalTableDir,TEMP_LOCAL_TABLE,NULL);
|
|
}
|
|
else
|
|
{
|
|
strcpy (LocalTableFilename,LOCAL_TABLE);
|
|
strcpy (LocalTempTableFilename,TEMP_LOCAL_TABLE);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
int mng_InitNetTables ()
|
|
{
|
|
char dir[255];
|
|
int dirlen=255;
|
|
Database->read("net directory", dir, &dirlen);
|
|
if (dir[0]==0)
|
|
Error ("D3_DIR environment variable not set.");
|
|
|
|
strcpy (NetD3Dir,dir);
|
|
mprintf ((1,"Net dir:%s\n",NetD3Dir));
|
|
ddio_MakePath (NetModelsDir,NetD3Dir,"data","models",NULL);
|
|
ddio_MakePath (NetSoundsDir,NetD3Dir,"data","sounds",NULL);
|
|
ddio_MakePath (NetRoomsDir,NetD3Dir,"data","rooms",NULL);
|
|
ddio_MakePath (NetBriefingDir,NetD3Dir,"data","briefings",NULL);
|
|
ddio_MakePath (NetScriptDir,NetD3Dir,"data","scripts",NULL);
|
|
ddio_MakePath (NetMiscDir,NetD3Dir,"data","misc",NULL);
|
|
ddio_MakePath (ManageGraphicsDir,NetD3Dir,"data","graphics",NULL);
|
|
ddio_MakePath (NetTableDir,NetD3Dir,"data","tables",NULL);
|
|
ddio_MakePath (NetArtDir,NetD3Dir,"data", "art", NULL);
|
|
ddio_MakePath (NetMusicDir, NetD3Dir, "data", "music", NULL);
|
|
ddio_MakePath (NetVoiceDir, NetD3Dir, "data", "voice", NULL);
|
|
ddio_MakePath (TableLockFilename,NetTableDir,"table.lok",NULL);
|
|
ddio_MakePath (BackupLockFilename,NetTableDir,"tablelok.bak",NULL);
|
|
ddio_MakePath (BackupTableFilename,NetTableDir,"table.bak",NULL);
|
|
ddio_MakePath (TableFilename,NetTableDir,NET_TABLE,NULL);
|
|
ddio_MakePath (TempTableLockFilename,NetTableDir,"lock.tmp",NULL);
|
|
ddio_MakePath (TempTableFilename,NetTableDir,TEMP_NET_TABLE,NULL);
|
|
ddio_MakePath (LockerFile,NetTableDir,"locker",NULL);
|
|
ddio_MakePath (VersionFile,NetTableDir,"TableVersion",NULL);
|
|
|
|
cf_SetSearchPath (ManageGraphicsDir,NULL);
|
|
cf_SetSearchPath (NetModelsDir,NULL);
|
|
cf_SetSearchPath (NetSoundsDir,NULL);
|
|
cf_SetSearchPath (NetRoomsDir,NULL);
|
|
cf_SetSearchPath (NetMiscDir,NULL);
|
|
cf_SetSearchPath (NetMusicDir, NULL);
|
|
cf_SetSearchPath (NetVoiceDir, NULL);
|
|
return 1;
|
|
}
|
|
void mng_CheckToCreateNetTables()
|
|
{
|
|
CFILE *infile,*outfile;
|
|
|
|
ASSERT (Stand_alone!=1);
|
|
|
|
infile=(CFILE *)cfopen (TableFilename,"rb");
|
|
if (infile==NULL)
|
|
{
|
|
if (errno==ENOENT)
|
|
{
|
|
outfile=(CFILE *)cfopen (TableFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
mprintf ((0,"Error creating table file! The network must be down...\n"));
|
|
Network_up=0;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewUnknownPage (outfile);
|
|
cfclose (outfile);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mprintf ((0,"Error creating table file! The network must be down...\n"));
|
|
Network_up=0;
|
|
}
|
|
}
|
|
|
|
if (infile)
|
|
cfclose (infile);
|
|
}
|
|
// Checks to see if there is a table file...if not, create one with a dummy page
|
|
void mng_CheckToCreateLocalTables()
|
|
{
|
|
CFILE *outfile;
|
|
|
|
if (!Network_up)
|
|
{
|
|
strcpy (TableFilename,NET_TABLE);
|
|
mprintf((0, "table filename = %s\n", TableFilename));
|
|
return;
|
|
}
|
|
|
|
if (!cfexist(LocalTableFilename))
|
|
{
|
|
outfile=(CFILE *)cfopen (LocalTableFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
Error("Error creating local table file!");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewUnknownPage (outfile);
|
|
cfclose (outfile);
|
|
}
|
|
}
|
|
}
|
|
// Creates directories if needed
|
|
void mng_InitLocalDirectories ()
|
|
{
|
|
char dir[255];
|
|
ddio_MakePath (dir,LocalD3Dir,"custom",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"custom","graphics",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"custom","sounds",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"custom","cache",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"custom","settings",NULL);
|
|
ddio_CreateDir(dir);
|
|
#ifdef MACINTOSH
|
|
ddio_MakePath (dir,LocalD3Dir,"pilots",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"demo",NULL);
|
|
ddio_CreateDir(dir);
|
|
#endif
|
|
cf_SetSearchPath (LocalCustomGraphicsDir,NULL);
|
|
cf_SetSearchPath (LocalCustomSoundsDir,NULL);
|
|
|
|
if (Network_up)
|
|
{
|
|
ddio_MakePath (dir,LocalD3Dir,"data",NULL);
|
|
ddio_CreateDir(dir);
|
|
|
|
ddio_MakePath (dir,LocalD3Dir,"data","tables",NULL);
|
|
ddio_CreateDir(dir);
|
|
|
|
ddio_MakePath (dir,LocalD3Dir,"data","graphics",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","sounds",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","rooms",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","levels",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","models",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","briefings",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","scripts",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","misc",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","art",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","music",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,LocalD3Dir,"data","voice",NULL);
|
|
ddio_CreateDir(dir);
|
|
}
|
|
}
|
|
void mng_InitNetDirectories ()
|
|
{
|
|
char dir[255];
|
|
|
|
if (Stand_alone)
|
|
return;
|
|
ddio_MakePath (dir,NetD3Dir,"data",NULL);
|
|
ddio_CreateDir(dir);
|
|
|
|
ddio_MakePath (dir,NetD3Dir,"data","tables",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","graphics",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","sounds",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","rooms",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","levels",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","models",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","briefings",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","scripts",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","misc",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","art",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","music",NULL);
|
|
ddio_CreateDir(dir);
|
|
ddio_MakePath (dir,NetD3Dir,"data","voice",NULL);
|
|
ddio_CreateDir(dir);
|
|
}
|
|
extern int TableVersionCurrent();
|
|
#if !defined(WIN32)
|
|
void mng_BackupTableFile(){}
|
|
#else
|
|
void mng_BackupTableFile ()
|
|
{
|
|
char str[200];
|
|
Fast_load_trick=0;
|
|
if (!TableVersionCurrent())
|
|
{
|
|
Error ("You must do a source update and recompile. The data on the network is newer that your sourcecode.");
|
|
return;
|
|
}
|
|
|
|
ddio_MakePath (str,LocalTableDir,NET_TABLE,NULL);
|
|
if (!cfexist(str))
|
|
{
|
|
TableTimeThreshold.dwHighDateTime=0;
|
|
TableTimeThreshold.dwLowDateTime=0;
|
|
}
|
|
else
|
|
{
|
|
WIN32_FIND_DATA filedata;
|
|
HANDLE filehandle=FindFirstFile (str,&filedata);
|
|
if (filehandle==INVALID_HANDLE_VALUE)
|
|
{
|
|
Error ("Couldn't open net table file for some reason!");
|
|
return;
|
|
}
|
|
TableTimeThreshold=filedata.ftLastWriteTime;
|
|
FindClose (filehandle);
|
|
}
|
|
|
|
if (!cfexist(str) || cf_Diff(str,TableFilename)) {
|
|
mprintf ((0,"Making local copy of table file.\n"));
|
|
|
|
if (!cf_CopyFile (str,TableFilename,1))
|
|
Error ("There was an error making a backup copy of the table file.\n");
|
|
ddio_MakePath (str,LocalTableDir,"tablelok.loc",NULL);
|
|
if (!cf_CopyFile (str,TableLockFilename,1))
|
|
Error ("There was an error making a backup copy of the locker table file.\n");
|
|
}
|
|
else
|
|
{
|
|
mprintf((0,"Local table file same as network copy.\n"));
|
|
TableTimeThreshold.dwHighDateTime=-1;
|
|
Fast_load_trick=1;
|
|
}
|
|
}
|
|
#endif
|
|
void mng_WriteUnknownPage (CFILE *outfile)
|
|
{
|
|
// Function for writing out "undefined" page...useful for placeholding
|
|
cf_WriteByte (outfile,PAGETYPE_UNKNOWN);
|
|
}
|
|
void mng_WriteNewUnknownPage (CFILE *outfile)
|
|
{
|
|
// Function for writing out "undefined" page...useful for placeholding
|
|
int offset=StartManagePage(outfile,PAGETYPE_UNKNOWN);
|
|
EndManagePage (outfile,offset);
|
|
}
|
|
// Clear out tracklocks
|
|
void mng_InitTrackLocks ()
|
|
{
|
|
for (int i=0;i<MAX_TRACKLOCKS;i++)
|
|
{
|
|
GlobalTrackLocks[i].used=0;
|
|
GlobalTrackLocks[i].pagetype=PAGETYPE_UNKNOWN;
|
|
GlobalTrackLocks[i].name[0]=0;
|
|
}
|
|
}
|
|
// Given a name, returns the index of the tracklock with that name
|
|
// -1 indicates that it wasn't found
|
|
int mng_FindTrackLock (char *name,int pagetype)
|
|
{
|
|
int i;
|
|
for (i=0;i<MAX_TRACKLOCKS;i++)
|
|
{
|
|
if (GlobalTrackLocks[i].used && GlobalTrackLocks[i].pagetype==pagetype && !stricmp (name,GlobalTrackLocks[i].name))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
// Searches through global array of tracklocks and returns first free one
|
|
// Sets the tracklock to be named "name" and its type "pagetype"
|
|
// returns -1 if none free
|
|
int mng_AllocTrackLock(char *name,int pagetype)
|
|
{
|
|
int i;
|
|
for (i=0;i<MAX_TRACKLOCKS;i++)
|
|
if (GlobalTrackLocks[i].used==0)
|
|
{
|
|
strcpy (GlobalTrackLocks[i].name,name);
|
|
GlobalTrackLocks[i].pagetype=pagetype;
|
|
GlobalTrackLocks[i].used=1;
|
|
mprintf ((0,"Tracklock %s allocated.\n",name));
|
|
return i;
|
|
}
|
|
Error ("Couldn't get a free tracklock!");
|
|
return -1;
|
|
}
|
|
// Frees a tracklock
|
|
void mng_FreeTrackLock (int n)
|
|
{
|
|
mprintf ((0,"Tracklock %s freed.\n",GlobalTrackLocks[n].name));
|
|
GlobalTrackLocks[n].pagetype=PAGETYPE_UNKNOWN;
|
|
GlobalTrackLocks[n].used=0;
|
|
GlobalTrackLocks[n].name[0]=0;
|
|
}
|
|
// Displays all the network locks of "name"
|
|
void mng_DisplayLockList (char *name)
|
|
{
|
|
mngs_Pagelock list[100];
|
|
char temp[200];
|
|
int max=100;
|
|
int num,i;
|
|
int length=0;
|
|
char str[5000];
|
|
#ifndef RELEASE
|
|
// Get the list
|
|
if ((num=mng_GetListOfLocks (list,max,name))<0)
|
|
{
|
|
OutrageMessageBox (MBOX_OK, ErrorString);
|
|
return;
|
|
}
|
|
else if (num==0)
|
|
{
|
|
OutrageMessageBox (MBOX_OK, "User has no pages locked.");
|
|
return;
|
|
}
|
|
|
|
// Make a large string with all the info in it
|
|
sprintf (str,"User %s has the following pages locked:\n\n",TableUser);
|
|
for (i=0;i<num;i++)
|
|
{
|
|
sprintf (temp,"%s:%s",PageNames[list[i].pagetype],list[i].name);
|
|
strcat (str,temp);
|
|
strcat (str,"\n");
|
|
length+=strlen(temp);
|
|
if (length>5000-100)
|
|
break;
|
|
}
|
|
// Display that string
|
|
OutrageMessageBox (MBOX_OK, str);
|
|
#endif
|
|
}
|
|
//Declare these here because it's too big to put on the stack on the Mac
|
|
static mngs_texture_page texpage;
|
|
static mngs_door_page doorpage;
|
|
static mngs_generic_page genericpage;
|
|
static mngs_sound_page soundpage;
|
|
static mngs_megacell_page megacellpage;
|
|
static mngs_ship_page shippage;
|
|
static mngs_weapon_page weaponpage;
|
|
static mngs_gamefile_page gamefilepage;
|
|
// IF YOU ADD ANY NEW PAGETYPE YOU MUST CHANGE THE FUNCTIONS LISTED UNDER THIS LINE
|
|
// TO DEAL WITH YOUR PAGE TYPE. IF YOU FORGET, YOU CAN CORRUPT THE PAGEFILE!!!!!
|
|
//------------------------------------------------------------------------------
|
|
// Given a pagetype, reads it in but discards it. Useful for parsing.
|
|
void mng_ReadDummyPage (CFILE *infile,ubyte pagetype)
|
|
{
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
break;
|
|
case PAGETYPE_POWERUP:
|
|
case PAGETYPE_ROBOT:
|
|
Error("Your local table file is invalid. You must update from the network.");
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
if (genericpage.objinfo_struct.description!=NULL){
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
mng_ReadNewMegacellPage (infile,&megacellpage);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
break;
|
|
default:
|
|
Int3(); // unrecognized pagetype
|
|
break;
|
|
}
|
|
}
|
|
// Reads a page in that we don't care about, and writes it right back out
|
|
// This is useful for replacing a specific page in a file but ignoring others
|
|
void mng_ReadWriteDummyPage (CFILE *infile,CFILE *outfile,ubyte pagetype)
|
|
{
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
// Read it in, write it out.
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
mng_WriteNewTexturePage (outfile,&texpage);
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
// Read it in, write it out.
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
mng_WriteNewDoorPage (outfile,&doorpage);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
// Read it in, write it out.
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
if (genericpage.objinfo_struct.description!=NULL)
|
|
{
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
// Read it in, write it out.
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
mng_WriteNewGamefilePage (outfile,&gamefilepage);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
// Read it in, write it out.
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
mng_WriteNewSoundPage (outfile,&soundpage);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
// Read it in, write it out.
|
|
mng_ReadNewMegacellPage (infile,&megacellpage);
|
|
mng_WriteNewMegacellPage (outfile,&megacellpage);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
// Read it in, write it out.
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
mng_WriteNewShipPage (outfile,&shippage);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
// Read it in, write it out.
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
mng_WriteNewUnknownPage (outfile);
|
|
break;
|
|
default:
|
|
Int3(); // unrecognized pagetype
|
|
break;
|
|
}
|
|
}
|
|
// Renames a page on the network
|
|
// This function is called when you rename your object, regardless if you check
|
|
// it in
|
|
int mng_RenamePage (char *oldname,char *newname,int pagetype)
|
|
{
|
|
int l,i;
|
|
mngs_Pagelock pl;
|
|
char oname[PAGENAME_LEN];
|
|
|
|
mprintf ((0,"Renaming %s to %s...\n",oldname,newname));
|
|
strcpy (oname,oldname);
|
|
strcpy (pl.name,oname);
|
|
pl.pagetype=pagetype;
|
|
// Make sure we own it
|
|
l=mng_CheckIfPageOwned (&pl,TableUser);
|
|
ASSERT (l==1);
|
|
strcpy (pl.name,newname);
|
|
strcpy (pl.holder,TableUser);
|
|
|
|
// First, change the name of the network pagelock
|
|
l=mng_ReplacePagelock (oname,&pl);
|
|
ASSERT (l==1);
|
|
switch (pagetype)
|
|
{
|
|
// Find the page type with this name and rename it
|
|
case PAGETYPE_TEXTURE:
|
|
i=FindTextureName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (GameTextures[i].name,newname);
|
|
|
|
l=mng_ReplacePage (oname,GameTextures[i].name,i,PAGETYPE_TEXTURE,0);
|
|
ASSERT (l==1);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_TEXTURE)!=-1)
|
|
mng_ReplacePage (oname,GameTextures[i].name,i,PAGETYPE_TEXTURE,1);
|
|
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
i=FindDoorName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Doors[i].name,newname);
|
|
l=mng_ReplacePage (oname,Doors[i].name,i,PAGETYPE_DOOR,0);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_DOOR)!=-1)
|
|
mng_ReplacePage (oname,Doors[i].name,i,PAGETYPE_DOOR,1);
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
i=FindObjectIDName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Object_info[i].name,newname);
|
|
|
|
l=mng_ReplacePage (oname,Object_info[i].name,i,PAGETYPE_GENERIC,0);
|
|
|
|
if (mng_FindTrackLock (oname,PAGETYPE_GENERIC)!=-1)
|
|
mng_ReplacePage (oname,Object_info[i].name,i,PAGETYPE_GENERIC,1);
|
|
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
i=FindGamefileName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Gamefiles[i].name,newname);
|
|
|
|
l=mng_ReplacePage (oname,Gamefiles[i].name,i,PAGETYPE_GAMEFILE,0);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_GAMEFILE)!=-1)
|
|
mng_ReplacePage (oname,Gamefiles[i].name,i,PAGETYPE_GAMEFILE,1);
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
i=FindSoundName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Sounds[i].name,newname);
|
|
l=mng_ReplacePage (oname,Sounds[i].name,i,PAGETYPE_SOUND,0);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_SOUND)!=-1)
|
|
mng_ReplacePage (oname,Sounds[i].name,i,PAGETYPE_SOUND,1);
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
i=FindMegacellName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Megacells[i].name,newname);
|
|
l=mng_ReplacePage (oname,Megacells[i].name,i,PAGETYPE_MEGACELL,0);
|
|
|
|
if (mng_FindTrackLock (oname,PAGETYPE_MEGACELL)!=-1)
|
|
mng_ReplacePage (oname,Megacells[i].name,i,PAGETYPE_MEGACELL,1);
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
i=FindShipName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Ships[i].name,newname);
|
|
|
|
l=mng_ReplacePage (oname,Ships[i].name,i,PAGETYPE_SHIP,0);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_SHIP)!=-1)
|
|
mng_ReplacePage (oname,Ships[i].name,i,PAGETYPE_SHIP,1);
|
|
|
|
ASSERT (l==1);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
i=FindWeaponName(oname);
|
|
ASSERT (i!=-1);
|
|
strcpy (Weapons[i].name,newname);
|
|
|
|
l=mng_ReplacePage (oname,Weapons[i].name,i,PAGETYPE_WEAPON,0);
|
|
if (mng_FindTrackLock (oname,PAGETYPE_WEAPON)!=-1)
|
|
mng_ReplacePage (oname,Weapons[i].name,i,PAGETYPE_WEAPON,1);
|
|
ASSERT (l==1);
|
|
break;
|
|
default:
|
|
Int3(); // Unknown type, get Jason
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
#define PROGRESS_PERCENTAGE_THRESHOLD 20
|
|
// This is the function that opens the table files and reads in the individual pages
|
|
// If you want your data to be in the game, it must hook into this function
|
|
int mng_LoadNetPages (int show_progress)
|
|
{
|
|
CFILE *infile;
|
|
ubyte pagetype;
|
|
char tablename[TABLE_NAME_LEN];
|
|
float start_time;
|
|
int n_pages = 0;
|
|
int total_bytes;
|
|
int current_byte;
|
|
float progress;
|
|
int int_progress=0;
|
|
int len;
|
|
|
|
mprintf ((0,"Loading pages..."));
|
|
if (Dedicated_server)
|
|
show_progress=0; // turn off progress meter for dedicated server
|
|
// If the network is up we still want to read from the local table because it
|
|
// will allow others to start the game at the same time
|
|
if (Network_up)
|
|
{
|
|
int farg=FindArg("-filter");
|
|
if (farg)
|
|
strcpy (tablename,GameArgs[farg+1]);
|
|
else
|
|
{
|
|
ddio_MakePath (tablename,LocalTableDir,NET_TABLE,NULL);
|
|
}
|
|
infile=cfopen (tablename,"rb");
|
|
}
|
|
else
|
|
infile=cfopen (TableFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open table file (%s) to read pages!\n",TableFilename));
|
|
Error("Cannot open table file <%s>",TableFilename);
|
|
return 0;
|
|
}
|
|
if (show_progress)
|
|
{
|
|
cfseek (infile,0,SEEK_END);
|
|
total_bytes=cftell (infile);
|
|
cfseek (infile,0,SEEK_SET);
|
|
}
|
|
start_time = timer_GetTime();
|
|
while (!cfeof(infile))
|
|
{
|
|
// Read in a pagetype. If its a page we recognize, load it
|
|
// mprintf ((0,"."));
|
|
if (show_progress)
|
|
{
|
|
|
|
current_byte=cftell (infile);
|
|
progress=(float)current_byte/(float)total_bytes;
|
|
progress*=PROGRESS_PERCENTAGE_THRESHOLD;
|
|
int temp_int_progress=progress;
|
|
if (temp_int_progress>int_progress)
|
|
{
|
|
int_progress=temp_int_progress;
|
|
InitMessage (TXT_INITDATA,progress/PROGRESS_PERCENTAGE_THRESHOLD);
|
|
}
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
if (!Old_table_method)
|
|
len=cf_ReadInt (infile);
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mprintf ((0,"T"));
|
|
|
|
PrintDedicatedMessage ("T");
|
|
mng_LoadNetTexturePage (infile);
|
|
break;
|
|
case PAGETYPE_POWERUP:
|
|
case PAGETYPE_ROBOT:
|
|
Error("Your local table file is invalid. You must update from the network.");
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mprintf ((0,"D"));
|
|
PrintDedicatedMessage ("D");
|
|
mng_LoadNetDoorPage (infile);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mprintf ((0,"G"));
|
|
PrintDedicatedMessage ("G");
|
|
mng_LoadNetGenericPage (infile);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mprintf ((0,"F"));
|
|
PrintDedicatedMessage ("F");
|
|
mng_LoadNetGamefilePage (infile);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mprintf ((0,"S"));
|
|
PrintDedicatedMessage ("S");
|
|
mng_LoadNetSoundPage (infile);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mprintf ((0,"P"));
|
|
PrintDedicatedMessage ("P");
|
|
mng_LoadNetShipPage (infile);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mprintf ((0,"W"));
|
|
PrintDedicatedMessage ("W");
|
|
mng_LoadNetWeaponPage (infile);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
mprintf ((0,"M"));
|
|
PrintDedicatedMessage ("M");
|
|
mng_LoadNetMegacellPage (infile);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
mprintf ((0,"?"));
|
|
break;
|
|
default:
|
|
Int3(); // Unrecognized pagetype, possible corrupt data following
|
|
return 0;
|
|
break;
|
|
}
|
|
n_pages++;
|
|
}
|
|
mprintf((0,"\n%d pages read in %.1f seconds.\n",n_pages,timer_GetTime()-start_time));
|
|
mprintf ((0,"\n"));
|
|
PrintDedicatedMessage ((0,"\nPage reading completed.\n"));
|
|
|
|
cfclose (infile);
|
|
|
|
// attempt to load extra.gam if found
|
|
char name_override[256];
|
|
strcpy(name_override,"extra.gam");
|
|
infile=cfopen (name_override,"rb");
|
|
if(!infile)
|
|
return 1;
|
|
|
|
mprintf((0,"==================================================\n"));
|
|
mprintf((0," Loading extra.gam \n"));
|
|
mprintf((0,"==================================================\n"));
|
|
PrintDedicatedMessage ("\nLoading extra.gam.....\n");
|
|
n_pages = 0;
|
|
|
|
TablefileNameOverride = name_override;
|
|
|
|
while (!cfeof(infile))
|
|
{
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt (infile);
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mprintf ((0,"T"));
|
|
PrintDedicatedMessage ("T");
|
|
mng_LoadNetTexturePage (infile,true);
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mprintf ((0,"D"));
|
|
PrintDedicatedMessage ("D");
|
|
mng_LoadNetDoorPage (infile,true);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mprintf ((0,"G"));
|
|
PrintDedicatedMessage ("G");
|
|
mng_LoadNetGenericPage (infile,true);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mprintf ((0,"F"));
|
|
PrintDedicatedMessage ("F");
|
|
mng_LoadNetGamefilePage (infile,true);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mprintf ((0,"S"));
|
|
PrintDedicatedMessage ("S");
|
|
mng_LoadNetSoundPage (infile,true);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mprintf ((0,"P"));
|
|
PrintDedicatedMessage ("P");
|
|
mng_LoadNetShipPage (infile,true);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mprintf ((0,"W"));
|
|
PrintDedicatedMessage ("W");
|
|
mng_LoadNetWeaponPage (infile,true);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
mprintf ((0,"?"));
|
|
break;
|
|
default:
|
|
Int3(); // Unrecognized pagetype, possible corrupt data following
|
|
cfclose(infile);
|
|
TablefileNameOverride = NULL;
|
|
return 0;
|
|
break;
|
|
}
|
|
n_pages++;
|
|
}
|
|
mprintf((0,"\n%d extra pages read.\n",n_pages));
|
|
TablefileNameOverride = NULL;
|
|
cfclose(infile);
|
|
return 1;
|
|
}
|
|
// Loads and allocs all pages found locally
|
|
int mng_LoadLocalPages ()
|
|
{
|
|
CFILE *infile;
|
|
ubyte pagetype;
|
|
int len;
|
|
|
|
mprintf ((0,"Overlaying local pages..."));
|
|
infile=cfopen (LocalTableFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open local table file (%s) to read pages!\n",LocalTableFilename));
|
|
return 1;
|
|
}
|
|
Loading_locals=1;
|
|
while (!cfeof(infile))
|
|
{
|
|
// Read in a pagetype. If its a page we recognize, load it
|
|
|
|
pagetype=cf_ReadByte (infile);
|
|
if (!Old_table_method)
|
|
len=cf_ReadInt (infile);
|
|
mprintf ((0,"."));
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mng_LoadLocalTexturePage (infile);
|
|
break;
|
|
case PAGETYPE_POWERUP:
|
|
case PAGETYPE_ROBOT:
|
|
Error("Your local table file is invalid. You must update from the network.");
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mng_LoadLocalDoorPage (infile);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mng_LoadLocalGenericPage (infile);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mng_LoadLocalGamefilePage (infile);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mng_LoadLocalSoundPage (infile);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mng_LoadLocalShipPage (infile);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mng_LoadLocalWeaponPage (infile);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
mng_LoadLocalMegacellPage (infile);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
break;
|
|
default:
|
|
Int3(); // Unrecognized pagetype, possible corrupt data following
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
mprintf ((0,"\n"));
|
|
cfclose (infile);
|
|
Loading_locals=0;
|
|
return 1;
|
|
}
|
|
#define MAX_TRIES 10000
|
|
// Removes a file, then renames another file to be the removed file. Get it?
|
|
// Returns 1 on success, else 0 on fail
|
|
int SwitcherooFiles (char *name,char *tempname)
|
|
{
|
|
/*// If we're changing the net table file, make a backup first!
|
|
if ((!stricmp (name,TableFilename)))
|
|
{
|
|
cf_CopyFile (BackupTableFilename,TableFilename);
|
|
cf_CopyFile (BackupLockFilename,TableLockFilename);
|
|
}*/
|
|
int num_tries=0;
|
|
while (!ddio_DeleteFile (name) && num_tries<MAX_TRIES)
|
|
{
|
|
Sleep (100);
|
|
num_tries++;
|
|
}
|
|
if (num_tries>=MAX_TRIES)
|
|
{
|
|
strcpy (ErrorString,"MANAGE:There was a problem deleting the table file.");
|
|
ASSERT (0); // GET JASON IMMEDIATELY
|
|
Int3();
|
|
return (0);
|
|
}
|
|
num_tries=0;
|
|
while ((rename (tempname,name)) && num_tries<=MAX_TRIES)
|
|
{
|
|
Sleep (100);
|
|
num_tries++;
|
|
}
|
|
if (num_tries>=MAX_TRIES)
|
|
{
|
|
strcpy (ErrorString,"MANAGE:There was a problem renaming the temp file.");
|
|
ASSERT (0); // Get JASON IMMEDIATELY
|
|
Int3();
|
|
return (0);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void mng_TransferPages ()
|
|
{
|
|
CFILE *infile,*outfile;
|
|
int pagetype;
|
|
int num_tracklocks=0;
|
|
mprintf ((0,"Transferring pages, please wait...\n"));
|
|
if (!mng_MakeLocker())
|
|
return;
|
|
infile=cfopen (TableFilename,"rb");
|
|
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open table file to transfer!\n"));
|
|
Int3();
|
|
return;
|
|
}
|
|
mngs_track_lock *local_tracklocks = (mngs_track_lock *) mem_malloc(sizeof(*local_tracklocks) * 5000);
|
|
// Do textures
|
|
int done=0;
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
int len=cf_ReadInt (infile);
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,texpage.tex_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_TEXTURE;
|
|
num_tracklocks++;
|
|
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,soundpage.sound_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_SOUND;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,weaponpage.weapon_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_WEAPON;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,genericpage.objinfo_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_GENERIC;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,doorpage.door_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_DOOR;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,shippage.ship_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_SHIP;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
strcpy (local_tracklocks[num_tracklocks].name,gamefilepage.gamefile_struct.name);
|
|
local_tracklocks[num_tracklocks].pagetype=PAGETYPE_GAMEFILE;
|
|
num_tracklocks++;
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
Int3();// huh?
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
cfclose (infile);
|
|
// Now go through and filter out all unused lock files
|
|
infile=(CFILE *)cfopen (TableLockFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
strcpy (ErrorString,"Couldn't open Table lock file!");
|
|
goto done;
|
|
}
|
|
outfile=(CFILE *)cfopen (TempTableLockFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
cfclose (infile);
|
|
strcpy (ErrorString,"Couldn't open temporary table lock file!");
|
|
goto done;
|
|
}
|
|
done=0;
|
|
mngs_Pagelock temp_pl;
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
if (mng_ReadPagelock (infile,&temp_pl))
|
|
{
|
|
int found=-1;
|
|
for (int i=0;i<num_tracklocks && found==-1;i++)
|
|
{
|
|
if (local_tracklocks[i].pagetype==temp_pl.pagetype && !stricmp (local_tracklocks[i].name,temp_pl.name))
|
|
{
|
|
found=i;
|
|
}
|
|
}
|
|
if (found!=-1)
|
|
mng_WritePagelock (outfile,&temp_pl);
|
|
else
|
|
{
|
|
mprintf ((0,"Found unused lock file %s\n",temp_pl.name));
|
|
}
|
|
|
|
}
|
|
else done=1;
|
|
}
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
|
|
if (remove (TableLockFilename))
|
|
{
|
|
sprintf (ErrorString,"There was a problem deleting the temp file - errno %d",errno);
|
|
goto done;
|
|
}
|
|
if (rename (TempTableLockFilename,TableLockFilename))
|
|
{
|
|
sprintf (ErrorString,"There was a problem renaming the temp file - errno %d",errno);
|
|
|
|
goto done;
|
|
}
|
|
mng_EraseLocker();
|
|
mprintf ((0,"Done transferring pages...good luck!\n"));
|
|
done:;
|
|
mem_free(local_tracklocks);
|
|
}
|
|
//#define DELETING_PAGELOCKS 1
|
|
//#define CLEANING_PAGELOCKS 1
|
|
// Given a list of names and a pagetype, unlocks the ones already inside the lock file
|
|
int mng_UnlockPagelockSeries (char *names[],int *pagetypes,int num);
|
|
// Goes through the pagelock table and deletes all duplicate entries
|
|
int mng_DeleteDuplicatePagelocks ();
|
|
void ReorderPagelocks ()
|
|
{
|
|
char *names[]={"Lava"};
|
|
int types[]={PAGETYPE_SOUND};
|
|
if (!mng_MakeLocker())
|
|
return;
|
|
mng_UnlockPagelockSeries (names,types,1);
|
|
|
|
//mng_DeleteDuplicatePagelocks ();
|
|
|
|
mng_EraseLocker();
|
|
}
|
|
// THIS IS A SPECIAL FUNCTION THAT YOU SHOULD ONLY USE IF YOU KNOW WHAT YOU ARE
|
|
// DOING...it simply reorders the table file so that the "primitives" are first.
|
|
// This helps in the load time of a table file.
|
|
void ReorderPages (int local)
|
|
{
|
|
CFILE *infile,*outfile;
|
|
ubyte pagetype;
|
|
int done=0;
|
|
int len;
|
|
#ifdef CLEANING_PAGELOCKS
|
|
mng_TransferPages();
|
|
return;
|
|
#endif
|
|
#ifdef DELETING_PAGELOCKS
|
|
ReorderPagelocks ();
|
|
return;
|
|
#endif
|
|
mprintf ((0,"Reordering pages, please wait...\n"));
|
|
if (local)
|
|
infile=cfopen (LocalTableFilename,"rb");
|
|
else
|
|
{
|
|
if (!mng_MakeLocker())
|
|
return;
|
|
infile=cfopen (TableFilename,"rb");
|
|
}
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open table file to reorder!\n"));
|
|
Int3();
|
|
return;
|
|
}
|
|
if (local)
|
|
outfile=cfopen (LocalTempTableFilename,"wb");
|
|
else
|
|
outfile=cfopen (TempTableFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
mprintf ((0,"Couldn't open temp table file to reorder!\n"));
|
|
cfclose (infile);
|
|
Int3();
|
|
return;
|
|
}
|
|
// Do textures
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_TEXTURE)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
mng_WriteNewTexturePage (outfile,&texpage);
|
|
|
|
}
|
|
// Do sounds
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_SOUND)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
mng_WriteNewSoundPage (outfile,&soundpage);
|
|
|
|
}
|
|
// Do weapons
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_WEAPON)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
// Ignore counter measure weapons
|
|
if (!(weaponpage.weapon_struct.flags & WF_SPAWNS_ROBOT))
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
}
|
|
// Do powerup generics
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_GENERIC)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
if (genericpage.objinfo_struct.type==OBJ_POWERUP)
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
if (genericpage.objinfo_struct.description!=NULL)
|
|
{
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
}
|
|
// Do standard generics
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_GENERIC)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
if (genericpage.objinfo_struct.type!=OBJ_POWERUP)
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
if (genericpage.objinfo_struct.description!=NULL)
|
|
{
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
}
|
|
// Do countermeasure weapons
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_WEAPON)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
if ((weaponpage.weapon_struct.flags & WF_SPAWNS_ROBOT))
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
}
|
|
|
|
// Do doors
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_DOOR)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
mng_WriteNewDoorPage (outfile,&doorpage);
|
|
|
|
}
|
|
// Do player ships
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_SHIP)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
mng_WriteNewShipPage (outfile,&shippage);
|
|
}
|
|
// Do gamefiles
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_GAMEFILE)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
mng_WriteNewGamefilePage (outfile,&gamefilepage);
|
|
}
|
|
// Do megacells
|
|
done=0;
|
|
cfseek (infile,0,SEEK_SET);
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt(infile);
|
|
// If not a door page, just read it in and ignore it
|
|
if (pagetype!=PAGETYPE_MEGACELL)
|
|
{
|
|
cfseek (infile,len-4,SEEK_CUR);
|
|
continue;
|
|
}
|
|
mng_ReadNewMegacellPage (infile,&megacellpage);
|
|
mng_WriteNewMegacellPage (outfile,&megacellpage);
|
|
}
|
|
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
if (local)
|
|
{
|
|
SwitcherooFiles (LocalTableFilename,LocalTempTableFilename);
|
|
}
|
|
else
|
|
{
|
|
SwitcherooFiles (TableFilename,TempTableFilename);
|
|
}
|
|
mng_EraseLocker();
|
|
|
|
}
|
|
// Returns true if the passed in pagelock is in the LockList, else false
|
|
bool InLockList (mngs_Pagelock *pl)
|
|
{
|
|
if (Starting_editor)
|
|
{
|
|
for (int i=0;i<Num_locklist;i++)
|
|
{
|
|
if (LockList[i].pagetype==pl->pagetype)
|
|
{
|
|
if (!stricmp(LockList[i].name,pl->name))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((mng_CheckIfPageOwned(pl,TableUser)) > 0) //DAJ -1FIX
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
// Given a filename, returns the type of primitive it is
|
|
int GetPrimType (char *name)
|
|
{
|
|
char ext[10];
|
|
char tname[_MAX_PATH];
|
|
int primtype;
|
|
ddio_SplitPath(name,tname,tname,ext);
|
|
if (!stricmp ("oof",ext))
|
|
primtype=PRIMTYPE_OOF;
|
|
else if (!stricmp ("ogf",ext))
|
|
primtype=PRIMTYPE_OGF;
|
|
else if (!stricmp ("oaf",ext))
|
|
primtype=PRIMTYPE_OAF;
|
|
else if (!stricmp ("wav",ext))
|
|
primtype=PRIMTYPE_WAV;
|
|
else
|
|
primtype=PRIMTYPE_FILE;
|
|
return primtype;
|
|
|
|
}
|
|
#if defined(WIN32)
|
|
// Builds a list of old files in a path
|
|
void BuildOldFilesForDirectory (char *path,FILETIME threshold)
|
|
{
|
|
HANDLE filehandle;
|
|
WIN32_FIND_DATA filedata;
|
|
char newpath[MAX_PATH];
|
|
ddio_MakePath(newpath,path,"*.*",NULL);
|
|
filehandle=FindFirstFile (newpath,&filedata);
|
|
bool go_ahead=true;
|
|
if (filehandle==INVALID_HANDLE_VALUE)
|
|
go_ahead=false;
|
|
while (go_ahead)
|
|
{
|
|
bool add_it=false;
|
|
|
|
// if this file is newer than the last time we updated, add it to the list
|
|
|
|
if (filedata.ftLastWriteTime.dwHighDateTime>threshold.dwHighDateTime)
|
|
add_it=true;
|
|
if (filedata.ftLastWriteTime.dwHighDateTime==threshold.dwHighDateTime)
|
|
{
|
|
if (filedata.ftLastWriteTime.dwLowDateTime>threshold.dwLowDateTime)
|
|
add_it=true;
|
|
}
|
|
if (filedata.ftCreationTime.dwHighDateTime>threshold.dwHighDateTime)
|
|
add_it=true;
|
|
if (filedata.ftCreationTime.dwHighDateTime==threshold.dwHighDateTime)
|
|
{
|
|
if (filedata.ftCreationTime.dwLowDateTime>threshold.dwLowDateTime)
|
|
add_it=true;
|
|
}
|
|
// Add it to the list!
|
|
if (add_it)
|
|
{
|
|
int primtype=GetPrimType (filedata.cFileName);
|
|
OldFiles[Num_old_files].type=primtype;
|
|
strcpy (OldFiles[Num_old_files].name,filedata.cFileName);
|
|
Num_old_files++;
|
|
}
|
|
go_ahead = (FindNextFile(filehandle,&filedata) != 0);
|
|
}
|
|
if (filehandle!=INVALID_HANDLE_VALUE)
|
|
FindClose (filehandle);
|
|
}
|
|
// Builds a list of old files so we know which ones to update
|
|
// Searches through all our netdirectories for old files
|
|
void BuildOldFileList (FILETIME threshold)
|
|
{
|
|
char str[MAX_PATH];
|
|
mprintf ((0,"Building old files list!\n"));
|
|
BuildOldFilesForDirectory (NetModelsDir,threshold);
|
|
BuildOldFilesForDirectory (NetSoundsDir,threshold);
|
|
BuildOldFilesForDirectory (NetMiscDir,threshold);
|
|
BuildOldFilesForDirectory (ManageGraphicsDir,threshold);
|
|
BuildOldFilesForDirectory (NetArtDir, threshold);
|
|
BuildOldFilesForDirectory (NetMusicDir,threshold);
|
|
BuildOldFilesForDirectory (NetVoiceDir,threshold);
|
|
ddio_MakePath (str,NetD3Dir,"data","levels",NULL);
|
|
BuildOldFilesForDirectory (str,threshold);
|
|
ddio_MakePath (str,NetD3Dir,"data","briefings",NULL);
|
|
BuildOldFilesForDirectory (str,threshold);
|
|
ddio_MakePath (str,NetD3Dir,"data","scripts",NULL);
|
|
BuildOldFilesForDirectory (str,threshold);
|
|
mprintf ((0,"Found %d old files.\n",Num_old_files));
|
|
}
|
|
#endif
|
|
// Returns true if the passed in primitive is old (ie needs to be updated from the network)
|
|
bool IsPrimitiveOld (char *name)
|
|
{
|
|
int primtype=GetPrimType (name);
|
|
for (int i=0;i<Num_old_files;i++)
|
|
{
|
|
if (OldFiles[i].type==primtype && !stricmp (OldFiles[i].name,name))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
// Updates a primitive if needed
|
|
// Localname = local version of the primname (with path)
|
|
// Netname = Network version of the primname (with path)
|
|
void UpdatePrimitive (char *localname,char *netname,char *primname,int pagetype,char *pagename)
|
|
{
|
|
bool update=false;
|
|
if (Starting_editor && !Use_old_update_method)
|
|
{
|
|
if (IsPrimitiveOld (primname))
|
|
update=true;
|
|
}
|
|
else
|
|
{
|
|
if (!cfexist (localname) || (cfexist(netname) && cf_Diff (localname,netname)))
|
|
update=true;
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
mngs_Pagelock temp_pl;
|
|
temp_pl.pagetype=pagetype;
|
|
strcpy (temp_pl.name,pagename);
|
|
if (!InLockList(&temp_pl))
|
|
{
|
|
mprintf ((0,"Making a local copy of %s for next time.\n",primname));
|
|
if (!cf_CopyFile (localname,netname,1))
|
|
{
|
|
Int3(); //get Jason
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Writes a chunk header. Writes chunk id & placeholder length. Returns chunk start pos
|
|
int StartManagePage(CFILE *ofile,ubyte pagetype)
|
|
{
|
|
int chunk_start_pos;
|
|
// Write pagetype
|
|
cf_WriteByte (ofile,pagetype);
|
|
chunk_start_pos = cftell(ofile);
|
|
cf_WriteInt(ofile,0); //placeholder for chunk len
|
|
|
|
return chunk_start_pos;
|
|
}
|
|
//Fill in page length when done writing
|
|
void EndManagePage(CFILE *ofile,int chunk_start_pos)
|
|
{
|
|
int save_pos = cftell(ofile);
|
|
int len = save_pos-chunk_start_pos;
|
|
//seek back to len field and fill in value
|
|
cfseek(ofile,chunk_start_pos,SEEK_SET);
|
|
cf_WriteInt(ofile,len); //write chunk length
|
|
//go back to end of file
|
|
cfseek(ofile,save_pos,SEEK_SET);
|
|
}
|
|
// Assigns a page to its appropriate structure and writes it out
|
|
void mng_AssignAndWritePage (int handle,int pagetype,CFILE *outfile)
|
|
{
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mng_AssignTextureToTexPage (handle,&texpage);
|
|
mng_WriteNewTexturePage (outfile,&texpage);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mng_AssignSoundToSoundPage (handle,&soundpage);
|
|
mng_WriteNewSoundPage (outfile,&soundpage);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mng_AssignWeaponToWeaponPage (handle,&weaponpage);
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mng_AssignObjInfoToGenericPage (handle,&genericpage);
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mng_AssignDoorToDoorPage (handle,&doorpage);
|
|
mng_WriteNewDoorPage (outfile,&doorpage);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
mng_AssignMegacellToMegacellPage (handle,&megacellpage);
|
|
mng_WriteNewMegacellPage (outfile,&megacellpage);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mng_AssignShipToShipPage (handle,&shippage);
|
|
mng_WriteNewShipPage (outfile,&shippage);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mng_AssignGamefileToGamefilePage (handle,&gamefilepage);
|
|
mng_WriteNewGamefilePage (outfile,&gamefilepage);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#define COPYBUFFER_SIZE 200000
|
|
// Given a texture handle, searches the table file and replaces the texture with the same name
|
|
// If local=1, then does it to the users local copy
|
|
// Returns 0 on error, else 1 if all is good
|
|
int mng_ReplacePage (char *srcname,char *destname,int handle,int dest_pagetype,int local)
|
|
{
|
|
CFILE *infile,*outfile;
|
|
ubyte pagetype,replaced=0;
|
|
int done=0,len;
|
|
mprintf ((0,"Replacing '%s' with '%s' (%s).\n",srcname,destname,local?"locally":"to network"));
|
|
|
|
if (local)
|
|
infile=cfopen (LocalTableFilename,"rb");
|
|
else
|
|
infile=cfopen (TableFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open table file to replace page %s!\n",srcname));
|
|
Int3();
|
|
return 0;
|
|
}
|
|
if (local)
|
|
outfile=cfopen (LocalTempTableFilename,"wb");
|
|
else
|
|
outfile=cfopen (TempTableFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
mprintf ((0,"Couldn't open temp table file to replace page %s!\n",srcname));
|
|
cfclose (infile);
|
|
Int3();
|
|
return 0;
|
|
}
|
|
// Allocate memory for copying
|
|
ubyte *copybuffer=(ubyte *)mem_malloc (COPYBUFFER_SIZE);
|
|
if (!copybuffer)
|
|
{
|
|
mprintf ((0,"Couldn't allocate memory to replace page %s!\n",srcname));
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
Int3();
|
|
return 0;
|
|
}
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt (infile);
|
|
// If not a texture page, just read it in and write it right back out
|
|
if (pagetype!=dest_pagetype)
|
|
{
|
|
ASSERT (len<COPYBUFFER_SIZE);
|
|
|
|
cf_ReadBytes(copybuffer, len-4,infile);
|
|
cf_WriteByte (outfile,pagetype);
|
|
cf_WriteInt (outfile,len);
|
|
if (len-4>0)
|
|
cf_WriteBytes (copybuffer,len-4,outfile);
|
|
|
|
continue;
|
|
}
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
{
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
if (!stricmp(srcname,texpage.tex_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewTexturePage (outfile,&texpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_SOUND:
|
|
{
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
if (!stricmp(srcname,soundpage.sound_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewSoundPage (outfile,&soundpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_WEAPON:
|
|
{
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
if (!stricmp(srcname,weaponpage.weapon_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_GENERIC:
|
|
{
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
if (!stricmp(srcname,genericpage.objinfo_struct.name))
|
|
{
|
|
// This is the page we want to replace, so write the new one out.
|
|
if (genericpage.objinfo_struct.description!=NULL)
|
|
{
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
genericpage.objinfo_struct.icon_name[0] = '\0';
|
|
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_DOOR:
|
|
{
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
if (!stricmp(srcname,doorpage.door_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewDoorPage (outfile,&doorpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_MEGACELL:
|
|
{
|
|
mng_ReadNewMegacellPage (infile,&megacellpage);
|
|
if (!stricmp(srcname,megacellpage.megacell_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewMegacellPage (outfile,&megacellpage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_SHIP:
|
|
{
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
if (!stricmp(srcname,shippage.ship_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewShipPage (outfile,&shippage);
|
|
}
|
|
break;
|
|
}
|
|
case PAGETYPE_GAMEFILE:
|
|
{
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
if (!stricmp(srcname,gamefilepage.gamefile_struct.name))
|
|
{
|
|
mng_AssignAndWritePage (handle,pagetype,outfile);
|
|
replaced=1;
|
|
}
|
|
else
|
|
{
|
|
mng_WriteNewGamefilePage (outfile,&gamefilepage);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!replaced)
|
|
{
|
|
// This is a new page, so append it to the end of file.
|
|
mng_AssignAndWritePage (handle,dest_pagetype,outfile);
|
|
}
|
|
if (replaced)
|
|
mprintf ((0,"Page replaced.\n"));
|
|
else
|
|
mprintf ((0,"New page added.\n"));
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
mem_free (copybuffer);
|
|
if (local)
|
|
{
|
|
if (!SwitcherooFiles (LocalTableFilename,LocalTempTableFilename))
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if (!SwitcherooFiles (TableFilename,TempTableFilename))
|
|
return 0;
|
|
}
|
|
return 1; // successful!
|
|
}
|
|
// Given a texture name, finds it in the table file and deletes it
|
|
// If local is 1, deletes from the local table file
|
|
int mng_DeletePage (char *name,int dest_pagetype,int local)
|
|
{
|
|
CFILE *infile,*outfile;
|
|
ubyte pagetype,replaced=0;
|
|
int done=0;
|
|
int deleted=0;
|
|
|
|
mprintf ((0,"Deleting %s (%s).\n",name,local?"locally":"on network"));
|
|
|
|
if (local)
|
|
infile=cfopen (LocalTableFilename,"rb");
|
|
else
|
|
infile=cfopen (TableFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open table file to delete page!\n"));
|
|
Int3();
|
|
return 0;
|
|
}
|
|
if (local)
|
|
outfile=cfopen (LocalTempTableFilename,"wb");
|
|
else
|
|
outfile=cfopen (TempTableFilename,"wb");
|
|
if (!outfile)
|
|
{
|
|
mprintf ((0,"Couldn't open temp table file to delete page!\n"));
|
|
cfclose (infile);
|
|
Int3();
|
|
return 0;
|
|
}
|
|
// Allocate memory for copying
|
|
ubyte *copybuffer=(ubyte *)mem_malloc (COPYBUFFER_SIZE);
|
|
if (!copybuffer)
|
|
{
|
|
mprintf ((0,"Couldn't allocate memory to delete page!\n"));
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
Int3();
|
|
return 0;
|
|
}
|
|
while (!done)
|
|
{
|
|
if (cfeof (infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
pagetype=cf_ReadByte (infile);
|
|
int len=cf_ReadInt (infile);
|
|
if (pagetype!=dest_pagetype)
|
|
{
|
|
ASSERT (len<COPYBUFFER_SIZE);
|
|
|
|
cf_ReadBytes(copybuffer, len-4,infile);
|
|
cf_WriteByte (outfile,pagetype);
|
|
cf_WriteInt (outfile,len);
|
|
if (len-4>0)
|
|
cf_WriteBytes (copybuffer,len-4,outfile);
|
|
|
|
continue;
|
|
}
|
|
switch (pagetype)
|
|
{
|
|
|
|
case PAGETYPE_TEXTURE:
|
|
{
|
|
mng_ReadNewTexturePage (infile,&texpage);
|
|
if (stricmp(name,texpage.tex_struct.name))
|
|
mng_WriteNewTexturePage (outfile,&texpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_DOOR:
|
|
{
|
|
mng_ReadNewDoorPage (infile,&doorpage);
|
|
if (stricmp(name,doorpage.door_struct.name))
|
|
mng_WriteNewDoorPage (outfile,&doorpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_GENERIC:
|
|
{
|
|
mng_ReadNewGenericPage (infile,&genericpage);
|
|
if (stricmp(name,genericpage.objinfo_struct.name))
|
|
mng_WriteNewGenericPage (outfile,&genericpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
if (genericpage.objinfo_struct.description!=NULL)
|
|
{
|
|
mem_free (genericpage.objinfo_struct.description);
|
|
genericpage.objinfo_struct.description = NULL;
|
|
}
|
|
genericpage.objinfo_struct.icon_name[0] = '\0';
|
|
break;
|
|
}
|
|
case PAGETYPE_SOUND:
|
|
{
|
|
mng_ReadNewSoundPage (infile,&soundpage);
|
|
if (stricmp(name,soundpage.sound_struct.name))
|
|
mng_WriteNewSoundPage (outfile,&soundpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_SHIP:
|
|
{
|
|
mng_ReadNewShipPage (infile,&shippage);
|
|
if (stricmp(name,shippage.ship_struct.name))
|
|
mng_WriteNewShipPage (outfile,&shippage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_WEAPON:
|
|
{
|
|
mng_ReadNewWeaponPage (infile,&weaponpage);
|
|
if (stricmp(name,weaponpage.weapon_struct.name))
|
|
mng_WriteNewWeaponPage (outfile,&weaponpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_MEGACELL:
|
|
{
|
|
mng_ReadNewMegacellPage (infile,&megacellpage);
|
|
if (stricmp(name,megacellpage.megacell_struct.name))
|
|
mng_WriteNewMegacellPage (outfile,&megacellpage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
case PAGETYPE_GAMEFILE:
|
|
{
|
|
mng_ReadNewGamefilePage (infile,&gamefilepage);
|
|
if (stricmp(name,gamefilepage.gamefile_struct.name))
|
|
mng_WriteNewGamefilePage (outfile,&gamefilepage);
|
|
else
|
|
deleted=1; // Don't write out the one we want to delete
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!local)
|
|
{
|
|
// It's gotta be there if on the network
|
|
ASSERT (deleted==1);
|
|
}
|
|
else
|
|
{
|
|
if (!deleted)
|
|
{
|
|
mprintf ((0,"Not found locally?!\n"));
|
|
}
|
|
}
|
|
cfclose (infile);
|
|
cfclose (outfile);
|
|
mem_free (copybuffer);
|
|
// Now, remove our table file and rename the temp file to be the table file
|
|
if (local)
|
|
{
|
|
if (!SwitcherooFiles (LocalTableFilename,LocalTempTableFilename))
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if (!SwitcherooFiles (TableFilename,TempTableFilename))
|
|
return 0;
|
|
}
|
|
return 1; // successful!
|
|
|
|
}
|
|
// Reads in a physics chunk from an open file
|
|
void mng_ReadPhysicsChunk (physics_info *phys_info,CFILE *infile)
|
|
{
|
|
phys_info->mass=cf_ReadFloat (infile);
|
|
phys_info->drag=cf_ReadFloat (infile);
|
|
phys_info->full_thrust=cf_ReadFloat (infile);
|
|
phys_info->flags=cf_ReadInt (infile);
|
|
phys_info->rotdrag=cf_ReadFloat (infile);
|
|
phys_info->full_rotthrust=cf_ReadFloat (infile);
|
|
phys_info->num_bounces=cf_ReadInt (infile);
|
|
phys_info->velocity.z=cf_ReadFloat (infile);
|
|
phys_info->rotvel.x=cf_ReadFloat (infile);
|
|
phys_info->rotvel.y=cf_ReadFloat (infile);
|
|
phys_info->rotvel.z=cf_ReadFloat (infile);
|
|
phys_info->wiggle_amplitude=cf_ReadFloat (infile);
|
|
phys_info->wiggles_per_sec=cf_ReadFloat (infile);
|
|
phys_info->coeff_restitution=cf_ReadFloat (infile);
|
|
phys_info->hit_die_dot=cf_ReadFloat (infile);
|
|
phys_info->max_turnroll_rate=cf_ReadFloat (infile);
|
|
phys_info->turnroll_ratio=cf_ReadFloat (infile);
|
|
|
|
}
|
|
// Writes out a physics chunk to an open file
|
|
void mng_WritePhysicsChunk (physics_info *phys_info,CFILE *outfile)
|
|
{
|
|
cf_WriteFloat (outfile,phys_info->mass);
|
|
cf_WriteFloat (outfile,phys_info->drag);
|
|
cf_WriteFloat (outfile,phys_info->full_thrust);
|
|
cf_WriteInt (outfile,phys_info->flags);
|
|
cf_WriteFloat (outfile,phys_info->rotdrag);
|
|
cf_WriteFloat (outfile,phys_info->full_rotthrust);
|
|
cf_WriteInt (outfile,phys_info->num_bounces);
|
|
cf_WriteFloat (outfile,phys_info->velocity.z);
|
|
cf_WriteFloat (outfile,phys_info->rotvel.x);
|
|
cf_WriteFloat (outfile,phys_info->rotvel.y);
|
|
cf_WriteFloat (outfile,phys_info->rotvel.z);
|
|
cf_WriteFloat (outfile,phys_info->wiggle_amplitude);
|
|
cf_WriteFloat (outfile,phys_info->wiggles_per_sec);
|
|
cf_WriteFloat (outfile,phys_info->coeff_restitution);
|
|
cf_WriteFloat (outfile,phys_info->hit_die_dot);
|
|
cf_WriteFloat (outfile,phys_info->max_turnroll_rate);
|
|
cf_WriteFloat (outfile,phys_info->turnroll_ratio);
|
|
}
|
|
// Writes out weapon battery info
|
|
void mng_WriteWeaponBatteryChunk (otype_wb_info *static_wb,CFILE *outfile)
|
|
{
|
|
int j;
|
|
cf_WriteFloat(outfile, static_wb->energy_usage);
|
|
cf_WriteFloat(outfile, static_wb->ammo_usage);
|
|
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
|
|
{
|
|
cf_WriteShort(outfile, static_wb->gp_weapon_index[j]);
|
|
}
|
|
|
|
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
|
|
{
|
|
cf_WriteByte(outfile, static_wb->gp_fire_masks[j]);
|
|
cf_WriteFloat(outfile, static_wb->gp_fire_wait[j]);
|
|
cf_WriteFloat(outfile, static_wb->anim_time[j]);
|
|
cf_WriteFloat(outfile, static_wb->anim_start_frame[j]);
|
|
cf_WriteFloat(outfile, static_wb->anim_fire_frame[j]);
|
|
cf_WriteFloat(outfile, static_wb->anim_end_frame[j]);
|
|
}
|
|
cf_WriteByte(outfile, static_wb->num_masks);
|
|
cf_WriteShort(outfile, static_wb->aiming_gp_index);
|
|
cf_WriteByte(outfile, static_wb->aiming_flags);
|
|
cf_WriteFloat(outfile, static_wb->aiming_3d_dot);
|
|
cf_WriteFloat(outfile, static_wb->aiming_3d_dist);
|
|
cf_WriteFloat(outfile, static_wb->aiming_XZ_dot);
|
|
cf_WriteShort(outfile, static_wb->flags);
|
|
cf_WriteByte(outfile, static_wb->gp_quad_fire_mask);
|
|
}
|
|
// Reads in weapon battery info
|
|
void mng_ReadWeaponBatteryChunk (otype_wb_info *static_wb,CFILE *infile,int version)
|
|
{
|
|
int j;
|
|
|
|
static_wb->energy_usage=cf_ReadFloat(infile);
|
|
static_wb->ammo_usage=cf_ReadFloat(infile);
|
|
|
|
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
|
|
{
|
|
static_wb->gp_weapon_index[j]=cf_ReadShort(infile);
|
|
}
|
|
|
|
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
|
|
{
|
|
static_wb->gp_fire_masks[j]=cf_ReadByte(infile);
|
|
static_wb->gp_fire_wait[j]=cf_ReadFloat(infile);
|
|
static_wb->anim_time[j]=cf_ReadFloat (infile);
|
|
static_wb->anim_start_frame[j]=cf_ReadFloat (infile);
|
|
static_wb->anim_fire_frame[j]=cf_ReadFloat (infile);
|
|
static_wb->anim_end_frame[j]=cf_ReadFloat (infile);
|
|
}
|
|
static_wb->num_masks=cf_ReadByte (infile);
|
|
static_wb->aiming_gp_index=cf_ReadShort(infile);
|
|
static_wb->aiming_flags=cf_ReadByte(infile);
|
|
static_wb->aiming_3d_dot=cf_ReadFloat(infile);
|
|
static_wb->aiming_3d_dist=cf_ReadFloat(infile);
|
|
static_wb->aiming_XZ_dot=cf_ReadFloat(infile);
|
|
if (version>=2)
|
|
static_wb->flags=cf_ReadShort(infile);
|
|
else
|
|
static_wb->flags=cf_ReadByte(infile);
|
|
static_wb->gp_quad_fire_mask=cf_ReadByte(infile);
|
|
}
|
|
// Writes a lighting chunk in from an open file
|
|
void mng_WriteLightingChunk ( light_info *lighting_info,CFILE *outfile)
|
|
{
|
|
cf_WriteFloat (outfile,lighting_info->light_distance);
|
|
cf_WriteFloat (outfile,lighting_info->red_light1);
|
|
cf_WriteFloat (outfile,lighting_info->green_light1);
|
|
cf_WriteFloat (outfile,lighting_info->blue_light1);
|
|
cf_WriteFloat (outfile,lighting_info->time_interval);
|
|
cf_WriteFloat (outfile,lighting_info->flicker_distance);
|
|
cf_WriteFloat (outfile,lighting_info->directional_dot);
|
|
cf_WriteFloat (outfile,lighting_info->red_light2);
|
|
cf_WriteFloat (outfile,lighting_info->green_light2);
|
|
cf_WriteFloat (outfile,lighting_info->blue_light2);
|
|
cf_WriteInt (outfile,lighting_info->flags);
|
|
cf_WriteInt (outfile,lighting_info->timebits);
|
|
cf_WriteByte (outfile,lighting_info->angle);
|
|
cf_WriteByte (outfile,lighting_info->lighting_render_type);
|
|
|
|
}
|
|
// Reads a lighting chunk in from an open file
|
|
void mng_ReadLightingChunk (light_info *lighting_info,CFILE *infile)
|
|
{
|
|
lighting_info->light_distance=cf_ReadFloat (infile);
|
|
lighting_info->red_light1=cf_ReadFloat (infile);
|
|
lighting_info->green_light1=cf_ReadFloat (infile);
|
|
lighting_info->blue_light1=cf_ReadFloat (infile);
|
|
lighting_info->time_interval=cf_ReadFloat (infile);
|
|
lighting_info->flicker_distance=cf_ReadFloat (infile);
|
|
lighting_info->directional_dot=cf_ReadFloat (infile);
|
|
lighting_info->red_light2=cf_ReadFloat (infile);
|
|
lighting_info->green_light2=cf_ReadFloat (infile);
|
|
lighting_info->blue_light2=cf_ReadFloat (infile);
|
|
lighting_info->flags=cf_ReadInt (infile);
|
|
lighting_info->timebits=cf_ReadInt (infile);
|
|
lighting_info->angle=cf_ReadByte (infile);
|
|
lighting_info->lighting_render_type=cf_ReadByte (infile);
|
|
}
|
|
|
|
// Record keeping
|
|
AddOnTablefile AddOnDataTables[MAX_ADDON_TABLES];
|
|
|
|
// the number of addon tables currently in memory
|
|
int Num_addon_tables=0;
|
|
|
|
// if not -1, then it is the addon table we are working with
|
|
int Loading_addon_table=-1;
|
|
|
|
//----------------------
|
|
// Add-on data routines
|
|
//----------------------
|
|
// Frees all the primitives associated with an page
|
|
void mng_FreePagetypePrimitives (int pagetype,char *name,int freetype)
|
|
{
|
|
int n;
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
n=FindTextureName (name);
|
|
ASSERT (n>=0);
|
|
if (GameTextures[n].flags & TF_ANIMATED)
|
|
FreeVClip(GameTextures[n].bm_handle);
|
|
else
|
|
bm_FreeBitmap (GameTextures[n].bm_handle);
|
|
if (GameTextures[n].flags & TF_DESTROYABLE && GameTextures[n].destroy_handle>=0 && GameTextures[n].destroy_handle!=n)
|
|
{
|
|
int oldn=n;
|
|
n=GameTextures[n].destroy_handle;
|
|
if (GameTextures[n].flags & TF_ANIMATED)
|
|
FreeVClip(GameTextures[n].bm_handle);
|
|
else
|
|
bm_FreeBitmap (GameTextures[n].bm_handle);
|
|
n=oldn;
|
|
}
|
|
if (freetype)
|
|
FreeTexture(n);
|
|
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
n=FindSoundName (name);
|
|
ASSERT (n>=0);
|
|
FreeSoundFile (Sounds[n].sample_index);
|
|
if (freetype)
|
|
FreeSound (n);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
n=FindWeaponName (name);
|
|
ASSERT (n>=0);
|
|
// Free weapon images
|
|
if (Weapons[n].flags & WF_HUD_ANIMATED)
|
|
FreeVClip(Weapons[n].hud_image_handle);
|
|
else
|
|
bm_FreeBitmap (Weapons[n].hud_image_handle);
|
|
if (Weapons[n].fire_image_handle!=-1)
|
|
{
|
|
if (Weapons[n].flags & WF_IMAGE_BITMAP)
|
|
bm_FreeBitmap (Weapons[n].fire_image_handle);
|
|
else if (Weapons[n].flags & WF_IMAGE_VCLIP)
|
|
FreeVClip (Weapons[n].fire_image_handle);
|
|
else
|
|
FreePolyModel(Weapons[n].fire_image_handle);
|
|
}
|
|
if (freetype)
|
|
FreeWeapon (n);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
n=FindShipName (name);
|
|
ASSERT (n>=0);
|
|
FreePolyModel (Ships[n].model_handle);
|
|
if (Ships[n].dying_model_handle!=-1)
|
|
FreePolyModel (Ships[n].dying_model_handle);
|
|
if (Ships[n].med_render_handle!=-1)
|
|
FreePolyModel (Ships[n].med_render_handle);
|
|
if (Ships[n].lo_render_handle!=-1)
|
|
FreePolyModel (Ships[n].lo_render_handle);
|
|
if (freetype)
|
|
FreeShip (n);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
n=FindObjectIDName (name);
|
|
ASSERT (n>=0);
|
|
|
|
FreePolyModel (Object_info[n].render_handle);
|
|
if (Object_info[n].med_render_handle!=-1)
|
|
FreePolyModel (Object_info[n].med_render_handle);
|
|
if (Object_info[n].lo_render_handle!=-1)
|
|
FreePolyModel (Object_info[n].lo_render_handle);
|
|
if (freetype)
|
|
FreeObjectID(n);
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
n=FindDoorName (name);
|
|
ASSERT (n>=0);
|
|
FreePolyModel (Doors[n].model_handle);
|
|
if (freetype)
|
|
FreeDoor (n);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// Takes our addon pages and frees/restores our data to the appropriate pages
|
|
void mng_PopAddonPages()
|
|
{
|
|
int i,n,ok;
|
|
|
|
ASSERT(Num_addon_tables>0);
|
|
if(Num_addon_tables<=0)
|
|
return; //no addon pages to pop off
|
|
|
|
Num_addon_tables--;
|
|
Loading_locals=0;
|
|
AddOnTablefile *addondata = &AddOnDataTables[Num_addon_tables];
|
|
|
|
for (i=0;i<addondata->Num_addon_tracklocks;i++)
|
|
{
|
|
mprintf ((0,"Freeing addon page %s [%s].\n",addondata->Addon_tracklocks[i].name,addondata->AddOnTableFilename));
|
|
|
|
// set the Loading_addon_table to the appropriate value...
|
|
// it depends on if we are overlaying from a previous tablefile
|
|
// or this isn't an overlay at all
|
|
// overlay = 0 (not an overlay of anything)
|
|
// overlay = 1 (overlay of main tablefile)
|
|
// overlay > 1 (overlay of addon table [overlay-2])
|
|
if(addondata->Addon_tracklocks[i].overlay>1)
|
|
{
|
|
// this is an overlay of another table file
|
|
Loading_addon_table=addondata->Addon_tracklocks[i].overlay-2;
|
|
}else
|
|
{
|
|
// this is an overlay of the main table file
|
|
// or not an overlay at all
|
|
Loading_addon_table=-1;
|
|
}
|
|
|
|
if (addondata->Addon_tracklocks[i].overlay>0)
|
|
{
|
|
// Free this data, then read the old stuff back in
|
|
mng_FreePagetypePrimitives (addondata->Addon_tracklocks[i].pagetype,addondata->Addon_tracklocks[i].name,0);
|
|
char *name=addondata->Addon_tracklocks[i].name;
|
|
switch (addondata->Addon_tracklocks[i].pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
{
|
|
n=FindTextureName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificTexPage (name,&texpage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignTexPageToTexture (&texpage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_SOUND:
|
|
{
|
|
n=FindSoundName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificSoundPage (name,&soundpage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignSoundPageToSound (&soundpage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_DOOR:
|
|
{
|
|
n=FindDoorName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificDoorPage (name,&doorpage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignDoorPageToDoor (&doorpage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_GENERIC:
|
|
{
|
|
n=FindObjectIDName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificGenericPage (name,&genericpage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignGenericPageToObjInfo (&genericpage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_SHIP:
|
|
{
|
|
n=FindShipName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificShipPage (name,&shippage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignShipPageToShip (&shippage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_WEAPON:
|
|
{
|
|
n=FindWeaponName (name);
|
|
ASSERT (n>=0);
|
|
ok=mng_FindSpecificWeaponPage (name,&weaponpage,addondata->Addon_tracklocks[i].stack_filepos);
|
|
if (ok)
|
|
{
|
|
ok=mng_AssignWeaponPageToWeapon (&weaponpage,n);
|
|
if (!ok)
|
|
Error ("Error 1 restoring page %s from addon data!",name);
|
|
}
|
|
else
|
|
Error ("Error 2 restoring page %s from addon data!",name);
|
|
break;
|
|
}
|
|
case PAGETYPE_GAMEFILE:
|
|
//I don't think there's anything we need to do here
|
|
break;
|
|
default:
|
|
Int3(); // bad type in list? Get Jason
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Not overlay, just free this data
|
|
mng_FreePagetypePrimitives (addondata->Addon_tracklocks[i].pagetype,addondata->Addon_tracklocks[i].name,1);
|
|
}
|
|
}
|
|
|
|
Loading_addon_table=-1;
|
|
}
|
|
// Simply sets no addon data to be loaded
|
|
void mng_ClearAddonTables ()
|
|
{
|
|
int count = Num_addon_tables;
|
|
while(count>0)
|
|
{
|
|
ASSERT(count==Num_addon_tables);
|
|
|
|
if(AddOnDataTables[count-1].Addon_tracklocks)
|
|
{
|
|
mng_PopAddonPages();
|
|
mem_free (AddOnDataTables[count-1].Addon_tracklocks);
|
|
AddOnDataTables[count-1].Addon_tracklocks = NULL;
|
|
AddOnDataTables[count-1].Num_addon_tracklocks = 0;
|
|
}
|
|
|
|
count--;
|
|
}
|
|
}
|
|
// Push the given table file as an addon table file
|
|
// returns true on success
|
|
bool mng_SetAddonTable(char *name)
|
|
{
|
|
ASSERT(Num_addon_tables<MAX_ADDON_TABLES);
|
|
if(Num_addon_tables>=MAX_ADDON_TABLES)
|
|
return false;
|
|
|
|
//make sure the table file exists!
|
|
if(!cfexist(name))
|
|
return false;
|
|
|
|
strcpy(AddOnDataTables[Num_addon_tables].AddOnTableFilename,name);
|
|
AddOnDataTables[Num_addon_tables].Addon_tracklocks=(mngs_track_lock *)mem_malloc (MAX_ADDON_TRACKLOCKS*sizeof(mngs_track_lock));
|
|
AddOnDataTables[Num_addon_tables].Num_addon_tracklocks = 0;
|
|
ASSERT (AddOnDataTables[Num_addon_tables].Addon_tracklocks);
|
|
memset(AddOnDataTables[Num_addon_tables].Addon_tracklocks,0,MAX_ADDON_TRACKLOCKS*sizeof(mngs_track_lock));
|
|
|
|
Num_addon_tables++;
|
|
return true;
|
|
}
|
|
|
|
// Pushes an addon pack onto the stack so we can keep track of it
|
|
void mng_PushAddonPage (int pagetype,char *name,int overlay)
|
|
{
|
|
ASSERT(Loading_addon_table>=0 && Loading_addon_table<MAX_ADDON_TABLES);
|
|
|
|
AddOnTablefile *addon = &AddOnDataTables[Loading_addon_table];
|
|
|
|
ASSERT (addon->Num_addon_tracklocks<MAX_ADDON_TRACKLOCKS);
|
|
|
|
// First check to see if this is a redundant page
|
|
for (int i=0;i<addon->Num_addon_tracklocks;i++)
|
|
{
|
|
if (addon->Addon_tracklocks[i].used && addon->Addon_tracklocks[i].pagetype==pagetype)
|
|
{
|
|
if (!stricmp (addon->Addon_tracklocks[i].name,name))
|
|
{
|
|
Int3();
|
|
Error ("Redundant addon page '%s' loaded...",name);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
mprintf ((0,"Adding addon page %s [%s] to list.\n",name,addon->AddOnTableFilename));
|
|
addon->Addon_tracklocks[addon->Num_addon_tracklocks].used=1;
|
|
addon->Addon_tracklocks[addon->Num_addon_tracklocks].pagetype=pagetype;
|
|
addon->Addon_tracklocks[addon->Num_addon_tracklocks].overlay=overlay;
|
|
addon->Addon_tracklocks[addon->Num_addon_tracklocks].stack_filepos = 0;
|
|
strcpy (addon->Addon_tracklocks[addon->Num_addon_tracklocks].name,name);
|
|
addon->Num_addon_tracklocks++;
|
|
}
|
|
|
|
// Compiles the addon pages. By looking at all the addon pages (after they have been
|
|
// loaded) and does some compiling and saving of information to speed up addon page
|
|
// freeing
|
|
void mng_CompileAddonPages(void)
|
|
{
|
|
if(Num_addon_tables<=0)
|
|
return; //no addon pages to pop off
|
|
|
|
int curr_tablefile,i,tf,pagetype,len,next_pos,page_pos;
|
|
CFILE *file;
|
|
char pagename[256];
|
|
bool found_page;
|
|
|
|
for(curr_tablefile=1;curr_tablefile<=Num_addon_tables;curr_tablefile++)
|
|
{
|
|
// find all the pages that are loaded from this tablefile
|
|
// overlay = 0 (not from any tablefile)
|
|
// overlay = 1 (from main tablefile)
|
|
// overlay > 1 (from addontable[overlay-2]
|
|
if(curr_tablefile==1)
|
|
{
|
|
file = cfopen(TableFilename,"rb");
|
|
mprintf((0,"Compiling addon pages of %s\n",TableFilename));
|
|
}
|
|
else
|
|
{
|
|
file = cfopen(AddOnDataTables[curr_tablefile-2].AddOnTableFilename,"rb");
|
|
mprintf((0,"Compiling addon pages of %s\n",AddOnDataTables[curr_tablefile-2].AddOnTableFilename));
|
|
}
|
|
ASSERT(file!=NULL);
|
|
|
|
// start reading the pages from this tablefile
|
|
// as we come across each page, check to see if it was
|
|
// ever overlayed.
|
|
while(!cfeof(file))
|
|
{
|
|
// Read in a pagetype. If its a page we recognize, load it
|
|
page_pos = cftell(file);
|
|
pagetype=cf_ReadByte (file);
|
|
len=cf_ReadInt (file);
|
|
next_pos = (page_pos + 1) + len;
|
|
|
|
// get the name of the page
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadByte(file);//type
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
cf_ReadShort(file);//version
|
|
cf_ReadString(pagename,PAGENAME_LEN,file);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
continue;
|
|
break;
|
|
default:
|
|
Int3(); // Unrecognized pagetype, possible corrupt data following
|
|
break;
|
|
}
|
|
|
|
// now look for all the places where this page is overlayed
|
|
found_page = false;
|
|
for(tf=0;tf<Num_addon_tables;tf++)
|
|
{
|
|
for(i=0;i<AddOnDataTables[tf].Num_addon_tracklocks;i++)
|
|
{
|
|
if(!AddOnDataTables[tf].Addon_tracklocks[i].used)
|
|
continue;
|
|
if(AddOnDataTables[tf].Addon_tracklocks[i].overlay!=curr_tablefile)
|
|
continue;
|
|
if(AddOnDataTables[tf].Addon_tracklocks[i].pagetype!=pagetype)
|
|
continue;
|
|
if(stricmp(pagename,AddOnDataTables[tf].Addon_tracklocks[i].name))
|
|
continue;
|
|
|
|
// this is it!
|
|
mprintf((0,"***Compiling: %s[%s] to %d\n",AddOnDataTables[tf].Addon_tracklocks[i].name,
|
|
(curr_tablefile==1)?TableFilename:AddOnDataTables[curr_tablefile-2].AddOnTableFilename,page_pos));
|
|
ASSERT(AddOnDataTables[tf].Addon_tracklocks[i].stack_filepos==0);
|
|
AddOnDataTables[tf].Addon_tracklocks[i].stack_filepos = page_pos;
|
|
found_page = true;
|
|
break;
|
|
}
|
|
|
|
if(found_page)
|
|
break;
|
|
}
|
|
|
|
// move on to the next page
|
|
cfseek(file,next_pos,SEEK_SET);
|
|
}
|
|
|
|
// done with this tablefile
|
|
cfclose(file);
|
|
}
|
|
}
|
|
|
|
//Error checking variables
|
|
bool Loading_addon = false;
|
|
int Data_error_count = 0;
|
|
FILE *Data_error_file = NULL;
|
|
char *Addon_filename;
|
|
|
|
// Loads and allocs all pages found locally
|
|
void mng_LoadAddonPages ()
|
|
{
|
|
CFILE *infile;
|
|
ubyte pagetype;
|
|
int len;
|
|
|
|
//Set flag & Clear error count
|
|
Loading_addon = true;
|
|
Data_error_count = 0;
|
|
|
|
if (Num_addon_tables==0)
|
|
return; // No addons to load
|
|
|
|
Loading_locals=0;
|
|
|
|
int c;
|
|
AddOnTablefile *addon;
|
|
|
|
for(c=0;c<Num_addon_tables;c++)
|
|
{
|
|
addon = &AddOnDataTables[c];
|
|
|
|
mprintf ((0,"------------------------------------\nLoading addon pages for %s....\n",addon->AddOnTableFilename));
|
|
Addon_filename = addon->AddOnTableFilename;
|
|
infile=cfopen (addon->AddOnTableFilename,"rb");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't addon table file (%s) to read pages!\n",addon->AddOnTableFilename));
|
|
return;
|
|
}
|
|
Loading_addon_table=c;
|
|
while (!cfeof(infile))
|
|
{
|
|
// Read in a pagetype. If its a page we recognize, load it
|
|
pagetype=cf_ReadByte (infile);
|
|
len=cf_ReadInt (infile);
|
|
|
|
mprintf ((0,"."));
|
|
switch (pagetype)
|
|
{
|
|
case PAGETYPE_TEXTURE:
|
|
mng_LoadLocalTexturePage (infile);
|
|
break;
|
|
case PAGETYPE_POWERUP:
|
|
case PAGETYPE_ROBOT:
|
|
Error("Your local table file is invalid. You must update from the network.");
|
|
break;
|
|
case PAGETYPE_DOOR:
|
|
mng_LoadLocalDoorPage (infile);
|
|
break;
|
|
case PAGETYPE_GENERIC:
|
|
mng_LoadLocalGenericPage (infile);
|
|
break;
|
|
case PAGETYPE_GAMEFILE:
|
|
mng_LoadLocalGamefilePage (infile);
|
|
break;
|
|
case PAGETYPE_SOUND:
|
|
mng_LoadLocalSoundPage (infile);
|
|
break;
|
|
case PAGETYPE_SHIP:
|
|
mng_LoadLocalShipPage (infile);
|
|
break;
|
|
case PAGETYPE_WEAPON:
|
|
mng_LoadLocalWeaponPage (infile);
|
|
break;
|
|
case PAGETYPE_MEGACELL:
|
|
mng_LoadLocalMegacellPage (infile);
|
|
break;
|
|
case PAGETYPE_UNKNOWN:
|
|
break;
|
|
default:
|
|
Int3(); // Unrecognized pagetype, possible corrupt data following
|
|
break;
|
|
}
|
|
}
|
|
mprintf ((0,"------------------------------------\n"));
|
|
cfclose (infile);
|
|
}
|
|
|
|
Loading_locals=0;
|
|
Loading_addon_table=-1;
|
|
|
|
mng_CompileAddonPages();
|
|
|
|
//Close error file
|
|
if (Data_error_file != NULL) {
|
|
fprintf(Data_error_file,"\nTotal errors: %d",Data_error_count);
|
|
fclose(Data_error_file);
|
|
}
|
|
|
|
//Clear flag
|
|
Loading_addon = false;
|
|
}
|
|
/*
|
|
#define MAX_256s 200
|
|
int Num_256s=0;
|
|
char Texture256Names[MAX_256s][80];
|
|
void Read256TextureNames ()
|
|
{
|
|
int n=FindArg ("-File256");
|
|
if (!n)
|
|
return;
|
|
CFILE *infile;
|
|
infile=(CFILE *)cfopen (GameArgs[n+1],"rt");
|
|
if (!infile)
|
|
{
|
|
mprintf ((0,"Couldn't open 256 file!\n"));
|
|
return;
|
|
}
|
|
|
|
char curline[200];
|
|
int done=0;
|
|
while (!done)
|
|
{
|
|
if (cfeof(infile))
|
|
{
|
|
done=1;
|
|
continue;
|
|
}
|
|
|
|
// Read a line and parse it
|
|
cf_ReadString (curline,200,infile);
|
|
if (curline[0]==';' || curline[1]==';' || curline[0]==' ' || curline[1]==' ')
|
|
continue;
|
|
if (!(isalnum(curline[0])))
|
|
continue;
|
|
strcpy (Texture256Names[Num_256s],curline);
|
|
Num_256s++;
|
|
}
|
|
cfclose (infile);
|
|
}*/
|
|
|
|
#include "pstring.h"
|
|
|
|
void DataError(char *fmt,...)
|
|
{
|
|
//Got a data error!
|
|
// Int3();
|
|
|
|
//Ignore this if not loading add-on data
|
|
if (! Loading_addon)
|
|
return;
|
|
|
|
//Increment error count
|
|
Data_error_count++;
|
|
|
|
//Write to file if switch specified
|
|
if (FindArg("-datacheck")) {
|
|
static char last_filename[_MAX_PATH];
|
|
va_list arglist;
|
|
char buf[1024];
|
|
|
|
va_start(arglist,fmt);
|
|
Pvsprintf(buf,sizeof(buf),fmt,arglist);
|
|
va_end(arglist);
|
|
|
|
//Open file if not already open
|
|
if (Data_error_file == NULL) {
|
|
Data_error_file = fopen("datacheck.out","wt");
|
|
|
|
if (Data_error_file == NULL)
|
|
return;
|
|
|
|
last_filename[0] = 0;
|
|
}
|
|
|
|
//If this is a new addon file, print the name
|
|
if (strcmp(last_filename,Addon_filename)) {
|
|
if (last_filename[0])
|
|
fprintf(Data_error_file,"\n\n");
|
|
fprintf(Data_error_file,"Errors in addon file <%s>:\n\n",Addon_filename);
|
|
strcpy(last_filename,Addon_filename);
|
|
}
|
|
|
|
//Print the message
|
|
fprintf(Data_error_file," ");
|
|
fprintf(Data_error_file,"%s",buf);
|
|
}
|
|
}
|