// It's necessary to explicitly import the Python files that define
// the Python representation of the classes and structs named in this
// file.  (Implicitly importing these files turned out to be a bad
// idea.)

from direct.distributed import DistributedObject
from direct.distributed import DistributedNode
from game.avatar import AvatarObject
from game.avatar import DistributedObjectHolder

// All of the named modules are imported into a common Python
// namespace, which is then searched for each named dclass or struct.
// It is OK for a dclass to be named in this file that doesn't have a
// corresponding Python representation, but it is then an error to
// receive a generate message for one of these objects.


// A simple typedef provides a name and a semantic context to types.
typedef uint32 DoId;


// A dclass defines a collection of "methods" which may be called as
// network messages.
dclass DistributedObject {
  setColor(uint8 red, uint8 green, uint8 blue);

  // The uint8[] syntax replaces the old uint8array type.  All of the
  // old hard-coded array types are now deprecated in favor of C-style
  // array definitions.
  setPropertiesList(uint8 properties[]);
};


// You can also define C-style structs.  This is really the same thing
// as a dclass, except it can be embedded in a message rather than
// created as an object in its own right.  The struct may or may not
// correspond with a Python class of the same name.  If the struct
// does have a Python representation, an instance of that class is
// created and passed in to functions that receive this kind of
// parameter; otherwise, a tuple with all of the fields is passed
// instead.

struct AvatarObject {
  // Limits to numeric ranges may be specified within parentheses
  // following the typename.
  uint8(0-10) type;
  int16(0-999, 2000-2999, 5000-5199) roomId;

  // You can specify a default initial value in case the value is not
  // already defined at the time generate is called.
  int8 code = 0;

  // You can also define "methods" on a struct, just as on a dclass.
  // This implies the existence of the corresponding get method
  // (e.g. getObjectCode() in this case), to query the information at
  // generate time.
  setObjectCode(int8(0-50) code, DoId player);
};


// Single inheritance is supported, but not multiple inheritance.
dclass DistributedObjectHolder : DistributedObject {
  dropObject(AvatarObject object);

  // You can also have an array of structs.  This specifies a
  // fixed-length array of five elements.  This is slightly more
  // optimal than an array of unrestricted length, since the length
  // prefix need not be transmitted as part of the message.
  setObjectList(AvatarObject objectArray[5]);

  // In addition to fixed-length arrays and unbounded arrays, you can
  // specify a range for the valid size of the array:
  setRelatedObjects(AvatarObject relatedObjects[0, 3 - 5] = [])
};

// You can specify a default initial value on the typedef, if you
// like.  This will be overridden by a default initial value specified
// on the instance.
typedef uint8(0-25) DNAColor = 1;
  
struct AvatarDNA {
  // This defines a character element that can be any one of the three
  // specified.  (It is similar in form to the uint8 definitions
  // below, except that the legal values are ASCII characters instead
  // of numbers.)
  char('a','q','x') type;

  // These specify one-byte numeric elements that can be any of the
  // values in the specified ranges.
  uint8(0-10) torsoIndex;
  uint8(0-5) headIndex;
  uint8(0-4) legsIndex;

  // A switch can be used to define alternate versions of the data
  // according to some value read from the stream.  In this example,
  // the alternate cases are very similar, but they need not be
  // similar at all.
  switch (uint8 gender) {
  case 1:
    // Girl clothes
    uint8(0-35) shirtIndex;
    DNAColor shirtColor;
    uint8(0-25) skirtIndex;
    DNAColor skirtColor;

  case 0:
    // Boy clothes
    uint8(0-20) shirtIndex;
    DNAColor shirtColor;
    uint8(0-15) shortsIndex;
    DNAColor shortsColor;
  };

  // Nested structure references.
  DNAColor armColor;
  DNAColor headColor;
};


dclass DistributedAvatar {
  // An example of defining the default value for a complex nested
  // field, like the above.
  setDNA(AvatarDNA dna = {'a', 1, 2, 3, { 1, 0, 1, 0, 1 }, 1, 1 }) required broadcast db;
};
