--- deliantra/server/socket/loop.C 2009/10/12 14:00:59 1.82 +++ deliantra/server/socket/loop.C 2012/11/11 05:53:12 1.97 @@ -1,24 +1,22 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. - * - * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2002-2003,2007 Mark Wedel & The Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen - * + * + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero 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. - * + * * You should have received a copy of the Affero GNU General Public License * and the GNU General Public License along with this program. If not, see * . - * + * * The authors can be reached via e-mail to */ @@ -45,8 +43,6 @@ #include #include -#include - #define BG_SCRUB_RATE 4 // how often to send a face in the background #define MAX_QUEUE_DEPTH 50 @@ -69,7 +65,6 @@ if (cmd_queue.size () >= MAX_QUEUE_DEPTH) { - //TODO: just disconnect here? reset_state (); send_packet_printf ("drawinfo %d command queue overflow, ignoring.", NDI_RED); } @@ -120,30 +115,37 @@ void client::tick () { - if (!pl || destroyed ()) + if (destroyed ()) return; - pl->dirty = true; + if (pl) + { + pl->dirty = true; - /* Update the players stats once per tick. More efficient than - * sending them whenever they change, and probably just as useful - */ - esrv_update_stats (pl); + /* Update the players stats once per tick. More efficient than + * sending them whenever they change, and probably just as useful + */ + pl->need_updated_stats (); + esrv_update_stats (pl); - sint32 weight = pl->ob->client_weight (); + if (pl->ns->update_spells) + esrv_update_spells (pl); - if (last_weight != weight) - { - pl->ob->update_stats (); - esrv_update_item (UPD_WEIGHT, pl->ob, pl->ob); - } + sint32 weight = pl->ob->client_weight (); - draw_client_map (pl); + if (last_weight != weight) + { + pl->ob->update_stats (); + esrv_update_item (UPD_WEIGHT, pl->ob, pl->ob); + } - if (update_look) - esrv_draw_look (pl); + draw_client_map (pl); - mapinfo_queue_run (); + if (update_look) + esrv_draw_look (pl); + + mapinfo_queue_run (); + } #if HAVE_TCP_INFO // check time of last ack, and, if too old, kill connection @@ -181,13 +183,14 @@ } #endif - rate_avail = min (max_rate + mss, rate_avail + max_rate); + // limit budget surplus/deficit by one mss, add per-tick budget + rate_avail = min (rate_avail, mss) + max_rate; int max_send = rate_avail; #if HAVE_TCP_INFO // further restrict the available bandwidth by the excess bandwidth available - max_send = min (max_send, (tcpi.tcpi_snd_cwnd - tcpi.tcpi_unacked + tcpi.tcpi_sacked) * mss); + min_it (max_send, (tcpi.tcpi_snd_cwnd - tcpi.tcpi_unacked + tcpi.tcpi_sacked) * mss); #endif // round to next-lowest mss @@ -203,7 +206,7 @@ if (!faces_sent [scrub_idx]) if (faceinfo *f = face_info (scrub_idx)) - if (f->type == FT_FACE || f->type == FT_SOUND) // only scrub faces and sounds for now + if (f->type == FT_IMAGE || f->type == FT_SOUND) // only scrub faces and sounds for now { send_face (scrub_idx, -120); flush_fx (); @@ -226,37 +229,32 @@ ixsend &ix = ixface.back (); - if (facedata *d = face_data (ix.idx, faceset)) - { - // estimate the packet header overhead "ix " + idx + (new)ofs - int pktlen = 3 + ber32::encoded_size (ix.idx) + ber32::encoded_size (ix.ofs); - int chunk = min (avail - packet::hdrlen, MAXSOCKBUF) - pktlen; - - // only transfer something if the amount of data transferred - // has a healthy relation to the header overhead - if (chunk < 64) - break; + // estimate the packet header overhead "ix " + idx + (new)ofs + int pktlen = 3 + ber32::encoded_size (ix.idx) + ber32::encoded_size (ix.ofs); + int chunk = min (avail - packet::hdrlen, MAXSOCKBUF) - pktlen; + + // only transfer something if the amount of data transferred + // has a healthy relation to the header overhead + if (chunk < 64) + break; - chunk = min (chunk, (int)ix.ofs); + chunk = min (chunk, (int)ix.ofs); - ix.ofs -= chunk; + ix.ofs -= chunk; - //fprintf (stderr, "i%dx %6d: %5d+%4d (%4d)\n", fxix, ix.idx,ix.ofs,chunk, ixface.size());//D + //fprintf (stderr, "i%dx %6d: %5d+%4d (%4d)\n", fxix, ix.idx,ix.ofs,chunk, ixface.size());//D - packet sl ("ix"); + packet sl ("ix"); - sl << ber32 (ix.idx) - << ber32 (ix.ofs) - << data (d->data.data () + ix.ofs, chunk); + sl << ber32 (ix.idx) + << ber32 (ix.ofs) + << data (ix.data + ix.ofs, chunk); - send_packet (sl); - } - else - ix.ofs = 0; + send_packet (sl); if (!ix.ofs) { - ixface.pop_back (); + ix_pop (); if (ixface.empty ()) break; @@ -268,14 +266,14 @@ } void -client::flush_sockets (void) +client::flush_sockets () { for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i) (*i)->flush (); } void -client::clock (void) +client::clock () { for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i) (*i)->tick ();