Threaded system pattern
select() system pattern
The object management layer has the following requirements:
Object ids should take the form of a case-sensitive alphanumeric
string ([a-z,A-Z,0-9]), at least 15 characters in length, allowing for
(15^62) 8.272905x10^72 unique object ids (more than 8,272,905,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
,000,000 objects). Alternatively, object ids can take the form of a numeric
id, at least 10 characters in length, though this will limit the total
number of unique object ids to (10^10) 1x10^10 unique object ids (10,000,000,000
objects).
The request handling portion of this layer parses requests from the Handler and invokes the appropriate script and accepts requests from scripts.
The script processing portion of this layer implements a scripting language that can invoke scripts associated with other objects, as well as intrinsic methods defined on objects. The scripting language is Python which will allow for on-line creation of persistent objects via methods on the object management portion of the layer. In-memory, transient objects can also be created using standard Python calls. A rich library of task management, event handling and notification, and object lookups and manipulation is provided by this layer, as well.
The map can be layered, if you like... TOP: mobiles MID: immobiles BOT: landscape mod Mobiles are defined as objects that can move or be moved. Avatars, items, NPCs, etc. Drop money on the ground and it turns into a mobile. Drop your sword and it's a mobile. Walk someplace and you're a mobile. Immobiles are defined as objects that are placed and not moved. Frequently, they include changes to the landscape. Immobiles include houses, walls, decorations, trees, and brush. Some immobiles may intrinsicly change the landscape (say, but ensuring a flat foundation for a house). Others (like trees) won't. Landscape modifications are cumulative changes to the landscape, typically by changing the characteristics of elevation, terrain type, and environment. Elevation indicates the altitude of the land. The terrain type is something like bare earth, grassland, mud, swamp, desert, or water. Environment includes special effects like poison gas, raditation, or fire. Landscape modifications should be area based, with a central coordinate or set of bounding coordinates (in a polygon) to minimize representation size. (Thus, an entire town could be brought to the same elevation with a single modification...the modelling engine would have to be intelligent enough to modify surrounding land unless you like abrupt, step-like cliffs.) An additional really cool feature to this is that player activity can have a semi-permanent impact on the landscape (say, if a player decided to dig a trench). The lifetime of these modifications should be limited. The underlying landscape is fractally (?) generated from a seed value (thanks, Raph, for the reminder...haven't done this since I wrote the terrain module of a battletech simulator on LambdaMOO). It is modified by the landscape modifier (stored in the database) and other layers are sucessively drawn upon it. Avatar movement across the landscape is typically limited by factors of: - significant elevation change (more than 1/2 the avatar's height) - placement of immobiles that are flagged impassable or are more than 1/2 the avatar's height - placement of mobiles that are flagged impassable (other avatars, for instance) or are more than 1/2 the avatar's height - attempted entry into a terrain that does not allow entry (say, water) Sparse mapping assists in one other crucial element in a coordinate based system. In a coordinate based system, event propagation is crucial. Certain events propagate farther than others (distances are in radius): - whisper is only audible in the immediately adjacent area (less than one meter) - talk is only audible to roughly three meters - shout is only audible to roughly thirty meters - a fireball propagates to roughly five meters A sparse map allows for faster, easier collection of adjacent objects than other methods. For comparison, we'll look at a tile-based containment system. In a tile-based containment system, each tile has a "contents" property that indicates what object is at that coordinate. This can be a mobile or immobile. To determine how far a talk has propagated, each tile in the three tile radius needs to be queried. You can either use an equation to get xy coordinates for matching tiles, then build a list of each tile, or use a recursive technique to explore each adjacent tile with a decrementing radius count and a shared list of all tiles visited. Either works. When the list of tiles to notify is built. it is iterated across and each tile is examined to determine if the object contained by the tile accepts the talk event. The talk event is then dispatched to those talk event listeners and the event is complete. (Yes, there are other ways of doing this.) In a coordinate-based, sparse map system with cartesian coordinates (not tiled, but smooth), an event is given an origin, and boundary conditions are assigned. Only those objects that possess coordinates within that boundary are checked, and only those that accept the talk event receive the event notification. Assuming an optimized lookup of coordinates, this system is less CPU intensive, and certainly less expensive in memory requirements. This means that a significant portion of the libraries used by the rules engine in my design for a MUD are composed of map management (movement and collision detection, event propagation, map composition, and communication of modification to the client), This places a burden on the database interface (registry) to provide speedy, memory efficient map coordinate lookup (R-tree anyone?).
The database has a number of tables representing objects, classes and class heirarchies, class methods, class fields, instance field values, etc. The object registry is responsible for keeping track of which objects are currently in memory and which objects are not in memory. Updates to not-in memory object field values can take place by updating the database field (typically, this would occur over a network message). Updates to in-memory objects should occur in memory and are serialized when the object is removed from memory or checkpointed.
Changes to class definitions should propagate through in-memory and not-in memory objects on an asynchronous basis. This can make compiled, working code fail as fields change names or are removed, as well as remove methods that are allowed. These will throw an appropriate exception.
Note that object pointers kept by the registry (in-memory references) are different from object ids used to look up objects. Undecided yet is how the registry will allow aliased objects (literal strings that return object ids or references). Additionally, a synthetic object id is generated for unique objects in a network space (typically, ip or hostname concatenated to an object id).
Types are defined in the database with a table. Types are defined by a name which is hard coded into the engine (so types can be referenced independant of numeric identity field and databases can be moved safely).
The scripts used to create this database are available. They are intended for use with the MySQL database but should be able to be easily converted to another database. Note that no behaviors or constraints are defined beyond references to foreign keys, uniqueness, and null/not-null.
+--------------------+ | Tables_in_Scripted | +--------------------+ | t_access | | t_class | | t_field | | t_field_instance | | t_method | | t_method_arg | | t_object | | t_type | +--------------------+ describe t_access; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | access_id | tinyint(4) | | PRI | NULL | auto_increment | select,insert,update,references | | access | varchar(11) | | UNI | | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+
describe t_class; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | class_id | int(11) | | PRI | NULL | auto_increment | select,insert,update,references | | parent_id | int(11) | YES | MUL | NULL | | select,insert,update,references | | class | varchar(64) | | UNI | | | select,insert,update,references | | fertile | char(1) | | | | | select,insert,update,references | | final | char(1) | | | | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+
describe t_field; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | field_id | bigint(20) | | PRI | NULL | auto_increment | select,insert,update,references | | class_id | int(11) | | MUL | 0 | | select,insert,update,references | | type_id | tinyint(4) | | | 0 | | select,insert,update,references | | access_id | tinyint(4) | | | 0 | | select,insert,update,references | | name | varchar(64) | | | | | select,insert,update,references | | value | text | YES | | NULL | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+
describe t_field_instance; +-----------+------------+------+-----+---------+-------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+------------+------+-----+---------+-------+---------------------------------+ | field_id | bigint(20) | | MUL | 0 | | select,insert,update,references | | object_id | int(11) | | MUL | 0 | | select,insert,update,references | | value | text | YES | | NULL | | select,insert,update,references | +-----------+------------+------+-----+---------+-------+---------------------------------+ t_field Stores data for instances of a field. field_id The field_id from the t_field table. object_id The object_id from the t_object table. value The value of this instance of a field. describe t_method; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | method_id | int(11) | | PRI | NULL | auto_increment | select,insert,update,references | | class_id | int(11) | | MUL | 0 | | select,insert,update,references | | type_id | tinyint(4) | | | 0 | | select,insert,update,references | | access_id | tinyint(4) | | | 0 | | select,insert,update,references | | name | varchar(64) | | | | | select,insert,update,references | | code | text | YES | | NULL | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ t_method Describes a method defined on a class. method_id The method's identification field. class_id The class_id from the t_class table. The class on which the method is defined. type_id The type returned by the method. access_id The access type allowed by the method as defined in the t_access table. name The name of the method. code The actual method source code to be interpreted. describe t_method_arg; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | arg_id | bigint(20) | | PRI | NULL | auto_increment | select,insert,update,references | | method_id | int(11) | | MUL | 0 | | select,insert,update,references | | type_id | tinyint(4) | | | 0 | | select,insert,update,references | | name | varchar(64) | | | | | select,insert,update,references | | idx | tinyint(4) | | | 0 | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ t_method_arg The method argument definitions for a method. arg_id The identifier for the argument. method_id The method associated with this argument. type_id The argument type. name The argument name (variable name passed into the method). idx The argument order or index in the method call. Should not be duplicated for each method_id. describe t_object; +-----------+---------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+---------+------+-----+---------+----------------+---------------------------------+ | object_id | int(11) | | PRI | NULL | auto_increment | select,insert,update,references | | class_id | int(11) | | MUL | 0 | | select,insert,update,references | +-----------+---------+------+-----+---------+----------------+---------------------------------+ t_object An instance of a class. object_id The unique object id (persistent id). class_id The class of the object. describe t_object_alias; +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ | alias_id | int(11) | | PRI | NULL | auto_increment | select,insert,update,references | | object_id | int(11) | | MUL | 0 | | select,insert,update,references | | alias | varchar(64) | | UNI | | | select,insert,update,references | +-----------+-------------+------+-----+---------+----------------+---------------------------------+ t_object_alias Links object alias names ($object) to object ids. alias_id The alias id. object_id The associated object. alias The alias of the object. describe t_type; +---------+------------+------+-----+---------+----------------+---------------------------------+ | Field | Type | Null | Key | Default | Extra | Privileges | +---------+------------+------+-----+---------+----------------+---------------------------------+ | type_id | tinyint(4) | | PRI | NULL | auto_increment | select,insert,update,references | | type | varchar(9) | | UNI | | | select,insert,update,references | +---------+------------+------+-----+---------+----------------+---------------------------------+ t_type The types in the language. type The type name (token).
Lists are stored in a serialized form: {val, val, val}. Lists are recrusively serialized and deserialized.
select method_name, method_id, class_id from t_method where class_id in (select parent_id from t_class where class_id = parent_id or class_id = (select class_id from t_object where object_id=1) )Still not right.