4
\$\begingroup\$

I want to handle weapon cool-down timers in a fair and predictable way on both client on server.

Situation:

  1. Multiple clients connected to server, which is doing hit detection / physics
  2. Clients have different latency for their connections to server ranging from 50ms to 500ms.
  3. They want to shoot weapons with fairly long reload/cool-down times (assume exactly 10 seconds) It is important that they get to shoot these weapons close to the cool-down time, as if some clients manage to shoot sooner than others (either because they are "early" or the others are "late") they gain a significant advantage.
  4. I need to show time remaining for reload on player's screen
  5. Clients can have clocks which are flat-out wrong (bad timezones, etc.)


What I'm currently doing to deal with latency:

  1. Client collects server side state in a history, tagged with server timestamps
  2. Client assesses his time difference with server time:

    behindServerTimeNs = (behindServerTimeNs + (System.nanoTime() - receivedState.getServerTimeNs())) / 2
    
  3. Client renders all state received from server 200 ms behind from his current time, adjusted by what he believes his time difference with server time is (whether due to wrong clocks, or lag). If he has server states on both sides of that calculated time, he (mostly LERP) interpolates between them, if not then he (LERP) extrapolates.

  4. No other client-side prediction of movement, e.g., to make his vehicle seem more responsive is done so far, but maybe will be added later


So how do I properly add weapon reload timers?


My first idea would be for the server to send each player the time when his reload will be done with each world state update, the client then adjusts it for the clock difference and thus can estimate when the reload will be finished in client-time (perhaps considering also for latency that the shoot message from client to server will take as well?), and if the user mashes the "shoot" button after (or perhaps even slightly before?) that time, send the shoot event.

The server would get the shoot event and consider the time shot was made as the server time when it was received. It would then discard it if it is nowhere near reload time, execute it immediately if it is past reload time, and hold it for a few physics cycles until reload is done in case if it was received a bit early.

It does all seem a bit convoluted, and I'm wondering whether it will work (e.g., whether it won't be the case that players with lower ping get better reload rates), and whether there are more elegant solutions to this problem.

\$\endgroup\$
2
  • \$\begingroup\$ take a look at this \$\endgroup\$
    – Ali1S232
    Commented Dec 15, 2012 at 10:26
  • \$\begingroup\$ I have read it previously. It is a very interesting article, but I'm afraid doing rollback for hit detection on server side is more complicated that I want to handle. Which sections in particular discuss my particular problem? \$\endgroup\$
    – John M
    Commented Dec 16, 2012 at 9:55

1 Answer 1

2
\$\begingroup\$

Is it totally necessary to manage reload times server side? Often the simplest way to do this is on the client side for both fairness and responsiveness. I'm no expert but what I would predict is that the current system encourages spamming and the server has to check whether each request is valid before discarding it, taking up more processing power.

Drawing up a basic model (ignoring processing times etc) of a client with 60ms ping we get:

Client sends event at 0ms
Server receives event at 30ms
Server sends time back to client, arrives 60ms
Client can shoot at 10030ms according to both server and client

If ping constant and player clicks once when told shot is ready:
    Client clicks to shoot at 10030ms
    Message arrives at server 10060ms
    Server sends back timer for 20060ms

If ping constant and player spams:
    Messages sent repeatedly to server between 30 and 10030ms
    Around 10030ms one of these messages arrives and is instantly accepted
    Server sends back timer of 20030ms

If ping spikes to ~250ms:
    Spamming is not affected as much as one of the messages will get through
    Single click is delayed by another ~100ms

It's a fair system as long as everyone is constantly clicking to shoot near the end of the reload but if you were to manage it client side the effect would only slow the time for the shot to fire and not the reload time itself (which would trigger instantly). In the above example every reload loses a few milliseconds which will build up until entire shots worth of time have been missed.

If the shot is sent to the server and the reload is local then the shot might be late but the reload will always be on time. The initial problem with slow/fast clocks is probably still a thing however. Depending on the language/framework you're using it might be possible to get a better measure of time. Beyond that I'm afraid I can't help much.

\$\endgroup\$
1
  • \$\begingroup\$ My intent was the client cannot spam unless he hacks the client/protocol, there is also client side validation. But the server side validation is there in case he does hack client/protocol for cheating purposes. Also, the client would be allowed to click at 10000ms, not 10030ms, as the client also knows the average trip time is 30ms. In case ping falls down to 30ms then the message would arrive early at 10015ms and get queued on the server for 15ms. However, in case of a ping spike to 250ms then the message arrives at 10250 and is 220ms late - not good. \$\endgroup\$
    – John M
    Commented Dec 16, 2012 at 9:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .