* This is called every tick if this is a _network_server * @param send_frame Whether to send the frame to the clients. */
| 1677 | * @param send_frame Whether to send the frame to the clients. |
| 1678 | */ |
| 1679 | void NetworkServer_Tick(bool send_frame) |
| 1680 | { |
| 1681 | #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME |
| 1682 | bool send_sync = false; |
| 1683 | #endif |
| 1684 | |
| 1685 | #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME |
| 1686 | if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) { |
| 1687 | _last_sync_frame = _frame_counter; |
| 1688 | send_sync = true; |
| 1689 | } |
| 1690 | #endif |
| 1691 | |
| 1692 | /* Now we are done with the frame, inform the clients that they can |
| 1693 | * do their frame! */ |
| 1694 | for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { |
| 1695 | /* We allow a number of bytes per frame, but only to the burst amount |
| 1696 | * to be available for packet receiving at any particular time. */ |
| 1697 | cs->receive_limit = std::min<size_t>(cs->receive_limit + _settings_client.network.bytes_per_frame, |
| 1698 | _settings_client.network.bytes_per_frame_burst); |
| 1699 | |
| 1700 | /* Check if the speed of the client is what we can expect from a client */ |
| 1701 | uint lag = NetworkCalculateLag(cs); |
| 1702 | switch (cs->status) { |
| 1703 | case NetworkClientSocket::STATUS_ACTIVE: |
| 1704 | if (lag > _settings_client.network.max_lag_time) { |
| 1705 | /* Client did still not report in within the specified limit. */ |
| 1706 | |
| 1707 | if (cs->last_packet + std::chrono::milliseconds(lag * MILLISECONDS_PER_TICK) > std::chrono::steady_clock::now()) { |
| 1708 | /* A packet was received in the last three game days, so the client is likely lagging behind. */ |
| 1709 | IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client's game state is more than {} ticks behind.", cs->client_id, cs->GetClientIP(), lag); |
| 1710 | } else { |
| 1711 | /* No packet was received in the last three game days; sounds like a lost connection. */ |
| 1712 | IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because the client did not respond for more than {} ticks.", cs->client_id, cs->GetClientIP(), lag); |
| 1713 | } |
| 1714 | cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); |
| 1715 | continue; |
| 1716 | } |
| 1717 | |
| 1718 | /* Report once per time we detect the lag, and only when we |
| 1719 | * received a packet in the last 2 seconds. If we |
| 1720 | * did not receive a packet, then the client is not just |
| 1721 | * slow, but the connection is likely severed. Mentioning |
| 1722 | * frame_freq is not useful in this case. */ |
| 1723 | if (lag > (uint)Ticks::DAY_TICKS && cs->lag_test == 0 && cs->last_packet + std::chrono::seconds(2) > std::chrono::steady_clock::now()) { |
| 1724 | IConsolePrint(CC_WARNING, "[{}] Client #{} is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id); |
| 1725 | cs->lag_test = 1; |
| 1726 | } |
| 1727 | |
| 1728 | if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) { |
| 1729 | /* This is a bad client! It didn't send the right token back within time. */ |
| 1730 | IConsolePrint(CC_WARNING, "Client #{} (IP: {}) is dropped because it fails to send valid acks.", cs->client_id, cs->GetClientIP()); |
| 1731 | cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); |
| 1732 | continue; |
| 1733 | } |
| 1734 | break; |
| 1735 | |
| 1736 | case NetworkClientSocket::STATUS_INACTIVE: |
no test coverage detected