Quote Originally Posted by technomage
I got the Indy Support Documentation, it was very helpful.

So is it a good idea to have this new engine use TCP to handle the initial handshakes/logins/important messages but to use UDP for messages that are very frequent :?:
Well, im not sure if its a good idea or not! There is a case for and against it. If i startched from scratch I would probably just go for UDP. This is my first attempt at network coding.

I did like the feature list of you AIR engine, especially the sync object stuff.

I have been thinking about how to make objects that automatically send changed data over the net to it's twin on the server. I did some tests using RTTI to serialize published properties to XML (binary would be better) and then rebuild the object from the serializer data, but I'm not sure if it would be as quick as a virtual merthods that is just overridden in the decendent classes.
I'm using virtual methods, I find from a coding point of view its quite easy. Plus there may be some data or complex logic you want to sync that isnt possible from a property. Also consider some objects might only have certain data that needs to be changed alot vs just on the initial sent. The position changes quite frequently but you only need to send the color (or whatever property) of it once.

For every object I put a Handle (unique integer) that is used for the clients to match obj with the server. If the client recieves a packet with a handle it doesnt know about, then the client requests a full update about that object. Thats a good way to make sure all your obj are being sent over UDP. I've avoided completely the sequential numbering of UDP packets and checking for out of order or missing packets, nor storing packet history on server, because basically take the assumption that any UDP data is not important because it may be overwritten by the next packet anyway. And if it isnt, the client will notice something fishy and request a new packet. Each object gets a time stamp from the last server update, plus a change counter. If the object has Changed and the time stamp is getting old, then the object is changing on the client improperly (although we do want to make sure the obj can change for prediction purposes), so the client again asks for a resync via the obj handle. This happens alot if you bump into a stack of boxes or some other unpredictable physics circumstance. I'm not sure what kind of network you want, but with 3d realtime physics this is the way I went to sync it.

Big drawback if you use virtual methods then you are restricting because your users have to inherit from your code (and there is no multiple inheritance in OOP)

heres an outline of the network stuff in AIR:
Code:
AIRSyncObject = Class(AIRObject)
private
  fSyncStamp: integer;
  fChange: integer;
  fPredictable: boolean;
  fExtraChanges: string;
protected
  function GetChanged: boolean;
public
  Constructor Create; override;
  Destructor Destroy; override;

  // time of last sync (for client/server synchronizing)
  property SyncStamp: integer read fSyncStamp write fSyncStamp;
  // changes?
  property Change: integer read fChange write fChange;
  // changed<>0
  property Changed&#58; boolean read GetChanged;
  // extra change info for packets
  property ExtraChanges&#58; string read fExtraChanges write fExtraChanges;
  // is this client-side predictable? &#40;wont send updates if true&#41;
  property Predictable&#58; boolean read fPredictable write fPredictable;
  // returns true if the engine should network this &#40;default&#41;,
  // false if not ... such as smoke effects, menus, etc
  function  Networked&#58; boolean; virtual;
  // network
  function  FullPacketOut&#58; string; virtual;
  procedure FullPacketIn&#40;const Packet&#58; TStrings&#41;; virtual;
  function  ChangedPacketOut&#58; string; virtual;
  procedure ChangedPacketIn&#40;const Packet&#58; TStrings&#41;; virtual;
  // change data
  procedure ChangeIncrease; overload;
  procedure ChangeIncrease&#40;aAmount&#58; integer&#41;; overload;
  procedure ChangeIncreaseMax;
  procedure ExtraChange&#40;const ExtraMsg&#58; string&#41;;
end;
hope that gives u some ideas.