bw logo

Chapter 5. EntityLoader (ENTITY_LOADER)

Table of Contents

5.1. Implementation

Currently, the server loads the spaces/main space as the default space on startup. However, it is only the CellApp which is loading the space, and it is only loading the space geometry. In order to be able to place entities in World Editor and have them appear on the server, we need to create a more advanced space loading mechanism. To this end, we will make a helper class called EntityLoader which will be used by the Space entity. It will be the responsibility of this class to parse the space .chunk files and create entity instances for every entity encountered.

Note

You may be wondering why the engine doesn't just create entities automatically. While it could, this would remove flexibility from the scripts. This way, the game specific scripts are able to tailor how and when entities are created.

While at the end of this chapter it will appear to the end-user that nothing has changed, we will have laid the groundwork for the next chapter which covers creation of a editor placeable entity. Inspecting the BaseApp logs after running this server shows that it was unable to actually load the Greeter entity. This is added in the next chapter.

5.1. Implementation

The EntityLoader class exists only on the base entity, and in this tutorial will be implemented in the same Python module file as the Space entity. The following operations are performed:

  • The Space entity creates a new instance of the EntityLoader class, and passes that instance into the BigWorld.fetchEntitiesFromChunks function. This function instructs the BaseApp to parse all .chunk files in the given path, which is done asynchronously in the background loading thread (in order to avoid IO from blocking the main thread).

  • Whenever a non client only <entity> section is encountered within the .chunk files, the engine will call EntityLoader.onSection with the relevant <DataSection>.

  • The script uses the properties passed in to the onSection method in order to create an entity instance using BigWorld.createBaseAnywhere. It passes the Space entity's cell mailbox so that the new entity knows which space to create itself in. Note that this paradigm assumes that all entity scripts will accept createOnCell as a property.

  • The engine notifies the EntityLoader when chunks have finished being parsed via the onFinish callback.

# scripts/base/Space.py

class Space( BigWorld.Base ):
    ...

    def onGetCell( self ):        
        print "Space.onGetCell loading entities from '%s'" % self.spaceDir
        BigWorld.fetchEntitiesFromChunks( self.spaceDir,
            EntityLoader( self ) )
    ...

class EntityLoader( object ):
    def __init__( self, spaceEntity ):
        self.spaceEntity = spaceEntity

    def onSection( self, entity, matrix ):
        entityType = entity.readString( "type" )
        properties = entity[ "properties" ]
        pos = matrix.applyToOrigin()

        # Create entity base
        BigWorld.createBaseAnywhere( entityType,
            properties,
            createOnCell = self.spaceEntity.cell,
            position = pos,
            direction = (matrix.roll, matrix.pitch, matrix.yaw) )

    def onFinish( self ):
        print "Finished loading entities for space", self.spaceEntity.spaceDir

Adjusted example tutorial/res/scripts/base/Space.py