# HG changeset patch # User Gerard Krijgsman # Date 1347879675 -7200 # Mon Sep 17 13:01:15 2012 +0200 # Node ID c7ab62c5e380fe728c48892e363295d748b5cdb2 # Parent adbc24a256767885b9709072de3956599188c9a6 Changed class variables to lowercase; added offset argument to all read() functions to make result.read() less complex; moved to bitbucket.org diff --git a/common.py b/common.py --- a/common.py +++ b/common.py @@ -9,16 +9,16 @@ class PlanetsData(object): """Base class for all Planets data objects""" - FILENAME = None # Default filename - COUNT = None # Default number of objects in a data file - PACK_LENGTH = None # Length of binary data for single object - PACK_FORMAT = None # Format of binary data for single object - FIELDS = () # Fields for single object + filename = None # Default filename + count = None # Default number of objects in a data file + pack_length = None # Length of binary data for single object + pack_format = None # Format of binary data for single object + fields = () # Fields for single object def __init__(self): # Expand field list where necessary (in case of dictionary fields) fields = [] - for field in self.FIELDS: + for field in self.fields: # tuple format: ('name', start, end,) start/end must be 'int' if isinstance(field, tuple) and (len(field) == 3): for i in range(field[1], field[1]+field[2]): @@ -26,10 +26,10 @@ else: fields.append(field) fields = tuple(fields) - if self.__class__.FIELDS is not fields: - self.__class__.FIELDS = fields + if self.__class__.fields is not fields: + self.__class__.fields = fields # Initialize fields - for field in self.FIELDS: + for field in self.fields: # Dictionary field: see EngSpec class in fixed.py for an example if isinstance(field, tuple): setattr(self, str(field[0])+'['+str(field[1])+']', None) @@ -39,12 +39,12 @@ def unpack(self, data): """Unpacks binary data into class instance variables""" - if len(data) is not self.PACK_LENGTH: + if len(data) is not self.pack_length: raise ValueError('Binary data passed has incorrect length') - values = struct.unpack(self.PACK_FORMAT, data) - if len(self.FIELDS) is not len(values): + values = struct.unpack(self.pack_format, data) + if len(self.fields) is not len(values): raise ValueError('Incorrect number of variables in pack format') - for name, value in zip(self.FIELDS, values): + for name, value in zip(self.fields, values): # Dictionary field: see EngSpec class in fixed.py for an example if isinstance(name, tuple): setattr(self, str(name[0])+'['+str(name[1])+']', value) @@ -64,14 +64,14 @@ """Unpacks binary data into a list of object instances""" result = {} if count is None: - if cls.COUNT is not None: - count = cls.COUNT - elif len(data) >= cls.PACK_LENGTH: - count = int(len(data) / cls.PACK_LENGTH) + if cls.count is not None: + count = cls.count + elif len(data) >= cls.pack_length: + count = int(len(data) / cls.pack_length) for i in range(1, count+1): # For compatibility, count from 1 and not 0 instance = cls() - start = cls.PACK_LENGTH*(i-1) - end = cls.PACK_LENGTH*i + start = cls.pack_length*(i-1) + end = cls.pack_length*i instance.unpack(data[start:end]) if instance.id is None: instance.id = i @@ -81,16 +81,19 @@ return result @classmethod - def read(cls, f, has_count=False, count=None): + def read(cls, f, offset=None, has_count=False, count=None): """Reads from file and loads contents in list of object instances""" + # Seek to offset if set. Not recommended if has_count & count are None + if offset is not None: + f.seek(offset) # Data may be preceeded by a WORD indicating how much objects follow if has_count: (count,) = struct.unpack('< h', f.read(2)) - # Load "count" objects or predetermined "COUNT" objects or whole file + # Load "count" objects or predetermined "count" objects or whole file if count is not None: - data = f.read(cls.PACK_LENGTH * count) - elif cls.COUNT is not None: - data = f.read(cls.PACK_LENGTH * cls.COUNT) + data = f.read(cls.pack_length * count) + elif cls.count is not None: + data = f.read(cls.pack_length * cls.count) else: data = f.read() result = cls.load(data, count) @@ -103,7 +106,7 @@ def open(cls, name, has_count=False, count=None): """Opens file and loads contents in list of object instances""" f = open(name,'rb') - result = cls.read(f, has_count, count) + result = cls.read(f, offset=None, has_count=has_count, count=count) f.close() return result diff --git a/fixed.py b/fixed.py --- a/fixed.py +++ b/fixed.py @@ -7,11 +7,11 @@ class BeamSpec(PlanetsData): """List of starship beam weapons""" - FILENAME = 'BEAMSPEC.DAT' - COUNT = 10 - PACK_LENGTH = 36 - PACK_FORMAT = '< 20s h h h h h h h h' - FIELDS = ('name', + filename = 'BEAMSPEC.DAT' + count = 10 + pack_length = 36 + pack_format = '< 20s h h h h h h h h' + fields = ('name', 'cost', 'tritanium', 'duranium', @@ -23,11 +23,11 @@ class EngSpec(PlanetsData): """List of starship engines""" - FILENAME = 'ENGSPEC.DAT' - COUNT = 9 - PACK_LENGTH = 66 - PACK_FORMAT = '< 20s h h h h h 9i' - FIELDS = ('name', + filename = 'ENGSPEC.DAT' + count = 9 + pack_length = 66 + pack_format = '< 20s h h h h h 9i' + fields = ('name', 'cost', 'tritanium', 'duranium', @@ -37,11 +37,11 @@ class HullSpec(PlanetsData): """List of starship hulls""" - FILENAME = 'HULLSPEC.DAT' - # No COUNT, but typically 105 objects in default HULLSPEC.DAT - PACK_LENGTH = 60 - PACK_FORMAT = '< 30s h h h h h h h h h h h h h h h' - FIELDS = ('name', + filename = 'HULLSPEC.DAT' + # No count, but typically 105 objects in default HULLSPEC.DAT + pack_length = 60 + pack_format = '< 30s h h h h h h h h h h h h h h h' + fields = ('name', 'picture', 'damaged', # Unused field for picture of damaged ship 'tritanium', @@ -60,11 +60,11 @@ class TorpSpec(PlanetsData): """List of starship torpedo weapons""" - FILENAME = 'TORPSPEC.DAT' - COUNT = 10 - PACK_LENGTH = 38 - PACK_FORMAT = '< 20s h h h h h h h h h' - FIELDS = ('name', + filename = 'TORPSPEC.DAT' + count = 10 + pack_length = 38 + pack_format = '< 20s h h h h h h h h h' + fields = ('name', 'torpedo_cost', 'launcher_cost', 'tritanium', diff --git a/player.py b/player.py --- a/player.py +++ b/player.py @@ -11,11 +11,11 @@ class Base(PlanetsData): """List of player's starbases""" - # No FILENAME, but typically: BDATAx.DAT or BDATAx.DIS (x=player) - # No COUNT, but obviously limited by number of planets - PACK_LENGTH = 156 - PACK_FORMAT = '< h h h h h h h h 9h 20h 10h 10h 10h h h h h h h h h h h h' - FIELDS = ('id', + # No filename, but typically: BDATAx.DAT or BDATAx.DIS (x=player) + # No count, but obviously limited by number of planets + pack_length = 156 + pack_format = '< h h h h h h h h 9h 20h 10h 10h 10h h h h h h h h h h h h' + fields = ('id', 'owner', 'defense', 'damage', @@ -42,11 +42,11 @@ class Planet(PlanetsData): """List of player's planets""" - # No FILENAME, but typically: PDATAx.DAT or PDATAx.DIS (x=player) - # No COUNT, but maximum 500 - PACK_LENGTH = 85 - PACK_FORMAT = ' 0) diff --git a/result.py b/result.py --- a/result.py +++ b/result.py @@ -18,21 +18,15 @@ raise InvalidResultFile('RST file size zero or not defined') pointers = _get_sections(f, filesize) # Read standard sections (should always exist, even if 0 items in section) - f.seek(pointers['ships']) - result['ships'] = Ship.read(f, has_count=True) - f.seek(pointers['targets']) - result['targets'] = Target.read_result(f, - extra_offset=pointers['extratargets']) - f.seek(pointers['planets']) - result['planets'] = Planet.read(f, has_count=True) - f.seek(pointers['bases']) - result['bases'] = Base.read(f, has_count=True) - f.seek(pointers['messages']) - result['messages'] = read_messages(f) - f.seek(pointers['shipxy']) - result['shipxy'] = ShipXY.read(f) - f.seek(pointers['general']) - result['general'] = read_general(f) + result['ships'] = Ship.read(f, offset=pointers['ships'], has_count=True) + result['targets'] = Target.read_result( + f, offset=pointers['targets'], extra_offset=pointers['extratargets']) + result['planets'] = Planet.read( + f, offset=pointers['planets'], has_count=True) + result['bases'] = Base.read(f, offset=pointers['bases'], has_count=True) + result['messages'] = read_messages(f, offset=pointers['messages']) + result['shipxy'] = ShipXY.read(f, offset=pointers['shipxy']) + result['general'] = read_general(f, offset=pointers['general']) return result def _valid_pointer(pointer, filesize, datasize): diff --git a/turn.py b/turn.py --- a/turn.py +++ b/turn.py @@ -7,7 +7,7 @@ from common import SIGNATURE, SUBVERSION, get_checksum CLIENT = 'VGA Planets v3.x library for Python' -URL = 'http://github.com/ghdpro/planets' +URL = 'https://bitbucket.org/ghdpro/planets' # VPH35.DLL magic numbers, taken from PCC v2's "trn.cc" source file VPH_MAGIC = (1585242373,