On behalf of Stephen Thorne of 2007, Stephen Thorne of 2012 would like to
apologise for using metaclasses.
On Sep 26, 2012 9:47 PM, "James Cameron" <quozl at us.netrek.org> wrote:

> G'day Bob,
>
> This awesome bit of code is from Stephen Thorne, possibly around 26th
> June 2007, during an IRC collaboration while we were organising a
> holiday technology camp.
>
> I've gathered it into my mind again just now, so that I can better
> explain it.
>
> The main requirement was a list of packet types and sizes, for
> processing the data stream from the server.  I had built something
> that was a bit ugly, using my limited knowledge of Python.  Stephen
> optimised it by using metaclasses.  I still have the IRC log from
> #netrek.
>
> sp_table is a dictionary of server packet types, indexed by the packet
> type, each entry holding a packet size in bytes and a packet handler
> object.
>
> sp_table is populated by the __new__ method of the ServerPacket class,
> which is called for each of the SP_* classes as they are defined.  The
> method calculates the size of the packet using the struct format
> string.  This saves having to track the packet format or size in more
> than one place.
>
> A lowercase global name is also added.  This ensures an instance of
> each object is preserved during execution, as well as making the
> object available for direct access.  Direct access is common for cp_*
> objects, but not for sp_* objects.  Examples of cp_* access are every
> keyboard handler.  Examples of sp_* access are the references to
> sp_badversion.why and sp_warning.synthetic().
>
> When the Client object is created in nt_init(), a pointer to the only
> instance of the SP class is given to it, and it is preserved in the
> Client object and used whenever a packet is received.  In particular,
> the find method of the SP class is called.
>
> So when a packet is received (in tcp_readable);
>
> - the first byte is examined,
>
> - the sp_table is referenced, to obtain the packet size,
>   (self.sp.find()),
>
> - enough bytes to fill the packet are dequeued from the network
>   socket, "if we have not got the complete packet, read some more",
>
> - the packet is passed to a packet type handler, (instance.handler()).
>
> The only thing I don't quite understand is how sp_table is used
> without triggering an error "UnboundLocalError: local variable
> 'sp_table' referenced before assignment", but it works.
>
> sp_table looks like this (print repr(sp_table)):
>
> {1: (84, <gytha.SP_MESSAGE object at 0xa394b0c>),
> 2: (4, <gytha.SP_PLAYER_INFO object at 0xa39436c>),
> 3: (8, <gytha.SP_KILLS object at 0xa3943ac>),
> 4: (12, <gytha.SP_PLAYER object at 0xa3944ac>),
> 5: (8, <gytha.SP_TORP_INFO object at 0xa3947ec>),
> 6: (12, <gytha.SP_TORP object at 0xa39484c>),
> 7: (16, <gytha.SP_PHASER object at 0xa394a0c>),
> 8: (8, <gytha.SP_PLASMA_INFO object at 0xa3948cc>),
> 9: (12, <gytha.SP_PLASMA object at 0xa39490c>),
> 10: (84, <gytha.SP_WARNING object at 0xa394c0c>),
> 11: (84, <gytha.SP_MOTD object at 0xa3940cc>),
> 12: (32, <gytha.SP_YOU object at 0xa39416c>),
> 13: (4, <gytha.SP_QUEUE object at 0xa3941ec>),
> 14: (28, <gytha.SP_STATUS object at 0xa39498c>),
> 15: (12, <gytha.SP_PLANET object at 0xa394a8c>),
> 16: (4, <gytha.SP_PICKOK object at 0xa39470c>),
> 17: (104, <gytha.SP_LOGIN object at 0xa39460c>),
> 18: (8, <gytha.SP_FLAGS object at 0xa39452c>),
> 19: (4, <gytha.SP_MASK object at 0xa39468c>),
> 20: (4, <gytha.SP_PSTATUS object at 0xa39442c>),
> 21: (4, <gytha.SP_BADVERSION object at 0xa394cec>),
> 22: (4, <gytha.SP_HOSTILE object at 0xa3942ec>),
> 23: (56, <gytha.SP_STATS object at 0xa394b8c>),
> 24: (52, <gytha.SP_PL_LOGIN object at 0xa39426c>),
> 25: (20, <gytha.SP_RESERVED object at 0xa39476c>),
> 26: (28, <gytha.SP_PLANET_LOC object at 0xa3945ac>),
> 28: (8, <gytha.SP_UDP_REPLY object at 0xa394dac>),
> 29: (4, <gytha.SP_SEQUENCE object at 0xa394e0c>),
> 32: (32, <gytha.SP_GENERIC_32 object at 0xa394f0c>),
> 39: (60, <gytha.SP_SHIP_CAP object at 0xa394e8c>),
> 46: (8, <gytha.SP_PING object at 0xa394d2c>),
> 60: (88, <gytha.SP_FEATURE object at 0xa394c6c>),
> -1: (0, <gytha.SP object at 0xa39406c>)}
>
> --
> James Cameron
> http://quozl.linux.org.au/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.us.netrek.org/pipermail/netrek-dev/attachments/20120926/4383cb77/attachment.html>