Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2001:
[Freeciv-Dev] Re: [RFC] Attaching information to objects
Home

[Freeciv-Dev] Re: [RFC] Attaching information to objects

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Brian Olson <locke@xxxxxxx>
Cc: Freeciv Development List <freeciv-dev@xxxxxxxxxxx>
Subject: [Freeciv-Dev] Re: [RFC] Attaching information to objects
From: Raimar Falke <hawk@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 13 Jan 2001 22:19:36 +0100
Reply-to: rf13@xxxxxxxxxxxxxxxxxxxxxxxx

On Sat, Jan 13, 2001 at 01:08:51PM -0700, Brian Olson wrote:
>     int {tile,player,city,unit}_get_attrib(int id, int key, int max_length, 
> char *data);
>     void {tile,player,city,unit}_set_attrib(int id, int key, int max_length, 
> char *data);
> 
> On Saturday, January 13, 2001, at 12:05 PM, Raimar Falke wrote:
> 
> > Maybe I also misunderstood you. Suppose we have an bodyguard agent and 
> > a auto-settler agent.  So both agents will allocate a key for the 
> > object type "unit". This could be done in an enum. So there will be 
> > SK_U_AUTO_SETTLER and SK_U_BODYGUARD. On an "classic" settler no key 
> > is set. On a bodyguarded auto-settle settler both keys will be 
> > set. And it may be possible that the value length grows at runtime 
> > (settler received another job).
> 
> I think this scenario entails something like the following:
> unit_set_attrib( settlerID, taskKey, sizeof(autoSettlerCommand), 
> anAutoSettlerCommand );
> /* where there are many struct *Command that begin with struct aCommand { 
> enum commandType{...}; ...}; */
> /* this autoSettlerCommand contains parameters about road/irrigation/etc 
> priorities */
> unit_set_attrib( guardID, taskKey, sizeof(bodyguardCommand), 
> aBodyguardCommand );
> /* the bodyguardCommand refers by id to settlerID */

IMO it should be:
unit_set_attrib( unit_id, SK_U_AUTO_SETTLER, sizeof(autoSettlerData), 
anAutoSettlerData);
unit_set_attrib( unit_id, SK_U_BODYGUARD, sizeof(bodyguardData), 
aBodyguardData);

Each agent can choose struct *Data freely. Only the agent can
interpret the bytestream.

> OR, does it maybe mean:
> unit_set_attrib( settlerID, roadKey, N, N*2 road coords to build );
> unit_set_attrib( settlerID, irrigateKey, N, N*2 tiles to irregate );
> etc
> unit_set_attrib( guardID, guardKey, sizeof(settlerID), &settlerID );

If the amount of data an agent wants to attach changes the agent can:
 - allocate more keys (not at runtime). There may be
   SK_U_AUTO_SETTLER_FEATURE_1 and SK_U_AUTO_SETTLER_FEATURE_2 for
   example.
 - enlarge the data. Problem: structs doesn't grow
 - always use the maximum amount and have some field unused. No
   problems with structs.

> All this of course dependant on being interpreted elsewhere by the script/AI 
> in question
> 
> > So there is no easy way to map between 
> > values and offset into the monolithic block except reserve the maximum 
> > value length in the block. Think about an efficent communication with 
> > the server. Regardless what I said above I looks like I now dislike 
> > the block idea. 
> 
> I don't think that consequence is entailed. The block I speak of is
> not the active data structure within the client, but a serialized
> version of the same that is ready for transmission and storage. I
> just want to keep complexity out of the server and in the client
> (and keep packet count low). And by keeping the complexity of
> knowing how to serialize this extra data in the client, if some day
> hashes are out and trees are in, the server need not know or change.

AFAIK there are no variable length packets so a transfer between
server and client is limited.

Say we have a compound key consiting of <object type, id, subkey>. And
there are values of variable length up to a maximum.

key1:1111111111111111111111
key2:222
key3:3
key4:444444444444444444444444444

The numbers denote the values. I know of two ways to map <key, value>s
into a block:
 - put them all together:
    key1:1111111111111111111111 key2:222 key3:3 key4:444444444444444444444444444
    There are problems if one values grows. It preserves space and bandwidth.
    At restarting time you have to find all keys.
 - pad them up to the maximum
    key1:1111111111111111111111ppppp
    key2:222pppppppppppppppppppppppp
    key3:3pppppppppppppppppppppppppp
    key4:444444444444444444444444444
    Values can grow. Needs extra space.

To reduce packet count you have to fill the packets. Something like
scather/gather(sp?) is needed to enable the client to
request/overwrite more than one continuous region of the block.

To reduce code on the server side what about this:
 - the client will contruct an compound keys like mention above
 - the server will load/store based on such key-value pairs. So there
   is only one hash per player. If you think this is to much you can
   reduce this to one hash by prefixing the key with the player-id.
Now the client is much more easy to code.

> The data only needs to be moved to the server at game save times. If
> the client crashes, is enlisting the server the right way to
> compensate? Why can't the client save it's extra data in a temporary
> file it may reload? If the connection is lost and reestablished, the
> client of course needs to get current game state, but does it _need_
> to be told what it's last auxiliary data was? Might a local file be
> the answer here too? I think really only at game-restore time does
> the server need to tell the client what it's aux data is.

I just don't like the idea. This would complicate the client (which of
the data is newer,...).

        Raimar

-- 
 email: rf13@xxxxxxxxxxxxxxxxx
  This customer comes into the computer store. "I'm looking for a mystery
  Adventure Game with lots of graphics. You know, something realy
  challenging". "Well," replied the clerk, "have you tried Windows 98 ?"



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