def dump(self, f, showContents=True, keyColumnWidth=25): """Dump a message in human readable form to the stream 'f'.""" from BZFlag import Protocol from StringIO import StringIO name = self.__class__.__name__ # If the message was received with Network.Socket.readMessage, # we can determine where it came from by its fromModule attribute direction = '' try: from BZFlag.Protocol import FromServer, ToServer if self.fromModule == ToServer: direction = "-->" elif self.fromModule == FromServer: direction = "<--" except AttributeError: pass f.write("%s %s\n" % (direction, name)) if not showContents: return # Attributes for us to ignore. These are generally things we annotate the message # with later. Note that this isn't a list of all such annotations- most notably, # 'protocol' is omitted since it's very useful to have in message dumps. ignoreList = ('eventLoop', 'socket', 'header', 'fromModule', 'fromAddress', 'client') # Recursively build a list of (key,value) tuples that will be displayed # to represent a message. This handles traversing into substructures # like FlagUpdate. def buildKeys(object, prefix=""): keys = object.__dict__.keys() keys.sort() lst = [] for key in keys: if key[0] != '_' and not key in ignoreList: value = object.__dict__[key] if isinstance(value, Protocol.Struct): lst.extend(buildKeys(value, prefix + key + ".")) else: lst.append((prefix + key, value)) return lst for (key, value) in buildKeys(self): if key == 'data': # Special decoding for 'data' members- do a hex dump d = StringIO() Util.hexDump(StringIO(value), d) value = ("%d bytes\n" % len(value)) + d.getvalue() else: # Let python decode everything else value = repr(value) # Handle printing multiline values properly lines = value.split("\n") print ("%%%ss: %%s" % keyColumnWidth) % (key, lines[0]) for line in lines[1:]: if line: f.write(" " * (keyColumnWidth + 2) + line + "\n")
def loadDataFile(self, name): """Load the texture from a file in our data directory. The main reason for this function to exist is so a texture can be pickled without hardcoding the data path in the pickle. """ self.loadImage(Image.open(Util.dataFile(name))) self.loader = ('loadDataFile', name) self.name = name
def __init__(self, name, sizes=defaultSizes): filename = Util.dataFile(name) pygame.font.init() self.sizes = {} self.sortedSizes = sizes self.sortedSizes.sort() for size in sizes: self.sizes[size] = RenderedFont(filename, size)
def __init__(self, name): self.encoding = 'utf8' self.meshes = {} self.parseStack = [] self.namespace = {} f = Util.autoFile(name) self.parse(f) f.close() for node in self.parseStack: self.extractMeshes(node, ()) del self.parseStack del self.namespace
def Heightmap(name, size = Scale.WorldSize, wallHeight = Scale.WallHeight, boxHeight = 20.0 * Scale.MuzzleHeight, ): """ Uses the given image file to make a heightmapped world. This is very silly and nobody should use this except as an example and a proof-of-concept. Requires PIL. Positional arguments: name : File or URI containing the heightmap, in any format PIL supports Keyword arguments: size : Distance along each side of the generated square world wallHeight : Height of the world's walls boxHeight : Maximum box height, corresponding to a fully white pixel """ import Image f = Util.autoFile(name, "rb") img = Image.open(f).convert("L") # Convert to grayscale w = World() w.erase() w.storeSkeletonHeader(size=size, wallHeight=wallHeight) # For now just output a box per nonzero pixel. If I expected # anyone to actually use this I'd make it combine rectangular # regions of the same pixel value into larger boxes. for y in xrange(img.size[1]): for x in xrange(img.size[0]): p = img.getpixel((x,y)) if p: w.storeBlock(WorldObjects.Box( center = ( (float(x) / img.size[0] - 0.5) * size, -(float(y) / img.size[1] - 0.5) * size, 0), size = (size / img.size[0], size / img.size[1], p / 255.0 * boxHeight), angle = 0)) w.storeSkeletonFooter() w.postprocess() f.close() return w
def Binary(name): """ Load a world from a binary file. This is the world format used in transit from server to client, and used in the client's world cache. Positional arguments: name : File or URI containing the binary world """ from BZFlag.Protocol import Common blockDict = Common.getMessageDict(WorldObjects) f = Util.autoFile(name) w = World() w.erase() while 1: # Read the block header header = WorldObjects.BlockHeader() packedHeader = f.read(header.getSize()) if len(packedHeader) < header.getSize(): raise Errors.ProtocolError("Premature end of binary world data") header.unmarshall(packedHeader) # Look up the block type and instantiate it try: block = blockDict[header.id]() except KeyError: raise Errors.ProtocolError( "Unknown block type 0x%04X in binary world data" % header.id) # Read the block body packedBody = f.read(block.getSize() - len(packedHeader)) if len(packedBody) < (block.getSize() - len(packedHeader)): raise Errors.ProtocolError("Incomplete block in binary world data") block.unmarshall(packedHeader + packedBody) w.storeBlock(block) # We're done if this was the EndOfData block if isinstance(block, WorldObjects.EndOfData): break w.postprocess() return w
def getMessageDict(module): """Return a dictionary mapping message IDs to message classes, given a module containing Message subclasses. """ return Util.getSubclassDict(module, Message, 'messageId')
parser = optik.OptionParser(usage = "usage: %prog [options] worlds") parser.add_option("-o", "--output", metavar="FILE", help="Sets the file or directory name to output thumbnails to.") parser.add_option("-s", "--size", metavar="WIDTHxHEIGHT", help="Sets the thumbnail size. Default is 160x160.", default="160x160") parser.add_option("-i", "--index", action="store_true", help="Generates an index of world files to the directory provided with -o.") parser.add_option("-f", "--format", metavar="EXTENSION", help="Sets the format, specified in the form of a file extension name, " + "of the images to generate when an explicit filename is not given. Default is 'png'.", default='png') parser.add_option("-a", "--oversample", metavar="AMOUNT", help="Sets the amount of oversampling. Higher numbers will produce smoother images " + "with thinner borders, but will require much more memory and CPU time. Default is 3.", default=3) parser.add_option("-t", "--template", metavar="FILE", help="Sets the template file to use for producing index output. Default is " + "'worldindex.html' in the data directory.", default=Util.dataFile('worldindex.html')) parser.add_option("-n", "--index-name", metavar="FILE", dest="indexName", help="Sets the name of the index file to produce in the output directory. Default is 'index.html'.", default="index.html") (options, args) = parser.parse_args() if len(args) == 0: parser.error("One or more world filenames must be specified on the command line.") if len(args) > 1 and options.output and not os.path.isdir(options.output): parser.error("An output directory must be specified for multiple input files, not an output file.") if options.index and options.output and not os.path.isdir(options.output): parser.error("An output directory must be specified for indexing mode, not an output file.") size = map(int, options.size.split("x")) oversample = int(options.oversample) worlds = []
def getDict(): """Return a dictionary mapping flag abbreviations to flag classes""" import BZFlag.Flag.List return Util.getSubclassDict(BZFlag.Flag.List, FlagBase, 'abbreviation')
def Text(name, size = Scale.WorldSize, wallHeight = Scale.WallHeight, ): """ Load a world from a text file. This is the default world format. Positional arguments: name : File or URI containing the world Keyword arguments: size : Default distance along each side of the generated square world wallHeight : Height of the world's walls """ import re f = Util.autoFile(name) w = World() section = None sectionDict = Util.getSubclassDict(WorldObjects, WorldObjects.WorldObject, 'textName', 'textSectionDict') # We won't actually add the objects to the world until later, # since we need to start the world out with walls and a game style # block, but we might get the information needed for those at any # point in the file. w.erase() blocks = [] for line in f: # If this is a kludge used by map editors to store extra # attributes. Don't process any comments on the line. if not line.startswith("#!"): line = re.sub("#.*", "", line) line = line.strip() if line: if section: # We're inside a section. Accumulate lines until 'end' sectionLines.append(line) if line == 'end': # Done with this section, process it. if section == 'world': # World information for line in sectionLines: tokens = re.split("\s+", line) keyword = tokens[0].lower() args = tokens[1:] if keyword == 'size': size = int(args[0]) else: # Assume all other sections are world objects try: cls = sectionDict[section] except KeyError: raise Errors.ProtocolError( "World file contains unknown section type '%s'" % section) inst = cls() inst.textRead(sectionLines) blocks.append(inst) section = None elif not line.startswith("#!"): # We're beginning a section section = line.lower() if section.find(" ") >= 0: raise Errors.ProtocolError("Unexpected whitespace within section name") sectionLines = [] if section: raise Errors.ProtocolError("World file has unterminated '%s' section" % section) # Now store all the blocks in our world w.storeSkeletonHeader(size, wallHeight) for block in blocks: w.storeBlock(block) w.storeSkeletonFooter() w.postprocess() return w
def load(name): from BZFlag import Util return defaultCache.load(Util.dataFile(name))