//cvar_t net_netaddress_ipv6 = {0, "net_address_ipv6", "[0:0:0:0:0:0:0:0]"};
// HostCache interface
-hostcache_mask_t hostcache_currentmask;
+hostcache_mask_t hostcache_andmasks[HOSTCACHE_ANDMASKCOUNT];
+hostcache_mask_t hostcache_ormasks[HOSTCACHE_ORMASKCOUNT];
+
hostcache_infofield_t hostcache_sortbyfield;
qboolean hostcache_sortdescending;
static qboolean _hc_testint( int A, hostcache_maskop_t op, int B )
{
- int diff;
-
- diff = A - B;
- switch( op ) {
- case HCMO_GREATER:
- if( !diff )
- return false;
- case HCMO_GREATEREQUAL:
- if( diff < 0 )
- return false;
- break;
- case HCMO_EQUAL:
- if( diff )
- return false;
- break;
- case HCMO_LESS:
- if( !diff )
- return false;
- case HCMO_LESSEQUAL:
- if( diff > 0 )
- return false;
- break;
- }
- return true;
+ if( op == HCMO_LESS )
+ return A < B;
+ else if( op == HCMO_LESSEQUAL )
+ return A <= B;
+ else if( op == HCMO_EQUAL )
+ return A == B;
+ else if( op == HCMO_GREATER )
+ return A > B;
+ else if( op == HCMO_NOTEQUAL )
+ return A != B;
+ else // HCMO_GREATEREQUAL
+ return A >= B;
}
-static qboolean _HostCache_TestMask( hostcache_info_t *info )
+static qboolean _hc_teststr( const char *A, hostcache_maskop_t op, const char *B )
{
- if( !_hc_testint( info->ping, hostcache_currentmask.pingtest, hostcache_currentmask.info.ping ) )
+ if( op == HCMO_CONTAINS ) // A info B mask
+ return *A && !!strstr( B, A ); // we want a real bool
+ else if( op == HCMO_NOTCONTAIN )
+ return !*A || !strstr( B, A );
+ else if( op == HCMO_LESS )
+ return strcmp( A, B ) < 0;
+ else if( op == HCMO_LESSEQUAL )
+ return strcmp( A, B ) <= 0;
+ else if( op == HCMO_EQUAL )
+ return strcmp( A, B ) == 0;
+ else if( op == HCMO_GREATER )
+ return strcmp( A, B ) > 0;
+ else if( op == HCMO_NOTEQUAL )
+ return strcmp( A, B ) != 0;
+ else // HCMO_GREATEREQUAL
+ return strcmp( A, B ) >= 0;
+}
+
+static qboolean _HostCache_TestMask( hostcache_mask_t *mask, hostcache_info_t *info )
+{
+ if( !_hc_testint( info->ping, mask->tests[HCIF_PING], mask->info.ping ) )
return false;
- if( !_hc_testint( info->maxplayers, hostcache_currentmask.maxplayerstest, hostcache_currentmask.info.maxplayers ) )
+ if( !_hc_testint( info->maxplayers, mask->tests[HCIF_MAXPLAYERS], mask->info.maxplayers ) )
return false;
- if( !_hc_testint( info->numplayers, hostcache_currentmask.numplayerstest, hostcache_currentmask.info.numplayers ) )
+ if( !_hc_testint( info->numplayers, mask->tests[HCIF_NUMPLAYERS], mask->info.numplayers ) )
return false;
- if( !_hc_testint( info->protocol, hostcache_currentmask.protocoltest, hostcache_currentmask.info.protocol ))
+ if( !_hc_testint( info->protocol, mask->tests[HCIF_PROTOCOL], mask->info.protocol ))
return false;
- if( *hostcache_currentmask.info.cname
- && !strstr( info->cname, hostcache_currentmask.info.cname ) )
+ if( *mask->info.cname
+ && !_hc_teststr( info->cname, mask->tests[HCIF_CNAME], mask->info.cname ) )
return false;
- if( *hostcache_currentmask.info.game
- && !strstr( info->game, hostcache_currentmask.info.game ) )
+ if( *mask->info.game
+ && !_hc_teststr( info->game, mask->tests[HCIF_GAME], mask->info.game ) )
return false;
- if( *hostcache_currentmask.info.mod
- && !strstr( info->mod, hostcache_currentmask.info.mod ) )
+ if( *mask->info.mod
+ && !_hc_teststr( info->mod, mask->tests[HCIF_MOD], mask->info.mod ) )
return false;
- if( *hostcache_currentmask.info.map
- && !strstr( info->map, hostcache_currentmask.info.map ) )
+ if( *mask->info.map
+ && !_hc_teststr( info->map, mask->tests[HCIF_MAP], mask->info.map ) )
return false;
- if( *hostcache_currentmask.info.name
- && !strstr( info->name, hostcache_currentmask.info.name ) )
+ if( *mask->info.name
+ && !_hc_teststr( info->name, mask->tests[HCIF_NAME], mask->info.name ) )
return false;
return true;
}
int start, end, mid;
if( hostcache_viewcount == HOSTCACHE_VIEWCACHESIZE )
return;
- // now check whether it passes through mask
- if( !_HostCache_TestMask( &entry->info ) )
+ // now check whether it passes through the masks mask
+ for( start = 0 ; hostcache_andmasks[start].active && start < HOSTCACHE_ANDMASKCOUNT ; start++ )
+ if( !_HostCache_TestMask( &hostcache_andmasks[start], &entry->info ) )
+ return;
+
+ for( start = 0 ; hostcache_ormasks[start].active && start < HOSTCACHE_ORMASKCOUNT ; start++ )
+ if( _HostCache_TestMask( &hostcache_ormasks[start], &entry->info ) )
+ break;
+ if( start == HOSTCACHE_ORMASKCOUNT || (start > 0 && !hostcache_ormasks[start].active) )
return;
if( !hostcache_viewcount ) {
_HostCache_Insert( &hostcache_cache[i] );
}
-void HostCache_ResetMask(void)
+void HostCache_ResetMasks(void)
{
- memset( &hostcache_currentmask, 0, sizeof( hostcache_mask_t ) );
+ memset( &hostcache_andmasks, 0, sizeof( hostcache_andmasks ) );
+ memset( &hostcache_andmasks, 0, sizeof( hostcache_andmasks ) );
}
void Net_Slist_f(void)
{
- HostCache_ResetMask();
+ HostCache_ResetMasks();
hostcache_sortbyfield = HCIF_PING;
hostcache_sortdescending = false;
if (m_state != m_slist) {
#define HOSTCACHE_TOTALSIZE 2048
#define HOSTCACHE_VIEWCACHESIZE 128
+#define HOSTCACHE_ANDMASKCOUNT 5
+#define HOSTCACHE_ORMASKCOUNT 5
typedef enum
{
- HCMO_GREATEREQUAL,
- HCMO_GREATER,
- HCMO_EQUAL,
+ // HCMO_CONTAINS is the default for strings
+ // HCMO_GREATEREQUAL is the default for numbers (also used when OP == CONTAINS or NOTCONTAINS
+ HCMO_CONTAINS,
+ HCMO_NOTCONTAIN,
+
HCMO_LESSEQUAL,
HCMO_LESS,
+ HCMO_EQUAL,
+ HCMO_GREATER,
+ HCMO_GREATEREQUAL,
+ HCMO_NOTEQUAL
} hostcache_maskop_t;
// struct with all fields that you can search for or sort by
typedef struct
{
- hostcache_maskop_t pingtest;
- hostcache_maskop_t maxplayerstest;
- hostcache_maskop_t numplayerstest;
- hostcache_maskop_t protocoltest;
+ qboolean active;
+ hostcache_maskop_t tests[HCIF_COUNT];
hostcache_info_t info;
} hostcache_mask_t;
-extern hostcache_mask_t hostcache_currentmask;
+extern hostcache_mask_t hostcache_andmasks[HOSTCACHE_ANDMASKCOUNT];
+extern hostcache_mask_t hostcache_ormasks[HOSTCACHE_ORMASKCOUNT];
+
extern hostcache_infofield_t hostcache_sortbyfield;
extern qboolean hostcache_sortdescending;
// Hostcache interface
// manually refresh the view set, do this after having changed the mask or any other flag
void HostCache_RebuildViewSet(void);
-void HostCache_ResetMask(void);
+void HostCache_ResetMasks(void);
void HostCache_QueryList(void);
#endif
float stringtokeynum(string key)
- resethostcachemask()
- sethostcachemaskstring(float fld, string str)
- sethostcachemasknumber(float fld, float num, float op)
+ resethostcachemasks()
+ sethostcachemaskstring(float mask, float fld, string str)
+ sethostcachemasknumber(float mask, float fld, float num, float op)
resorthostcache()
sethostcachesort(float field, float descending)
refreshhostcache()
/*
========================
-VM_M_resethostcachemask
+VM_M_resethostcachemasks
-resethostcachemask()
+resethostcachemasks()
========================
*/
-void VM_M_resethostcachemask( void )
+void VM_M_resethostcachemasks( void )
{
- HostCache_ResetMask();
+ HostCache_ResetMasks();
}
========================
VM_M_sethostcachemaskstring
-sethostcachemaskstring(float field, string str)
+sethostcachemaskstring(float mask, float fld, string str, float op)
+0-511 and
+512 - 1024 or
========================
*/
void VM_M_sethostcachemaskstring( void )
{
char *str;
+ int masknr;
+ hostcache_mask_t *mask;
+ int field;
- VM_SAFEPARMCOUNT( 2, VM_M_sethostcachemask );
+ VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemaskstring );
str = PRVM_G_STRING( OFS_PARM1 );
if( !str )
- PRVM_ERROR( "VM_M_sethostcachemask: null string passed!" );
+ PRVM_ERROR( "VM_M_sethostcachemaskstring: null string passed!" );
+
+ masknr = PRVM_G_FLOAT( OFS_PARM0 );
+ if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
+ mask = &hostcache_andmasks[masknr];
+ else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
+ mask = &hostcache_ormasks[masknr - 512 ];
+ else {
+ Con_Printf( "VM_M_sethostcachemaskstring: invalid mask number %i\n", masknr );
+ return;
+ }
- switch( (int) PRVM_G_FLOAT( OFS_PARM0 ) ) {
+ field = (int) PRVM_G_FLOAT( OFS_PARM1 );
+
+ switch( field ) {
case HCIF_CNAME:
- strncpy( hostcache_currentmask.info.cname, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.cname) );
+ strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
break;
case HCIF_NAME:
- strncpy( hostcache_currentmask.info.name, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.name) );
+ strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
break;
case HCIF_MAP:
- strncpy( hostcache_currentmask.info.map, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.map) );
+ strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
break;
case HCIF_MOD:
- strncpy( hostcache_currentmask.info.mod, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.mod) );
+ strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
break;
case HCIF_GAME:
- strncpy( hostcache_currentmask.info.game, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.game) );
+ strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
break;
default:
- Con_Printf( "VM_M_sethostcachemask: Bad field number %i passed!\n", PRVM_G_INT( OFS_PARM0 ) );
+ Con_Printf( "VM_M_sethostcachemaskstring: Bad field number %i passed!\n", field );
+ return;
}
+
+ mask->active = true;
+ mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
}
/*
========================
VM_M_sethostcachemasknumber
-sethostcachemasknumber(float field, float num, float op)
+sethostcachemasknumber(float mask, float fld, float num, float op)
+
+0-511 and
+512 - 1024 or
========================
*/
void VM_M_sethostcachemasknumber( void )
{
int number;
- hostcache_maskop_t operand;
- VM_SAFEPARMCOUNT( 3, VM_M_sethostcachemasknumber );
+ hostcache_mask_t *mask;
+ int masknr;
+ int field;
+ VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemasknumber );
+
+ masknr = PRVM_G_FLOAT( OFS_PARM0 );
+ if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
+ mask = &hostcache_andmasks[masknr];
+ else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
+ mask = &hostcache_ormasks[masknr - 512 ];
+ else {
+ Con_Printf( "VM_M_sethostcachemasknumber: invalid mask number %i\n", masknr );
+ return;
+ }
- number = PRVM_G_FLOAT( OFS_PARM1 );
- operand = (int) PRVM_G_FLOAT( OFS_PARM2 );
+ number = PRVM_G_FLOAT( OFS_PARM2 );
+ field = (int) PRVM_G_FLOAT( OFS_PARM1 );
- switch( (int) PRVM_G_FLOAT( OFS_PARM0 ) ) {
+ switch( field ) {
case HCIF_MAXPLAYERS:
- hostcache_currentmask.info.maxplayers = number;
- hostcache_currentmask.maxplayerstest = operand;
+ mask->info.maxplayers = number;
break;
case HCIF_NUMPLAYERS:
- hostcache_currentmask.info.numplayers = number;
- hostcache_currentmask.numplayerstest = operand;
+ mask->info.numplayers = number;
break;
case HCIF_PING:
- hostcache_currentmask.info.ping = number;
- hostcache_currentmask.pingtest = operand;
+ mask->info.ping = number;
break;
case HCIF_PROTOCOL:
- hostcache_currentmask.info.protocol = number;
- hostcache_currentmask.protocoltest = operand;
+ mask->info.protocol = number;
break;
default:
- Con_Printf( "VM_M_sethostcachemask: Bad field number %i passed!\n", PRVM_G_INT( OFS_PARM0 ) );
+ Con_Printf( "VM_M_sethostcachemasknumber: Bad field number %i passed!\n", field );
+ return;
}
+
+ mask->active = true;
+ mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
}
VM_M_gethostcachestring,
VM_M_parseentitydata,
VM_M_stringtokeynum,
- VM_M_resethostcachemask,
+ VM_M_resethostcachemasks,
VM_M_sethostcachemaskstring,
VM_M_sethostcachemasknumber,
VM_M_resorthostcache,