nel-all
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nel] Game Object Models


From: John Hayes
Subject: [Nel] Game Object Models
Date: Mon, 21 Jan 2002 18:47:30 -0500

I read through the archive of the NeL library and found it interesting
because I'm working on my own project and mostly focusing on areas where
NeL is silent.

In the source code, mailing list and documentation - I couldn't find any
references to an application object model or persistence, and these are
pretty big components. It is also the core mechanism for automating
database storage, the network protocol, marshalling and transaction
integrity.

I'll give an example about how the object model relates to the network
protocol:

There was a great deal of discussion about TCP vs. UDP and assuming you
want some form of reliability, UDP gives you control over the frequency
and conditions for retransmission. In terms of server resources,
successful packet transmission time, bandwidth use - they're probably
pretty close (with Nagle Algorithm disabled), and if these were the only
factors you couldn't justify the added complexity.

The problem is TCP is substantially slower for retransmission because it
uses a fairly lazy algorithm to ask for retransmission - it waits a bit
before asking again for a packet. Because there's a connection to make,
timing out and reconnecting is very slow ... like a minute - and the
whole game is halted in the meantime because TCP enforces ordering
despite whatever application level dependencies exist.

Ok, so no TCP, UDP is great but you don't want to reimplement TCP all
over again - reliability is good but you want the minimum number of
packet dependencies (loose ordering so the game doesn't stall) and the
minimum amount of retransmission (discard what you no longer care about)
but conflicting goal of a minimum amount of latency for retransmission
when it's required.

So - what kind of rules can we make up for this? Network messages from
the server to the client have two functions - updating state and
"one-shot" actions (which is really a special case of updating state).

If a character is running along, they have a running state and a
position state that are continually updated. They may also have internal
states like their "tiredness", "hunger" which may be related from the
game logic's POV, but not the client - assuming the client is rather
dumb, or applies simple algorithms like dead-reckoning until it gets an
authoritative update from the server.

Now the packet example, in this and all examples - all failed packet
transmissions (lost, malformed) are considered equal.

Update Position v1
Update Position v2 (lost)
Update Position v3

If the client receives v3, it doesn't care if v2 is lost - for
frequently updating fields, no need for retransmission.

Update Position v1 (lost)
Update Tiredness v1

The client can process the Tiredness packet because it's on a different
"stream" from the position - it may ask for position to be
retransmitted.

Update Position v2
Update Position v1

The second packet is ignored because the client already has a newer
version of the state.

Now this is all very application specific (as was argued on the mailing
list). But software can be pretty good at figuring this stuff out when
given a little metadata to work with, and this is where the object model
steps in.

You have an object model, and you want to replicate part of this object
model to the client, and you want to replicate another part of the
object model to all clients that can "see" your object.

The tricky part can be the granularity for these replications, doing the
entire object at once is very easy and requires no more server state
than a "version flag" but uses a tons of bandwidth - replicating a
single field is very efficient from a bandwidth POV but requires more
server state to manage. A practical system would have property groups
which are considered to be likely to change at the same interval.

---

Here's one possible design for a system to perform this kind of
tracking:

Each object has a version number and everything that attaches has a
dirty mask of which fields are out of date. As an object changes - it
broadcasts the aggregate of fields that changed during a transaction to
each of the listeners, if it matches their listen mask, they get an
update and the object version increments.

The listener transmits all of the fields in the dirty mask to the
client. Client responds which version and which fields are up to date
and if the version hasn't incremented the server clears the dirty mask.
The server could keep a history of which dirty masks applied to which
versions to keep from pathologically retransmitting fields which haven't
changed.

An object model can also serve to tune such a protocol. First by
packaging fields together into mask bits and second by setting times for
each mask bit when the client might get suspicious. If the client is
expected to have the latest data but the latest data may be dropped, how
long should the server wait before retransmitting any given data? If
it's something interactive - not very long, something that's slowly
updated, it should give a reasonably long wait.

I'd hate to be encoding rules like these in source code and it probably
wouldn't be practical in the end anyways.

---

I'm currently working on an object model with these kinds of
capabilities - the major attraction to me is it allows other activities
like network data and persistence to be decoupled from the application.

Right now, it builds the database tables, queries, and C++ classes
(opaque in-memory layout, no code generation) from an XML file like this
extract:

<schema>
        <class name="Entity">
                <field name="template" type="int"/>
                <field name="aspects" type="binary" length="16"/>
                <field name="behavior" type="int"/>
                <field name="name" type="string" length="16"/>
                <field name="children" type="ownsmany" related="Entity"
inverse="parent"/>
                <field name="parent" type="ownsmany" related="Entity"
inverse="children"/>
        </class>
</schema>

---

This is a lot at once, but I'm hoping to stir up some conversation :-)

John
- These aren't the thoughts you're looking for


reply via email to

[Prev in Thread] Current Thread [Next in Thread]