--- deliantra/server/socket/request.C 2007/05/28 21:22:26 1.100
+++ deliantra/server/socket/request.C 2007/07/29 18:34:46 1.117
@@ -1,23 +1,22 @@
/*
- * This file is part of Crossfire TRT, the Multiplayer Online Role Playing Game.
+ * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
*
* Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
* Copyright (©) 2001,2007 Mark Wedel
* Copyright (©) 1992,2007 Frank Tore Johansen
*
- * Crossfire TRT is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * Crossfire TRT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*
* The authors can be reached via e-mail to
*/
@@ -147,8 +146,7 @@
check_map_change (player *pl)
{
client &socket = *pl->ns;
- object *ob = pl->ob;
- char buf[MAX_BUF]; /* eauugggh */
+ object *ob = pl->observe;
if (socket.current_map != ob->map || socket.force_newmap)
{
@@ -166,13 +164,12 @@
if (ob->map->tile_path[2]) flags |= 4;
if (ob->map->tile_path[3]) flags |= 8;
- snprintf (buf, MAX_BUF, "mapinfo - spatial %d %d %d %d %d %s",
- flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, ob->map->width, ob->map->height, &ob->map->path);
+ socket.send_packet_printf ("mapinfo - spatial %d %d %d %d %d %s",
+ flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y,
+ ob->map->width, ob->map->height, &ob->map->path);
}
else
- snprintf (buf, MAX_BUF, "mapinfo current");
-
- socket.send_packet (buf);
+ socket.send_packet ("mapinfo current");
}
}
else if (socket.current_x != ob->x || socket.current_y != ob->y)
@@ -195,8 +192,8 @@
region *reg = ob->region ();
if (socket.current_region != reg)
{
+ INVOKE_PLAYER (REGION_CHANGE, pl, ARG_REGION (reg), ARG_REGION (socket.current_region));
socket.current_region = reg;
- socket.send_packet_printf ("drawinfo 0 You are now %s.\n(use whereami for more details)", ®->longname);
}
}
@@ -206,29 +203,17 @@
* that information.
*/
void
-RequestInfo (char *buf, int len, client * ns)
+RequestInfo (char *buf, int len, client *ns)
{
- char *params = NULL, *cp;
-
- /* No match */
- char bigbuf[MAX_BUF];
- int slen;
-
- /* Set up replyinfo before we modify any of the buffers - this is used
- * if we don't find a match.
- */
- strcpy (bigbuf, "replyinfo ");
- slen = strlen (bigbuf);
- safe_strcat (bigbuf, buf, &slen, MAX_BUF);
+ char *params;
/* find the first space, make it null, and update the
* params pointer.
*/
- for (cp = buf; *cp != '\0'; cp++)
- if (*cp == ' ')
+ for (params = buf; *params; params++)
+ if (*params == ' ')
{
- *cp = '\0';
- params = cp + 1;
+ *params++ = 0;
break;
}
@@ -241,7 +226,13 @@
else if (!strcmp (buf, "spell_paths"))
send_spell_paths (ns, params);
else
- ns->send_packet (bigbuf, len);
+ {
+ // undo tokenisation above and send replyinfo with the request unchanged
+ if (*params)
+ *--params = ' ';
+
+ ns->send_packet_printf ("replyinfo %s", buf);
+ }
}
void
@@ -475,27 +466,6 @@
}
/**
- * client requested an image. send it rate-limited
- * before flushing.
- */
-void
-AskFaceCmd (char *buf, int len, client *ns)
-{
- ns->askface.push_back (atoi (buf));
-}
-
-/**
- * Tells client the picture it has to use
- * to smooth a picture number given as argument.
- */
-void
-AskSmooth (char *buf, int len, client *ns)
-{
- ns->send_face (atoi (buf));
- ns->flush_fx ();
-}
-
-/**
* This handles the general commands from the client (ie, north, fire, cast,
* etc.)
*/
@@ -526,7 +496,6 @@
pl->count = 0;
}
-
/**
* This handles the general commands from the client (ie, north, fire, cast,
* etc.). It is a lot like PlayerCmd above, but is called with the
@@ -538,7 +507,7 @@
{
if (len <= 6)
{
- LOG (llevDebug, "Corrupt ncom command <%s> not long enough - discarding\n", buf);
+ LOG (llevDebug, "%s: corrupt ncom command <%s>: not long enough (%d) - discarding\n", pl->ns->host, buf, len);
return;
}
@@ -742,16 +711,18 @@
if (pl->combat_ob)
buf << " Combat" << (pl->ob->current_weapon == pl->combat_ob ? "*" : "") << ": " << pl->combat_ob->name;
+#if 0
//TODO: remove this when slot system is working, this is only for debugging
if (pl->ob->chosen_skill)
buf << " Skill*: " << pl->ob->chosen_skill->name;
+#endif
//TODO: maybe golem should become the current_weapon, quite simply?
if (pl->golem)
buf << " Golem*: " << pl->golem->name;
+ buf << '\0';
buf.linearise (obuf);
- obuf [buf.size ()] = 0;
}
#define AddIfInt64(Old,New,Type) if (Old != New) {\
@@ -795,10 +766,12 @@
if (!ns)
return;
- object *ob = pl->ob;
+ object *ob = pl->observe;
if (!ob)
return;
+ player *opl = ob->contr ? static_cast(ob->contr) : pl;
+
packet sl ("stats");
AddIfShort (ns->last_stats.hp, ob->stats.hp, CS_STAT_HP);
@@ -816,7 +789,7 @@
AddIfShort (ns->last_stats.Cha, ob->stats.Cha, CS_STAT_CHA);
for (int s = 0; s < NUM_SKILLS; s++)
- if (object *skill = pl->last_skill_ob[s])
+ if (object *skill = opl->last_skill_ob[s])
if (skill->stats.exp != ns->last_skill_exp [s])
{
ns->last_skill_exp [s] = skill->stats.exp;
@@ -841,10 +814,10 @@
flags = 0;
- if (pl->fire_on)
+ if (opl->fire_on)
flags |= SF_FIREON;
- if (pl->run_on)
+ if (opl->run_on)
flags |= SF_RUNON;
AddIfShort (ns->last_flags, flags, CS_STAT_FLAGS);
@@ -868,7 +841,7 @@
AddIfInt (ns->last_path_denied, ob->path_denied, CS_STAT_SPELL_DENY);
}
- rangetostring (pl, buf); /* we want use the new fire & run system in new client */
+ rangetostring (opl, buf); /* we want use the new fire & run system in new client */
AddIfString (ns->stats.range, buf, CS_STAT_RANGE);
set_title (ob, buf);
AddIfString (ns->stats.title, buf, CS_STAT_TITLE);
@@ -960,7 +933,7 @@
if (ob)
ns.send_faces (ob);
else
- ns.send_face (face_num);
+ ns.send_face (face_num, 10);
sl << uint16 (face_num);
return 1;
@@ -1012,45 +985,66 @@
}
/**
- * This function uses the new map1 protocol command to send the map
- * to the client. It is necessary because the old map command supports
- * a maximum map size of 15x15.
- * This function is much simpler than the old one. This is because
- * the old function optimized to send as few face identifiers as possible,
- * at the expense of sending more coordinate location (coordinates were
- * only 1 byte, faces 2 bytes, so this was a worthwhile savings). Since
- * we need 2 bytes for coordinates and 2 bytes for faces, such a trade off
- * maps no sense. Instead, we actually really only use 12 bits for coordinates,
- * and use the other 4 bits for other informatiion. For full documentation
- * of what we send, see the doc/Protocol file.
- * I will describe internally what we do:
- * the ns->lastmap shows how the map last looked when sent to the client.
- * in the lastmap structure, there is a cells array, which is set to the
- * maximum viewable size (As set in config.h).
- * in the cells, there are faces and a count value.
- * we use the count value to hold the darkness value. If -1, then this space
- * is not viewable.
- * we use faces[0] faces[1] faces[2] to hold what the three layers
- * look like.
+ * Draws client map.
*/
void
-draw_client_map1 (object *pl)
+draw_client_map (player *pl)
{
+ object *ob = pl->observe;
+ if (!ob->active)
+ return;
+
+ maptile *plmap = ob->map;
+
+ /* If player is just joining the game, he isn't here yet, so the map
+ * can get swapped out. If so, don't try to send them a map. All will
+ * be OK once they really log in.
+ */
+ if (!plmap || plmap->in_memory != MAP_IN_MEMORY)
+ return;
+
int x, y, ax, ay, startlen, max_x, max_y, oldlen;
- sint16 nx, ny;
int estartlen, eoldlen;
uint8 eentrysize;
uint16 ewhatstart, ewhatflag;
uint8 extendedinfos;
- maptile *m;
- client &socket = *pl->contr->ns;
+ check_map_change (pl);
+ prefetch_surrounding_maps (pl->ob);
- if (!pl->active)
- return;
+ /* do LOS after calls to update_position */
+ if (ob != pl->ob)
+ clear_los (pl);
+ else if (pl->do_los)
+ {
+ update_los (ob);
+ pl->do_los = 0;
+ }
+
+ /**
+ * This function uses the new map1 protocol command to send the map
+ * to the client. It is necessary because the old map command supports
+ * a maximum map size of 15x15.
+ * This function is much simpler than the old one. This is because
+ * the old function optimized to send as few face identifiers as possible,
+ * at the expense of sending more coordinate location (coordinates were
+ * only 1 byte, faces 2 bytes, so this was a worthwhile savings). Since
+ * we need 2 bytes for coordinates and 2 bytes for faces, such a trade off
+ * maps no sense. Instead, we actually really only use 12 bits for coordinates,
+ * and use the other 4 bits for other informatiion. For full documentation
+ * of what we send, see the doc/Protocol file.
+ * I will describe internally what we do:
+ * the ns->lastmap shows how the map last looked when sent to the client.
+ * in the lastmap structure, there is a cells array, which is set to the
+ * maximum viewable size (As set in config.h).
+ * in the cells, there are faces and a count value.
+ * we use the count value to hold the darkness value. If -1, then this space
+ * is not viewable.
+ * we use faces[0] faces[1] faces[2] to hold what the three layers
+ * look like.
+ */
- check_map_change (pl->contr);
- prefetch_surrounding_maps (pl);
+ client &socket = *pl->ns;
packet sl (socket.mapmode == Map1Cmd ? "map1" : "map1a");
packet esl;
@@ -1084,16 +1078,30 @@
/* We could do this logic as conditionals in the if statement,
* but that started to get a bit messy to look at.
*/
- max_x = pl->x + (socket.mapx + 1) / 2;
- max_y = pl->y + (socket.mapy + 1) / 2;
-
- maptile *plmap = pl->map;
+ max_x = ob->x + (socket.mapx + 1) / 2;
+ max_y = ob->y + (socket.mapy + 1) / 2;
- for (y = pl->y - socket.mapy / 2; y < max_y; y++, ay++)
+ for (y = ob->y - socket.mapy / 2; y < max_y; y++, ay++)
{
+ sint16 nx, ny;
+ maptile *m = 0;
+
ax = 0;
- for (x = pl->x - socket.mapx / 2; x < max_x; x++, ax++)
+ for (x = ob->x - socket.mapx / 2; x < max_x; x++, ax++)
{
+ // check to see if we can simply go one right quickly
+ ++nx;
+ if (m && nx >= m->width)
+ m = 0;
+
+ if (!m)
+ {
+ nx = x; ny = y; m = plmap;
+
+ if (!xy_normalise (m, nx, ny))
+ m = 0;
+ }
+
int emask, mask;
emask = mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4;
@@ -1102,10 +1110,6 @@
/* If the coordinates are not valid, or it is too dark to see,
* we tell the client as such
*/
- nx = x;
- ny = y;
- m = get_map_from_coord (plmap, &nx, &ny);
-
if (!m)
{
/* space is out of map. Update space and clear values
@@ -1123,7 +1127,7 @@
m->touch ();
- int d = pl->contr->blocked_los[ax][ay];
+ int d = pl->blocked_los[ax][ay];
if (d > 3)
{
@@ -1196,6 +1200,7 @@
lastcell.count = d;
mapspace &ms = m->at (nx, ny);
+ ms.update ();
if (socket.extmap)
{
@@ -1215,14 +1220,14 @@
if (op->stats.maxhp > 0 && (unsigned) op->stats.maxhp > (unsigned) op->stats.hp)
{
stat_hp = 255 - (op->stats.hp * 255 + 254) / op->stats.maxhp;
- stat_width = op->arch->tail_x;
+ stat_width = op->arch->max_x - op->arch->x; //TODO: should be upper-left edge
}
}
if (op->msg && op->msg[0] == '@')
flags |= 1;
- if (op->type == PLAYER && op != pl)
+ if (op->type == PLAYER && op != ob)
player = op->count;
}
@@ -1276,24 +1281,23 @@
if (update_space (sl, socket, ms, lastcell, 1))
mask |= 0x2;
- if (ms.player () == pl
- && (pl->invisible & (pl->invisible < 50 ? 1 : 7)))
+ if (ms.player () == ob
+ && (ob->invisible & (ob->invisible < 50 ? 1 : 7)))
{
// force player to be visible to himself if invisible
- if (lastcell.faces[0] != pl->face)
+ if (lastcell.faces[0] != ob->face)
{
- lastcell.faces[0] = pl->face;
+ lastcell.faces[0] = ob->face;
mask |= 0x1;
- sl << uint16 (pl->face);
+ sl << uint16 (ob->face);
- socket.send_faces (pl);
+ socket.send_faces (ob);
}
}
/* Top face */
else if (update_space (sl, socket, ms, lastcell, 0))
mask |= 0x1;
-
/* Check to see if we are in fact sending anything for this
* space by checking the mask. If so, update the mask.
@@ -1362,74 +1366,10 @@
}
}
-/**
- * Draws client map.
- */
-void
-draw_client_map (object *pl)
-{
- int i, j;
- sint16 ax, ay; /* ax and ay goes from 0 to max-size of arrays */
- int mflags;
- struct Map newmap;
- maptile *m, *pm;
-
- if (pl->type != PLAYER)
- {
- LOG (llevError, "draw_client_map called with non player/non eric-server\n");
- return;
- }
-
- pm = pl->map;
-
- /* If player is just joining the game, he isn't here yet, so the map
- * can get swapped out. If so, don't try to send them a map. All will
- * be OK once they really log in.
- */
- if (pm == NULL || pm->in_memory != MAP_IN_MEMORY)
- return;
-
- memset (&newmap, 0, sizeof (struct Map));
-
- for (j = (pl->y - pl->contr->ns->mapy / 2); j < (pl->y + (pl->contr->ns->mapy + 1) / 2); j++)
- for (i = (pl->x - pl->contr->ns->mapx / 2); i < (pl->x + (pl->contr->ns->mapx + 1) / 2); i++)
- {
- ax = i;
- ay = j;
- m = pm;
- mflags = get_map_flags (m, &m, ax, ay, &ax, &ay);
-
- if (mflags & P_OUT_OF_MAP)
- continue;
-
- /* If a map is visible to the player, we don't want to swap it out
- * just to reload it. This should really call something like
- * swap_map, but this is much more efficient and 'good enough'
- */
- if (mflags & P_NEW_MAP)
- m->timeout = 50;
- }
-
- /* do LOS after calls to update_position */
- if (pl->contr->do_los)
- {
- update_los (pl);
- pl->contr->do_los = 0;
- }
-
- /* Big maps need a different drawing mechanism to work */
- draw_client_map1 (pl);
-}
-
-
/*****************************************************************************/
-
/* GROS: The following one is used to allow a plugin to send a generic cmd to*/
-
/* a player. Of course, the client need to know the command to be able to */
-
/* manage it ! */
-
/*****************************************************************************/
void
send_plugin_custom_message (object *pl, char *buf)
@@ -1592,6 +1532,8 @@
spell->face = face_find ("burnout.x11", blank_face);
}
+ pl->ns->send_face (spell->face);
+
/* send the current values */
sl << uint32 (spell->count)
<< uint16 (spell->level)
@@ -1636,16 +1578,17 @@
* won't take us over the length limit for the socket, if it does,
* we need to send what we already have, and restart packet formation
*/
+ if (spell->type != SPELL)
+ continue;
+
/* Seeing crashes by overflowed buffers. Quick arithemetic seems
* to show add_spell is 26 bytes + 2 strings. However, the overun
* is hundreds of bytes off, so correcting 22 vs 26 doesn't seem
* like it will fix this
*/
- if (spell->type != SPELL)
- continue;
-
if (sl.length () >= (MAXSOCKBUF - (26 + strlen (spell->name) + (spell->msg ? strlen (spell->msg) : 0))))
{
+ pl->ns->flush_fx ();
pl->ns->send_packet (sl);
sl.reset ();
@@ -1670,6 +1613,7 @@
}
/* finally, we can send the packet */
+ pl->ns->flush_fx ();
pl->ns->send_packet (sl);
}