Author Topic: chop, chop, chop (network code)  (Read 15478 times)

daniel.santos

  • Guest
chop, chop, chop (network code)
« on: 19 December 2008, 11:46:50 »
I'm chopping up the networking code now, so I wont have an 0.2.11a.  Instead, I'm going to try to bring a number of things in line that I've wanted to do for some time and it's appearing as though its also the best way to achieve the desired results.  I will post again when I have something to test.  I'll also try to get a post out that outlines the new networking classes architecture for those technically interested.

In short, it will be hybrid client-server/peer-to-peer, support network game pause and speed change (after agreement from all players), and each network connection will have it's own thread to receive data and use IPC to notify other (interested) threads when that data is ready.  Unfortunately, I'll have to have a thread for each network connection (which really isn't all that bad).  It's very technically possible to do this with just one thread (::WaitForMultipleObjects() on windows and select() or pselect() on linux), but that would require me to implement pthread support in all of the Glest threading classes -- actually, that's only if I want t have a thread be able to wait on either I/O or an IPC eventm, so SCRATCH THAT! ... Take Two:  I would have to modify the Socket class to be able to use select() (linux) or WaitForMultipleObjects() (windows) to support that -- hah! I'm glad I wrote this post because I overlooked that (my earlier design was going to use thread conditions for inter-thread signalling).

Either way, one thing is should provide is less lag and a better game synchronization.  Also, the peer-to-peer support is optional, so if two clients can't talk to each other (i.e., firewall or routing issues), but they can both talk to the server, the server will transparently relay events as it does now.  This will also set the stage for supporting the ability for other clients to take over as server should the server drop.

I already did a pretty big re-write of the network messaging layer, and that's going largely unchanged (except to add support for exchanging status data better).

EDIT: Oh yea, and one more thing.  I think this game really needs UDP support.  So if anybody out there is in the mood to examine how the messaging layer works and is good ad UDP-based protocols, please knock yourself out.  I'm actually good at it myself, but it's a time issue.  We would also probably have to modify the NetworkMessage classes to specify an importance, so some packets would need to be delivered, need to be in order and arrive within X time, while others can be out or order and get dropped and it's no big deal (obviously, corrupt is never ok and UDP's checksum is too small to be reliable, so our own checksum would need to be tagged on as well).

hailstone

  • Local Moderator
  • Battle Machine
  • ********
  • Posts: 1,568
    • View Profile
Re: chop, chop, chop (network code)
« Reply #1 on: 20 December 2008, 04:07:53 »
Sounds good. I'm planning on doing  "Internet Protocols And Services" unit in the first semester so I could look into it when I'm finished with the GUI, if you haven't done it yourself by then.
Glest Advanced Engine - Admin/Programmer
https://sourceforge.net/projects/glestae/

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #2 on: 20 December 2008, 09:01:06 »

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #3 on: 20 December 2008, 09:34:25 »
hah! I said it was a work in progress and I already changed the states.  I realized that it wont ever allow you to be in progress of changing both pause and speed states at the same time, so we don't need them separate.  So here are the new states
Code: [Select]
enum State {
STATE_UNCONNECTED, // not yet connected
STATE_LISTENING, // not yet connected, but listening for connections
STATE_CONNECTED, // established a connection and sent (or sending) handshake
STATE_INTRODUCED, // handshake completed
STATE_READY, // ready to start the game
STATE_LAUNCHING, // starting game
STATE_PLAY, // game started (normal play state)
STATE_PAUSED, // game paused
STATE_QUIT, // quit game requested/initiated
STATE_END, // game terminated

STATE_COUNT
};

enum ParamChange { // T - target frame required or not
PARAM_CHANGE_NONE, // n - no pending state changes
PARAM_CHANGE_REQUESTED, // y - state change requested
PARAM_CHANGE_REQ_ACK, // y - pause request acknowledged
PARAM_CHANGE_REQ_ACCEPTED, // y - pause request accepted
PARAM_CHANGE_REQ_DENIED, // y - pause request denied
PARAM_CHANGE_COMMITED, // n - state change committed (paused, unpaused, speed changed, etc.)

PARAM_CHANGE_COUNT
};
enum GameParam {
GAME_PARAM_NONE,
GAME_PARAM_PAUSED,
GAME_PARAM_UNPAUSED,
GAME_PARAM_SPEED,

GAME_PARAM_COUNT
};
So now ParamChange is used to pause, unpause and change speed where GameParam will specify which parameter of the game is being changed (new target speed specified separately).  Also, this doesn't mean that there always has to be approval, for instance, when you start the game you may specify that anybody can pause the game without confirmation, but speed changes require confirmation.  You may also have speed changes only take effect 10 seconds after requested so there's time to warn everybody about the impending change.

If it's not too much work, I may add a mechanism to replace dropped connections with an Ai and also to allow dropped players to re-connect, although it will probably require forcing a pause (at least, it will be easiest to implement that way. :) )  I eventually want it to be something that players in a lobby (maybe spring lobby?) can browse games and there be a game they can join at any time, even though it's already started.  I'm not in a hurry there though.

wciow

  • Behemoth
  • *******
  • Posts: 968
    • View Profile
Re: chop, chop, chop (network code)
« Reply #4 on: 20 December 2008, 10:27:50 »
Argh my brain just melted!  :mrgreen:

Seriously though I'm sure its gonna be awesome!

p.s I'm off to make a smiley of a brain melting.
Check out my new Goblin faction - https://forum.megaglest.org/index.php?topic=9658.0

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #5 on: 20 December 2008, 12:38:42 »
lol!! Sorry, it was really intended more for hailstone and other C++/OO experienced people who would be interested :)

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #6 on: 21 December 2008, 01:14:23 »
:lol:

Hi,
please explain me the following situation i didn't get how it will work:
We have two clients and one server. client are called C1 and C2 server is called S.
Everyone can reach each other ( so no routing is needed )
If C1 wants to execute a command he sends it directly to S and C2.
This command mus be executed with the next keyframe( or when? ).
But what happens if the command transmission needs too long to reach C2, but it reaches S in time?
The command will be executed on S and C1 but not on C2 in the same key frame.
How does C2 know that he has to wait for a command when he reaches the keyframe?

In the current implementation C2 knows that he has to wait for command from the server because he gets a command(probably empty one) for every keyframe. So C2 knows, he has to wait when he reaches a key frame without getting a command from the server.

How will this work in the new implementation?
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

hailstone

  • Local Moderator
  • Battle Machine
  • ********
  • Posts: 1,568
    • View Profile
Re: chop, chop, chop (network code)
« Reply #7 on: 22 December 2008, 06:26:07 »
I think this is how it works.

frameUpdateBegin is called to specify which frame is being referred to, messages such as commands are sent, then frameUpdateEnd is called to say that information for a frame has ended.

Is there a distinction made between a game host (the creator of the game) and a network host?
Glest Advanced Engine - Admin/Programmer
https://sourceforge.net/projects/glestae/

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #8 on: 22 December 2008, 07:56:23 »
hurray for titi!  I spent 20 minutes typing a response and then I learned some things from your question.

So first off, hailstone has it pretty close.  Actually, frameUpdateBegin() and frameUpdateEnd() (for the network interface classes) are called before and after the "world" is updated.  The only reason there are two calls is to mark the beginning of the frame (tell the ClientInterface or ServerInterface what the new frame is ) and do any pre-world update calculations and then the frameUpdateEnd() to tell the network layer to send (any) data queued up while updating the world.  I want it to get sent at the end of updating the world so that it will be smaller (less packets means less headers and other overhead, plus if we're compressing the data, you get better compression ratios when compressing larger amounts of data).

But the short answer to titi's question, as it stands now is that I don't care about key frames anymore and I just send commands to everybody as soon as they are issued.  More precisely, C1 would send the new command to both S and C2, S would know not to relay the command to C2 and both would process the command as soon as they received it (no matter which frame it was).  However, I have a better idea now.

Before I go into that, the new class NetworkMessageStatus is used to transmit status changes between clients, servers and peers and is also the base class for many other messages (intro, ready, launch, command list, etc.).  It's one of those bit mangeling classes, so let me just post it's current code (which is sure to change further).  Note that the term "peer" is generic and can refer to any remote relationship (server to client, client to server or client to client)
Code: [Select]
class NetworkMessageStatus : public NetworkMessage {
    enum DataMasks {
        DATA_MASK_SOURCE            = 0x0000000fu,
        DATA_MASK_STATE             = 0x000000f0u,
        DATA_MASK_PARAM_CHANGE      = 0x00000700u,
        DATA_MASK_GAME_PARAM        = 0x00001800u,
        DATA_MASK_GAME_SPEED        = 0x0000e000u,
        DATA_MASK_HAS_FRAME         = 0x00010000u,
        DATA_MASK_HAS_TARGET_FRAME  = 0x00020000u,
        DATA_MASK_FRAME_IS_16_BITS  = 0x00040000u
    };

    uint8 connections;  /** bitmask of peers to whom a connection is established */
    uint32 data;        /** contains various data packed into 32 bits */
    uint32 frame;       /** (optional) the current frame at the time this message was generated */
    uint32 targetFrame; /** (optional) the frame that actions specified in this packet are intended for */

public:
    NetworkMessageStatus(NetworkDataBuffer &buf, NetworkMessageType type = NMT_STATUS);
    NetworkMessageStatus(const Host &host, NetworkMessageType type = NMT_STATUS,
            bool includeFrame = true, GameSpeed speed = GAME_SPEED_NORMAL, uint32 targetFrame = 0);
    virtual ~NetworkMessageStatus();

    uint8 getConnections() const        {return connections;}
    bool isConnected(size_t i) const    {assert(i < GameConstants::maxPlayers); return connections & (1 << i);}
    uint32 getData() const              {return data;}
    uint8 getSource() const             {return static_cast<uint8>       (data & DATA_MASK_SOURCE);}
    State getState() const              {return static_cast<State>      ((data & DATA_MASK_STATE) >> 4);}
    ParamChange getParamChange() const  {return static_cast<ParamChange>((data & DATA_MASK_PARAM_CHANGE) >> 8);}
    GameParam getGameParam() const      {return static_cast<GameParam>  ((data & DATA_MASK_GAME_PARAM) >> 11);}
    GameSpeed getGameSpeed() const      {return static_cast<GameSpeed>  ((data & DATA_MASK_GAME_SPEED) >> 13) ;}
    bool isResumeSaved() const          {return static_cast<bool>        (data & DATA_MASK_IS_RESUME);}
    bool hasFrame() const               {return static_cast<bool>        (data & DATA_MASK_HAS_FRAME);}
    bool hasTargetFrame() const         {return static_cast<bool>        (data & DATA_MASK_HAS_TARGET_FRAME);}
    uint32 getFrame() const             {return frame;}
    uint32 getTargetFrame() const       {return targetFrame;}

    virtual size_t getNetSize() const;
    virtual size_t getMaxNetSize() const;
    virtual void read(NetworkDataBuffer &buf);
    virtual void write(NetworkDataBuffer &buf) const;
   
protected:
    void init(const Host &host);
   
    void setConnection(size_t i, bool value) {
        assert(i < GameConstants::maxPlayers);
        uint8 mask = 1 << i;
        data = value ? data | mask : data & ~mask;
    }

    void setConnection(size_t i) {
        assert(i < GameConstants::maxPlayers);
        data = data | 1 << i;
    }

    void setConnections(bool *values) {
        connections = 0;
        for(size_t i = 0; i < GameConstants::maxPlayers; ++i) {
            if(values[i]) {
                data = data | 1 << i;
            }
        }
    }

    void setSource(uint8 value) {
        assert(value < GameConstants::maxPlayers);
        data = (data & ~DATA_MASK_SOURCE) | value;
    }

    void setState(State value) {
        assert(value < STATE_COUNT);
        data = (data & ~DATA_MASK_STATE) | (value << 4);
    }

    void setParamChange(ParamChange value) {
        assert(value < PARAM_CHANGE_COUNT);
        data = (data & ~DATA_MASK_PARAM_CHANGE) | (value << 8);
    }

    void setGameParam(GameParam value) {
        assert(value < GAME_PARAM_COUNT);
        data = (data & ~DATA_MASK_GAME_PARAM) | (value << 11);
    }

    void setGameSpeed(GameSpeed value) {
        assert(value < GAME_SPEED_COUNT);
        data = (data & ~DATA_MASK_GAME_SPEED) | (value << 13);
    }

    void setResumeSaved(bool value) {
        data = value ? data | DATA_MASK_IS_RESUME : data & ~DATA_MASK_IS_RESUME;
    }
   
    void setFrame(uint32 frame) {
        data = data | DATA_MASK_HAS_FRAME;
        this->frame = frame;
    }

    void setTargetFrame(uint32 targetFrame) {
        data = data | DATA_MASK_HAS_TARGET_FRAME;
        this->targetFrame = targetFrame;
    }
};

So this class conveys a lot of status information and packs it down into a maxiumum of 13 bytes.  Using other techniques, I can get this thing down to 5 bytes max, but this is good enough for now.  The connections byte specifies a bit mask of each peer that the originator of this message is connected to.  The data section uses 4 bits to specify the originator.  This isn't usually necessary because that information can be learned from the socket it comes in on its self, but it may be relayed from the server, so that way a client can know the update of the status of one of it's peers that it may not be able to communicate directly with.  But most importantly, there is a frame and targetFrame.

The targetFrame was originally intended to coordinate pause and speed change requests so that it could all happen at the same time on every participant in the game.  It occurred to me that a game could be kept better in sync if commands were not executed immediately on the local machine.  Instead, they could be given a target frame in the future and queued up locally and on the peers so that the command will (ideally) be executed at the same time on every machine.  By having this behavior on the server as well, it should cancel out the "home field advantage" (i.e., being the server wont have any advantage).

This does not go for auto-commands by the way, these are always executed locally and are not transmitted at all because it's presumed that (as long as the data is the same on each machine) they can each figure these out on their own.  Perhaps it would be helpful to transmit these however so the server can verify that an auto-command being executed on a client is accurate and be able to correct a client if needed.  As an example, if a client thinks his unit is close enough to see an enemy unit and attack it but on the server, they are one cell off (not an unlikely condition), the server can send correcting information to update both the unit that attempted to execute the auto command and the unit it thought it saw.  It may look funny because the unit would start to attack but then warp back though, but that hopefully shouldn't take long (maybe 400 milliseconds).

As a side note on the NetworkMessageStatus class, it can still be trimmed down a lot.  I'm not using the DATA_MASK_FRAME_IS_16_BITS field and I can also cram part of the frame bits into the unused portion of the data field and only use extra bytes for frame.  Also, I can have one message that sends the full frame as a 32 bit number but is only sent when the top 24 bits change.  The rest of the time, it can transmit only the lower 8 bits of the frame number.  Perhaps even better, I can use part of the data to specify how many bytes of the frame and target frame I'm sending and the upper portion will be recycled from the previous update.  I wont mess with that until after all of these other issues are resolved, but there's a lot that can be done in very few bits.

Also, one thing that is changing is the way clients wait for a laggy server.  At present, if a client hasn't received an update from the server for a key frame, the client stops rendering, updating sound, etc., it essentially suspends the main thread until that is received or a max wait timeout has expired.  Now, it will behave as though it's paused, so rendering continues, the mouse cursor continues to move around, sounds don't stop and you can still issue commands, etc.  You may have never experienced this before unless you play a game where the server is very slow (like when you compile a debug build and you're debugging it with millions of sanity checks running a second :) ), but it's a pain to deal with.  I have some other ideas for ways to address this that I'll worry about once this networking rework is done.

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #9 on: 22 December 2008, 21:49:00 »
ok, I think i got it now but I'm not really shure if it will work.
Every client plays its own local game, influenced by commands and updates it gets from outside. You are no longer trying to keep the games of the clients in sync.
I think this will cause jumping units with nearly every update. Even after an update command which was sent from the server to the clients the currently units will not be in sync, because the update commands delay( network ) is different for every client !
By this you will play a whole game out of sync with nearly every unit, only hold together by server updates.
A typical problem this will cause:
You see one of your units next to a line of trees in the west. Now you give a command to walk to the west and your plan is to have your units noth of this line of trees. But when your command is executed on the server the unit is a bit more south of the tree line, so it will walk south of the tree line. Now if the updates for this unit arrives your client, suddenly you see your unit in the south of the tree line, not in the north as you want it. this will be something very annoying for players, because their commands are not executed the way they wanted/planned it.

But I must admit that this asyncronous implementation is very very complicated to understand( and to debug!!) and I probably didn't get it right now.
I must say that I would still prefer an improved version of the original way it was done.
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
IDEA!
« Reply #10 on: 26 December 2008, 10:17:40 »
IDEA!!!

What about this:

- Commands are bound to key frames.
- Clients don't wait for commands which doesn't reach them
- All Clients(including the server) have a rollback system, so they can rollback and execute commands in the past which reach them too late.

More excatly:
Before executing the commands in a keyframe you copy all current unit states into a list.
Now you store the commands that will be executed with this unit list.
Unit list and command list are your state for this key Frame.
After storing the state you execute the commands of this state.
This is done for every keyframe and let's say the last 10 keyframes are stored this way.

What happens if some commands reaches the client which were meant for an old keyframe?
Add the old commands to the command lists of the keyframes for which they where meant. .
Now restore the keyframe state of the oldest command and playback the whole game up to the current frame.
Now everything should be fine again.

If you are reached by a command which is meant for a keyFrame which is no longer in the rollback list, the game is really out of sync and you can stop with an error message or something else ( full update from server for example ).

By this you will get no more "waiting for server" lag and you can play with very bad conections without getting too much trouble.
BUT: This will probably very cpu/memory intensive ?

A problem that will be there are the update commands which are send by the server. These update commands are based on the servers state, which must not be correct because he doesn't has all information yet if you don't run a full server client concept. So I would prefer this client server concept because the server is always up to date.

What do you think of this?
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

hailstone

  • Local Moderator
  • Battle Machine
  • ********
  • Posts: 1,568
    • View Profile
Re: chop, chop, chop (network code)
« Reply #11 on: 29 December 2008, 02:01:03 »
I like the rollback idea. Would need checkpoints, like you said, so it doesn't redo the whole lot. It might have performance problems - think of how many transactions go into a database for a bank which would use such a system.
Glest Advanced Engine - Admin/Programmer
https://sourceforge.net/projects/glestae/

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #12 on: 29 December 2008, 10:13:44 »
titi, thanks for the input.  The idea of being able to rollback a command sounds good in some ways, but it also sounds very tedious to code and can have fairly significant CPU overhead (probably not much memory overhead though).  I say "can" have because commands aren't sent all that often, so it shouldn't be too much of a load.  None the less, it will still be a LOT of code to implement.

I think a better idea may be to use the "targetFrame" but have the lead time on commands vary according to the max lag being experienced in the game.  That way, if a server gets a command late, it can (maybe) fast-forward the command and send updates to peers, but re-adjust the min lead time for the targetFrame of newly issued commands.

As far as key frames, I'm completely eliminating them except for using them to force clients to wait for the server and visa-versa when a client gets too far behind (maybe 1 second or so).

So right now, every command issued will be given a targetFrame, even locally. So if I'm a client on frame 421 and I want to tell my guys to walk somewhere, I send the command and queue it up locally to occur on frame 431 (for instance), a 10 frame lead time (or 250 mS).  Since I'm also sending to peers, they should get it in time as well.  Then, when I reach frame 431, it comes out of the command queue.

I think that most of the units jumping around that you've seen is due to the problem with the server not sending its commands!! :O  I'm also going to change updates so that instead of units instantly appearing at their new location when an update is received, they will warp there over a period of 200-ish milliseconds so it's a little easier to see what's happening.  Alternately, I may figure out a way to cause them to move to their updated location more casually (very fast walking for instance).

Either way, I have a lot of re-assembling (of the code) to do.  Adding a networking thread will actually improve many characteristics of network play because the thread is only there to deal with net communications and I've done a LOT of multithreaded programming in my life (13-ish years?)  Also, I just added a condition/event class to make synchronization more fun in addition to a wait() function in Socket that allows you specify multiple sockets to wait on -- that way you can use non-blocking socket calls, but keep your thread asleep until there's really something to do.  This reduces CPU while allowing the most optimal response times to I/O (and only requires one extra thread).  In addition, when the network thread receives data, it notifies the main thread so no more polling is needed (GameInteface::onReceive()).

I'll post an updated class diagram when I get home.

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #13 on: 29 December 2008, 22:12:02 »
Is it really so hard to implement this rollback system?

To create a "checkpoint" you ?simply? have to clone the list of units(deep clone).
and add the list of commands which are sent by the server (or do you need a clone of them too? ) .
Thats all you need to have a checkpoint.

Now for a rollback:
1. remove all units from the current unit list.
2. add all units from the checkpoints list
now you should have the state of the old checkpoint.

The thing I don't really know is how to fast forward gamesplay  back to the current frame.
Isn't there something like this "fast forward" already implemented in glest?
Or is this the point where the things get complicated?
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

hailstone

  • Local Moderator
  • Battle Machine
  • ********
  • Posts: 1,568
    • View Profile
Re: chop, chop, chop (network code)
« Reply #14 on: 1 January 2009, 12:29:55 »
Some interesting articles on multiplayer programming:
http://www.gamasutra.com/view/feature/3 ... g_for_.php
http://www.gamasutra.com/view/feature/3 ... r_math.php

@titi:
It seems like you are talking about period saving with loading latest save when out of sync rather than a transaction style rollback system.
Glest Advanced Engine - Admin/Programmer
https://sourceforge.net/projects/glestae/

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #15 on: 1 January 2009, 19:10:20 »
I will think about the articles, probabaly there is something useful in them I will study them...

For my idea:
I'm not talking about transactions based on every command like its possible in databases for example. In my idea the checkpoints to which you can rollback are made by hand ( and there is more than one checkpoint, I talked about 10 of them! ).
If you say "begin Transaction" in a database system a "checkpoint" is made to which you can return with a rollback. In a database system it's in fact not a copy of the whole state, but it has the same effect. Most database systems log all changes made until a commit is made, but this is useless for glest, because you cannot log all changes(movements of units and so on).

But I'm definitly NOT talking about periodical savings. I talked about some kind of rollbacks to execute commands which didn't reach you in time.
This is especially interisting when you use UDP instead of TCP for communication which doesn't guarantee that messages arrive.
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

Ayrin Greenflag

  • Horseman
  • ****
  • Posts: 188
    • View Profile
    • http://www.lostinn.com/ayrin
Re: chop, chop, chop (network code)
« Reply #16 on: 6 January 2009, 11:42:27 »
don't know if it could be useful ... i remember the old diablo network game that has some kind of jump coz of lag (56k connection) you was walking and suddenly a monster appairs and hit you...or you suddenly jump back coz you was hitten...i think they used a kind of sync check between server and clients if it doesn't match server information overhead clients ones.
Pretty annoying with lag but worked pretty good in other cases.

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #17 on: 7 January 2009, 10:39:52 »
I don't think I'll be pursuing a transactional mechanism at this time, although I do intend to enhance the "fast forward" mechanism.  Currently, when a command packet arrives late or an update arrives, the unit's state can be fast forwarded, but only to the point of finishing the current cycle of the skill they are on (or that is specified in the update).  I'll be expanding this so that it can complete an iteration of a skill.  But for now, I believe that adding a command delay should be sufficient to solve most of these issues.  The initial value will be 250 milliseconds (10 world frames), but the server will adjust this as needed based upon ping times, I'm figuring making it the average ping time plus 2 world frames (50 milliseconds).  This has the added benefit of removing some of the advantage that the player on the server would otherwise have, because everybody's commands will get executed at the same time (in theory).

If a command does arrive late, I can issue the command to the unit and then tell it to fast forward execution by however late it was and that will solve most of the problems associated with late arrival.  It will not solve problems of the units being located in the wrong cell however (for instance, if they were walking and you issued a stop command that arrived too late).  None the less, when a late condition is detected, an update can also be sent from the server (or requested by a client) for the effected units.

I'm home now, so I'm back on Linux, hurray!  I'll redo the UML class diagram with the current design tomorrow or friday and post it for your viewing pleasure.  But it's coming along, but it's a lot of rework (I'm mostly finished at this point).

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #18 on: 7 January 2009, 16:00:43 »
Adjustable keyframe times based on server pings are a good idea!
I think this will make the game more stable and I can play with someone from america ( pings from 300ms up to 600ms ).
I would not lower the keyframes under 250 ms. I think 250 ms is the current value and it works quite OK.

I hope it will work, but I see lots of problems with your asyncronous way of playing the game. I fear it will result in an update orgy after a while.
But probably I'm wrong, I will help you where I can (tests ... :) ).
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #19 on: 29 January 2009, 02:24:48 »
Hey everybody, sorry I haven't been on the forum much lately, I've been busy with other stuff and probably will continue to be so for another week.  None the less, I have been doing some work on the networking code and I decided it was appropriate to do a reassessment of the requirements and design.  Upon doing so, I discovered a lot of things that will further change the design of GAE, but I haven't decided how much of this should go into 0.2.12 yet so I present it here.  Hailstone, any feedback would be appreciated.  I think I have a pretty clear path forward for 0.2.12, taking the middle road.

Below are the requirements and the portion I'm thinking should go in 0.2.12.  Perhaps at some point (very soon) I should write a formal word document and keep it in source control, but this is good enough for now.  This may read as verbose to some, but this is the nature of a requirements/specification text: it must be verbose to eliminate ambiguity.  Ambiguity kills.  I've done software engineering, consulting, business, software and systems analysis for over a decade, trust me on this, I know what I'm talking about.  The version in green is only my current proposed target version.  It's once thing to discuss ideas, but when spelling out requirements prior to building an application, completeness is important.  Imagine trying to build a building with incomplete blue prints.  Anyway, here they are (I'll likely revise them, so look for a "LAST UPDATED") comment at the end of this post.
.

Definitions
First some definitions for clarity's sake:
  • unexpected disconnect: describes a situation where a TCP socket error occurs (socket timed out, remote peer reset connection, no route to host, etc.) or the socket remains active, but no data has been received for a specified amount of time (currently 30 seconds and will probably remain that).
  • intentional disconnect: one where a network message stating that the player has chosen to leave the game is transmitted prior to any other network failure, such as reset connect, etc.
  • participant: For the sake of these requirements, a "participant" will mean any participant in a network game, either a client or server (and does not describe the relationship between two participants).
.

General Networking and Lobby
  • [current]: Each player slot will be numbered (starting with one) and the first slot will be assigned to the local player by default (as is now) (added 3/5/2009 for clarity)
  • [current]: Server (hosting of the game) should be able to change game settings while clients are still connecting (as is now)
  • [0.2.12]: Clients should be able to connect when server is in lobby but there's not an open slot set to "network" (i.e., be in limbo for a time while host changes settings).  If a client attempts to connect when there is an open network slot, they will be assigned to the first available network slot (as is current behavior).  If there are none, the new client will be assigned to the "limbo queue" while the server is still in the lobby.  If the server subsequently opens a network slot, the client highest in the limbo queue will be automatically assigned to that slot. (modified 3/5/2009)
  • [0.2.12]: Any clients who remain in the limbo queue when the server launches the game will be disconnected.  (added 3/5/2009)
  • [>=0.3]: In the future, the "limbo queue" will become the "spectator list" and any clients who reside in this spectator's list when the server starts the game will be allowed to observe the game as a spectator, but may not chat (except, perhaps with other spectators).  This will override the previous requirement. (added 3/5/2009)
  • [0.2.12]: Removing a network slot shouldn't kick a client (as above) until game is actually started (if there are connected clients who weren't given a slot).  Instead, any clients assigned to the network slot that was removed will be kicked to the next available slot (if one is open) or sent to the limbo queue. (added 3/5/2009)
  • [0.2.12]: Clients should see the current game settings.  Every time the server changes them, it should update on clients so they can see the changes, discuss them in chat, etc.
  • [>=0.2.12]: Server should be able to kick and ban a particular client at any time (in the lobby and in game)
  • [>0.2.12]: Server should be able to move clients around to different network slots (in lobby) (currently, it's first come-first server). Server should also be able to move clients to and from the limbo queue. (added 3/5/2009)
  • [0.2.12]: As mentioned before, networking will become peer-peer/server instead of client server (i.e., a hybrid of peer to peer and client/server).  The server still maintains control of the game and "dictates" game state to clients, but clients communicate with each other (when possible) so the server doesn't have to relay actions by client commands -- this reduces lag time.
  • [>=0.2.12]: When clients aren't able to connect to each other, the server will continue to relay commands.
  • [0.2.12]: The server pings all of its clients and each client the server and all connected peers once per second.  Ping messages (class Game::Net::NetworkMessagePing) already contain the local machine time of the originator and when returned, they get the local machine time of the recipient attached to it.  This will now be used, along with the average latency, to determine the approximate local machine time of each network participant, paving the way for more advanced and efficient game/world management (these options are explored in the last two sections).
  • [0.2.12]: The state of each client's connection or lack there of is communicated to the server periodically (maybe every 8 seconds or so) along with latency statistics.  The client's latency to the server its self is also communicated.  If a UDP-based network layer is later established, these statistics will include packet loss (corrupted packets will always be counted as lost).  This enables the server to know who needs messages forwarded to them. If a client looses a connection to a peer, the connection status update is transmitted to the server immediately.
  • [>=0.3]: Shared control: Two or more clients may be assigned to the same faction, thus allowing more than one client to control the same faction.  This can be very handy where duties are split between the players and can be a fun twist. For the UI, this means that the server will need to be able to have more than one client assigned per slot and that the join game client menu will need to be able to display that. (added for clarity 3/5/2009)
  • [>=0.3]: DOS attack detection should be implemented as some level, even if trivial.  While I have not heard of anybody attempting to exploit either Glest or GAE's networking to perform attacks, a minimal level of DOS detection should be in order.  While I'm saying 0.3 or later for this requirement, safe-guards for buffer overrun exploits are always a constant must and after 0.2.12, it wouldn't hurt to carefully review the networking code and make sure it's safe.
.
 
Disconnects, Reconnects and New Game-Time Connections
The following items target 0.2.12 specifically:
  • [0.2.12]: When a client disconnects (either intentionally or unexpectedly), the disconnected player's faction is left uncontrolled.  This is the current behavior for the most part.
  • [0.2.12]: When a client disconnects intentionally, a message should be sent to server and all peers (or relayed by server if peers weren't connected) so that the cause of disconnect is known.  This should not cause an auto-save.
  • [0.2.12]: When a client disconnects unexpectedly, the game should auto-save on server and all peers (as it does currently).  If this brings the number of clients connected to the server to zero, then the game should pause and a message box should ask the server if they want to quit or not (this is also current behavior).  If there is at least one other client connected, game play should not be interrupted (the disconnected client's faction will be left uncontrolled as previously described).
The following overrides the 0.2.12 specifications above and target a release >0.2.12 (maybe even the 0.3 branch for some requirements).
  • [>0.2.12]: If a client disconnects for any reason (intentionally, unexpectedly or kicked), the server should be prompted (message box) and be able to replace that player's faction with an AI of their choice or uncontrolled.  This message box should have the escape key linked to choose the "uncontrolled" option so they may quickly exit the message box if need be. (FIXME: this requirement mixes user interface design and functional requirements)
  • [>0.2.12]: The server should be able to change any non-player-controlled (i.e., AI or uncontrolled) faction's controller with another non-player controller at game time, including making the faction uncontrolled.  These changes should always be broadcast to clients in a way that is clear (like a message to the console and a "beep" type of sound) but un-obtrusive.
  • [>0.2.12]: When a client disconnects unexpectedly, the game pauses on all peers and everybody is notified.  More specifically, the server shall transmit a mandatory pause command to all clients effective in approximately average_latency milliseconds.  The client should be able to reconnect while the game is still in progress, without everybody else having to leave the game.  The server should be able to choose a course of action from the following:a) remain paused to see if the client re-connects, b) resume game leaving the disconnected player's faction un-controlled or c)  resume game replacing the disconnected player's faction with an AI of the server's choice.  Again, each client should clearly be notified.
  • [>0.2.12]: When a server disconnects, either intentionally or unexpectedly:
    • If the disconnect was unexpected, each client will auto-save the game (this is current behavior).
    • If there is only one client, then the client is converted to a server, paused and given the same options a server is given when a client disconnects (see above, identical behavior)
    • If there is more than one client, a lottery is performed to determine who will be promoted to the server, after which behavior will be the same as if a client had disconnected (described above).
  • [>0.2.12]: glestadv.ini shall have a new setting NetAllowClientReconnect with the values of "none", "prompt" and "auto".  If set to "none", clients who were disconnected (intentionally or not) shall not be allowed to reconnect to the server while game is still in progress.  If set to "prompt" and the client was not kicked, the server will be prompted and asked if the client should be allowed to reconnect and resume control of their faction.  If set to "auto" and the client was not kicked, the client will automatically resume control of their faction when they attempt to reconnect.
  • [>0.2.12]: glestadv.ini shall have a new boolean setting NetAllowLateClients.  If true and the a client attempts to connect to the server while a game is already in progress, then the server is prompted and may choose to a) drop the connection, b) replace an AI with the new client or c) add the client to an existing player-controlled faction.  In the case of option c, the client controlling the target faction must be prompted and give approval.  If set to false, clients who connect at game time who were not previously disconnected are told to bugger off.
  • [>0.2.12]: If NetAllowClientReconnect is set to "none" and NetAllowLateClients is false, the server will stop listening for new connections to reduce possible exposure.  If  NetAllowClientReconnect is set to "prompt" or "auto" and NetAllowLateClients is false, then the server will stop listening for new connections when the game starts, but begin listening again if a client drops.
.
 
Game settings, speed and pause
  • [0.2.12]: Some in glestadv.ini will be transmitted from the server to each client in a network game and these will be used for game play (overriding their local settings).  This includes the following glestadv.ini values:
    • GsAutoRepairEnabled - rather or not auto-repair is allowed *
    • GsAutoReturnEnabled - rather or not units will automatically return from auto-commands like auto-attack, auto-repair, etc. *
    • GsDayTime - how long a day lasts
    • GsFogOfWarEnabled
    • GsRandStartLocs
    • NetPauseAllowed
    • NetChangeSpeedAllowed
    • GsSpeedFastest - applicable only if NetChangeSpeedAllowed is true
    • GsSpeedSlowest - applicable only if NetChangeSpeedAllowed is true
    • GsWorldUpdateFps
    * Indicates that the server dictates rather or not the setting may be enabled by the client, but does not turn it on unless the client already has it enabled in their glesetadv.ini (a.k.a., Game::Config object). (added 3/5/2009)
  • [0.2.12]: If NetPauseAllowed is true, any game participant may pause the game.  When a pause is requested, a target execution time is sent (probably 2x the max average latency) so that all participants pause on the same frame.  The same is true for speed changes if NetChangeSpeedAllowed.  The rules for this should probably be more flexible, but this is the current 0.2.12 implementation plan.
  • [>0.2.12]: Future NetPauseAllowed and NetChangeSpeedAllowed may need more options besides true and false.  Instead, it may need to be something like "not allowed", "allowed", "allowed only with vote" and have a "min pause lead time" and a "min speed change lead time" to keep players from changing game speed when it suits them without consent from other players. (More exploration and details of this requirement are needed)
  • [>0.2.12]: The New Game UI will need to be able to change these and display changes the server makes on each client in the lobby.
  • [>=0.2.12]: In a network game, weather events should determined by the server and dictated to clients.  At current (both GAE and original Glest) there can exist different weather conditions on two different participants.
.

I've reached the maximum message size for this forum, so I'll resume this in the next post...

EDIT: 2009-01-28: Added weather sync requirement
EDIT: 2009-03-05: Made modifications (in blue) consistient with hailstone's feedback here.  Outstanding issues:
  • Synching tech trees and/or sharing content like tileset, maps, etc.
  • password-protected games
« Last Edit: 6 March 2009, 00:54:19 by daniel.santos »

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #20 on: 29 January 2009, 02:26:02 »
    Ok, here's the rest of the requirements...

World updates and rendering
Some of these requirements have been mentioned in other places and some are not network-related, but important enough to mention here since they are closely tied to the way game play will function.
  • [0.2.12]: Begin tracking game time in milliseconds since start, excepting time paused.  This mechanism will eventually replace world frames.  For network games, this time is dictated by the server and each client figures out the correct offset from their local machine time using timing information from ping latency calculations.  Server will dictate the offset from its own local machine time and that will keep all clients in sync when pausing and speed changes occur.
  • [>0.2.12, perhaps 0.3.x]: Entirely eliminate "world frame" concept and replace it with a sophisticated scheduling mechanism that runs the appropriate updates when needed and no more.  (Implementation Note: The base classes for this functionality are already coded and used for other timing mechanisms in 0.2.12)
  • [>=0.2.12]: Entirely remove updates to animation progress (data member Game::Unit::animProgress) from world update and replace with a time-based (millisecond) system.  When a skill starts the start time is recorded (expressed in "game time" milliseconds).  When rendering begins, the animation progress will be calculated based upon the current game time and animation start time -- thus, regardless of world updates, animations will always play out at the same speed.  Currently, if world updates aren't happening 40 times per seconds, there are a multitude of problems that can result, including projectiles not being fired! (this happens in original Glest engine as well).  Thus, this requirement will change the mechanism that determines when projectiles will fire (see ProjectileParticleSystem, AttackParticleSystem and ParticleObserver).  When the complex scheduling is implemented, it will simply be scheduled (so this requirement may wait until that is implemented, I'm not sure yet).  This requirement is the primary implement to enabling a schedule-based world, lessoning the burden of needing the world updates as frequently, will result in smoother animations and eliminate MANY wasted CPU cycles that occur in both GAE and original Glest.
  • [>0.2.12]: Although not network related, the above requirement is also integral in plans to optimize the way mesh morphing (a.k.a., "interpolation") is performed to reduce CPU cycles as well as improve animation smoothness and overall (rendering) frame rate.  This is part of the proposal to implement an "interpolation thread pool" (containing one or more threads) that will begin asynchronously interpolating mesh data for the upcoming rendering frame using current rendering FPS statistics to predict when the next rendering frame will probably occur.  Errors in such prediction will probably be ignored since the next frame rate calculation will generally make up the difference for the next rendering cycle and the variance should be so small as to be unnoticable.  Plus, if rendering begins before interpolation for the target rendering frame has completed, it can update the Interpolator's (for lack of a better name) target rendering time with the actual so that the remaining animations will be accurate.
  • [>0.3]: As a final addendum to the above two requirements, a new setting in glestadv.ini RenderAnimationSmoothness will eventually be introduced.  The valid values will be something like 0.125 to 1.0 and specify the ratio of mesh morphing to frame rendering.  At 1.0, all meshes are morphed every rendering frame.  At 0.5, meshes are morphed every other frame and at 0.125, every eighth.  This will add one more variable to control performance vs appearance. (Currently, it happens at every rendering frame, but the Unit::animProgress only updates a max of 40 times per second, so at 60 rendering frames per second, 20 of those are wasted re-interpolating mesh data when Unit::animProgress hasn't changed!)
.
 
Network game play and World Updates
  • [0.2.12]: As mentioned in the "General Networking and Lobby" section, the server will track the average latency for each connection its clients, its clients connection to the server and each client connection to its peers (or lack thereof).  Thus, the server will be able to predict with reasonable accuracy how long it takes for a message to be transferred from one participant to another.  This value will be used to set a "command lead time" that is broadcast periodically to each client by the server, may change depending upon network conditions and will generally be something like 1.5x to 2.0x the average_latency time of the slowest connection in the game (and ideally less than 500 milliseconds -- and such a hard limit may be set).  When any game participant issues a command to their units, it is given a scheduled execution time (in 0.2.12 it will be expressed as a target frame, but that will change to "game time", expressed in milliseconds, in subsequent implementations).  This scheduled execution time is transmitted over the network along with the command(s) and the command(s) are queued locally instead of being immediately issued.  Once the scheduled execution time or frame arrives, the commands will be executed locally with the anticipation that each game participant will execute them at the same time, or at least the same game time or frame as the server will always be running the game approximately half_average_latency (equal to average_latency / 2) milliseconds ahead of clients.  This should not only be a good mechanism to keep games in sync, it will also eliminate most of the advantage that playing on the server has over clients.
  • [>=0.2.12]: If the commands arrive later than the scheduled, the recipient will issue the command and then fast-forward the commanded units by the appropriate number of frames (for initial implementation) or milliseconds (in future implementation).  If the commands arrived late to a client, the client will send an update request to the server for each commanded unit.  This will cause the server to send a full update for each of those units (updates & update requests have been in place for several releases now).
  • [>=0.4-ish]: To fully eliminate any advantage the server has over the clients, its possible to cause rendering on the server to represent game state half_average_latency milliseconds later than current.  This will require a fairly large "insulation" layer between game state and rendering, however, and may not be worth it.
.

I still want to cover the new messaging, so I'll do that with yet another post.  I'll probably draw up a formal sequence diagram, because I think that works well.

daniel.santos

  • Guest
Re: chop, chop, chop (network code)
« Reply #21 on: 29 January 2009, 05:13:20 »
grr, I can't get either Argouml nor Umbrello to make descent sequence diagrams for me so I'll spell it out with text  >:(

So each message will have a source and destination (just like a real sequence diagram).  For brievity, I'll use S for Server, C1 for Client1 and C2 for Client2.  This diagram (psudo-diagram) illustrates a network conversation for a 3- player network game.  Note that sequence IDs with alpha suffix attempts to denote async operations.  When this sequence completes, a new game will have started.

New Network Game Sequence Diagram (network communications)
Code: [Select]
1   S             : listen
2   S <- C1       : connect
3   S -> C1       : accept
4   S -> C1       : handshake       Game::Net::NetworkMessageHandshake (formerly
                                    NetworkMessageIntro) contains version info (of server software)
                                    and the id and uid the server is assigning to the new client.
5   S <- C1       : handshake       Client responds sending it's version, and echoing the newly
                                    assigned id and uid.
6   S <- C1       : player info     Sends a NetworkMessagePlayerInfo object which encapsulates a
                                    Game::PlayerInfo object and status (NetworkPlayerStatus) info.
                                    PlayerInfo contains player name, relevant config preferences and
                                    network info (Game::Net::NetworkInfo) from the perspective of
                                    the remote client.  Thus, their percieved IP address may be a
                                    VPN address. The PlayerInfo object's networkInfo.localHostName
                                    will contain the host name as the remote host percieves it.
7   S -> C1       : game info       NetworkMessageGameInfo contains GameSettings and
                                    Game::PlayerInfo + status for all players.
8        C1       : listen          C1 is now considered to be fully connected and will now start
                                    listening for peer connections
9   S <------- C2 : connect
10  S -------> C2 : accept
11  S -------> C2 : handshake
12  S <------- C2 : handshake
13  S <------- C2 : player info
14a S -> C1       : game info
14b S -------> C2 : game info
15             C2 : listen
16       C1 <- C2 : connect         Onus is on the newly connected client to attempt to contact peers
17       C1 -> C2 : accept
18       C1 -> C2 : handshake       UID of C1 sent to C2 along with handshake
19       C1 <- C2 : handshake       UID of C2 sent to C1 as well
20a S <- C1       : status update   clients must report that they have established a connection to
20b S <------- C2 : status update   each other
21a S -> C1       : game info       from this point forward, the server will no longer relay
21b S -------> C2 : game info       commands from C1 to C2 or visa-versa
22  S             : host uses UI to change game settings
23a S -> C1       : game info
23b S -------> C2 : game info
24  S             : host chooses "launch game" from UI
25a S -> C1       : launch
25b S -------> C2 : launch
26a S             : loads           Loads all game data (map, tileset and faction tree) and builds a
26b      C1       : loads           Shared::Util::Checksums object
26c            C2 : loads
27a S             : wait until all clients are ready
28a S <- C1       : report ready    Game::Net::NetworkMessageReady sent to server with Checksums
28b S <------- C2 : report ready    object.  If it doesn't match the server, then the server pukes
                                    on them.
29a S -> C1       : begin game at x time
29b S -------> C2 : begin game at x time
30a S             : starts game
30b      C1       : starts game
30c            C2 : starts game
Note that at various points in this sequence, alternate routes may occur for items 3 and 10 if a client is banned by the server (by IP address) and also for 18 and 19 if the UID, IP address and player name provided by each client does not match the values sent by the server in the game info message. 

Saved Games
When restoring a saved network game, the saved game file is sent from the server to all clients at some point in this sequence prior to step 25.  Probably, it should not be sent with the GameInfo necessarily.  Perhaps there should be a delay of about 15 seconds between the time the server selects the saved game file and it decides to transmit it to clients.  The reason for this is that we don't want to send every saved game file as they scroll through them, perhaps trying to find the appropriate saved game to resume.  At every change, a new NetworkMessageGameInfo should be sent immediately however (or within 1000 milliseconds) so that each client has an updated view of what they are about to play.  This message (without the entire saved game) is much smaller and can be sent more frequently.  Of course, if less than 15 seconds have passed since the host/server selected the saved game to restore and they hit the launch button, it should force the saved game file to be transmitted immediately.

EDIT: Correction in sequence (there was also two step 5s)
EDIT: 2009-03-26: Updated sequence, changed numbering (fixed numbering problems), added more details in sequence, added information for how saved games should be handled.
EDIT: 2009-04-14: Moved assignment of player ID and uid from the game info message to the handshake and clarified how checksums are managed.
« Last Edit: 15 April 2009, 05:57:33 by daniel.santos »

hailstone

  • Local Moderator
  • Battle Machine
  • ********
  • Posts: 1,568
    • View Profile
Re: chop, chop, chop (network code)
« Reply #22 on: 31 January 2009, 03:01:26 »
Looks good.

OT:
Quote
but this is the nature of a requirements/specification text
Apparently this is a specific language. I read this about the C++ Standard by James Kanze at http://groups.google.com/group/comp.lang.c++/browse_thread/thread/28b14a1308974070:
"The standard is written in a variant of English sometimes called standardese. It's designed (or at least intended) to be
absolutely precise and unambiguous, even at the cost of understandability. It doesn't always succeed with its intent,
but in all cases, precision and a lack of ambiguity have precedence over readability."

Anyway back on topic now.

Quote
[0.2.12]: Clients should be able to connect when server is in lobby but there's not an open slot set to "network" (i.e., be in limbo for a time while host changes settings)

Will the server want the first people in to automatically be assigned to a slot? and it doesn't explain what happens when there are two people in limbo and a slot is opened.

I propose that a que (with a max amount of items) be created where players are sent to when they join. The server can then add or remove the desired network or CPU players to or from a slot (the position of which is moveable by the server). Empty slots should be visual and numerical.

Perhaps before clients connect server can adjust settings then press a listen button to allow clients to enter the que (something useful for a master server so games don't appear immediately).

How will specators be dealt with?

Quote
# GsAutoRepairEnabled - rather or not auto-repair is allowed
# GsAutoReturnEnabled - rather or not units will automatically return from auto-commands like auto-attack, auto-repair, etc.

I don't know if I agree with GsAutoRepairEnabled and GsAutoReturnEnabled being forced on clients. It seems like personal preference to me.

Also here are some things that you didn't mention: syncing tech trees or downloading maps, password protected joining.
Glest Advanced Engine - Admin/Programmer
https://sourceforge.net/projects/glestae/

Omega

  • MegaGlest Team
  • Dragon
  • ********
  • Posts: 6,167
  • Professional bug writer
    • View Profile
    • Personal site
Re: chop, chop, chop (network code)
« Reply #23 on: 31 January 2009, 10:58:43 »
By syncing, do you mean the ability to play on a map or tileset that one player does not have? If so, that is a must. Not sure how that'll cope with a tileset though, seeing the size of that.

Why can't we have each player choose his or her own tileset? The as long as the walkable/unwalkable parts are the same, it shouldn't change gameplay. (most tilesets have the same items as walkable/unwalkable anyway).

Lookin' good. I never could understand network code. That's the one thing worse than AI. (AI isn't that bad actually, unless we are talking about RTS AI, which I imagine is the hardest).
Edit the MegaGlest wiki: http://docs.megaglest.org/

My personal projects: http://github.com/KatrinaHoffert

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: chop, chop, chop (network code)
« Reply #24 on: 17 February 2009, 10:02:58 »
Do you have any news for us here? Is there any progress or trouble?

One little wish (if you are still on it), please keep in mind that we once want a master server to setup/find games.
We need no implementations yet, just keep it in mind when you design protocols.
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

 

anything