Jump to content
  • Advertisement
Sign in to follow this  
Kroah

Client giving orders problem (RTS)

This topic is 3919 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, Even if this is my first post, i enjoy reading this forum regularly. I'm actually writing a small RTS like game for myself, and i'm currently in a dead end. What my game currently do: - the game is a client/server application - i use client prediction and update with server datas when needed It works pretty well. The problem comes when a client gives an order which can't be predicted and *could* interract directly with another client. Example: both players share the same primary ressource like money. Both players give the order 'build a big building ($500)' at the same time, but the shared ressource can only afford for 1. In this case, the client can't predict anything. Because if they build before the validation of the server, both players will build the building because they think they have enough money:
                             Client 1 | Client 2 | Server
t=0                              $500       $500     $500
t=1 (build with prediction)        $0         $0     $500 (error: both clients has built)
t=2 (order send to the server)     $0         $0    -$500
I've resolved this by waiting a validation from the server telling 'yes you can build'. That's why there's a slight delay (not noticeable) between the order given by the player, and the effective order taking effect on the screen:
                                Client 1 | Client 2 | Server
t=0                                 $500       $500     $500
t=1 (build without prediction)      $500       $500       $0 (clients wait validation)
t=2 (response from server)            $0         $0       $0 (ok: only one of the both client has built)
The real problem rises in the following case: The player can give a LOT of orders in 1 second! Example: He has 1000$, and buy 500 units costing 2$ each. For some internal rules i can't change, the only order available is 'Buy 1 unit (costing 2$)'. The order 'Buy 500 units (costing a total of 1000$)' can't be done (which could be a good solution). By giving 500 orders 'Buy 1 unit costing 2$' the game lags because at each order, the client waits the validation of the server. And i can't predict anything (like for the moves), because i can't rollback or correct the client if the server invalides the orders. I hope i'm enough clear :) Do you have any idea to solve this problem ? Thank you all, Pascal

Share this post


Link to post
Share on other sites
Advertisement
hi,

why do you want to share ressources?

if 2 players can play together you could implement something like:
if players belong to same group -> option to send a player in the group some of your ressources...

so the ressources CAN be shared but every group member owns its own...

you would not have the problem to send all the commands to the server and still can share ressources

i know that something like that could make the gameplay a bit slower but no other solution came to mind

Share this post


Link to post
Share on other sites
Quote:
Original post by Noobico
why do you want to share ressources?


In fact this is just a simplified example to illustrate my problem.

Share this post


Link to post
Share on other sites
You have several possibilities:
  • Complete server authority. The client may do nothing without the server's approval. The client sends orders (build this here) to the server, and the server responds with the actual events (a building appears there). The client is mostly a glorified terminal with interpolation properties.

    This is slightly different from your current situation, is that you don't wait for confirmation. You send the orders and receive the effects (not confirmation) of your orders asynchronously.

  • Delayed server authority. The client keeps in memory the state of the world at time T, and, if the server doesn't send the diff to T+1 quickly, simulates times T+1, T+2, T+k according to the same rules as the server. Then, the server sends it the diff between times T and T+1, and the client drops everything except the state at time T+1, and resumes simulation.

    This eliminates lag (since the orders are reflected immediately, even if cancelled by the server), though it might be confusing if the network lags too much and too many things are rolled back.

  • Object taint. Like delayed server authority, except only "tainted" objects are send over network, rolled back and recomputed. "Taint" hits objects whose state was unpredictable because of client interaction, and spreads along interactions.

    More complex, but faster.

Share this post


Link to post
Share on other sites
You should try to explain further, since I too can't see the problem clearly.
In a regular RTS each player has their own resources and share these via a market or similar, but you already know this probably. =)

You could also do a different approach, i.e allow player to start a construction and then build it resource by resource. If a build costs 500 and two players begins building it - both players each end up with a half-finished building.
The constructing would, of course, continue when resources are available.

Another option would be that ALL communication goes through the server, i.e nothing gets built unless the server says its okay.

/Robert

Share this post


Link to post
Share on other sites
Quote:
Original post by Rasmadrak
In a regular RTS each player has their own resources and share these via a market or similar, but you already know this probably. =)


Starcraft has a mode where all players on a team control the same 'player' (one initial command center and builders, shared units, shared resource pools).

Share this post


Link to post
Share on other sites
Quote:
  • Complete server authority: [...]

  • This was my first implementation. But i had too much lag (Nethertheless, i wanted to try it).
    Quote:
  • Object taint. Like delayed server authority, except only "tainted" objects are send over network, rolled back and recomputed. "Taint" hits objects whose state was unpredictable because of client interaction, and spreads along interactions.

  • Actually, this is what i've done. But because lots of orders are sent simultaneously by each client and they do prediction before receiving server validation, there are too much rollbacks and it gives strange results on the screen (you build a building and it disappears 2 seconds later). So this kind of order aren't rollbackable and so unpredictable like you said (i can't take the assumption the order is validated by the server).

    Quote:
    You could also do a different approach, i.e allow player to start a construction and then build it resource by resource. If a build costs 500 and two players begins building it - both players each end up with a half-finished building.

    If i don't find any solution to my problem, i'll have to change the rules to minimize the number of orders given at the same time (1 order 'build 500 units' instead of 500 orders 'build 1 unit'). But it *will* give another type of game :/

    Quote:
    Another option would be that ALL communication goes through the server, i.e nothing gets built unless the server says its okay.

    This was my first implementation like i said above. This removes the rollbacks but add big lags.

    The 'best' solution i've found was to simulate client-side with prediction (for others stuffs) and wait for validation from server for unpredictable orders. But building lots of units takes now several seconds (build 1 unit->wait validation->build 1 unit->wait validation, ...500 times).

    I think that commercial RTS games resolve this kind of problem by minimizing the number of validations needed from the server and so decreasing waits (or rollbacks). In my case, this changes the rules. But before doing that (the last solution for me), i wanted to know if i'm missing something :)

    Quote:
    Starcraft has a mode where all players on a team control the same 'player' (one initial command center and builders, shared units, shared resource pools).

    Yes, this is exactly this situation.

    Thank you for your help,
    Pascal

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Kroah
    Actually, this is what i've done. But because lots of orders are sent simultaneously by each client and they do prediction before receiving server validation, there are too much rollbacks and it gives strange results on the screen (you build a building and it disappears 2 seconds later).


    Are there so many collisions? Ouch...

    Besides, you have to keep in mind that:
    • You must prove that your server and client are in sync. Subtle race conditions can and do occur when systems are not thoroughly proven to work.
    • You don't have to start simulating right away. If you're in a laggy environment, you can get away with lagging for a short time before starting simulation and players will just have to accept it. Alternately, you may just slow down simulation speed.


    Quote:
    (build 1 unit->wait validation->build 1 unit->wait validation, ...500 times).


    Why are you waiting for validation before building the next unit?


    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by ToohrVyk
    Quote:
    (build 1 unit->wait validation->build 1 unit->wait validation, ...500 times).


    Why are you waiting for validation before building the next unit?


    I understand this may look strange, like wanting building 500 units one by one. But this is a rule limitation.
    The game i'm programming is an adaptation of an old game (multiplayer on the same computer), and i try to be the most faithful possible (and multiplayer across internet). I've reverse engineered the game, and i want to keep the same algorithm than the original.

    In this game, the AI builds 1 unit by one in a kind of loop (simplified):
    - while money > $2
    - build unit
    - end-while


    But this money may be shared among several players playing simultaneously.

    I don't want to change the AI (it will change too much the behavior).

    So this same loop may be executed by more than 1 player, and here comes the problem if i don't wait the validation: the two players think they have enough money, but the other one has already used this money. So i add validation and sync, but this lag (lots of validations):
    - while
    - send server 'build unit' order
    - wait response
    - if OK, build unit locally (server has already built it)
    - if KO, break
    - end-while


    This works perfectly for 10 loops, but not for 500 loops... which may be 3000 near the end of the game.

    Quote:
    Are there so many collisions? Ouch...

    Yes, like you see above, all the AIs play simultaneously (up to 4 sharing money) which gives 4 loops of 500 build units using the same variable 'money'.

    Pascal

    Share this post


    Link to post
    Share on other sites
    I would suggest the variation:
    - while money > $2
    - send server 'build unit' order
    - pay money for the unit
    - add unit to build list
    - end-while


    Then, when you receive an OK, you move the unit from the build list to the real world as if it had been built earlier. When you receive a KO, you remove it from the build list and refund. If no response, you also remove it and refund.

    By sending so many "build unit" requests to the server, any compression algorithm running on your packets will reduce the payload to almost nothing (compared to 3000 orders), and the same for a returning "OK, OK, ... OK, KO, ... KO" sequence.

    Share this post


    Link to post
    Share on other sites
    Sign in to follow this  

    • Advertisement
    ×

    Important Information

    By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

    Participate in the game development conversation and more when you create an account on GameDev.net!

    Sign me up!