|
From: <cro...@li...> - 2005-03-23 21:36:17
|
Module Name: crossfire
Committed By: cavesomething
Date: Wed Mar 23 21:35:13 UTC 2005
Modified Files:
crossfire/common: region.c
crossfire/doc/Developers: regions
crossfire/include: libproto.h sproto.h
crossfire/lib: regions
crossfire/server: c_misc.c
Log Message:
allow who command to take regions as arguments, if a region is given as an argument then only the players in the region are shown. Partial region names can be used also. Calling who on its own shows everyone that was shown before.
Start of context diffs
Index: crossfire/common/region.c
diff -c crossfire/common/region.c:1.1 crossfire/common/region.c:1.2
*** crossfire/common/region.c:1.1 Tue Mar 15 13:06:19 2005
--- crossfire/common/region.c Wed Mar 23 13:34:30 2005
***************
*** 1,6 ****
/*
* static char *rcsid_map_c =
! * "$Id: region.c,v 1.1 2005/03/15 21:06:19 ryo_saeba Exp $";
*/
/*
--- 1,6 ----
/*
* static char *rcsid_map_c =
! * "$Id: region.c,v 1.2 2005/03/23 21:34:30 cavesomething Exp $";
*/
/*
***************
*** 56,61 ****
--- 56,67 ----
LOG(llevInfo,"Got no region or fallback for region %s.\n", region_name);
return NULL;
}
+
+ /* This might need optimising at some point. */
+ region *get_region_by_map(mapstruct *m) {
+ return get_region_by_name(get_name_of_region_for_map(m));
+ }
+
/*
* Since we won't assume all maps have a region set properly, we need an
* explicit check that it is, this is much nicer here than scattered throughout
***************
*** 72,77 ****
--- 78,159 ----
return "unknown";
}
+ /*
+ * Tries to find a region that 'name' corresponds to.
+ * It looks, in order, for:
+ * an exact match to region name (case insensitive)
+ * an exact match to longname (case insensitive)
+ * a substring that matches to the longname (eg Kingdom)
+ * a substring that matches to the region name (eg nav)
+ * if it can find none of these it returns the first parentless region
+ * (there should be only one of these - the top level one)
+ * If we got a NULL, then just return the top level region
+ *
+ */
+ region *get_region_from_string(char *name) {
+ region *reg;
+ char *substr;
+ sint16 i;
+
+ if (name==NULL) {
+ for (reg=first_region;reg->parent!=NULL;reg=reg->parent);
+ return reg;
+ }
+ char *p = strchr(name, '\n');
+ if (p) *p = '\0';
+ for (reg=first_region;reg!=NULL;reg=reg->next)
+ if (!strcasecmp(reg->name, name)) return reg;
+
+ for (reg=first_region;reg!=NULL;reg=reg->next)
+ if (reg->longname != NULL) {
+ if (!strcasecmp(reg->longname, name)) return reg;
+ }
+
+ substr=NULL;
+ for (reg=first_region;reg!=NULL;reg=reg->next)
+ if (reg->longname != NULL) {
+ substr=strstr(reg->longname, name);
+ if (substr != NULL) return reg;
+ }
+ for (reg=first_region;reg!=NULL;reg=reg->next)
+ if (reg->longname != NULL) {
+ /*
+ * This is not a bug, we want the region that is most identifiably a discrete
+ * area in the game, eg if we have 'scor', we want to return 'scorn' and not
+ * 'scornarena', regardless of their order on the list so we only look at those
+ * regions with a longname set.
+ */
+ substr=strstr(reg->name, name);
+ if (substr != NULL) return reg;
+ }
+ for (reg=first_region;reg!=NULL;reg=reg->next) {
+ substr=strstr(reg->name, name);
+ if (substr != NULL) return reg;
+ }
+ /* if we are still here, we are going to have to give up, and give the top level region */
+ for (reg=first_region;reg->parent!=NULL;reg=reg->parent);
+ return reg;
+ }
+
+ /*
+ * returns 1 if the player is in the region reg, or a child region thereof
+ * otherwise returns 0
+ * if passed a NULL region returns -1
+ */
+
+ int region_is_child_of_region(region *child, region *r) {
+
+ if (r==NULL)
+ return -1;
+ if (child == NULL)
+ return 0;
+ if (!strcmp(child->name, r->name))
+ return 1;
+ else if(child->parent!=NULL)
+ return region_is_child_of_region(child->parent,r);
+ else return 0;
+ }
+
/*
* the longname of a region is not a required field, any given region
* may want to not set it and use the parent's one instead. so, we:
Index: crossfire/doc/Developers/regions
diff -c crossfire/doc/Developers/regions:1.1 crossfire/doc/Developers/regions:1.2
*** crossfire/doc/Developers/regions:1.1 Tue Mar 15 13:42:25 2005
--- crossfire/doc/Developers/regions Wed Mar 23 13:34:37 2005
***************
*** 1,7 ****
Included herein is a description of the Region system, as implemented in March 2005.
- Revision 0.1.1 - BT Lally.
-
If by the time you read this, this date is old, then this file may not have been kept
up to date, either that or no relevant changes have occurred, the Changelog should help
you determine which is the case.
--- 1,5 ----
***************
*** 153,158 ****
--- 151,166 ----
given a name returns the region with that name, or the fallback if there isn't one.
Used by the map loader and stuff using get_name_of_region_for_map at the moment.
+ extern int region_is_child_of_region(region *child, region *r);
+ 1 if the child is a subregion of r
+ 0 otherwise
+
+ extern region *get_region_from_string(char *name);
+ tries to guess which region 'name' corresponds to
+
+ extern region *get_region_by_map(mapstruct *m);
+ takes a map returns the region it is in.
+
extern char *get_name_of_region_for_map(mapstruct *m);
takes a map and returns the name of the region it is in.
***************
*** 178,187 ****
There is a command whereami that prints the regions name and description.
*****Known/suspected bugs*****
! Random maps probably don't get their regions set properly (haven't tried to verify this, not least
! because I am not even sure what 'properly' should be).
The region parser is not particularly robust, it dies if the 'endmsg' line is missing,
or if 'nomore' is missing, or if the 'end' line is missing. These stop the server from
--- 186,197 ----
There is a command whereami that prints the regions name and description.
+ who can be given regions as arguments, and only show the players in that region.
+
*****Known/suspected bugs*****
! Random maps probably don't get their regions set properly (though I am not quite sure what
! 'properly' should be here).
The region parser is not particularly robust, it dies if the 'endmsg' line is missing,
or if 'nomore' is missing, or if the 'end' line is missing. These stop the server from
***************
*** 193,201 ****
whereiseverybody command, showing region and the number of players there.
- modify who command so that PK servers can elect to show only region to other players
- (making it more challenging to hunt other players).
-
medium term:
Have the regions file 'compiled' in the same way the archetypes are.
--- 203,208 ----
Index: crossfire/include/libproto.h
diff -c crossfire/include/libproto.h:1.58 crossfire/include/libproto.h:1.59
*** crossfire/include/libproto.h:1.58 Tue Mar 15 13:06:20 2005
--- crossfire/include/libproto.h Wed Mar 23 13:34:39 2005
***************
*** 345,352 ****
--- 345,355 ----
extern void free_all_recipes(void);
/* region.c */
extern char *get_region_longname(region *r);
+ extern int region_is_child_of_region(region *child, region *r);
+ extern region *get_region_from_string(char *name);
extern char *get_region_msg(region *r);
extern region *get_region_by_name(char *region_name);
+ extern region *get_region_by_map(mapstruct *m);
extern char *get_name_of_region_for_map(mapstruct *m);
extern void parse_regions();
extern void init_regions();
Index: crossfire/include/sproto.h
diff -c crossfire/include/sproto.h:1.117 crossfire/include/sproto.h:1.118
*** crossfire/include/sproto.h:1.117 Tue Mar 22 15:22:41 2005
--- crossfire/include/sproto.h Wed Mar 23 13:34:56 2005
***************
*** 151,156 ****
--- 151,157 ----
void current_map_info(object *op);
void current_region_info(object *op);
int command_who(object *op, char *params);
+ void display_who_entry(object *op, player *pl, char *format);
void get_who_escape_code_value(char *return_val, const char letter, player *pl);
int command_malloc(object *op, char *params);
int command_mapinfo(object *op, char *params);
Index: crossfire/lib/regions
diff -c crossfire/lib/regions:1.3 crossfire/lib/regions:1.4
*** crossfire/lib/regions:1.3 Mon Mar 21 11:29:24 2005
--- crossfire/lib/regions Wed Mar 23 13:35:04 2005
***************
*** 11,17 ****
endmsg
end
region world
! longname Somewhere in the world.
msg
If you are seeing this, someone goofed, you should never see this message.
endmsg
--- 11,17 ----
endmsg
end
region world
! longname The World.
msg
If you are seeing this, someone goofed, you should never see this message.
endmsg
***************
*** 158,163 ****
--- 158,170 ----
Describe Port Joesph
endmsg
end
+ region pupland
+ parent world
+ longname Pupland
+ msg
+ Describe pupland
+ endmsg
+ end
region ancientpupland
parent pupland
longname Pupland of Times Long Past
***************
*** 171,183 ****
Describe Nurnberg
endmsg
end
- region pupland
- parent world
- longname Pupland
- msg
- Describe pupland
- endmsg
- end
region lonetown
parent pupland
msg
--- 178,183 ----
Index: crossfire/server/c_misc.c
diff -c crossfire/server/c_misc.c:1.52 crossfire/server/c_misc.c:1.53
*** crossfire/server/c_misc.c:1.52 Tue Mar 22 15:22:42 2005
--- crossfire/server/c_misc.c Wed Mar 23 13:35:07 2005
***************
*** 1,6 ****
/*
* static char *rcsid_c_misc_c =
! * "$Id: c_misc.c,v 1.52 2005/03/22 23:22:42 ryo_saeba Exp $";
*/
/*
--- 1,6 ----
/*
* static char *rcsid_c_misc_c =
! * "$Id: c_misc.c,v 1.53 2005/03/23 21:35:07 cavesomething Exp $";
*/
/*
***************
*** 268,274 ****
int command_who (object *op, char *params) {
player *pl;
uint16 i;
! char tmpbuf[HUGE_BUF];
int num_players = 0;
int num_wiz = 0;
int num_afk = 0;
--- 268,275 ----
int command_who (object *op, char *params) {
player *pl;
uint16 i;
! region *reg;
! char* format;
int num_players = 0;
int num_wiz = 0;
int num_afk = 0;
***************
*** 285,356 ****
strcpy(settings.who_format, "%N_the_%t%h%d%n[%m]");
if (!strcmp(settings.who_wiz_format,""))
strcpy(settings.who_wiz_format, "%N_the_%t%h%d%nLevel %l [%m](@%i)(%c)");
! for(pl=first_player;pl!=NULL;pl=pl->next) {
! if(pl->ob->map == NULL)
continue;
if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ)) continue;
if (pl->state==ST_PLAYING || pl->state==ST_GET_PARTY_PASSWORD) {
num_players++;
chars = (chars_names *) realloc(chars, num_players*sizeof(chars_names));
! if (chars == NULL)
! {
new_draw_info(NDI_UNIQUE, 0, op, "who failed - out of memory!");
return 0;
}
! sprintf(chars[num_players-1].namebuf, "");
chars[num_players-1].login_order = num_players;
/*Check for WIZ's & AFK's*/
if (QUERY_FLAG(pl->ob,FLAG_WIZ))
num_wiz++;
if (QUERY_FLAG(pl->ob,FLAG_AFK))
num_afk++;
- if (op == NULL || QUERY_FLAG(op, FLAG_WIZ)) {
- for (i=0;i<=strlen(settings.who_wiz_format);i++) {
- if (settings.who_wiz_format[i]=='%') {
- i++;
- get_who_escape_code_value(tmpbuf,settings.who_wiz_format[i],pl);
- strcat(chars[num_players-1].namebuf, tmpbuf);
- }
- else if (settings.who_wiz_format[i]=='_')
- strcat(chars[num_players-1].namebuf," "); /* allow '_' to be used in place of spaces */
- else {
- sprintf(tmpbuf,"%c",settings.who_wiz_format[i]);
- strcat(chars[num_players-1].namebuf,tmpbuf);
- }
- }
- }
- else {
- for (i=0;i<=strlen(settings.who_format);i++) {
- if (settings.who_format[i]=='%') {
- i++;
- get_who_escape_code_value(tmpbuf,settings.who_format[i],pl);
- strcat(chars[num_players-1].namebuf, tmpbuf);
- }
- else if (settings.who_format[i]=='_')
- strcat(chars[num_players-1].namebuf," "); /* allow '_' to be used in place of spaces */
- else {
- sprintf(tmpbuf,"%c",settings.who_format[i]);
- strcat(chars[num_players-1].namebuf,tmpbuf);
- }
- }
- }
}
}
! if (first_player != (player *) NULL)
! {
! sprintf(players_str, "Total Players (%d) -- WIZ(%d) AFK(%d)", num_players, num_wiz, num_afk);
! new_draw_info(NDI_UNIQUE, 0, op, players_str);
}
qsort (chars, num_players, sizeof(chars_names), name_cmp);
for (i=0;i<num_players;i++)
! new_draw_info(NDI_UNIQUE, 0, op, chars[i].namebuf);
! free (chars);
return 1;
}
/* Returns the value of the escape code used in the who format specifier
* the values are:
* N Name of character
--- 286,366 ----
strcpy(settings.who_format, "%N_the_%t%h%d%n[%m]");
if (!strcmp(settings.who_wiz_format,""))
strcpy(settings.who_wiz_format, "%N_the_%t%h%d%nLevel %l [%m](@%i)(%c)");
+ if (op == NULL || QUERY_FLAG(op, FLAG_WIZ))
+ format=settings.who_wiz_format;
+ else
+ format=settings.who_format;
! reg=get_region_from_string(params);
!
! for (pl=first_player;pl!=NULL;pl=pl->next) {
! if (pl->ob->map == NULL)
continue;
if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ)) continue;
+
+ if(!region_is_child_of_region(get_region_by_map(pl->ob->map),reg)) continue;
if (pl->state==ST_PLAYING || pl->state==ST_GET_PARTY_PASSWORD) {
num_players++;
chars = (chars_names *) realloc(chars, num_players*sizeof(chars_names));
! if (chars == NULL) {
new_draw_info(NDI_UNIQUE, 0, op, "who failed - out of memory!");
return 0;
}
! sprintf(chars[num_players-1].namebuf, "%s", pl->ob->name);
chars[num_players-1].login_order = num_players;
/*Check for WIZ's & AFK's*/
if (QUERY_FLAG(pl->ob,FLAG_WIZ))
num_wiz++;
if (QUERY_FLAG(pl->ob,FLAG_AFK))
num_afk++;
}
}
! if (first_player != (player *) NULL) {
! if (reg == NULL)
! new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players (%d) -- WIZ(%d) AFK(%d)",
! num_players, num_wiz, num_afk);
! else if (reg->longname == NULL)
! new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players in %s (%d) -- WIZ(%d) AFK(%d)",
! reg->name, num_players, num_wiz, num_afk);
! else
! new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players in %s (%d) -- WIZ(%d) AFK(%d)",
! reg->longname, num_players, num_wiz, num_afk);
}
qsort (chars, num_players, sizeof(chars_names), name_cmp);
for (i=0;i<num_players;i++)
! display_who_entry(op, find_player(chars[i].namebuf), format);
! free(chars);
return 1;
}
+ /* Display a line of 'who' to op, about pl, using the formatting specified by format */
+ void display_who_entry(object *op, player *pl, char *format) {
+ char tmpbuf[MAX_BUF];
+ char outbuf[MAX_BUF];
+ sint16 i;
+ outbuf[0]='\0'; /* we strcat to this, so reset it here. */
+ if (pl==NULL) {
+ LOG(llevError,"display_who_entry(): I was passed a null player");
+ return;
+ }
+ for (i=0;i<=strlen(format);i++) {
+ if (format[i]=='%') {
+ i++;
+ get_who_escape_code_value(tmpbuf,format[i],pl);
+ strcat(outbuf, tmpbuf);
+ }
+ else if (format[i]=='_')
+ strcat(outbuf," "); /* allow '_' to be used in place of spaces */
+ else {
+ sprintf(tmpbuf,"%c",format[i]);
+ strcat(outbuf,tmpbuf);
+ }
+ }
+ new_draw_info(NDI_UNIQUE, 0, op, outbuf);
+ }
+
/* Returns the value of the escape code used in the who format specifier
* the values are:
* N Name of character
|