rework server browser slightly.

reimplement -Flogicops in qcc.
fix qcc problems with if_float fix enabled.
remove redundant norefs.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4909 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-18 22:11:30 +00:00
parent bb4003396b
commit 2ee86c0314
18 changed files with 651 additions and 225 deletions

View File

@ -99,9 +99,10 @@ typedef struct serverdetailedinfo_s
float time;
int ping;
char name[64];
char skin[64];
char skin[16];
char team[16];
char topc;
char botc;
char botc;
} players[MAX_CLIENTS];
} serverdetailedinfo_t;
@ -172,6 +173,7 @@ typedef struct player_s
int frags;
int colour;
char skin[8];
char team[8];
netadr_t adr;
struct player_s *next;
@ -184,7 +186,7 @@ extern master_t *master;
extern player_t *mplayers;
void Master_SetupSockets(void);
void CL_QueryServers(void);
qboolean CL_QueryServers(void);
int Master_CheckPollSockets(void);
void MasterInfo_Shutdown(void);
void MasterInfo_Request(master_t *mast);

View File

@ -5248,7 +5248,8 @@ char *CL_ParseChat(char *text, player_info_t **player, int *msgflags)
if (flags)
{
if (cl_nofake.value == 1 || (cl_nofake.value == 2 && flags != 2)) {
if (cl_nofake.value == 1 || (cl_nofake.value == 2 && !(flags & (TPM_OBSERVEDTEAM | TPM_TEAM))))
{
for (p = s; *p; p++)
if (*p == 13 || (*p == 10 && p[1]))
*p = ' ';
@ -5384,7 +5385,7 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
*(msg - 2) = 0; // it's assumed that msg has 2 chars before it due to strstr
}*/
if (*msg == '\r')
if (0)//*msg == '\r')
{
name = msg;
msg = strstr(msg, ": ");
@ -5441,7 +5442,9 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
c = '0' + c;
if (name)
if (plrflags & TPM_QTV)
Q_strncatz(fullchatmessage, "QTV ^m", sizeof(fullchatmessage));
else if (name)
{
if (memessage)
{

View File

@ -1301,6 +1301,7 @@ void QDECL vectoangles(vec3_t fwd, vec3_t ang);
#define TPM_SPECTATOR 4
#define TPM_FAKED 16
#define TPM_OBSERVEDTEAM 32
#define TPM_QTV 64 //should only be qtv_say_game/qtv_say_team_game
void CL_Say (qboolean team, char *extra);
int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr);

View File

@ -769,7 +769,7 @@ void Menu_DownloadStuff_f (void)
menu = M_CreateMenu(sizeof(dlmenu_t));
info = menu->data;
menu->event = M_Download_UpdateStatus;
menu->predraw = M_Download_UpdateStatus;
/*
menu->selecteditem = (menuoption_t *)(info->list = MC_AddCustom(menu, 0, 32, NULL));
info->list->draw = M_Download_Draw;

View File

@ -703,10 +703,10 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
static void MenuDraw(menu_t *menu)
{
if (menu->event)
menu->event(menu);
if (!menu->dontexpand)
menu->xpos = ((vid.width - 320)>>1);
if (menu->predraw)
menu->predraw(menu);
MenuDrawItems(menu->xpos, menu->ypos, menu->options, menu);
// draw tooltip
if (menu->selecteditem && menu->tooltip && realtime > menu->tooltiptime)
@ -739,6 +739,9 @@ static void MenuDraw(menu_t *menu)
}
}
}
if (menu->postdraw)
menu->postdraw(menu);
}
@ -2030,14 +2033,12 @@ static qboolean MC_GuiKey(int key, menu_t *menu)
}
extern int m_save_demonum;
qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
{
if (key == K_ESCAPE || key == K_MOUSE2)
{
extern int m_save_demonum;
extern cvar_t cl_demoreel, con_stayhidden;
if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected && cl_demoreel.ival)
CL_NextDemo ();
//don't spam menu open+close events if we're not going to be allowing the console to appear
if (con_stayhidden.ival && cls.state == ca_disconnected)
@ -2046,7 +2047,15 @@ qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
Key_Dest_Remove(kdm_menu);
m_state = m_none;
cls.demonum = m_save_demonum;
/* if (m_save_demonum != -1)
{
cls.demonum = m_save_demonum;
m_save_demonum = -1;
if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected && cl_demoreel.ival)
CL_NextDemo ();
}
*/
return true;
}
return false;
@ -2067,6 +2076,12 @@ void M_Menu_Main_f (void)
return;
#endif
/* if (cls.demoplayback)
{
m_save_demonum = cls.demonum;
cls.demonum = -1;
}
*/
SCR_EndLoadingPlaque(); //just in case...
/*

View File

@ -23,9 +23,11 @@ static cvar_t sb_showplayers = CVARF("sb_showplayers", "1", CVAR_ARCHIVE);
static cvar_t sb_showfraglimit = CVARF("sb_showfraglimit", "0", CVAR_ARCHIVE);
static cvar_t sb_showtimelimit = CVARF("sb_showtimelimit", "0", CVAR_ARCHIVE);
static cvar_t sb_alpha = CVARF("sb_alpha", "0.3", CVAR_ARCHIVE);
static cvar_t sb_alpha = CVARF("sb_alpha", "0.5", CVAR_ARCHIVE);
static float refreshedtime;
static int isrefreshing;
static qboolean serverpreview;
extern cvar_t slist_writeserverstxt;
extern cvar_t slist_cacheinfo;
@ -336,7 +338,8 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned
return true;
}
if (oldselection == info->selectedpos)
goto joinserver;
serverpreview = true;
// goto joinserver;
return true;
}
@ -353,6 +356,8 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned
{
server = Master_SortedServer(info->selectedpos);
if (server)
serverpreview = true;
/*
{
if (key == 's' || key == K_SPACE)
Cbuf_AddText("spectator 1\n", RESTRICT_LOCAL);
@ -369,6 +374,7 @@ joinserver:
M_RemoveAllMenus();
}
*/
return true;
}
else
@ -383,15 +389,276 @@ static void SL_PreDraw (menu_t *menu)
serverlist_t *info = (serverlist_t*)(menu + 1);
Master_CheckPollSockets();
CL_QueryServers();
if (isrefreshing)
{
if (!CL_QueryServers() && isrefreshing<=1)
{
//extra second, to ensure we got replies
isrefreshing = 2;
refreshedtime = Sys_DoubleTime()+1;
}
if (isrefreshing == 2)
{
if (refreshedtime < Sys_DoubleTime())
{
isrefreshing = false;
Master_SortServers();
}
}
}
snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u/%u/%u\n", Master_NumSorted(), Master_NumPolled(), Master_TotalCount());
info->numslots = Master_NumSorted();
snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u/%u/%u\n", info->numslots, Master_NumPolled(), Master_TotalCount());
}
static void SL_PostDraw (menu_t *menu)
{
static char *helpstrings[] =
{
"rmb: cancel",
"j: join",
"o: observe",
"v: say server info",
"ctrl-v: say_team server info",
"c: copy server info to clipboard",
"ctrl-c: copy server info only to clipboard",
"i: view serverinfo",
"k: toggle this info"
};
char buf[64];
serverlist_t *info = (serverlist_t*)(menu + 1);
Master_CheckPollSockets();
if (serverpreview)
{
serverinfo_t *server = selectedserver.inuse?Master_InfoForServer(&selectedserver.adr):NULL;
R2D_ImageColours(1,1,1,1);
if (server && server->moreinfo)
{
int lx, x, y, i;
int h = 0;
if (serverpreview == 3)
h = countof(helpstrings);
else if (serverpreview == 2)
{
for (i = 0; ; i++)
{
char *key = Info_KeyForNumber(server->moreinfo->info, i);
if (!strcmp(key, "hostname") || !strcmp(key, "status")) //these are part of the header
;
else if (*key)
h++;
else
break;
}
}
else
h += server->moreinfo->numplayers+2;
h += 4;
h *= 8;
Draw_TextBox(vid.width/2 - 100-12, vid.height/2 - h/2 - 8-8, 200/8+1, h/8+1);
// Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 - 8, "Refreshing, please wait", 200, 2, false);
// Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 + 0, va("%i of %i", Master_NumPolled(), Master_TotalCount()), 200, 2, false);
lx = vid.width/2 - 100;
y = vid.height/2 - h/2 - 4;
x = lx;
Draw_FunStringWidth (x, y, Info_ValueForKey(server->moreinfo->info, "hostname"), 200, 2, false);
y += 8;
Draw_FunStringWidth (x, y, Info_ValueForKey(server->moreinfo->info, "status"), 200, 2, false);
y += 8;
Draw_FunStringWidth (x, y, NET_AdrToString(buf, sizeof(buf), &server->adr), 200, 2, false);
y += 8;
Draw_FunStringWidth (x, y, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f", 200, 2, false);
y+=8;
if (serverpreview == 3)
{
x = lx;
for (i = 0; i < countof(helpstrings); i++)
{
Draw_FunStringWidth (x, y, helpstrings[i], 200, false, false);
y += 8;
}
Draw_FunStringWidth (x, y, Info_ValueForKey(server->moreinfo->info, "status"), 200, false, false);
y += 8;
Draw_FunStringWidth (x, y, NET_AdrToString(buf, sizeof(buf), &server->adr), 200, false, false);
y += 8;
}
else if (serverpreview == 2)
{
for (i = 0; ; i++)
{
char *key = Info_KeyForNumber(server->moreinfo->info, i);
if (!strcmp(key, "hostname") || !strcmp(key, "status"))
;
else if (*key)
{
char *value = Info_ValueForKey(server->moreinfo->info, key);
x = lx;
Draw_FunStringWidth (x, y, key, 100, false, false);
x+=100;
Draw_FunStringWidth (x, y, value, 100, false, false);
y += 8;
}
else
break;
}
}
else
{
int teamplay = atoi(Info_ValueForKey(server->moreinfo->info, "teamplay"));
x = lx;
Draw_FunStringWidth (x, y, "^mFrgs", 28, false, false);
x += 28+8;
Draw_FunStringWidth (x, y, "^mPng", 28, false, false);
x += 3*8+8;
if (teamplay)
{
Draw_FunStringWidth (x, y, "^mTeam", 4*8, false, false);
x += 4*8+8;
Draw_FunStringWidth (x, y, "^mName", 12*8, false, false);
x += 12*8+8;
}
else
{
Draw_FunStringWidth (x, y, "^mName", 16*8, false, false);
x += 16*8+8;
}
y+=8;
for (i = 0; i < server->moreinfo->numplayers; i++)
{
x = lx;
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].topc), 1.0);
R2D_FillBlock (x, y+1, 28, 3);
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].botc), 1.0);
R2D_FillBlock (x, y+4, 28, 4);
Draw_FunStringWidth (x, y, va("%3i", server->moreinfo->players[i].frags), 28, false, false);
x += 28+8;
Draw_FunStringWidth (x, y, va("%3i", server->moreinfo->players[i].ping), 28, false, false);
x += 3*8+8;
if (teamplay)
{
Draw_FunStringWidth (x, y, server->moreinfo->players[i].team, 4*8, false, false);
x += 4*8+8;
Draw_FunStringWidth (x, y, server->moreinfo->players[i].name, 12*8, false, false);
x += 12*8+8;
}
else
{
Draw_FunStringWidth (x, y, server->moreinfo->players[i].name, 16*8, false, false);
x += 16*8+8;
}
y += 8;
}
Draw_FunStringWidth (lx, y, "^h(press k for keybind help)", 200, false, false);
}
}
else
{
Draw_TextBox(vid.width/2 - 100-12, vid.height/2 - 32, 200/8, 64/8);
Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 - 8, "Querying server", 200, 2, false);
Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 + 0, "Please wait", 200, 2, false);
}
}
else if (isrefreshing)
{
R2D_ImageColours(1,1,1,1);
Draw_TextBox(vid.width/2 - 100-12, vid.height/2 - 32, 200/8, 64/8);
Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 - 8, "Refreshing, please wait", 200, 2, false);
Draw_FunStringWidth(vid.width/2 - 100, vid.height/2 + 0, va("%i of %i", Master_NumPolled(), Master_TotalCount()), 200, 2, false);
}
else if (!info->numslots)
{
R2D_ImageColours(1,1,1,1);
if (!Master_TotalCount())
{
Draw_FunStringWidth(0, vid.height/2 - 8, "No servers found", vid.width, 2, false);
Draw_FunStringWidth(0, vid.height/2 + 0, "Check internet connection", vid.width, 2, false);
}
else
{
Draw_FunStringWidth(0, vid.height/2 - 8, "All servers were filtered out", vid.width, 2, false);
Draw_FunStringWidth(0, vid.height/2 + 0, "Change filter settings", vid.width, 2, false);
}
}
}
static qboolean SL_Key (int key, menu_t *menu)
{
serverlist_t *info = (serverlist_t*)(menu + 1);
if (serverpreview)
{
char buf[64];
serverinfo_t *server = selectedserver.inuse?Master_InfoForServer(&selectedserver.adr):NULL;
extern qboolean keydown[];
qboolean ctrldown = keydown[K_LCTRL] || keydown[K_RCTRL];
if (key == K_ESCAPE || key == K_MOUSE2)
{
serverpreview = false;
return true;
}
else if (key == 'i')
{
serverpreview = ((serverpreview==2)?1:2);
return true;
}
else if (key == 'k')
{
serverpreview = ((serverpreview==3)?1:3);
return true;
}
else if (key == 'o' || key == 'j' || key == K_ENTER) //join
{
if (key == 's' || key == 'o')
Cbuf_AddText("spectator 1\n", RESTRICT_LOCAL);
else if (key == 'j')
Cbuf_AddText("spectator 0\n", RESTRICT_LOCAL);
if ((server->special & SS_PROTOCOLMASK) == SS_NETQUAKE)
Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(buf, sizeof(buf), &server->adr)), RESTRICT_LOCAL);
else
Cbuf_AddText(va("connect %s\n", NET_AdrToString(buf, sizeof(buf), &server->adr)), RESTRICT_LOCAL);
return true;
}
else if (server && key == 'c' && ctrldown) //copy to clip
{
Sys_SaveClipboard(NET_AdrToString(buf, sizeof(buf), &server->adr));
return true;
}
else if (server && (key == 'v' || key == 'c')) //say to current server
{
char *s;
char safename[128];
Q_strncpyz(safename, server->name, sizeof(safename));
//ALWAYS sanitize your inputs.
while(s = strchr(safename, ';'))
*s = ' ';
while(s = strchr(safename, '\n'))
*s = ' ';
if (key == 'c')
Sys_SaveClipboard(va("%s - %s\n", server->name, NET_StringToAdr(buf, sizeof(buf), &server->adr)));
else if (ctrldown)
Cbuf_AddText(va("say_team %s - %s\n", server->name, NET_StringToAdr(buf, sizeof(buf), &server->adr)), RESTRICT_LOCAL);
else
Cbuf_AddText(va("say %s - %s\n", server->name, NET_StringToAdr(buf, sizeof(buf), &server->adr)), RESTRICT_LOCAL);
return true;
}
//eat (nearly) all keys
else if (!(key == K_UPARROW || key == K_DOWNARROW))
return true;
}
if (key == K_HOME)
{
info->scrollpos = 0;
@ -401,7 +668,7 @@ static qboolean SL_Key (int key, menu_t *menu)
if (key == K_END)
{
info->selectedpos = info->numslots-1;
info->scrollpos = info->selectedpos - (vid.height-16-7)/8;
info->scrollpos = info->selectedpos - (vid.height-16-7)/8+8;
return true;
}
if (key == K_PGDN)
@ -436,6 +703,12 @@ static qboolean SL_Key (int key, menu_t *menu)
{
snprintf(info->mappic->picturename, 32, "levelshots/nomap");
}
if (serverpreview && server)
{
selectedserver.inuse = true;
SListOptionChanged(server);
}
}
if (info->selectedpos < 0)
@ -471,6 +744,7 @@ static void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu)
static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu)
{
extern qboolean keydown[K_MAX];
serverlist_t *info = (serverlist_t*)(menu + 1);
mpic_t *pic;
@ -504,9 +778,12 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu)
R2D_FillBlock(x, y, 8, 8);
}
if (keydown[K_MOUSE1])
if (mousecursor_x >= ths->common.posx && mousecursor_x < ths->common.posx + ths->common.width)
if (mousecursor_y >= ths->common.posy && mousecursor_y < ths->common.posy + ths->common.height)
info->sliderpressed = true;
if (info->sliderpressed)
{
extern qboolean keydown[K_MAX];
if (keydown[K_MOUSE1])
{
float my;
@ -514,7 +791,7 @@ static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu)
my = mousecursor_y;
my -= ths->common.posy;
if (R2D_SafeCachePic("scrollbars/slidebg.tga"))
if (R_GetShaderSizes(R2D_SafeCachePic("scrollbars/slidebg.tga"), NULL, NULL, false)>0)
{
my -= 32+8;
my /= ths->common.height - (64+16);
@ -543,7 +820,7 @@ static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key, unsigned
my = mousecursor_y;
my -= ths->common.posy;
if (R2D_SafeCachePic("scrollbars/slidebg.png"))
if (R_GetShaderSizes(R2D_SafeCachePic("scrollbars/slidebg.tga"), NULL, NULL, false)>0)
{
my -= 32+8;
my /= ths->common.height - (64+16);
@ -630,6 +907,7 @@ static void SL_Remove (menu_t *menu)
static qboolean SL_DoRefresh (menuoption_t *opt, menu_t *menu, int key)
{
MasterInfo_Refresh();
isrefreshing = true;
return true;
}
@ -653,7 +931,8 @@ void M_Menu_ServerList2_f(void)
m_state = m_complex;
menu = M_CreateMenu(sizeof(serverlist_t));
menu->event = SL_PreDraw;
menu->predraw = SL_PreDraw;
menu->postdraw = SL_PostDraw;
menu->key = SL_Key;
menu->remove = SL_Remove;
@ -674,7 +953,7 @@ void M_Menu_ServerList2_f(void)
cust->common.height = info->visibleslots;
cust->common.width = 8;
info->visibleslots = (info->visibleslots-7)/8;
info->visibleslots = (info->visibleslots-8)/8;
for (i = 0, y = 16; i <= info->visibleslots; y +=8, i++)
{
cust = MC_AddCustom(menu, 0, y, NULL, i);
@ -720,7 +999,7 @@ void M_Menu_ServerList2_f(void)
#endif
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*3, "Hide Proxies", SL_ReFilter, 3);
info->filtertext =
MC_AddEditCvar (menu, 128, 200, vid.height - 64+8*4, "Filter", sb_filtertext.name, true);
MC_AddEditCvar (menu, 128, 200, vid.height - 64+8*4, "Filter ", sb_filtertext.name, true);
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*5, "Only Favs ", SL_ReFilter, 5);
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*6, "Hide Empty", SL_ReFilter, 6);
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*7, "Hide Full ", SL_ReFilter, 7);
@ -762,6 +1041,7 @@ void M_Menu_ServerList2_f(void)
Master_SetSortField(sortkey, descending);
MasterInfo_Refresh();
isrefreshing = true;
}
static float quickconnecttimeout;
@ -812,6 +1092,7 @@ static void M_QuickConnect_PreDraw(menu_t *menu)
//retry
MasterInfo_Refresh();
isrefreshing = true;
quickconnecttimeout = Sys_DoubleTime() + 5;
}
@ -845,11 +1126,12 @@ void M_QuickConnect_f(void)
m_state = m_complex;
MasterInfo_Refresh();
isrefreshing = true;
quickconnecttimeout = Sys_DoubleTime() + 5;
menu = M_CreateMenu(sizeof(serverlist_t));
menu->event = M_QuickConnect_PreDraw;
menu->predraw = M_QuickConnect_PreDraw;
menu->key = M_QuickConnect_Key;
menu->remove = M_QuickConnect_Remove;

View File

@ -353,7 +353,7 @@ void M_Menu_Audio_Speakers_f (void)
menu = M_CreateMenu(sizeof(audiomenuinfo_t));
info = menu->data;
menu->key = M_Audio_Key;
menu->event = M_Audio_StartSound;
menu->predraw = M_Audio_StartSound;
for (i = 0; i < 6; i++)
info->speaker[i] = MC_AddBufferedText(menu, 0, 0, 0, va("%i", i), false, true);
@ -2570,7 +2570,7 @@ void M_Menu_Video_f (void)
menu->selecteditem = (union menuoption_s *)info->renderer;
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 152, menu->selecteditem->common.posy, NULL, false);
*/
menu->event = CheckCustomMode;
menu->predraw = CheckCustomMode;
}
#ifndef MINIMAL

View File

@ -285,9 +285,10 @@ typedef struct menu_s {
void *data; //typecast
void (*remove) (struct menu_s *);
void (*remove) (struct menu_s *);
qboolean (*key) (int key, struct menu_s *); //true if key was handled
void (*event) (struct menu_s *);
void (*predraw) (struct menu_s *);
void (*postdraw) (struct menu_s *);
menuoption_t *options;
menuoption_t *selecteditem;

View File

@ -564,7 +564,6 @@ cvar_t slist_cacheinfo = SCVAR("slist_cacheinfo", "0"); //this proves dangerous,
cvar_t slist_writeserverstxt = SCVAR("slist_writeservers", "0");
void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad);
void CL_QueryServers(void);
int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite);
void MasterInfo_RemoveAllPlayers(void);
@ -1313,7 +1312,7 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b
//add dupes too (eg: ipv4+ipv6)
for (i = 1; i < found; i++)
{
master_t *alt;
// master_t *alt;
if (adrs[i].type == NA_INVALID)
continue;
@ -2162,9 +2161,11 @@ void MasterInfo_Request(master_t *mast)
#endif
#ifdef Q2CLIENT
case MP_QUAKE2:
NET_SendPollPacket (11, va("%c%c%c%cstatus\n", 255, 255, 255, 255), mast->adr);
break;
#endif
case MP_QUAKEWORLD:
NET_SendPollPacket (11, va("%c%c%c%cstatus\n", 255, 255, 255, 255), mast->adr);
NET_SendPollPacket (11, va("%c%c%c%cstatus 23\n", 255, 255, 255, 255), mast->adr);
break;
#ifdef NQPROT
case MP_NETQUAKE:
@ -2382,7 +2383,7 @@ void Master_QueryServer(serverinfo_t *server)
NET_SendPollPacket (strlen(data), data, server->adr);
}
//send a packet to each server in sequence.
void CL_QueryServers(void)
qboolean CL_QueryServers(void)
{
static int poll;
int op;
@ -2431,7 +2432,7 @@ void CL_QueryServers(void)
if (!server)
{
poll = 0;
return;
return false;
}
if (op == 0)
@ -2484,11 +2485,12 @@ void CL_QueryServers(void)
Master_QueryServer(server);
}
poll++;
return;
return true;
}
poll = 0;
return false;
}
unsigned int Master_TotalCount(void)
@ -2510,7 +2512,7 @@ unsigned int Master_NumPolled(void)
for (info = firstserver; info; info = info->next)
{
if (info->maxplayers)
if (!info->sends)
count++;
}
return count;
@ -2574,7 +2576,7 @@ void MasterInfo_RemovePlayers(netadr_t *adr)
}
}
void MasterInfo_AddPlayer(netadr_t *serveradr, char *name, int ping, int frags, int colours, char *skin)
void MasterInfo_AddPlayer(netadr_t *serveradr, char *name, int ping, int frags, int colours, char *skin, char *team)
{
player_t *p;
p = Z_Malloc(sizeof(player_t));
@ -2582,6 +2584,7 @@ void MasterInfo_AddPlayer(netadr_t *serveradr, char *name, int ping, int frags,
p->adr = *serveradr;
p->colour = colours;
p->frags = frags;
Q_strncpyz(p->team, team, sizeof(p->team));
Q_strncpyz(p->name, name, sizeof(p->name));
Q_strncpyz(p->skin, skin, sizeof(p->skin));
mplayers = p;
@ -2790,14 +2793,12 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
}
else //qw response
{
details.players[clnum].time = atoi(token);
details.players[clnum].ping = atoi(token);
msg = token;
token = strchr(msg+1, ' ');
if (!token)
break;
details.players[clnum].ping = atoi(token);
token = strchr(token+1, '\"');
if (!token)
break;
@ -2830,9 +2831,24 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
if (!token)
break;
details.players[clnum].botc = atoi(token);
token = strchr(msg+1, '\"');
Q_strncpyz(details.players[clnum].team, "", sizeof(details.players[clnum].team));
if (token)
{
msg = strchr(token+1, '\"');
if (msg)
{
len = msg - token;
if (len >= sizeof(details.players[clnum].team))
len = sizeof(details.players[clnum].team);
Q_strncpyz(details.players[clnum].team, token+1, len);
details.players[clnum].team[len] = '\0';
}
}
}
MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin);
MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin, details.players[clnum].team);
info->players = ++details.numplayers;

View File

@ -2230,6 +2230,44 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
}
*/
if (!flags)
{
char *qtv = NULL;
if (!strncmp(s, "#0:qtv_say_game:#", 17))
{
qtv = s+16;
flags = TPM_QTV|TPM_SPECTATOR;
}
else if (!strncmp(s, "#0:qtv_say_team_game:#", 22))
{
qtv = s+21;
flags = TPM_QTV|TPM_TEAM|TPM_SPECTATOR;
}
if (flags)
{
*offset = (qtv - s);
for (;;)
{
char *sub = qtv;
if (*sub == '#')
{
strtoul(sub+1, &sub, 10);
if (*sub++ == ':')
{
qtv = strstr(sub, ": ");
if (qtv)
{
*offset = (sub - s);
qtv += 2;
continue;
}
}
}
break;
}
}
}
return flags;
}

View File

@ -124,7 +124,8 @@ Global
{2866F783-6B44-4655-A38D-D53874037454}.Debug|x64.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLDebug|Win32.ActiveCfg = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLDebug|Win32.Build.0 = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLDebug|x64.ActiveCfg = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLDebug|x64.ActiveCfg = Debug|x64
{2866F783-6B44-4655-A38D-D53874037454}.GLDebug|x64.Build.0 = Debug|x64
{2866F783-6B44-4655-A38D-D53874037454}.GLRelease|Win32.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLRelease|Win32.Build.0 = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.GLRelease|x64.ActiveCfg = Release|Win32

View File

@ -63,7 +63,10 @@ pbool PreCompile(void)
qccClearHunk();
strcpy(qcc_gamedir, "");
qcchunk = malloc(qcchunksize=128*1024*1024);
if (sizeof(void*) > 4)
qcchunk = malloc(qcchunksize=512*1024*1024);
else
qcchunk = malloc(qcchunksize=128*1024*1024);
while(!qcchunk && qcchunksize > 8*1024*1024)
{
qcchunksize /= 2;

View File

@ -345,8 +345,9 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
printf ("stripped : %s\n", PR_StringToNative(ppf, f->s_name));
else
{
int st = pr_stack[i].s;
if (pr_progstate[progs].linenums)
printf ("%12s:%i: %s\n", PR_StringToNative(ppf, f->s_file), pr_progstate[progs].linenums[pr_stack[i].s], PR_StringToNative(ppf, f->s_name));
printf ("%12s:%i: %s\n", PR_StringToNative(ppf, f->s_file), pr_progstate[progs].linenums[st], PR_StringToNative(ppf, f->s_name));
else
printf ("%12s : %s\n", PR_StringToNative(ppf, f->s_file), PR_StringToNative(ppf, f->s_name));
}

View File

@ -436,7 +436,7 @@ QCC_opcode_t pr_opcodes[] =
{7, "<CPIF>", "CP_ITOF", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_float},
{7, "<CPFI>", "CP_FTOI", -1, ASSOC_LEFT, &type_pointer, &type_float, &type_integer},
{7, ".", "INDIRECT", 1, ASSOC_LEFT, &type_entity, &type_field, &type_integer},
{7, ".", "LOADF_I", 1, ASSOC_LEFT, &type_entity, &type_field, &type_integer},
{7, "=", "STOREP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer},
{7, "=", "STOREP_IF", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_integer},
{7, "=", "STOREP_FI", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_float},
@ -567,7 +567,12 @@ QCC_opcode_t pr_opcodes[] =
{7, "<IF_F>", "IF_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
{7, "<IFNOT_F>","IFNOT_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
/*
{7, "<=>", "STOREF_F", -1, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
{7, "<=>", "STOREF_V", -1, ASSOC_RIGHT, &type_entity, &type_field, &type_vector},
{7, "<=>", "STOREF_IF", -1, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
{7, "<=>", "STOREF_FI", -1, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
*/
/* emulated ops begin here */
{7, "<>", "OP_EMULATED", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
@ -2692,7 +2697,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{ //optimise based on last statement.
if (op - pr_opcodes == OP_IFNOT_I)
{
if (opt_shortenifnots && var_a.cast && (statements[numstatements-1].op == OP_NOT_F || statements[numstatements-1].op == OP_NOT_FNC || statements[numstatements-1].op == OP_NOT_ENT))
if (opt_shortenifnots && var_a.cast && var_a.sym->refcount == 1 && (statements[numstatements-1].op == OP_NOT_F || statements[numstatements-1].op == OP_NOT_FNC || statements[numstatements-1].op == OP_NOT_ENT))
{
if (statements[numstatements-1].c.sym == var_a.sym && statements[numstatements-1].c.ofs == var_a.ofs)
{
@ -2711,7 +2716,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
}
else if (op - pr_opcodes == OP_IFNOT_F)
{
if (opt_shortenifnots && var_a.cast && statements[numstatements-1].op == OP_NOT_F)
if (opt_shortenifnots && var_a.cast && var_a.sym->refcount == 1 && statements[numstatements-1].op == OP_NOT_F)
{
if (statements[numstatements-1].c.sym == var_a.sym && statements[numstatements-1].c.ofs == var_a.ofs)
{
@ -2772,6 +2777,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
if (!QCC_OPCodeValid(op))
{
QCC_sref_t tmp;
//FIXME: add support for flags so we don't corrupt temps
switch(op - pr_opcodes)
{
@ -3030,79 +3036,81 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_c, var_a, NULL, STFL_PRESERVEA);
case OP_IF_S:
var_c = QCC_PR_GetSRef(type_string, "string_null", NULL, true, 0, false);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
tmp = QCC_MakeFloatConst(0);
tmp.cast = type_string;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, tmp, NULL);
op = &pr_opcodes[OP_IF_I];
break;
case OP_IFNOT_S:
var_c = QCC_PR_GetSRef(type_string, "string_null", NULL, true, 0, false);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
tmp = QCC_MakeFloatConst(0);
tmp.cast = type_string;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, tmp, NULL);
op = &pr_opcodes[OP_IFNOT_I];
break;
case OP_IF_F:
var_c = QCC_MakeFloatConst(0);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
tmp = QCC_MakeFloatConst(0);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, tmp, NULL);
op = &pr_opcodes[OP_IF_I];
break;
case OP_IFNOT_F:
var_c = QCC_MakeFloatConst(0);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
tmp = QCC_MakeFloatConst(0);
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, tmp, NULL);
op = &pr_opcodes[OP_IFNOT_I];
break;
case OP_ADDSTORE_F:
op = &pr_opcodes[OP_ADD_F];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_ADDSTORE_I:
op = &pr_opcodes[OP_ADD_I];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_ADDSTORE_FI:
op = &pr_opcodes[OP_ADD_FI];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
// case OP_ADDSTORE_IF:
// fixme: result is a float but needs to be an int
// op = &pr_opcodes[OP_ADD_IF];
// var_c = var_b;
// tmp = var_b;
// var_b = var_a;
// var_a = var_c;
// var_a = tmp;
// break;
case OP_SUBSTORE_F:
op = &pr_opcodes[OP_SUB_F];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_SUBSTORE_FI:
op = &pr_opcodes[OP_SUB_FI];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
// case OP_SUBSTORE_IF:
// fixme: result is a float but needs to be an int
// op = &pr_opcodes[OP_SUB_IF];
// var_c = var_b;
// tmp = var_b;
// var_b = var_a;
// var_a = var_c;
// var_a = tmp;
// break;
case OP_SUBSTORE_I:
op = &pr_opcodes[OP_SUB_I];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_BITNOT_I:
@ -3118,35 +3126,35 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
case OP_DIVSTORE_F:
op = &pr_opcodes[OP_DIV_F];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_DIVSTORE_FI:
op = &pr_opcodes[OP_DIV_FI];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
// case OP_DIVSTORE_IF:
// fixme: result is a float, but needs to be an int
// op = &pr_opcodes[OP_DIV_IF];
// var_c = var_b;
// tmp = var_b;
// var_b = var_a;
// var_a = var_c;
// var_a = tmp;
// break;
case OP_DIVSTORE_I:
op = &pr_opcodes[OP_DIV_I];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_MULSTORE_F:
op = &pr_opcodes[OP_MUL_F];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
// case OP_MULSTORE_IF:
// fixme: result is a float, but needs to be an int
@ -3157,49 +3165,49 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
// break;
case OP_MULSTORE_FI:
op = &pr_opcodes[OP_MUL_FI];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_ADDSTORE_V:
op = &pr_opcodes[OP_ADD_V];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_SUBSTORE_V:
op = &pr_opcodes[OP_SUB_V];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_MULSTORE_VF:
op = &pr_opcodes[OP_MUL_VF];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_MULSTORE_VI:
op = &pr_opcodes[OP_MUL_VI];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_BITSETSTORE_I:
op = &pr_opcodes[OP_BITOR_I];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_BITSETSTORE_F:
op = &pr_opcodes[OP_BITOR_F];
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
break;
case OP_STOREP_P:
@ -3227,9 +3235,9 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
break;
case OP_BITCLR_I:
var_c = var_b;
tmp = var_b;
var_b = var_a;
var_a = var_c;
var_a = tmp;
if (QCC_OPCodeValid(&pr_opcodes[OP_BITCLRSTORE_I]))
{
op = &pr_opcodes[OP_BITCLRSTORE_I];
@ -8014,7 +8022,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
}
else
{
QCC_statement_t *logicjump;
//go straight for the correct priority.
for (op = opcodeprioritized[priority][opnum]; op; op = opcodeprioritized[priority][++opnum])
// for (op=pr_opcodes ; op->name ; op++)
@ -8023,6 +8031,18 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
// continue;
if (!QCC_PR_CheckToken (op->name))
continue;
logicjump = NULL;
if (opt_logicops && lhsr->type == REF_GLOBAL)
{
lhsd = QCC_RefToDef(lhsr, true);
if (op == &pr_opcodes[OP_AND_F]) //guarenteed to be false if the lhs is false
logicjump = QCC_Generate_OP_IFNOT(lhsd, true);
else if (op == &pr_opcodes[OP_OR_F]) //guarenteed to be true if the lhs is true
logicjump = QCC_Generate_OP_IF(lhsd, true);
}
else
lhsd = QCC_RefToDef(lhsr, true);
rhsr = QCC_PR_RefExpression (&rhsbuf, priority-1, exprflags | EXPR_DISALLOW_ARRAYASSIGN);
@ -8032,10 +8052,23 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
}
else
{
lhsd = QCC_RefToDef(lhsr, true);
rhsd = QCC_RefToDef(rhsr, true);
op = QCC_PR_ChooseOpcode(lhsd, rhsd, &opcodeprioritized[priority][opnum]);
if (logicjump) //logic shortcut jumps to just before the if. the rhs is uninitialised if the jump was taken, but the lhs makes it deterministic.
{
logicjump->b.ofs = &statements[numstatements] - logicjump;
if (logicjump->b.ofs == 1)
numstatements--; //err, that was pointless.
else if (logicjump->b.ofs == 2 && !(logicjump[1].op >= OP_CALL0 && logicjump[1].op <= OP_CALL8) && !(logicjump[1].op >= OP_CALL1H && logicjump[1].op <= OP_CALL8H))
{
logicjump[0] = logicjump[1];
numstatements--; //don't bother if the jump is the same cost as the thing we're trying to skip (calls are expensive despite being a single opcode).
}
else
optres_logicops++;
}
lhsd = QCC_PR_Statement (op, lhsd, rhsd, NULL);
lhsr = QCC_DefToRef(retbuf, lhsd);
}

View File

@ -778,7 +778,13 @@ HWND CreateAnEditControl(HWND parent, pbool *scintillaokay)
Scintilla_RegisterClasses(scintilla);
#else
if (!scintilla && scintillaokay)
{
#ifdef _WIN64
scintilla = LoadLibrary("SciLexer_64.dll");
if (!scintilla)
#endif
scintilla = LoadLibrary("SciLexer.dll");
}
#endif
if (!richedit)
@ -1484,6 +1490,70 @@ static void scin_get_line_indent(HWND editpane, int lineidx, char *indentbuf, si
*indentbuf = 0; //failed
}
void Scin_HandleCharAdded(editor_t *editor, struct SCNotification *not, int pos)
{
if (not->ch == '(')
{
char *s = GetTooltipText(editor, pos-1, FALSE);
tooltip_editor = NULL;
if (s)
SendMessage(editor->editpane, SCI_CALLTIPSHOW, (WPARAM)pos, (LPARAM)s);
}
else if (not->ch == '}')
{ //if the first char on the line, fix up indents to match previous-1
char prevline[65536];
char newline[4096];
int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0);
int lineidx = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0);
int linestart = SendMessage(editor->editpane, SCI_POSITIONFROMLINE, lineidx, 0);
int plen;
int nlen = SendMessage(editor->editpane, SCI_LINELENGTH, lineidx, 0);
if (nlen >= sizeof(newline))
return;
nlen = SendMessage(editor->editpane, SCI_GETLINE, lineidx, (LPARAM)newline);
if (linestart > 2)
{
scin_get_line_indent(editor->editpane, lineidx, prevline, sizeof(prevline));
plen = strlen(prevline);
if (plen > nlen)
return; //already indented a bit or something
if (!strncmp(prevline, newline, plen)) //same indent
{
SendMessage(editor->editpane, SCI_CHARLEFT, 0, 0); //move to the indent
SendMessage(editor->editpane, SCI_BACKTAB, 0, 0); //do shift-tab to un-indent the current selection (one line supposedly)
SendMessage(editor->editpane, SCI_CHARRIGHT, 0, 0); //and move back to the right of the }
}
}
}
else if (not->ch == '\r' || not->ch == '\n')
{
char linebuf[65536];
int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0);
int lineidx = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0);
int linestart = SendMessage(editor->editpane, SCI_POSITIONFROMLINE, lineidx, 0);
int len = SendMessage(editor->editpane, SCI_LINELENGTH, lineidx, 0);
if (pos == linestart)
{
scin_get_line_indent(editor->editpane, lineidx, linebuf, sizeof(linebuf));
SendMessage(editor->editpane, SCI_REPLACESEL, 0, (LPARAM)linebuf);
}
}
/*
else if (0)//(!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0))
{
char buffer[65536];
char prefixbuffer[128];
char *pre = WordUnderCursor(editor, prefixbuffer, sizeof(prefixbuffer), NULL, 0, SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0));
if (pre && *pre)
if (GenAutoCompleteList(pre, buffer, sizeof(buffer)))
{
SendMessage(editor->editpane, SCI_AUTOCSETFILLUPS, 0, (LPARAM)"\t\n");
SendMessage(editor->editpane, SCI_AUTOCSHOW, strlen(pre), (LPARAM)buffer);
}
}
*/
}
static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
@ -1669,64 +1739,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
}
break;
case SCN_CHARADDED:
if (not->ch == '(')
{
char *s = GetTooltipText(editor, pos-1, FALSE);
tooltip_editor = NULL;
if (s)
SendMessage(editor->editpane, SCI_CALLTIPSHOW, (WPARAM)pos, (LPARAM)s);
}
else if (not->ch == '}')
{ //if the first char on the line, fix up indents to match previous-1
char prevline[65536];
char newline[4096];
int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0);
int lineidx = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0);
int linestart = SendMessage(editor->editpane, SCI_POSITIONFROMLINE, lineidx, 0);
int plen;
int nlen = SendMessage(editor->editpane, SCI_LINELENGTH, lineidx, 0);
if (nlen >= sizeof(newline))
break;
nlen = SendMessage(editor->editpane, SCI_GETLINE, lineidx, (LPARAM)newline);
if (linestart > 2)
{
scin_get_line_indent(editor->editpane, lineidx, prevline, sizeof(prevline));
plen = strlen(prevline);
if (plen > nlen)
break; //already indented a bit or something
if (!strncmp(prevline, newline, plen)) //same indent
{
SendMessage(editor->editpane, SCI_CHARLEFT, 0, 0); //move to the indent
SendMessage(editor->editpane, SCI_BACKTAB, 0, 0); //do shift-tab to un-indent the current selection (one line supposedly)
SendMessage(editor->editpane, SCI_CHARRIGHT, 0, 0); //and move back to the right of the }
}
}
}
else if (not->ch == '\r' || not->ch == '\n')
{
char linebuf[65536];
int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0);
int lineidx = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0);
int linestart = SendMessage(editor->editpane, SCI_POSITIONFROMLINE, lineidx, 0);
int len = SendMessage(editor->editpane, SCI_LINELENGTH, lineidx, 0);
if (pos == linestart)
{
scin_get_line_indent(editor->editpane, lineidx, linebuf, sizeof(linebuf));
SendMessage(editor->editpane, SCI_REPLACESEL, 0, (LPARAM)linebuf);
}
}
else if (0)//(!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0))
{
char buffer[65536];
char prefixbuffer[128];
char *pre = WordUnderCursor(editor, prefixbuffer, sizeof(prefixbuffer), NULL, 0, SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0));
if (pre && *pre)
if (GenAutoCompleteList(pre, buffer, sizeof(buffer)))
{
SendMessage(editor->editpane, SCI_AUTOCSETFILLUPS, 0, (LPARAM)"\t\n");
SendMessage(editor->editpane, SCI_AUTOCSHOW, strlen(pre), (LPARAM)buffer);
}
}
Scin_HandleCharAdded(editor, not, pos);
break;
case SCN_SAVEPOINTREACHED:
editor->modified = false;

View File

@ -92,11 +92,15 @@ void GoToDefinition(char *name)
//we want the body, so zoom to the first statement of the function instead
if (def->type->type == ev_function && def->constant && !def->arraysize)
{
fnc = &functions[def->symboldata->function];
if (fnc->code>=0 && fnc->s_file)
int fnum = def->symboldata[def->ofs].function;
if (fnum > 0 && fnum < numfunctions)
{
EditFile(strings+fnc->s_file, statements[fnc->code].linenum-1, false);
return;
fnc = &functions[fnum];
if (fnc->code>=0 && fnc->s_file)
{
EditFile(strings+fnc->s_file, statements[fnc->code].linenum-1, false);
return;
}
}
}
if (!def->s_file)

View File

@ -10666,54 +10666,54 @@ void PR_DumpPlatform_f(void)
#undef comfieldstring
#undef comfieldfunction
{"URI_Get_Callback", "noref void(float reqid, float responsecode, string resourcebody)", QW|NQ|CS|MENU, "Called as an eventual result of the uri_get builtin."},
{"SpectatorConnect", "noref void()", QW|NQ, "Called when a spectator joins the game."},
{"SpectatorDisconnect", "noref void()", QW|NQ, "Called when a spectator disconnects from the game."},
{"SpectatorThink", "noref void()", QW|NQ, "Called each frame for each spectator."},
{"SV_ParseClientCommand", "noref void(string cmd)", QW|NQ, "Provides QC with a way to intercept 'cmd foo' commands from the client. Very handy. Self will be set to the sending client, while the 'cmd' argument can be tokenize()d and each element retrieved via argv(argno). Unrecognised cmds MUST be passed on to the clientcommand builtin."},
{"SV_ParseClusterEvent", "noref void(string dest, string from, string cmd, string info)", QW|NQ, "Part of cluster mode. Handles cross-node events that were sent via clusterevent, on behalf of the named client."},
{"SV_ParseConnectionlessPacket", "noref float(string sender, string body)", QW|NQ, "Provides QC with a way to communicate between servers, or with client server browsers. Sender is the sender's ip. Body is the body of the message. You'll need to add your own password/etc support as required. Self is not valid."},
{"SV_PausedTic", "noref void(float pauseduration)", QW|NQ, "For each frame that the server is paused, this function will be called to give the gamecode a chance to unpause the server again. the pauseduration argument says how long the server has been paused for (the time global is frozen and will not increment while paused). Self is not valid."},
{"SV_ShouldPause", "noref float(float newstatus)", QW|NQ, "Called to give the qc a change to block pause/unpause requests. Return false for the pause request to be ignored. newstatus is 1 if the user is trying to pause the game. For the duration of the call, self will be set to the player who tried to pause, or to world if it was triggered by a server-side event."},
{"SV_RunClientCommand", "noref void()", QW|NQ, "Called each time a player movement packet was received from a client. Self is set to the player entity which should be updated, while the input_* globals specify the various properties stored within the input packet. The contents of this function should be somewaht identical to the equivelent function in CSQC, or prediction misses will occur. If you're feeling lazy, you can simply call 'runstandardplayerphysics' after modifying the inputs."},
{"SV_AddDebugPolygons", "noref void()", QW|NQ, "Called each video frame. This is the only place where ssqc is allowed to call the R_BeginPolygon/R_PolygonVertex/R_EndPolygon builtins. This is exclusively for debugging, and will break in anything but single player as it will not be called if the engine is not running both a client and a server."},
{"SV_PlayerPhysics", "noref void()", QW|NQ, "Legacy method to tweak player input that does not reliably work with prediction (prediction WILL break). Mods that care about prediction should use SV_RunClientCommand instead. If pr_no_playerphysics is set to 1, this function will never be called, which will either fix prediction or completely break player movement depending on whether the feature was even useful."},
{"EndFrame", "noref void()", QW|NQ, "Called after non-player entities have been run at the end of the physics frame. Player physics is performed out of order and can/will still occur between EndFrame and BeginFrame."},
{"SV_CheckRejectConnection","noref string(string addr, string uinfo, string features) ", QW|NQ, "Called to give the mod a chance to ignore connection requests based upon client protocol support or other properties. Use infoget to read the uinfo and features arguments."},
{"ClassChangeWeapon", "noref void()", H2, "Hexen2 support. Called when cl_playerclass changes. Self is set to the player who is changing class."},
{"URI_Get_Callback", "void(float reqid, float responsecode, string resourcebody)", QW|NQ|CS|MENU, "Called as an eventual result of the uri_get builtin."},
{"SpectatorConnect", "void()", QW|NQ, "Called when a spectator joins the game."},
{"SpectatorDisconnect", "void()", QW|NQ, "Called when a spectator disconnects from the game."},
{"SpectatorThink", "void()", QW|NQ, "Called each frame for each spectator."},
{"SV_ParseClientCommand", "void(string cmd)", QW|NQ, "Provides QC with a way to intercept 'cmd foo' commands from the client. Very handy. Self will be set to the sending client, while the 'cmd' argument can be tokenize()d and each element retrieved via argv(argno). Unrecognised cmds MUST be passed on to the clientcommand builtin."},
{"SV_ParseClusterEvent", "void(string dest, string from, string cmd, string info)", QW|NQ, "Part of cluster mode. Handles cross-node events that were sent via clusterevent, on behalf of the named client."},
{"SV_ParseConnectionlessPacket", "float(string sender, string body)", QW|NQ, "Provides QC with a way to communicate between servers, or with client server browsers. Sender is the sender's ip. Body is the body of the message. You'll need to add your own password/etc support as required. Self is not valid."},
{"SV_PausedTic", "void(float pauseduration)", QW|NQ, "For each frame that the server is paused, this function will be called to give the gamecode a chance to unpause the server again. the pauseduration argument says how long the server has been paused for (the time global is frozen and will not increment while paused). Self is not valid."},
{"SV_ShouldPause", "float(float newstatus)", QW|NQ, "Called to give the qc a change to block pause/unpause requests. Return false for the pause request to be ignored. newstatus is 1 if the user is trying to pause the game. For the duration of the call, self will be set to the player who tried to pause, or to world if it was triggered by a server-side event."},
{"SV_RunClientCommand", "void()", QW|NQ, "Called each time a player movement packet was received from a client. Self is set to the player entity which should be updated, while the input_* globals specify the various properties stored within the input packet. The contents of this function should be somewaht identical to the equivelent function in CSQC, or prediction misses will occur. If you're feeling lazy, you can simply call 'runstandardplayerphysics' after modifying the inputs."},
{"SV_AddDebugPolygons", "void()", QW|NQ, "Called each video frame. This is the only place where ssqc is allowed to call the R_BeginPolygon/R_PolygonVertex/R_EndPolygon builtins. This is exclusively for debugging, and will break in anything but single player as it will not be called if the engine is not running both a client and a server."},
{"SV_PlayerPhysics", "void()", QW|NQ, "Legacy method to tweak player input that does not reliably work with prediction (prediction WILL break). Mods that care about prediction should use SV_RunClientCommand instead. If pr_no_playerphysics is set to 1, this function will never be called, which will either fix prediction or completely break player movement depending on whether the feature was even useful."},
{"EndFrame", "void()", QW|NQ, "Called after non-player entities have been run at the end of the physics frame. Player physics is performed out of order and can/will still occur between EndFrame and BeginFrame."},
{"SV_CheckRejectConnection","string(string addr, string uinfo, string features) ", QW|NQ, "Called to give the mod a chance to ignore connection requests based upon client protocol support or other properties. Use infoget to read the uinfo and features arguments."},
{"ClassChangeWeapon", "void()", H2, "Hexen2 support. Called when cl_playerclass changes. Self is set to the player who is changing class."},
/* //mvdsv compat
{"UserInfo_Changed", "//noref void()", QW},
{"localinfoChanged", "//noref void()", QW},
{"ChatMessage", "//noref void()", QW},
{"UserCmd", "//noref void()", QW},
{"ConsoleCmd", "//noref void()", QW},
{"UserInfo_Changed", "//void()", QW},
{"localinfoChanged", "//void()", QW},
{"ChatMessage", "//void()", QW},
{"UserCmd", "//void()", QW},
{"ConsoleCmd", "//void()", QW},
*/
{"CSQC_Init", "noref void(float apilevel, string enginename, float engineversion)", CS, "Called at startup. enginename and engineversion are arbitary hints and can take any form. enginename should be consistant between revisions, but this cannot truely be relied upon."},
{"CSQC_WorldLoaded", "noref void()", CS, "Called after model+sound precaches have been executed. Gives a chance for the qc to read the entity lump from the bsp."},
{"CSQC_Shutdown", "noref void()", CS, "Specifies that the csqc is going down. Save your persistant settings here."},
{"CSQC_UpdateView", "noref void(float vwidth, float vheight, float notmenu)", CS, "Called every single video frame. The CSQC is responsible for rendering the entire screen."},
{"CSQC_UpdateViewLoading", "noref void(float vwidth, float vheight, float notmenu)", CS, "Alternative to CSQC_UpdateView, called when the engine thinks there should be a loading screen. If present, will inhibit the engine's normal loading screen, deferring to qc to draw it."},
{"CSQC_Parse_StuffCmd", "noref void(string msg)", CS, "Gives the CSQC a chance to intercept stuffcmds. Use the tokenize builtin to parse the message. Unrecognised commands would normally be localcmded, but its probably better to drop unrecognised stuffcmds completely."},
{"CSQC_Parse_CenterPrint", "noref float(string msg)", CS, "Gives the CSQC a chance to intercept centerprints. Return true if you wish the engine to otherwise ignore the centerprint."},
{"CSQC_Parse_Damage", "noref float(float save, float take, vector inflictororg)", CS, "Called as a result of player.dmg_save or player.dmg_take being set on the server.\nReturn true to completely inhibit the engine's colour shift and damage rolls, allowing you to do your own thing.\nYou can use punch_roll += (normalize(inflictororg-player.origin)*v_right)*(take+save)*autocvar_v_kickroll; as a modifier for the roll angle should the player be hit from the side, and slowly fade it away over time."},
{"CSQC_Parse_Print", "noref void(string printmsg, float printlvl)", CS, "Gives the CSQC a chance to intercept sprint/bprint builtin calls. CSQC should filter by the client's current msg setting and then pass the message on to the print command, or handle them itself."},
{"CSQC_Parse_Event", "noref void()", CS, "Called when the client receives an SVC_CGAMEPACKET. The csqc should read the data or call the error builtin if it does not recognise the message."},
{"CSQC_InputEvent", "noref float(float evtype, float scanx, float chary, float devid)", CS, "Called whenever a key is pressed, the mouse is moved, etc. evtype will be one of the IE_* constants. The other arguments vary depending on the evtype. Key presses are not guarenteed to have both scan and unichar values set at the same time."},
{"CSQC_Input_Frame", "noref void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_ConsoleCommand", "noref float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
{"CSQC_ConsoleLink", "noref float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."},
{"CSQC_Ent_Update", "noref void(float isnew)", CS},
{"CSQC_Ent_Remove", "noref void()", CS},
{"CSQC_Event_Sound", "noref float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod)", CS},
{"CSQC_Init", "void(float apilevel, string enginename, float engineversion)", CS, "Called at startup. enginename and engineversion are arbitary hints and can take any form. enginename should be consistant between revisions, but this cannot truely be relied upon."},
{"CSQC_WorldLoaded", "void()", CS, "Called after model+sound precaches have been executed. Gives a chance for the qc to read the entity lump from the bsp."},
{"CSQC_Shutdown", "void()", CS, "Specifies that the csqc is going down. Save your persistant settings here."},
{"CSQC_UpdateView", "void(float vwidth, float vheight, float notmenu)", CS, "Called every single video frame. The CSQC is responsible for rendering the entire screen."},
{"CSQC_UpdateViewLoading", "void(float vwidth, float vheight, float notmenu)", CS, "Alternative to CSQC_UpdateView, called when the engine thinks there should be a loading screen. If present, will inhibit the engine's normal loading screen, deferring to qc to draw it."},
{"CSQC_Parse_StuffCmd", "void(string msg)", CS, "Gives the CSQC a chance to intercept stuffcmds. Use the tokenize builtin to parse the message. Unrecognised commands would normally be localcmded, but its probably better to drop unrecognised stuffcmds completely."},
{"CSQC_Parse_CenterPrint", "float(string msg)", CS, "Gives the CSQC a chance to intercept centerprints. Return true if you wish the engine to otherwise ignore the centerprint."},
{"CSQC_Parse_Damage", "float(float save, float take, vector inflictororg)", CS, "Called as a result of player.dmg_save or player.dmg_take being set on the server.\nReturn true to completely inhibit the engine's colour shift and damage rolls, allowing you to do your own thing.\nYou can use punch_roll += (normalize(inflictororg-player.origin)*v_right)*(take+save)*autocvar_v_kickroll; as a modifier for the roll angle should the player be hit from the side, and slowly fade it away over time."},
{"CSQC_Parse_Print", "void(string printmsg, float printlvl)", CS, "Gives the CSQC a chance to intercept sprint/bprint builtin calls. CSQC should filter by the client's current msg setting and then pass the message on to the print command, or handle them itself."},
{"CSQC_Parse_Event", "void()", CS, "Called when the client receives an SVC_CGAMEPACKET. The csqc should read the data or call the error builtin if it does not recognise the message."},
{"CSQC_InputEvent", "float(float evtype, float scanx, float chary, float devid)", CS, "Called whenever a key is pressed, the mouse is moved, etc. evtype will be one of the IE_* constants. The other arguments vary depending on the evtype. Key presses are not guarenteed to have both scan and unichar values set at the same time."},
{"CSQC_Input_Frame", "void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_ConsoleCommand", "float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
{"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."},
{"CSQC_Ent_Update", "void(float isnew)", CS},
{"CSQC_Ent_Remove", "void()", CS},
{"CSQC_Event_Sound", "float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod)", CS},
// {"CSQC_ServerSound", "//void()", CS},
{"CSQC_LoadResource", "noref float(string resname, string restype)", CS, "Called each time some resource is being loaded. CSQC can invoke various draw calls to provide a loading screen, until WorldLoaded is called."},
{"CSQC_Parse_TempEntity", "noref float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead."},
{"CSQC_LoadResource", "float(string resname, string restype)", CS, "Called each time some resource is being loaded. CSQC can invoke various draw calls to provide a loading screen, until WorldLoaded is called."},
{"CSQC_Parse_TempEntity", "float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead."},
{"GameCommand", "noref void(string cmdtext)", CS|MENU},
{"GameCommand", "void(string cmdtext)", CS|MENU},
{"init", "noref void(float prevprogs)", QW|NQ|CS, "Part of FTE_MULTIPROGS. Called as soon as a progs is loaded, called at a time when entities are not valid. This is the only time when it is safe to call addprogs without field assignment. As it is also called as part of addprogs, this also gives you a chance to hook functions in modules that are already loaded (via externget+externget)."},
{"initents", "noref void()", QW|NQ|CS, "Part of FTE_MULTIPROGS. Called after fields have been finalized. This is the first point at which it is safe to call spawn(), and is called before any entity fields have been parsed. You can use this entrypoint to send notifications to other modules."},
{"init", "void(float prevprogs)", QW|NQ|CS, "Part of FTE_MULTIPROGS. Called as soon as a progs is loaded, called at a time when entities are not valid. This is the only time when it is safe to call addprogs without field assignment. As it is also called as part of addprogs, this also gives you a chance to hook functions in modules that are already loaded (via externget+externget)."},
{"initents", "void()", QW|NQ|CS, "Part of FTE_MULTIPROGS. Called after fields have been finalized. This is the first point at which it is safe to call spawn(), and is called before any entity fields have been parsed. You can use this entrypoint to send notifications to other modules."},
{"m_init", "void()", MENU},
{"m_shutdown", "void()", MENU},
@ -11233,6 +11233,7 @@ void PR_DumpPlatform_f(void)
, FULLENGINENAME, FTE_VER_MAJOR, FTE_VER_MINOR, Cmd_Argv(0), Cmd_Args());
VFS_PRINTF(f, "#pragma noref 1\n");
VFS_PRINTF(f, "//#pragma flag enable logicops\n");
VFS_PRINTF(f, "#pragma warning error Q101 /*too many parms*/\n");
VFS_PRINTF(f, "#pragma warning error Q105 /*too few parms*/\n");

View File

@ -1038,6 +1038,7 @@ CONNECTIONLESS COMMANDS
#define STATUS_PLAYERS 2
#define STATUS_SPECTATORS 4
#define STATUS_SPECTATORS_AS_PLAYERS 8 //for ASE - change only frags: show as "S"
#define STATUS_SHOWTEAMS 16
/*
================
@ -1056,6 +1057,7 @@ void SVC_Status (void)
int ping;
int top, bottom;
char frags[64];
char *skin, *team, *botpre;
int slots=0;
@ -1079,32 +1081,42 @@ void SVC_Status (void)
ping = SV_CalcPing (cl, false);
name = cl->name;
skin = Info_ValueForKey (cl->userinfo, "skin");
team = Info_ValueForKey (cl->userinfo, "team");
if (!cl->state || cl->protocol == SCP_BAD) //show bots differently. Just to be courteous.
Con_Printf ("%i %i %i %i \"BOT:%s\" \"%s\" %i %i\n", cl->userid,
cl->old_frags, (int)(realtime - cl->connection_started)/60,
ping, cl->name, Info_ValueForKey (cl->userinfo, "skin"), top, bottom);
botpre = "BOT:";
else
{
if (cl->spectator)
{ //silly mvdsv stuff
if (displayflags & STATUS_SPECTATORS_AS_PLAYERS)
{
frags[0] = 'S';
frags[1] = '\0';
}
else
{
ping = -ping;
sprintf(frags, "%i", -9999);
name = va("\\s\\%s", name);
}
botpre = "";
if (cl->spectator)
{ //silly mvdsv stuff
if (displayflags & STATUS_SPECTATORS_AS_PLAYERS)
{
frags[0] = 'S';
frags[1] = '\0';
}
else
sprintf(frags, "%i", cl->old_frags);
{
ping = -ping;
sprintf(frags, "%i", -9999);
name = va("\\s\\%s", name);
}
}
else
sprintf(frags, "%i", cl->old_frags);
Con_Printf ("%i %s %i %i \"%s\" \"%s\" %i %i\n", cl->userid,
if (displayflags & STATUS_SHOWTEAMS)
{
Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i \"%s\"\n", cl->userid,
frags, (int)(realtime - cl->connection_started)/60,
ping, name, Info_ValueForKey (cl->userinfo, "skin"), top, bottom);
ping, botpre, name, skin, top, bottom, team);
}
else
{
Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i\n", cl->userid,
frags, (int)(realtime - cl->connection_started)/60,
ping, botpre, name, skin, top, bottom);
}
}
else