Split the user storage location and the data folder in the app specific external storage in the folders `data` and `user` instead of writing the user setting directly to the external storage.
Remove unnecessary storage permissions. The client only accesses files in its own external storage location, hence these permissions are not necessary for Android API 19 and higher, which is always given as we only target API 19 and higher.
Only unpack changed assets when their hash in the integrity index is different instead of unpacking all assets again, so the app starts faster after updates. Avoid unpacking the entire integrity index file unless it changed, by initially reading only the first hash directly from the asset, so the app starts faster when the data is up-to-date.
Add error handling for external storage not being accessible and other I/O errors during unpacking of assets.
Add `android_main.h` header to export the `InitAndroid` function and potentially other functions in the future. The `extern "C"` and `__attribute__((visibility("default")))` attributes seem to be unnecessary, as this function is only called directly from the native code like many other functions without these attributes.
Initialize the Android storage after the loggers, so the log message are printed properly.
Add documentation for the use of `std::exit` on Android, which is used to forcefully terminate the entire process, to ensure that static variables will be initialized correctly when the app is started again after quitting. Returning from the main function is not enough, as this only results in the native thread terminating, but the Java thread will continue. Java does not support unloading libraries once they have been loaded, so all static variables will not have their expected initial values anymore when the app is started again after quitting.
Use `fs_chdir` and `fs_makedir` instead of `chdir` and `mkdir`.
Time score will now always be used for any game with the flag `GAMEINFOFLAG_TIMESCORE` set in the `CNetObj_GameInfoEx` object. If the flag is not set, points score is used instead.
Backwards compatibility for old demos, that were recorded without this net object and flag, is removed. For old demos, points score is always assumed now.
Closes#6700.
This reverts commit caa062c88c.
As this decreased FPS and caused the background quad to be rendered twice when using a map background in entities mode.
Always force landscape orientation to be used for the game on Android.
Hide the title bar so it is not shown when starting the game. There is also a bug with SDL currently that leads to the title bar and status bar being shown permanently after minimizing and reopening the app, which is alleviated by hiding the title bar.
Always use black color to clear the window with all graphics backends, instead of using `cl_background_color` or `cl_background_entities_color`, respectively, as the clear color. The respective map background color is rendered using a quad in `CMapLayers` instead, so this should not affect appearance of maps. This does not have any noticeable effect on FPS. Previously, the unused part of the window (when it is resized smaller than 5:4 aspect ratio), was colored using the map background color, whereas now it will be cleared black consistently.
The color parameters of the `IGraphics::Clear` function and of the `SCommand_Clear` command are removed, as we always expect the screen to be cleared black now.
The parameter `ForceClearNow` of the `IGraphics::Clear` function was already unused previously and is also removed.
Interpret fast repeated presses of the back-button (3 times within 1 second) as a quit-event, so the app can be quit cleanly and quickly without using the UI. The client settings are otherwise not saved if the app is closed by minimizing it using the home button and waiting for the OS to kill it or by discarding it in the recent apps view.
Translate the Android back-button to the escape-key, so it can be used to navigate back in menus, open/close the ingame menu, close the editor etc.
Trap the Android back button by setting the `SDL_ANDROID_TRAP_BACK_BUTTON` hint, so it can be handled in our code reliably instead of letting the system handle it.
The graphics backends only support the RGBA format with the `SCommand_Texture_Create` and `SCommand_Texture_Update` commands, so the `TexFormatToOpenGLFormat`, `TextureFormatToVulkanFormat` and `TexFormatToNewOpenGLFormat` functions and the command member variables for the format are unnecessary. The `TexFormatToNewOpenGLFormat` function was unused.
Add additional checks to ensure that the `CVideo::Stop` function and the functions called by it will correctly stop the current video also if the video was not started successfully, i.e. if `CVideo::Start` returned `false` from any of the error branches.
In the `CVideo::Stop` function, iterate over the vectors of video and audio threads directly instead of using `m_VideoThreads` and `m_AudioThreads`, which do not reflect the actual count if the initialization failed before the threads were created.
In the `CVideo::Stop` function, only call `av_write_trailer` if the video recording was stated successfully, i.e. only if `avformat_write_header` was called successfully, as this will otherwise cause the client to crash. Closes#6375.
In the `CVideo::Stop` function, only call `avio_closep` if the format context was allocated.
In the `CVideo::FinishFrames` function, ensure that the codec has been allocated and opened, otherwise using it is not allowed.
Add assertions to the `CVideo::Start` and `Stop` functions to ensure that the same video is not started/stopped multiple times.
Crash with assertion when the size of the graphics is different from the video currently being rendered, instead of causing weirder bugs and a corrupted video file.
The wrong sampling rate was being used for video recording if the client is not restarted after changing the `snd_rate` config variable.
Ensure that the correct bit rate is used if the sample rate was adjusted because the selected value is not supposed.
Use `log_error` for all errors and consistently format all error messages.
Handle all ffmpeg errors and output the formatted ffmpeg error message when possible.
Register a log callback for ffmpeg log messages to delegate them to our logging system, to fix the log messages being interleaved with our log messages and not using the correct line breaks on Windows.
Stop video and demo immediately and show an error message popup if the video could not be started successfully.
Remove unnecessary debug output from ffmpeg.
Removed member prefix m_ used for local variables.
Removed all b, c, i hungarian notation prefixes for boolean, const and integers.
Fixed local variables using lower_snake_case instead of UpperCamelCase.
Renamed all ``float wSearch = TextRender()->TextWidth..`` to ``float SearchWidth = ..``.
Fix leak of pending future logger log messages if the future logger is not set, in particular when the `logfile` config variable is not set or the file could not be opened, by setting a logger that discards all log messages in this case.
Closes#8265.
When changing the screen width, height or refresh rate config variables to 0 or negative values, which are not allowed by the backend, automatically revert the config variables to the actual values again to ensure that the config variables stay in sync with the state of the window. This fixes the client crashing in the graphics settings when setting the screen width and height to 0 via the console, which causes a division by zero when calculating the aspect ratio.
According to the documentation, this function returns `0` on success and a negative number (error code) otherwise, which would cause an allocation of an invalid size.
The third parameter of the `op_read` function specifies the remaining size of the buffer, but we always passed the total size of the buffer without respecting the position at which the data is written into the buffer.
Set the data pointer of the sample only when the sample has been loaded successfully, so the invalid sample data is not freed again when decoding fails.
Otherwise the snapshots may incorrectly be invalidated because a change of the `cl_dummy` variable is detected when connecting to another server after disconnecting while the dummy is active.
Send dummy ready and enter game when connection is online based on its state instead of when the security token is not unknown anymore, which should effectively be the same condition but more understandable. This is also how it's already done for the main connection so the `SecurityTokenUnknown` function can be removed as it's unused now.
The console was not keeping its current scoll position if entries from the backlog are removed due to being recycled when new entries are added. For this purpose, a callback function is added to the ringbuffer to handle popped items, so the scrolling position of the console can be updated based on the number of lines of the removed backlog entries.
Add optional filename argument to `start_video` command, to start recording to a video file with a specific filename, instead of always using the current timestamp.
Add log messages to `start_video` and `stop_video` commands to indicate success and errors.
Make the `CClient::StartVideo` function non-`static` and reduce duplicate code in the `Con_StartVideo` function.
Determine the video filename outside of the `CVideo` constructor, same as for demos.
Fix game times and prediction not being updated when only exactly two snapshots have been received, due to the conditions `m_aReceivedSnapshots[...] >= 3`. These specific condition are not necessary and replaced with simpler checks whether the current snapshot is set. Some duplicate nested conditions are also removed.
Pump the network first in `CClient::Update` before updating anything else, to ensure that snapshots are received from the network client before the game times and prediction are being updated based on the current snapshots.
Fix current and previous game tick always being `0` on the first call of `IGameClient::OnNewSnapshot` when two snapshot have been received. Now, the game ticks are properly initialized from the two initial snapshots.
Fix old inputs sometimes being used in prediction after changing map because inputs with tick `-1` were not being ignored.
Ensure all snapshots and game times are properly cleared when entering the game.
Clear current server info when playing demos to ensure that the score kind (points, time) is detected correctly. Previously, when playing a demo with points score kind and `cl_demo_assume_race 0`, the score was not shown as points when the last server that the client connected to had a race gametype.
Move the implementation for `cl_demo_assume_race` together with the rest of the demo server info initialization in the `CClient::DemoPlayer_Play` function.
These conditions are contained in an `if(State() == IClient::STATE_ONLINE)` branch and the state does not change while inside this branch, so these checks are unnecessary.
For the internet/favorite tabs, instead of combining the country/type filters of all communities in one view, track the country/type filters separately for these tabs using the new, reserved community name `all`. This should make the filters less confusing to use, as changing the country/type filters in one tab will not influence the other tabs anymore. Though the country/type filters of the internet and favorite tabs are still combined, as this is also the case for the community filter.
However, this made it possible to select country/type filters that exclude all servers, by first excluding some countries/types and then changing the selected communities so all selectable countries/types are excluded. To prevent this, the filters will now include all countries/types, if they would otherwise exclude all selectable countries/types.
To do this more efficiently, the community cache is moved from the menus to the engine serverbrowser. To avoid using the UI page in the engine serverbrowser, the serverbrowser type is instead used to detect if the community cache should be updated. This required additional changes in the menus to ensure that the UI page and the serverbrowser type stay in sync with each other, which would otherwise cause incorrect server entries to be shown for one frame when switching tabs. The serverbrowser type is now refreshed immediately when the menu page is changed with the `CMenus::SetMenuPage` function, which allowed removing duplicate code for the server browser tab buttons. The `CMenus::RefreshBrowserTab` function does not take the page to be refreshed as argument anymore, as it always was only used to refresh the current page. Instead, a `bool` argument is used to specify whether the refresh should be forced even if the server browser type has not changed.
Closes#8158.
Adding the snap to the demo is the last usage of `pTmpBuffer3`
all prior usages of it copy the data if needed.
So we can edit it in place. No need to copy it into a new buffer.
Simply hide the favorite community tabs in the offline server browser with screen resolutions where not enough width is available.
The ingame server browser can always show at least 5 favorite community tabs with all screen resolutions.
Pass `CImageInfo` arguments to various graphics and text render functions instead of passing the components (data pointer, width, height, format/pixel size) of the image info separately.
Pass texture/file name to loading functions when available to improve error/warning messages.
Invalid UTF-8 will not be read from config files with `CLineReader` anymore and the local console never allowed entering invalid UTF-8, so this additional mangling of invalid UTF-8 string config variable values is unnecessary.
The engine graphics do not need to be involved with freeing image data.
The `Free` function now also ensures that all other member variables are cleared when freeing the image data.
The `unknown address` log message got printed very often because many servers have 0.6 and 0.7 addresses but only 0.6 addresses are considered valid by the client.
`CNetConsole` will now ignore received lines containing invalid UTF-8 codepoints. Previously, it was possible to crash the server on Windows with Econ commands like `exec <invalid UTF-8>`.
Previously, usage of `void *`, `unsigned char *` and `uint8_t *` was mixed in various places for pointers to raw image data and the pointers ended up being cast to `uint8_t *` at some point anyway. Now only `uint8_t *` is used consistently, which improves type safety and readability. Casts to `uint8_t *` are now only necessary when using `malloc` or when reading data from a map.
We want to change the state of the job from `STATE_QUEUED` to
`STATE_RUNNING`, but not from `STATE_ABORTED`. Previously, the code
usedd `exchange` to change the state and compared non-atomically
afterwards. This led to `STATE_ABORTED` being replaced by
`STATE_RUNNING` in a race. With `compare_exchange_strong`, this can no
longer happen.
Fixes#8044.
Fix HTTP client effectively shutting down by entering the `ERROR` state when a request cannot be added. Now only the invalid request is aborted immediately. The `ERROR` state is now only entered when a curl function fails in a way where recovery is not possible.
Fix occasional deadlock when HTTP client is shutting down after entering the `ERROR` state, by also immediately aborting new requests when the HTTP client is already in the `ERROR` state.
Remove unused `CHttp::EState::STOPPING`.
When image blitting is supported by the Vulkan backend, the color picker was reading incorrect pixel values, because the offset positions for the blitting region are the positions of the top-left and bottom-right corners, but instead the top-left offset and size (width, height) were passed as arguments.
Closes#8040.
Instead of defining the macro `WIN32_LEAN_AND_MEAN` and sometimes also the macro `_WIN32_WINNT` in each file that directly or indirectly includes `<windows.h>`, only define these macros once consistently in `CMakeLists.txt`.
Also define `NTDDI_VERSION`, which is the new macro to specify the minimum Windows version starting with Windows Vista. This macro needs to be defined in addition to old `_WIN32_WINNT` macro, according to the documentation.
See https://learn.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers
Add `IJob::Abortable(bool)` function which jobs can call to specify whether they can be aborted. Jobs are not abortable per default. Abortable jobs may have their state set to `IJob::STATE_ABORTED` at any point if the job was aborted. The job state should be checked periodically in the `IJob::Run` function and the job should terminate at the earliest, safe opportunity when aborted. Scheduled jobs which are not abortable are guaranteed to fully complete before the job pool is shut down. However, if the job pool is already shutting down, no additional jobs will be enqueue anymore and abortable jobs will immediately be aborted.
In particular, the sound loading, community icon loading, master chooser and host lookup jobs are specified as being abortable. Conversely, the jobs saving replay demos, editor maps and screenshots are expected to finish before the client is shut down.
When the client is quitting/restarting, it will now disconnect from the current server first, before saving the config, to ensure that any actions that happen on disconnect (demo recorders being stopped etc.) happen first. The shutdown message is rendered before disconnecting and waiting for background jobs to finish.
The HTTP client is now initialized later during server launch, after the network initialization. Error handling is added and the server stops if the HTTP client could not be initialized, same as the client.
The `RunBlocking` functions are removed, as they are not used anymore after curl-multi was added.
The function `IJob::Status` is renamed to `State` and `IJob::STATE_PENDING` is renamed to `STATE_QUEUED` for consistency with naming of the HTTP client.
The member variables of the engine interface are encapsulated and the `jobs.h` include is removed from `engine.h`, which removes transitive includes of `system.h`.
Documentation for all job and job pool API is added.
Matching the requester allows "reliable" and "unreliable" pings.
"Reliable" pings suffer from re-sends, thus might not accurately reflect
the latency, "unreliable" pings might not arrive at all.