PACKAGEMANAGER is now a compiletime feature in its own right, and can be enabled separately from WEBCLIENT (although won't be able to download without WEBCLIENT).

SAVEDGAMES is now a new compiletime feature. Deathmatch/dedicated servers can freely disable it.
menuqc now makes sure that any fields it needs are actually present.
developer 1 should now report glsl line numbers a bit more reliably.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5284 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-08-04 07:05:20 +00:00
parent 61c0b9f83b
commit 0b2be8f4ba
21 changed files with 330 additions and 164 deletions

View file

@ -3,8 +3,7 @@
//FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http. //FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http.
#include "quakedef.h" #include "quakedef.h"
#ifdef WEBCLIENT #ifdef PACKAGEMANAGER
#define PACKAGEMANAGER
#if !defined(NOBUILTINMENUS) && !defined(SERVERONLY) #if !defined(NOBUILTINMENUS) && !defined(SERVERONLY)
#define DOWNLOADMENU #define DOWNLOADMENU
#endif #endif
@ -134,7 +133,6 @@ typedef struct package_s {
struct package_s *alternative; //alternative (hidden) forms of this package. struct package_s *alternative; //alternative (hidden) forms of this package.
unsigned int trymirrors;
char *mirror[8]; //FIXME: move to two types of dep... char *mirror[8]; //FIXME: move to two types of dep...
char gamedir[16]; char gamedir[16];
enum fs_relative fsroot; enum fs_relative fsroot;
@ -172,7 +170,10 @@ typedef struct package_s {
char name[1]; char name[1];
} *deps; } *deps;
#ifdef WEBCLIENT
struct dl_download *download; struct dl_download *download;
unsigned int trymirrors;
#endif
int flags; int flags;
int priority; int priority;
@ -190,8 +191,12 @@ static int domanifestinstall; //SECURITY_MANIFEST_*
#ifdef PLUGINS #ifdef PLUGINS
static qboolean pluginpromptshown; //so we only show prompts for new externally-installed plugins once, instead of every time the file is reloaded. static qboolean pluginpromptshown; //so we only show prompts for new externally-installed plugins once, instead of every time the file is reloaded.
#endif #endif
#ifdef WEBCLIENT
static qboolean doautoupdate; //updates will be marked (but not applied without the user's actions) static qboolean doautoupdate; //updates will be marked (but not applied without the user's actions)
static qboolean pkg_updating; //when flagged, further changes are blocked until completion. static qboolean pkg_updating; //when flagged, further changes are blocked until completion.
#else
static const qboolean pkg_updating = false;
#endif
//FIXME: these are allocated for the life of the exe. changing basedir should purge the list. //FIXME: these are allocated for the life of the exe. changing basedir should purge the list.
static int numdownloadablelists = 0; static int numdownloadablelists = 0;
@ -1152,11 +1157,13 @@ void PM_Shutdown(void)
{ {
numdownloadablelists--; numdownloadablelists--;
#ifdef WEBCLIENT
if (downloadablelist[numdownloadablelists].curdl) if (downloadablelist[numdownloadablelists].curdl)
{ {
DL_Close(downloadablelist[numdownloadablelists].curdl); DL_Close(downloadablelist[numdownloadablelists].curdl);
downloadablelist[numdownloadablelists].curdl = NULL; downloadablelist[numdownloadablelists].curdl = NULL;
} }
#endif
downloadablelist[numdownloadablelists].received = 0; downloadablelist[numdownloadablelists].received = 0;
Z_Free(downloadablelist[numdownloadablelists].url); Z_Free(downloadablelist[numdownloadablelists].url);
downloadablelist[numdownloadablelists].url = NULL; downloadablelist[numdownloadablelists].url = NULL;
@ -1232,6 +1239,7 @@ static void PM_UnmarkPackage(package_t *package)
return; //looks like its already deselected. return; //looks like its already deselected.
package->flags &= ~(DPF_MARKED); package->flags &= ~(DPF_MARKED);
#ifdef WEBCLIENT
//Is this safe? //Is this safe?
package->trymirrors = 0; //if its enqueued, cancel that quickly... package->trymirrors = 0; //if its enqueued, cancel that quickly...
if (package->download) if (package->download)
@ -1239,6 +1247,7 @@ static void PM_UnmarkPackage(package_t *package)
DL_Close(package->download); DL_Close(package->download);
package->download = NULL; package->download = NULL;
} }
#endif
//remove stuff that depends on us //remove stuff that depends on us
for (o = availablepackages; o; o = o->next) for (o = availablepackages; o; o = o->next)
@ -1530,7 +1539,7 @@ static void PM_PrintChanges(void)
} }
static void PM_ApplyChanges(void); static void PM_ApplyChanges(void);
#ifdef WEBCLIENT
static void PM_ListDownloaded(struct dl_download *dl) static void PM_ListDownloaded(struct dl_download *dl)
{ {
int i; int i;
@ -1619,6 +1628,7 @@ static void PM_ListDownloaded(struct dl_download *dl)
} }
} }
} }
#endif
//retry 1== //retry 1==
static void PM_UpdatePackageList(qboolean autoupdate, int retry) static void PM_UpdatePackageList(qboolean autoupdate, int retry)
{ {
@ -1633,6 +1643,10 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
if (*pm_downloads_url.string) if (*pm_downloads_url.string)
PM_AddSubList(pm_downloads_url.string, "", true, true); PM_AddSubList(pm_downloads_url.string, "", true, true);
#ifndef WEBCLIENT
for (i = 0; i < numdownloadablelists; i++)
downloadablelist[i].received = true;
#else
doautoupdate |= autoupdate; doautoupdate |= autoupdate;
//kick off the initial tier of list-downloads. //kick off the initial tier of list-downloads.
@ -1673,6 +1687,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
PM_PrintChanges(); PM_PrintChanges();
} }
} }
#endif
} }
@ -1860,6 +1875,7 @@ static void PM_WriteInstalledPackages(void)
} }
} }
#ifdef WEBCLIENT
//callback from PM_Download_Got, extracts each file from an archive //callback from PM_Download_Got, extracts each file from an archive
static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath) static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath)
{ //this is gonna suck. threading would help, but gah. { //this is gonna suck. threading would help, but gah.
@ -2114,6 +2130,7 @@ static char *PM_GetTempName(package_t *p)
Z_Free(ts); Z_Free(ts);
return Z_StrDup(destname); return Z_StrDup(destname);
} }
#endif
/*static void PM_AddDownloadedPackage(const char *filename) /*static void PM_AddDownloadedPackage(const char *filename)
{ {
@ -2143,8 +2160,9 @@ static char *PM_GetTempName(package_t *p)
int PM_IsApplying(qboolean listsonly) int PM_IsApplying(qboolean listsonly)
{ {
package_t *p;
int count = 0; int count = 0;
#ifdef WEBCLIENT
package_t *p;
int i; int i;
if (!listsonly) if (!listsonly)
{ {
@ -2159,12 +2177,14 @@ int PM_IsApplying(qboolean listsonly)
if (downloadablelist[i].curdl) if (downloadablelist[i].curdl)
count++; count++;
} }
#endif
return count; return count;
} }
//looks for the next package that needs downloading, and grabs it //looks for the next package that needs downloading, and grabs it
static void PM_StartADownload(void) static void PM_StartADownload(void)
{ {
#ifdef WEBCLIENT
vfsfile_t *tmpfile; vfsfile_t *tmpfile;
char *temp; char *temp;
package_t *p; package_t *p;
@ -2284,6 +2304,7 @@ static void PM_StartADownload(void)
//clear the updating flag once there's no more activity needed //clear the updating flag once there's no more activity needed
pkg_updating = downloading; pkg_updating = downloading;
#endif
} }
//'just' starts doing all the things needed to remove/install selected packages //'just' starts doing all the things needed to remove/install selected packages
static void PM_ApplyChanges(void) static void PM_ApplyChanges(void)
@ -2291,17 +2312,22 @@ static void PM_ApplyChanges(void)
package_t *p, **link; package_t *p, **link;
char temp[MAX_OSPATH]; char temp[MAX_OSPATH];
#ifdef WEBCLIENT
if (pkg_updating) if (pkg_updating)
return; return;
pkg_updating = true; pkg_updating = true;
#endif
//delete any that don't exist //delete any that don't exist
for (link = &availablepackages; *link ; ) for (link = &availablepackages; *link ; )
{ {
p = *link; p = *link;
#ifdef WEBCLIENT
if (p->download) if (p->download)
; //erk, dude, don't do two! ; //erk, dude, don't do two!
else if ((p->flags & DPF_PURGE) || (!(p->flags&DPF_MARKED) && (p->flags&DPF_ENABLED))) else
#endif
if ((p->flags & DPF_PURGE) || (!(p->flags&DPF_MARKED) && (p->flags&DPF_ENABLED)))
{ //if we don't want it but we have it anyway. don't bother to follow this logic when reinstalling { //if we don't want it but we have it anyway. don't bother to follow this logic when reinstalling
qboolean reloadpacks = false; qboolean reloadpacks = false;
struct packagedep_s *dep; struct packagedep_s *dep;
@ -2416,12 +2442,14 @@ static void PM_ApplyChanges(void)
link = &(*link)->next; link = &(*link)->next;
} }
#ifdef WEBCLIENT
//and flag any new/updated ones for a download //and flag any new/updated ones for a download
for (p = availablepackages; p ; p=p->next) for (p = availablepackages; p ; p=p->next)
{ {
if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED) && !p->download) if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED) && !p->download)
p->trymirrors = ~0u; p->trymirrors = ~0u;
} }
#endif
PM_StartADownload(); //and try to do those downloads. PM_StartADownload(); //and try to do those downloads.
} }
@ -2496,14 +2524,18 @@ static qboolean PM_DeclinedPackages(char *out, size_t outsize)
} }
static void PM_PromptApplyChanges_Callback(void *ctx, int opt) static void PM_PromptApplyChanges_Callback(void *ctx, int opt)
{ {
#ifdef WEBCLIENT
pkg_updating = false; pkg_updating = false;
#endif
if (opt == 0) if (opt == 0)
PM_ApplyChanges(); PM_ApplyChanges();
} }
static void PM_PromptApplyChanges(void); static void PM_PromptApplyChanges(void);
static void PM_PromptApplyDecline_Callback(void *ctx, int opt) static void PM_PromptApplyDecline_Callback(void *ctx, int opt)
{ {
#ifdef WEBCLIENT
pkg_updating = false; pkg_updating = false;
#endif
if (opt == 1) if (opt == 1)
{ {
PM_DeclinedPackages(NULL, 0); PM_DeclinedPackages(NULL, 0);
@ -2514,6 +2546,7 @@ static void PM_PromptApplyChanges(void)
{ {
unsigned int changes; unsigned int changes;
char text[8192]; char text[8192];
#ifdef WEBCLIENT
//lock it down, so noone can make any changes while this prompt is still displayed //lock it down, so noone can make any changes while this prompt is still displayed
if (pkg_updating) if (pkg_updating)
{ {
@ -2521,6 +2554,7 @@ static void PM_PromptApplyChanges(void)
return; return;
} }
pkg_updating = true; pkg_updating = true;
#endif
strcpy(text, "Really decline the following\nrecommendedpackages?\n\n"); strcpy(text, "Really decline the following\nrecommendedpackages?\n\n");
if (PM_DeclinedPackages(text+strlen(text), sizeof(text)-strlen(text))) if (PM_DeclinedPackages(text+strlen(text), sizeof(text)-strlen(text)))
@ -2530,7 +2564,11 @@ static void PM_PromptApplyChanges(void)
strcpy(text, "Apply the following changes?\n\n"); strcpy(text, "Apply the following changes?\n\n");
changes = PM_ChangeList(text+strlen(text), sizeof(text)-strlen(text)); changes = PM_ChangeList(text+strlen(text), sizeof(text)-strlen(text));
if (!changes) if (!changes)
{
#ifdef WEBCLIENT
pkg_updating = false;//no changes... pkg_updating = false;//no changes...
#endif
}
else else
M_Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, text, "Apply", NULL, "Cancel"); M_Menu_Prompt(PM_PromptApplyChanges_Callback, NULL, text, "Apply", NULL, "Cancel");
} }
@ -2903,11 +2941,13 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m)
if (p->alternative && (p->flags & DPF_HIDDEN)) if (p->alternative && (p->flags & DPF_HIDDEN))
p = p->alternative; p = p->alternative;
#ifdef WEBCLIENT
if (p->download) if (p->download)
Draw_FunString (x+4, y, va("%i", (int)p->download->qdownload.percent)); Draw_FunString (x+4, y, va("%i", (int)p->download->qdownload.percent));
else if (p->trymirrors) else if (p->trymirrors)
Draw_FunString (x+4, y, "PND"); Draw_FunString (x+4, y, "PND");
else else
#endif
{ {
switch((p->flags & (DPF_ENABLED | DPF_MARKED))) switch((p->flags & (DPF_ENABLED | DPF_MARKED)))
{ {
@ -3055,14 +3095,17 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsig
} }
} }
} }
#ifdef WEBCLIENT
else else
p->trymirrors = 0; p->trymirrors = 0;
#endif
return true; return true;
} }
return false; return false;
} }
#ifdef WEBCLIENT
static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m)
{ {
char *settings[] = char *settings[] =
@ -3094,6 +3137,17 @@ static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct menu_s *m, int
return false; return false;
} }
static qboolean MD_MarkUpdatesButton (union menuoption_s *mo,struct menu_s *m,int key)
{
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
{
PM_MarkUpdates();
return true;
}
return false;
}
#endif
qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key) qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key)
{ {
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
@ -3114,15 +3168,6 @@ static qboolean MD_ApplyDownloads (union menuoption_s *mo,struct menu_s *m,int k
return false; return false;
} }
static qboolean MD_MarkUpdatesButton (union menuoption_s *mo,struct menu_s *m,int key)
{
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
{
PM_MarkUpdates();
return true;
}
return false;
}
static qboolean MD_RevertUpdates (union menuoption_s *mo,struct menu_s *m,int key) static qboolean MD_RevertUpdates (union menuoption_s *mo,struct menu_s *m,int key)
{ {
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
@ -3154,20 +3199,22 @@ static void MD_AddItemsToDownloadMenu(menu_t *m)
y+=8; y+=8;
if (!prefixlen) if (!prefixlen)
{ {
#ifdef WEBCLIENT
MC_AddCommand(m, 0, 170, y, "Mark Updates", MD_MarkUpdatesButton); MC_AddCommand(m, 0, 170, y, "Mark Updates", MD_MarkUpdatesButton);
y+=8; y+=8;
#endif
MC_AddCommand(m, 0, 170, y, "Revert Updates", MD_RevertUpdates); MC_AddCommand(m, 0, 170, y, "Revert Updates", MD_RevertUpdates);
y+=8; y+=8;
}
if (!prefixlen) #ifdef WEBCLIENT
{
c = MC_AddCustom(m, 0, y, p, 0); c = MC_AddCustom(m, 0, y, p, 0);
c->draw = MD_AutoUpdate_Draw; c->draw = MD_AutoUpdate_Draw;
c->key = MD_AutoUpdate_Key; c->key = MD_AutoUpdate_Key;
c->common.width = 320; c->common.width = 320;
c->common.height = 8; c->common.height = 8;
y += 8; y += 8;
#endif
} }
y+=4; //small gap y+=4; //small gap

View file

@ -187,9 +187,6 @@ qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_se
void M_Menu_Options_f (void) void M_Menu_Options_f (void)
{ {
extern cvar_t crosshair, r_projection; extern cvar_t crosshair, r_projection;
#ifndef CLIENTONLY
extern cvar_t sv_autosave;
#endif
int y; int y;
static const char *projections[] = { static const char *projections[] = {
@ -211,7 +208,8 @@ void M_Menu_Options_f (void)
NULL NULL
}; };
#ifndef CLIENTONLY #if !defined(CLIENTONLY) && defined(SAVEDGAMES)
extern cvar_t sv_autosave;
static const char *autosaveopts[] = { static const char *autosaveopts[] = {
"Off", "Off",
"30 secs", "30 secs",
@ -234,8 +232,8 @@ void M_Menu_Options_f (void)
menubulk_t bulk[] = { menubulk_t bulk[] = {
MB_CONSOLECMD("Customize controls", "menu_keys\n", "Modify keyboard and mouse inputs."), MB_CONSOLECMD("Customize controls", "menu_keys\n", "Modify keyboard and mouse inputs."),
#ifdef WEBCLIENT #ifdef PACKAGEMANAGER
MB_CONSOLECMD("Updates and packages", "menu_download\n", "Modify keyboard and mouse inputs."), MB_CONSOLECMD("Updates and Packages", "menu_download\n", "Configure additional content and plugins."),
#endif #endif
MB_CONSOLECMD("Go to console", "toggleconsole\nplay misc/menu2.wav\n", "Open up the engine console."), MB_CONSOLECMD("Go to console", "toggleconsole\nplay misc/menu2.wav\n", "Open up the engine console."),
MB_CONSOLECMD("Reset to defaults", "cvarreset *\nexec default.cfg\nplay misc/menu2.wav\n", "Reloads the default configuration."), MB_CONSOLECMD("Reset to defaults", "cvarreset *\nexec default.cfg\nplay misc/menu2.wav\n", "Reloads the default configuration."),
@ -250,7 +248,7 @@ void M_Menu_Options_f (void)
MB_CHECKBOXCVAR("Lookspring", lookspring, 0), MB_CHECKBOXCVAR("Lookspring", lookspring, 0),
MB_CHECKBOXCVAR("Lookstrafe", lookstrafe, 0), MB_CHECKBOXCVAR("Lookstrafe", lookstrafe, 0),
MB_CHECKBOXCVAR("Windowed Mouse", _windowed_mouse, 0), MB_CHECKBOXCVAR("Windowed Mouse", _windowed_mouse, 0),
#ifndef CLIENTONLY #if !defined(CLIENTONLY) && defined(SAVEDGAMES)
MB_COMBOCVAR("Auto Save", sv_autosave, autosaveopts, autosavevals, NULL), MB_COMBOCVAR("Auto Save", sv_autosave, autosaveopts, autosavevals, NULL),
#endif #endif
MB_SPACING(4), MB_SPACING(4),

View file

@ -4,7 +4,7 @@
#include "winquake.h" #include "winquake.h"
#include "shader.h" #include "shader.h"
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS
#ifndef CLIENTONLY #if !defined(CLIENTONLY) && defined(SAVEDGAMES)
//============================================================================= //=============================================================================
/* LOAD/SAVE MENU */ /* LOAD/SAVE MENU */
@ -329,10 +329,10 @@ void M_Menu_SinglePlayer_f (void)
MC_AddConsoleCommand (menu, 64, 170, 40, "Easy", va("closemenu; skill 0;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0)); MC_AddConsoleCommand (menu, 64, 170, 40, "Easy", va("closemenu; skill 0;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0));
MC_AddConsoleCommand (menu, 64, 170, 48, "Medium", va("closemenu; skill 1;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0)); MC_AddConsoleCommand (menu, 64, 170, 48, "Medium", va("closemenu; skill 1;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0));
MC_AddConsoleCommand (menu, 64, 170, 56, "Hard", va("closemenu; skill 2;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0)); MC_AddConsoleCommand (menu, 64, 170, 56, "Hard", va("closemenu; skill 2;deathmatch 0; coop %i;newgame\n", cl_splitscreen.ival>0));
#ifdef SAVEDGAMES
MC_AddConsoleCommand (menu, 64, 170, 72, "Load Game", "menu_load\n"); MC_AddConsoleCommand (menu, 64, 170, 72, "Load Game", "menu_load\n");
MC_AddConsoleCommand (menu, 64, 170, 80, "Save Game", "menu_save\n"); MC_AddConsoleCommand (menu, 64, 170, 80, "Save Game", "menu_save\n");
#endif
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 48, 0, 40, NULL, false); menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 48, 0, 40, NULL, false);
return; return;
#endif #endif
@ -455,8 +455,10 @@ void M_Menu_SinglePlayer_f (void)
menu->selecteditem = (menuoption_t*) menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "New Game", "menu_single class demo1\n"); MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "New Game", "menu_single class demo1\n");
} }
#ifdef SAVEDGAMES
MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Save Game", "menu_save\n"); MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Save Game", "menu_save\n");
MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Load Game", "menu_load\n"); MC_AddConsoleCommandHexen2BigFont(menu, 80, y+=20, "Load Game", "menu_load\n");
#endif
} }
menu->cursoritem = (menuoption_t *)MC_AddCursor(menu, &resel, 56, menu->selecteditem?menu->selecteditem->common.posy:0); menu->cursoritem = (menuoption_t *)MC_AddCursor(menu, &resel, 56, menu->selecteditem?menu->selecteditem->common.posy:0);
@ -474,8 +476,10 @@ void M_Menu_SinglePlayer_f (void)
menu->selecteditem = (menuoption_t*) menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommandQBigFont (menu, 72, 32, "New Game", "closemenu;disconnect;maxclients 1;samelevel \"\";deathmatch \"\";set_calc coop ($cl_splitscreen>0);startmap_sp\n"); MC_AddConsoleCommandQBigFont (menu, 72, 32, "New Game", "closemenu;disconnect;maxclients 1;samelevel \"\";deathmatch \"\";set_calc coop ($cl_splitscreen>0);startmap_sp\n");
#ifdef SAVEDGAMES
MC_AddConsoleCommandQBigFont (menu, 72, 52, "Load Game", "menu_load\n"); MC_AddConsoleCommandQBigFont (menu, 72, 52, "Load Game", "menu_load\n");
MC_AddConsoleCommandQBigFont (menu, 72, 72, "Save Game", "menu_save\n"); MC_AddConsoleCommandQBigFont (menu, 72, 72, "Save Game", "menu_save\n");
#endif
menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, &resel, 54, 32); menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, &resel, 54, 32);
return; return;
@ -525,12 +529,14 @@ void M_Menu_SinglePlayer_f (void)
menu->selecteditem = (menuoption_t *)b; menu->selecteditem = (menuoption_t *)b;
b->common.width = width; b->common.width = width;
b->common.height = 20; b->common.height = 20;
#ifdef SAVEDGAMES
b = MC_AddConsoleCommand (menu, 72, 304, 52, "", "menu_load\n"); b = MC_AddConsoleCommand (menu, 72, 304, 52, "", "menu_load\n");
b->common.width = width; b->common.width = width;
b->common.height = 20; b->common.height = 20;
b = MC_AddConsoleCommand (menu, 72, 304, 72, "", "menu_save\n"); b = MC_AddConsoleCommand (menu, 72, 304, 72, "", "menu_save\n");
b->common.width = width; b->common.width = width;
b->common.height = 20; b->common.height = 20;
#endif
#if MAX_SPLITS > 1 #if MAX_SPLITS > 1
b = (menubutton_t*)MC_AddCvarCombo(menu, 72, 72+width/2, 92, "", &cl_splitscreen, opts, vals); b = (menubutton_t*)MC_AddCvarCombo(menu, 72, 72+width/2, 92, "", &cl_splitscreen, opts, vals);

View file

@ -1222,7 +1222,7 @@ void M_Init_Internal (void)
return; return;
internalmenusregistered = true; internalmenusregistered = true;
#ifndef CLIENTONLY #if !defined(CLIENTONLY) && defined(SAVEDGAMES)
Cmd_AddCommand ("menu_save", M_Menu_Save_f); Cmd_AddCommand ("menu_save", M_Menu_Save_f);
Cmd_AddCommand ("menu_load", M_Menu_Load_f); Cmd_AddCommand ("menu_load", M_Menu_Load_f);
Cmd_AddCommand ("menu_loadgame", M_Menu_Load_f); //q2... Cmd_AddCommand ("menu_loadgame", M_Menu_Load_f); //q2...
@ -1371,7 +1371,7 @@ void M_Init (void)
Cmd_AddCommand ("menu_servers", M_Menu_ServerList2_f); Cmd_AddCommand ("menu_servers", M_Menu_ServerList2_f);
#endif #endif
//downloads menu needs sandboxing, so cannot be provided by qc. //downloads menu needs sandboxing, so cannot be provided by qc.
#ifdef WEBCLIENT #ifdef PACKAGEMANAGER
Cmd_AddCommand ("menu_download", Menu_DownloadStuff_f); Cmd_AddCommand ("menu_download", Menu_DownloadStuff_f);
#endif #endif
//demo menu is allowed to see outside of the quakedir. you can't replicate that in qc's sandbox. //demo menu is allowed to see outside of the quakedir. you can't replicate that in qc's sandbox.

View file

@ -1817,6 +1817,8 @@ static void QCBUILTIN PF_m_setmodel(pubprogfuncs_t *prinst, struct globalvars_s
model_t *mod = Mod_ForName(modelname, MLV_WARN); model_t *mod = Mod_ForName(modelname, MLV_WARN);
if (modelval) if (modelval)
modelval->string = G_INT(OFS_PARM1); //lets hope garbage collection is enough. modelval->string = G_INT(OFS_PARM1); //lets hope garbage collection is enough.
else
Con_Printf("PF_m_setmodel: no model field!\n");
if (mod) if (mod)
while(mod->loadstate == MLS_LOADING) while(mod->loadstate == MLS_LOADING)
@ -1834,7 +1836,10 @@ static void QCBUILTIN PF_m_setcustomskin(pubprogfuncs_t *prinst, struct globalva
const char *skindata = PF_VarString(prinst, 2, pr_globals); const char *skindata = PF_VarString(prinst, 2, pr_globals);
eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "skinobject", ev_string, &menuc_eval.skinobject); eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "skinobject", ev_string, &menuc_eval.skinobject);
if (!val) if (!val)
{
Con_Printf("PF_m_setcustomskin: no skinobject field!\n");
return; return;
}
if (val->_float > 0) if (val->_float > 0)
{ {
@ -1858,6 +1863,8 @@ static void QCBUILTIN PF_m_setorigin(pubprogfuncs_t *prinst, struct globalvars_s
eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "origin", ev_vector, &menuc_eval.origin); eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "origin", ev_vector, &menuc_eval.origin);
if (val) if (val)
VectorCopy(org, val->_vector); VectorCopy(org, val->_vector);
else
Con_Printf("PF_m_setorigin: no origin field!\n");
} }
static void QCBUILTIN PF_m_clearscene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_m_clearscene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -2645,6 +2652,12 @@ qboolean MP_Init (void)
PR_ProgsAdded(menu_world.progs, mprogs, "menu.dat"); PR_ProgsAdded(menu_world.progs, mprogs, "menu.dat");
//ensure that there's space for these fields in.
//other fields will always be referenced/defined by the qc, or 0.
PR_RegisterFieldVar(menu_world.progs, ev_string, "model", -1, -1);
PR_RegisterFieldVar(menu_world.progs, ev_vector, "origin", -1, -1);
PR_RegisterFieldVar(menu_world.progs, ev_float, "skinobject", -1, -1);
menuentsize = PR_InitEnts(menu_world.progs, 8192); menuentsize = PR_InitEnts(menu_world.progs, 8192);

View file

@ -1453,7 +1453,7 @@ void V_ClearRefdef(playerview_t *pv)
r_refdef.fovv_x = 0; r_refdef.fovv_x = 0;
r_refdef.fovv_y = 0; r_refdef.fovv_y = 0;
r_refdef.drawsbar = cl.intermissionmode == IM_NONE; r_refdef.drawsbar = (cl.intermissionmode == IM_NONE);
r_refdef.flags = 0; r_refdef.flags = 0;
r_refdef.areabitsknown = false; r_refdef.areabitsknown = false;

View file

@ -111,6 +111,7 @@
#define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'. #define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'.
//#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) //#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
//#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) //#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define SAVEDGAMES //Can save the game.
// Networking options // Networking options
#define NQPROT //act as an nq client/server, with nq gamecode. #define NQPROT //act as an nq client/server, with nq gamecode.
@ -124,6 +125,7 @@
//#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea. //#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea.
#define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections. #define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections.
#define CL_MASTER //Clientside Server Browser functionality. #define CL_MASTER //Clientside Server Browser functionality.
#define PACKAGEMANAGER //Allows the user to enable/disable/download(with WEBCLIENT) packages and plugins.
// Audio Drivers // Audio Drivers
#define AVAIL_OPENAL #define AVAIL_OPENAL

View file

@ -113,6 +113,7 @@
//#define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'. //#define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'.
////#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) ////#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
////#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) ////#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
//#define SAVEDGAMES //Can save the game.
// Networking options // Networking options
//#define NQPROT //act as an nq client/server, with nq gamecode. //#define NQPROT //act as an nq client/server, with nq gamecode.
@ -126,6 +127,7 @@
//#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea. //#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea.
//#define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections. //#define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections.
//#define CL_MASTER //Clientside Server Browser functionality. //#define CL_MASTER //Clientside Server Browser functionality.
//#define PACKAGEMANAGER //Allows the user to enable/disable/download packages and plugins.
// Audio Drivers // Audio Drivers
//#define AVAIL_OPENAL //#define AVAIL_OPENAL

View file

@ -110,6 +110,7 @@
//#define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'. //#define SUBSERVERS //Allows the server to fork itself, each acting as an MMO-style server instance of a single 'realm'.
//#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) //#define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
//#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) //#define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define SAVEDGAMES //Can save the game.
// Networking options // Networking options
//#define NQPROT //act as an nq client/server, with nq gamecode. //#define NQPROT //act as an nq client/server, with nq gamecode.
@ -123,6 +124,7 @@
//#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea. //#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea.
#define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections. #define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections.
#define CL_MASTER //Clientside Server Browser functionality. #define CL_MASTER //Clientside Server Browser functionality.
//#define PACKAGEMANAGER //Allows the user to enable/disable/download packages and plugins.
// Audio Drivers // Audio Drivers
#define AVAIL_OPENAL #define AVAIL_OPENAL

View file

@ -163,6 +163,8 @@
#undef HAVE_MEDIA_DECODER //can play cin/roq, more with plugins #undef HAVE_MEDIA_DECODER //can play cin/roq, more with plugins
#undef HAVE_MEDIA_ENCODER //capture/capturedemo work. #undef HAVE_MEDIA_ENCODER //capture/capturedemo work.
#undef HAVE_SPEECHTOTEXT //windows speech-to-text thing #undef HAVE_SPEECHTOTEXT //windows speech-to-text thing
//#define SAVEDGAMES //Can save the game.
#undef PACKAGEMANAGER //Allows the user to enable/disable/download packages and plugins.
#ifdef COMPILE_OPTS #ifdef COMPILE_OPTS
//things to configure qclib, which annoyingly doesn't include this file itself //things to configure qclib, which annoyingly doesn't include this file itself

View file

@ -2242,6 +2242,11 @@ bspx_header_t *BSPX_Setup(model_t *mod, char *filebase, unsigned int filelen, lu
return h; return h;
} }
#ifdef SERVERONLY
void BSPX_LoadEnvmaps(model_t *mod, bspx_header_t *bspx, void *mod_base)
{
}
#else
/* /*
void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum uploadfmt *fmt); void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum uploadfmt *fmt);
void BSPX_RenderEnvmaps(model_t *mod) void BSPX_RenderEnvmaps(model_t *mod)
@ -2408,9 +2413,6 @@ void BSPX_LoadEnvmaps(model_t *mod, bspx_header_t *bspx, void *mod_base)
} }
} }
#if 1//ndef SERVERONLY
struct bspxrw struct bspxrw
{ {
fromgame_t fg; fromgame_t fg;
@ -2632,7 +2634,13 @@ unsigned int Mod_NearestCubeForSurf(msurface_t *surf, denvmap_t *envmap, size_t
for (n = 0; n < nenvmap; n++) for (n = 0; n < nenvmap; n++)
{ {
VectorSubtract(mid, envmap[n].origin, diff); VectorSubtract(mid, envmap[n].origin, diff);
#if 1
//axial distance
dist = min(min(fabs(diff[0]), fabs(diff[1])), fabs(diff[2]));
#else
//radial distance (squared)
dist = DotProduct(diff,diff); dist = DotProduct(diff,diff);
#endif
if (bestdist > dist) if (bestdist > dist)
{ {
best = n; best = n;

View file

@ -736,10 +736,12 @@ void Mod_Purge(enum mod_purge_e ptype)
} }
} }
#ifndef SERVERONLY
void Mod_FindCubemaps_f(void); void Mod_FindCubemaps_f(void);
void Mod_Realign_f(void); void Mod_Realign_f(void);
void Mod_BSPX_List_f(void); void Mod_BSPX_List_f(void);
void Mod_BSPX_Strip_f(void); void Mod_BSPX_Strip_f(void);
#endif
/* /*
=============== ===============
@ -777,10 +779,12 @@ void Mod_Init (qboolean initial)
Cmd_AddCommand("sv_saveentfile", Mod_SaveEntFile_f); Cmd_AddCommand("sv_saveentfile", Mod_SaveEntFile_f);
Cmd_AddCommand("version_modelformats", Mod_PrintFormats_f); Cmd_AddCommand("version_modelformats", Mod_PrintFormats_f);
#ifndef SERVERONLY
Cmd_AddCommandD("map_findcubemaps", Mod_FindCubemaps_f, "Scans the entities of a map to find reflection envmap sites and determines the nearest one to each surface."); Cmd_AddCommandD("map_findcubemaps", Mod_FindCubemaps_f, "Scans the entities of a map to find reflection envmap sites and determines the nearest one to each surface.");
Cmd_AddCommandD("map_realign", Mod_Realign_f, "Reads the named bsp and writes it back out with only alignment changes."); Cmd_AddCommandD("map_realign", Mod_Realign_f, "Reads the named bsp and writes it back out with only alignment changes.");
Cmd_AddCommandD("map_bspx_list", Mod_BSPX_List_f, "Lists all lumps (and their sizes) in the specified bsp."); Cmd_AddCommandD("map_bspx_list", Mod_BSPX_List_f, "Lists all lumps (and their sizes) in the specified bsp.");
Cmd_AddCommandD("map_bspx_strip", Mod_BSPX_Strip_f, "Strips a named extension lump from a bsp file."); Cmd_AddCommandD("map_bspx_strip", Mod_BSPX_Strip_f, "Strips a named extension lump from a bsp file.");
#endif
} }
if (initial) if (initial)

View file

@ -1877,26 +1877,74 @@ static const char *glsl_hdrs[] =
NULL NULL
}; };
qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *prstrings[], GLint length[], const char *shadersource) #define GLSLPARTS (64+16)
struct glslparts_s
{
const GLchar *str[GLSLPARTS];
GLint len[GLSLPARTS];
const GLchar *file[GLSLPARTS];
int line[GLSLPARTS];
int strings;
const char *error;
};
static void GLSlang_GenerateInternal(struct glslparts_s *glsl, const char *shadersource)
{
if (glsl->strings == GLSLPARTS)
{
glsl->error = "Too many parts";
return;
}
glsl->str[glsl->strings] = shadersource;
glsl->len[glsl->strings] = strlen(shadersource);
glsl->file[glsl->strings] = NULL;
glsl->line[glsl->strings] = 0;
glsl->strings += 1;
}
static void GLSlang_Generate(struct glslparts_s *glsl, const char *shadersource, GLint length, const char *filename, int linenumber)
{
if (glsl->strings == GLSLPARTS)
{
glsl->error = "Too many parts";
return;
}
glsl->str[glsl->strings] = shadersource;
glsl->len[glsl->strings] = length;
glsl->file[glsl->strings] = filename;
glsl->line[glsl->strings] = linenumber;
glsl->strings += 1;
}
static qboolean GLSlang_GenerateIncludes(struct glslparts_s *glsl, const char *shadersource, const char *filename, int linenumber)
{ {
int i; int i;
char *incline, *inc; char *incline, *inc;
char incname[256]; char incname[256];
while((incline=strstr(shadersource, "#include"))) while((incline=strstr(shadersource, "#include")))
{ {
if (*strings == maxstrings)
return false;
/*emit up to the include*/ /*emit up to the include*/
if (incline - shadersource) if (incline - shadersource)
{ {
prstrings[*strings] = shadersource; char *e = incline;
length[*strings] = incline - shadersource; while(e > shadersource && (e[-1] == ' ' || e[-1] == '\t'))
*strings += 1; e--;
if (e > shadersource && e[-1] == '\n')
GLSlang_Generate(glsl, shadersource, e-shadersource, filename, linenumber);
else
GLSlang_Generate(glsl, shadersource, incline-shadersource, filename, linenumber);
} }
incline += 8; incline += 8;
incline = COM_ParseOut (incline, incname, sizeof(incname)); incline = COM_ParseOut (incline, incname, sizeof(incname));
if (!incline)
{
glsl->error = "missing include name";
return false;
}
while (*incline == ' ' || *incline == '\t')
incline++;
if (!strncmp(incname, "cvar/", 5)) if (!strncmp(incname, "cvar/", 5))
{ {
@ -1904,17 +1952,13 @@ qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *pr
if (var) if (var)
{ {
var->flags |= CVAR_SHADERSYSTEM; var->flags |= CVAR_SHADERSYSTEM;
if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, var->string)) if (!GLSlang_GenerateIncludes(glsl, var->string, NULL, 0))
return false; return false;
} }
else else
{ {
/*dump something if the cvar doesn't exist*/ /*dump something if the cvar doesn't exist*/
if (*strings == maxstrings) GLSlang_Generate(glsl, "0", strlen("0"), filename, linenumber);
return false;
prstrings[*strings] = "0";
length[*strings] = strlen("0");
*strings += 1;
} }
} }
else else
@ -1923,38 +1967,39 @@ qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *pr
{ {
if (!strcmp(incname, glsl_hdrs[i])) if (!strcmp(incname, glsl_hdrs[i]))
{ {
if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, glsl_hdrs[i+1])) if (!GLSlang_GenerateIncludes(glsl, glsl_hdrs[i+1], glsl_hdrs[i], 1))
return false; return false;
break; break;
} }
} }
if (!glsl_hdrs[i]) if (!glsl_hdrs[i])
{ {
if (FS_LoadFile(incname, (void**)&inc) != (qofs_t)-1) size_t sz;
inc = COM_LoadTempMoreFile(incname, &sz);
if (inc)
{ {
if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, inc)) if (!GLSlang_GenerateIncludes(glsl, inc, NULL, 1))
{
FS_FreeFile(inc);
return false; return false;
} }
FS_FreeFile(inc); else
{
glsl->error = "include file not found";
return false; //FIXME: add a warning
} }
} }
} }
/*move the pointer past the include*/ /*move the pointer past the include*/
shadersource = incline; while (shadersource < incline)
}
if (*shadersource)
{ {
if (*strings == maxstrings) if (*shadersource == '\n')
return false; linenumber++;
shadersource++;
/*dump the remaining shader string*/
prstrings[*strings] = shadersource;
length[*strings] = strlen(prstrings[*strings]);
*strings += 1;
} }
}
if (*shadersource)
GLSlang_Generate(glsl, shadersource, strlen(shadersource), filename, linenumber);
return true; return true;
} }
@ -1965,11 +2010,12 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
{ {
GLhandleARB shader; GLhandleARB shader;
int i; int i;
const GLchar *prstrings[64+16]; struct glslparts_s glsl;
GLint length[sizeof(prstrings)/sizeof(prstrings[0])];
int strings = 0;
char verline[64]; char verline[64];
glsl.strings = 0;
glsl.error = NULL;
if (!shadersource) if (!shadersource)
return 0; return 0;
@ -2013,44 +2059,32 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
Q_snprintfz(verline, sizeof(verline), "#version %u compatibility\n", ver); Q_snprintfz(verline, sizeof(verline), "#version %u compatibility\n", ver);
else else
Q_snprintfz(verline, sizeof(verline), "#version %u\n", ver); //core assumed, where defined Q_snprintfz(verline, sizeof(verline), "#version %u\n", ver); //core assumed, where defined
prstrings[strings] = verline; GLSlang_GenerateInternal(&glsl, verline);
length[strings] = strlen(prstrings[strings]);
strings++;
} }
} }
while(*precompilerconstants) while(*precompilerconstants)
{ GLSlang_GenerateInternal(&glsl, *precompilerconstants++);
prstrings[strings] = *precompilerconstants++;
length[strings] = strlen(prstrings[strings]);
strings++;
}
prstrings[strings] = "#define ENGINE_"DISTRIBUTION"\n"; GLSlang_GenerateInternal(&glsl, "#define ENGINE_"DISTRIBUTION"\n");
length[strings] = strlen(prstrings[strings]);
strings++;
switch (shadertype) switch (shadertype)
{ {
case GL_FRAGMENT_SHADER_ARB: case GL_FRAGMENT_SHADER_ARB:
prstrings[strings] = "#define FRAGMENT_SHADER\n"; GLSlang_GenerateInternal(&glsl, "#define FRAGMENT_SHADER\n");
length[strings] = strlen(prstrings[strings]);
strings++;
if (gl_config.gles) if (gl_config.gles)
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\n" "precision highp float;\n"
"#else\n" "#else\n"
"precision mediump float;\n" "precision mediump float;\n"
"#endif\n" "#endif\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
if (ver >= 130) if (ver >= 130)
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
//gl3+ deprecated the some things. these are removed in forwards-compatible / core contexts. //gl3+ deprecated the some things. these are removed in forwards-compatible / core contexts.
//varying became either in or out, which is important if you have geometry shaders... //varying became either in or out, which is important if you have geometry shaders...
"#define varying in\n" "#define varying in\n"
@ -2071,20 +2105,16 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
"out vec4 fte_fragdata3;" "out vec4 fte_fragdata3;"
"\n#endif\n" //gles3 requires this "\n#endif\n" //gles3 requires this
"#define gl_FragColor fte_fragdata0\n" "#define gl_FragColor fte_fragdata0\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
else else
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#define fte_fragdata0 gl_FragData[0]\n" "#define fte_fragdata0 gl_FragData[0]\n"
"#define fte_fragdata1 gl_FragData[1]\n" "#define fte_fragdata1 gl_FragData[1]\n"
"#define fte_fragdata2 gl_FragData[2]\n" "#define fte_fragdata2 gl_FragData[2]\n"
"#define fte_fragdata3 gl_FragData[3]\n" "#define fte_fragdata3 gl_FragData[3]\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
if (prog) if (prog)
@ -2127,82 +2157,62 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
for (i = 0; i < countof(defaultsamplernames); i++) for (i = 0; i < countof(defaultsamplernames); i++)
{ {
if (prog->defaulttextures & (1u<<i)) if (prog->defaulttextures & (1u<<i))
{ GLSlang_GenerateInternal(&glsl, defaultsamplernames[i]);
prstrings[strings] = defaultsamplernames[i];
length[strings] = strlen(prstrings[strings]);
strings++;
}
} }
#endif #endif
for (i = 0; i < prog->numsamplers && i < countof(numberedsamplernames); i++) for (i = 0; i < prog->numsamplers && i < countof(numberedsamplernames); i++)
{ GLSlang_GenerateInternal(&glsl, numberedsamplernames[i]);
prstrings[strings] = numberedsamplernames[i];
length[strings] = strlen(prstrings[strings]);
strings++;
}
} }
break; break;
case GL_GEOMETRY_SHADER_ARB: case GL_GEOMETRY_SHADER_ARB:
prstrings[strings] = "#define GEOMETRY_SHADER\n"; GLSlang_GenerateInternal(&glsl, "#define GEOMETRY_SHADER\n");
length[strings] = strlen(prstrings[strings]);
strings++;
break; break;
case GL_TESS_CONTROL_SHADER_ARB: case GL_TESS_CONTROL_SHADER_ARB:
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#define TESS_CONTROL_SHADER\n" "#define TESS_CONTROL_SHADER\n"
"#if __VERSION__ < 400\n" "#if __VERSION__ < 400\n"
"#extension GL_ARB_tessellation_shader : enable\n" "#extension GL_ARB_tessellation_shader : enable\n"
"#endif\n"; "#endif\n"
//varyings are arrays, so don't bother defining that here. //varyings are arrays, so don't bother defining that here.
length[strings] = strlen(prstrings[strings]); );
strings++;
break; break;
case GL_TESS_EVALUATION_SHADER_ARB: case GL_TESS_EVALUATION_SHADER_ARB:
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#define TESS_EVALUATION_SHADER\n" "#define TESS_EVALUATION_SHADER\n"
"#if __VERSION__ < 400\n" "#if __VERSION__ < 400\n"
"#extension GL_ARB_tessellation_shader : enable\n" "#extension GL_ARB_tessellation_shader : enable\n"
"#endif\n" "#endif\n"
"#define varying out\n"; "#define varying out\n"
length[strings] = strlen(prstrings[strings]); );
strings++;
break; break;
case GL_VERTEX_SHADER_ARB: case GL_VERTEX_SHADER_ARB:
prstrings[strings] = "#define VERTEX_SHADER\n"; GLSlang_GenerateInternal(&glsl, "#define VERTEX_SHADER\n");
length[strings] = strlen(prstrings[strings]);
strings++;
#ifdef RTLIGHTS #ifdef RTLIGHTS
if (!r_shadow_shadowmapping.ival && ver >= 120) if (!r_shadow_shadowmapping.ival && ver >= 120)
{ {
prstrings[strings] = "invariant gl_Position;\n"; GLSlang_GenerateInternal(&glsl, "invariant gl_Position;\n");
length[strings] = strlen(prstrings[strings]);
strings++;
} }
#endif #endif
if (gl_config.gles) if (gl_config.gles)
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\n" "precision highp float;\n"
"#else\n" "#else\n"
"precision mediump float;\n" "precision mediump float;\n"
"#endif\n" "#endif\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
if (ver >= 130) if (ver >= 130)
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#define attribute in\n" "#define attribute in\n"
"#define varying out\n" "#define varying out\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
if (gl_config_nofixedfunc) if (gl_config_nofixedfunc)
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"attribute vec3 v_position1;\n" "attribute vec3 v_position1;\n"
"#ifdef FRAMEBLEND\n" "#ifdef FRAMEBLEND\n"
"attribute vec3 v_position2;\n" "attribute vec3 v_position2;\n"
@ -2218,13 +2228,11 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
#else #else
"#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
#endif #endif
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
else else
{ {
prstrings[strings] = GLSlang_GenerateInternal(&glsl,
"#ifdef FRAMEBLEND\n" "#ifdef FRAMEBLEND\n"
"attribute vec3 v_position2;\n" "attribute vec3 v_position2;\n"
"uniform vec2 e_vblend;\n" "uniform vec2 e_vblend;\n"
@ -2236,24 +2244,51 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
"uniform mat4 m_modelviewprojection;\n" "uniform mat4 m_modelviewprojection;\n"
"#define ftetransform ftransform\n" "#define ftetransform ftransform\n"
"#endif\n" "#endif\n"
; );
length[strings] = strlen(prstrings[strings]);
strings++;
} }
break; break;
default: default:
prstrings[strings] = "#define UNKNOWN_SHADER\n"; GLSlang_GenerateInternal(&glsl, "#define UNKNOWN_SHADER\n");
length[strings] = strlen(prstrings[strings]);
strings++;
break; break;
} }
GLSlang_GenerateIncludes(sizeof(prstrings)/sizeof(prstrings[0]), &strings, prstrings, length, shadersource); GLSlang_GenerateIncludes(&glsl, shadersource, name, 1);
shader = qglCreateShaderObjectARB(shadertype); shader = qglCreateShaderObjectARB(shadertype);
if (gl_workaround_ati_shadersource.ival) if (developer.ival)
{
GLcharARB *combined;
int totallen = 1;
for (i = 0; i < glsl.strings; i++)
totallen += glsl.len[i] + 64;
combined = malloc(totallen);
totallen = 0;
combined[totallen] = 0;
for (i = 0; i < glsl.strings; i++)
{
if (ver && !i)
; //#version MUST be the first line, don't prefix it with a #line, it'll just break things.
else if (!totallen || combined[totallen-1] == '\n')
{ //last line was a newline, hurrah. safe to insert without breaking anything
Q_snprintfz(combined+totallen, 64, "#line %i %i //%s\n", glsl.line[i], i, glsl.file[i]);
totallen += strlen(combined+totallen);
}
else if (glsl.len[i] && *glsl.str[i] == '\n')
{ //last line didn't end with a newline, but there is one after. that's okay too, but we need to play it safe.
Q_snprintfz(combined+totallen, 64, "\n#line %i %i //%s\n", glsl.line[i], i, glsl.file[i]);
totallen += strlen(combined+totallen);
}
//now shove stuff there.
memcpy(combined+totallen, glsl.str[i], glsl.len[i]);
totallen += glsl.len[i];
combined[totallen] = 0;
}
qglShaderSourceARB(shader, 1, (const GLcharARB**)&combined, NULL);
free(combined);
}
else if (gl_workaround_ati_shadersource.ival)
{ {
/*ATI Driver Bug: ATI drivers ignore the 'length' array. /*ATI Driver Bug: ATI drivers ignore the 'length' array.
this code does what the drivers fail to do. this code does what the drivers fail to do.
@ -2262,22 +2297,22 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
*/ */
GLcharARB *combined; GLcharARB *combined;
int totallen = 1; int totallen = 1;
for (i = 0; i < strings; i++) for (i = 0; i < glsl.strings; i++)
totallen += length[i]; totallen += glsl.len[i];
combined = malloc(totallen); combined = malloc(totallen);
totallen = 0; totallen = 0;
combined[totallen] = 0; combined[totallen] = 0;
for (i = 0; i < strings; i++) for (i = 0; i < glsl.strings; i++)
{ {
memcpy(combined + totallen, prstrings[i], length[i]); memcpy(combined + totallen, glsl.str[i], glsl.len[i]);
totallen += length[i]; totallen += glsl.len[i];
combined[totallen] = 0; combined[totallen] = 0;
} }
qglShaderSourceARB(shader, 1, (const GLcharARB**)&combined, NULL); qglShaderSourceARB(shader, 1, (const GLcharARB**)&combined, NULL);
free(combined); free(combined);
} }
else else
qglShaderSourceARB(shader, strings, prstrings, length); qglShaderSourceARB(shader, glsl.strings, glsl.str, glsl.len);
qglCompileShaderARB(shader); qglCompileShaderARB(shader);
return shader; return shader;

View file

@ -13621,7 +13621,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, const char *name, QCC_function_t *s
} }
else if (type->type == ev_field) else if (type->type == ev_field)
{ {
if (type->aux_type->type == ev_vector && !arraysize) if (type->aux_type->type == ev_vector && !arraysize && *def->name != ':')
{ {
//do the vector thing. //do the vector thing.
QC_snprintfz(newname, sizeof(newname), "%s_x", def->name); QC_snprintfz(newname, sizeof(newname), "%s_x", def->name);

View file

@ -5625,11 +5625,12 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
d = QCC_PR_GetDef(NULL, membername, NULL, 0, 0, GDF_CONST); d = QCC_PR_GetDef(NULL, membername, NULL, 0, 0, GDF_CONST);
if (!d) if (!d)
{ {
d = QCC_PR_GetDef(QCC_PR_FieldType(*basictypes[newparm->type]), membername, NULL, 2, 0, GDF_CONST|GDF_POSTINIT); d = QCC_PR_GetDef(QCC_PR_FieldType(*basictypes[newparm->type]), membername, NULL, 2, 0, GDF_CONST|GDF_POSTINIT|GDF_USED);
// for (i = 0; (unsigned int)i < newparm->size*(arraysize?arraysize:1); i++) // for (i = 0; (unsigned int)i < newparm->size*(arraysize?arraysize:1); i++)
// d->symboldata[i]._int = pr.size_fields+i; // d->symboldata[i]._int = pr.size_fields+i;
// pr.size_fields += i; // pr.size_fields += i;
d->used = true;
d->referenced = true; //always referenced, so you can inherit safely. d->referenced = true; //always referenced, so you can inherit safely.
} }
if (d->arraysize < basicindex+(arraysize?arraysize:1)) if (d->arraysize < basicindex+(arraysize?arraysize:1))
@ -5637,7 +5638,17 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (d->symboldata) if (d->symboldata)
QCC_PR_ParseError(ERR_INTERNAL, "array members are kinda limited, sorry. try rearranging them or adding padding for alignment\n"); //FIXME: add relocs to cope with this all of a type can then be contiguous and thus allow arrays. QCC_PR_ParseError(ERR_INTERNAL, "array members are kinda limited, sorry. try rearranging them or adding padding for alignment\n"); //FIXME: add relocs to cope with this all of a type can then be contiguous and thus allow arrays.
else else
d->arraysize = basicindex+(arraysize?arraysize:1); {
int newsize = basicindex+(arraysize?arraysize:1);
if (d->type->type == ev_union || d->type->type == ev_struct)
d->arraysize = newsize;
else while(d->arraysize < newsize)
{
QC_snprintfz(membername, sizeof(membername), "::%s[%i]", basictypenames[newparm->type], d->arraysize/d->type->size);
QCC_PR_DummyDef(d->type, membername, d->scope, 0, d, d->arraysize, true, GDF_CONST);
d->arraysize+=d->type->size;
}
}
} }
} }
QCC_FreeDef(d); QCC_FreeDef(d);

View file

@ -604,6 +604,25 @@ void QCC_PrintStrings (void)
} }
}*/ }*/
void QCC_SortFields (void)
{
int i, j;
QCC_ddef32_t t;
// good 'ol bubble sort
//(qsort doesn't guarentee ordering)
for (i = 0; i < numfielddefs; i++)
{
for (j = i; j < numfielddefs; j++)
if (fields[i].ofs > fields[j].ofs)
{
t = fields[i];
fields[i] = fields[j];
fields[j] = t;
}
}
}
void QCC_PrintFields (void) void QCC_PrintFields (void)
{ {
extern char *basictypenames[]; extern char *basictypenames[];
@ -1855,6 +1874,7 @@ pbool QCC_WriteData (int crc)
printf("code: %s:%i: %s%s%s %s@%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs); printf("code: %s:%i: %s%s%s %s@%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs);
#endif #endif
} }
QCC_SortFields();
if (dupewarncount > 10 && !verbose) if (dupewarncount > 10 && !verbose)
QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "suppressed %i more warnings about unreferenced variables, as you clearly don't care about the first 10.", dupewarncount-10); QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "suppressed %i more warnings about unreferenced variables, as you clearly don't care about the first 10.", dupewarncount-10);

View file

@ -1,7 +1,7 @@
#include "quakedef.h" #include "quakedef.h"
#include "pr_common.h" #include "pr_common.h"
#ifndef CLIENTONLY #if !defined(CLIENTONLY) && defined(SAVEDGAMES)
extern cvar_t skill; extern cvar_t skill;
extern cvar_t deathmatch; extern cvar_t deathmatch;
@ -9,7 +9,7 @@ extern cvar_t coop;
extern cvar_t teamplay; extern cvar_t teamplay;
extern cvar_t pr_enable_profiling; extern cvar_t pr_enable_profiling;
cvar_t sv_savefmt = CVARFD("sv_savefmt", "1", CVAR_SAVE, "Specifies the format used for the saved game.\n0=legacy.\n1=fte\n2=binary"); cvar_t sv_savefmt = CVARFD("sv_savefmt", "", CVAR_SAVE, "Specifies the format used for the saved game.\n0=legacy.\n1=fte\n2=binary");
cvar_t sv_autosave = CVARFD("sv_autosave", "5", CVAR_SAVE, "Interval for autosaves, in minutes. Set to 0 to disable autosave."); cvar_t sv_autosave = CVARFD("sv_autosave", "5", CVAR_SAVE, "Interval for autosaves, in minutes. Set to 0 to disable autosave.");
void SV_Savegame_f (void); void SV_Savegame_f (void);
@ -78,7 +78,7 @@ void SV_SavegameComment (char *text, size_t textsize)
#ifndef QUAKETC #ifndef QUAKETC
//expects the version to have already been parsed //expects the version to have already been parsed
void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version) static void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
{ {
//FIXME: Multiplayer save probably won't work with spectators. //FIXME: Multiplayer save probably won't work with spectators.
char mapname[MAX_QPATH]; char mapname[MAX_QPATH];
@ -394,7 +394,7 @@ static void SV_LegacySavegame (const char *savename)
} }
sprintf (name, "%s", savename); sprintf (name, "%s", savename);
COM_RequireExtension (name, ".sav", sizeof(name)); COM_RequireExtension (name, ".sav", sizeof(name)); //do NOT allow .pak etc
if (!FS_NativePath(name, FS_GAMEONLY, native, sizeof(native))) if (!FS_NativePath(name, FS_GAMEONLY, native, sizeof(native)))
return; return;
Con_TPrintf (U8("Saving game to %s...\n"), native); Con_TPrintf (U8("Saving game to %s...\n"), native);
@ -1109,7 +1109,7 @@ void SV_SaveLevelCache(const char *savedir, qboolean dontharmgame)
//FIXME: static entities //FIXME: static entities
//FIXME: midi track //FIXME: midi track
//FIXME: custom temp-ents? //FIXME: custom temp-ents?
//FIXME: pending uri_gets? (if only just to report fails) //FIXME: pending uri_gets? (if only just to report fails on load)
//FIXME: routing calls? //FIXME: routing calls?
//FIXME: sql queries? //FIXME: sql queries?
//FIXME: frik files? //FIXME: frik files?

View file

@ -116,7 +116,9 @@ typedef struct
unsigned int csqcchecksum; unsigned int csqcchecksum;
qboolean mapchangelocked; qboolean mapchangelocked;
#ifdef SAVEDGAMES
double autosave_time; double autosave_time;
#endif
double time; double time;
double starttime; double starttime;
int framenum; int framenum;
@ -1572,7 +1574,6 @@ typedef struct
int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *headerend, qtvpendingstate_t *p); int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *headerend, qtvpendingstate_t *p);
// savegame.c // savegame.c
void SV_LegacySavegame_f(void);
void SV_Savegame_f (void); void SV_Savegame_f (void);
void SV_Savegame_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx); void SV_Savegame_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx);
void SV_Loadgame_f (void); void SV_Loadgame_f (void);

View file

@ -675,6 +675,7 @@ void SV_Map_f (void)
if (!isrestart) if (!isrestart)
SV_SaveSpawnparms (); SV_SaveSpawnparms ();
#ifdef SAVEDGAMES
if (newunit) if (newunit)
SV_FlushLevelCache(); //forget all on new unit SV_FlushLevelCache(); //forget all on new unit
else if (startspot && !isrestart && !newunit) else if (startspot && !isrestart && !newunit)
@ -698,6 +699,7 @@ void SV_Map_f (void)
#endif #endif
SV_SaveLevelCache(NULL, false); SV_SaveLevelCache(NULL, false);
} }
#endif
#ifdef Q3SERVER #ifdef Q3SERVER
{ {
@ -783,7 +785,11 @@ void SV_Map_f (void)
} }
SCR_SetLoadingFile("spawnserver"); SCR_SetLoadingFile("spawnserver");
if (newunit || !startspot || cinematic || !SV_LoadLevelCache(NULL, level, startspot, false)) if (newunit || !startspot || cinematic
#ifdef SAVEDGAMES
|| !SV_LoadLevelCache(NULL, level, startspot, false)
#endif
)
{ {
if (waschangelevel && !startspot) if (waschangelevel && !startspot)
startspot = ""; startspot = "";
@ -854,12 +860,13 @@ void SV_Map_f (void)
Cvar_Set(nsv, ""); Cvar_Set(nsv, "");
} }
#ifdef SAVEDGAMES
if (q2savetos0) if (q2savetos0)
{ {
if (sv.state != ss_cinematic) //too weird. if (sv.state != ss_cinematic) //too weird.
SV_Savegame("s0", true); SV_Savegame("s0", true);
} }
#endif
if (isDedicated) if (isDedicated)
Mod_Purge(MP_MAPCHANGED); Mod_Purge(MP_MAPCHANGED);

View file

@ -650,7 +650,9 @@ void SV_UnspawnServer (void) //terminate the running server.
free(svs.clients); free(svs.clients);
svs.clients = NULL; svs.clients = NULL;
svs.allocated_client_slots = 0; svs.allocated_client_slots = 0;
#ifdef SAVEDGAMES
SV_FlushLevelCache(); SV_FlushLevelCache();
#endif
NET_CloseServer (); NET_CloseServer ();
SV_RunCmdCleanup(); SV_RunCmdCleanup();
} }
@ -1614,7 +1616,9 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
if (!startspot) if (!startspot)
{ {
#ifdef SAVEDGAMES
SV_FlushLevelCache(); //to make sure it's caught SV_FlushLevelCache(); //to make sure it's caught
#endif
for (i=0 ; i<sv.allocated_client_slots ; i++) for (i=0 ; i<sv.allocated_client_slots ; i++)
{ {
if (svs.clients[i].spawninfo) if (svs.clients[i].spawninfo)
@ -1730,7 +1734,9 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
SV_SetMoveVars(); SV_SetMoveVars();
sv.starttime = Sys_DoubleTime() - sv.time; sv.starttime = Sys_DoubleTime() - sv.time;
#ifdef SAVEDGAMES
sv.autosave_time = sv.time + sv_autosave.value*60; sv.autosave_time = sv.time + sv_autosave.value*60;
#endif
} }
#endif #endif

View file

@ -4899,8 +4899,10 @@ float SV_Frame (void)
{ {
isidle = false; isidle = false;
#ifdef SAVEDGAMES
if (sv.time > sv.autosave_time) if (sv.time > sv.autosave_time)
SV_AutoSave(); SV_AutoSave();
#endif
} }
} }
else else
@ -5203,10 +5205,9 @@ void SV_InitLocal (void)
Cmd_AddCommand ("openroute", SV_OpenRoute_f); Cmd_AddCommand ("openroute", SV_OpenRoute_f);
#ifndef NOBUILTINMENUS #ifdef SAVEDGAMES
#ifndef SERVERONLY #if !defined(NOBUILTINMENUS) && !defined(SERVERONLY)
Cvar_Register(&sv_autosave, cvargroup_servercontrol); Cvar_Register(&sv_autosave, cvargroup_servercontrol);
#endif
#endif #endif
Cvar_Register(&sv_savefmt, cvargroup_servercontrol); Cvar_Register(&sv_savefmt, cvargroup_servercontrol);
#ifndef QUAKETC #ifndef QUAKETC
@ -5216,6 +5217,7 @@ void SV_InitLocal (void)
Cmd_AddCommandAD ("loadgame", SV_Loadgame_f, SV_Savegame_c, "Loads an existing saved game."); Cmd_AddCommandAD ("loadgame", SV_Loadgame_f, SV_Savegame_c, "Loads an existing saved game.");
Cmd_AddCommandAD ("save", SV_Savegame_f, SV_Savegame_c, "Saves the game to the named location."); Cmd_AddCommandAD ("save", SV_Savegame_f, SV_Savegame_c, "Saves the game to the named location.");
Cmd_AddCommandAD ("load", SV_Loadgame_f, SV_Savegame_c, "Loads an existing saved game."); Cmd_AddCommandAD ("load", SV_Loadgame_f, SV_Savegame_c, "Loads an existing saved game.");
#endif
SV_MVDInit(); SV_MVDInit();