Setting a vote timeout longer than 60 seconds with `sv_vote_time` caused the vote network messages to be discarded with the error message `weird message 'Sv_VoteSet' (15), failed on 'm_Timeout'` by the client, as the protocol did not allow longer vote timeouts.
This changes the protocol so the vote timeout can be any positive integer although for now the maximum `sv_vote_time` value is changed back to 60 again to preserve compatibility with old clients.
Closes#7583.
The invalid sound index is `-1` but the check in the editor for the sound preview assumed it was `0`. We should use a type-safe wrapper to avoid this in the future, like for texture handles.
The popup menu render function can open/close other popups, which may resize the vector of popup menus and thus invalidate the current popup menu variable before the popup is closed. We therefore store the popup UI element ID in a separate variable to avoid the access to the potentially invalidated popup menu variable after the popup menu is rendered.
Also prevent invalidated popup menu from being rendered for one frame after it is closed by clicking outside.
Closes#7565.
Support registering arbitrary number of interfaces with `IKernel` instead at most 32.
Assert when incorrect arguments are passed to `IKernel` functions instead of returning a `bool`, which was not being handled in all cases. These functions are not expected to fail expect on programming errors.
Consistently order and format creation and registration of kernel interfaces in client and server.
Additionally, ensure snapshots are cleared and dummy is disconnected when disconnecting programatically with `DisconnectWithReason`.
Add `NETADDR_ZEROED` and `UUID_ZEROED` for more convenient initialization without using `mem_zero`.
Add stricter error handling when converting between UTF-16 (wide characters) and UTF-8 (multi-byte) on Windows.
The `windows_wide_to_utf8` function now returns an `std::optional`, which will be empty if the argument contains invalid UTF-16. Files/folders with names containing invalid UTF-16 are now ignored on Windows. It was previously not possible to use these files either, as converting their names to UTF-8 changed the invalid codepoints to unicode replacement characters.
The `windows_utf8_to_wide` function now fails with an assertion error if the argument contains invalid UTF-8, as this should never happen.
Closes#7486.
Add `CHttpRequest::ExpectSha256` function to specify expected SHA256 for HTTP downloads. If the download completes with a different SHA256 hash than expected, then the download fails and the file is deleted.
Closes#7485.
Move all code for handling of config variables from console to config manager. The console no longer depends on the config manager, instead the config manager now depends on the console.
Add `struct`s to manage config variables of different types (int, color and string). The config manager now keeps a list of all config variables, so usage of the preprocessor can be avoided except for code to initially create all config variables. Additionally, a separate list of just the game config variables (config variables with `CFGFLAG_GAME`) is kept to optimize the `ResetGameSettings` function, as this function is called whenever connecting to a server and should be fast. Previously, this function was even less efficient because it preformed a linear search for every individual game config variable to find the respective command data.
Move console commands that opperate only on config variables (`reset`, `toggle` and `+toggle`) to config manager. Ensure that these commands only opperate on the desired config variables (client or server, respectively) by checking `IConsole::FlagMask`.
Add `IConfigManager::SetReadOnly` function to set/unset config variables as read-only instead of manually overriding the command handlers for the `sv_rescue` and `sv_test_cmds` config variables. This also fixes that read-only config variables could still be changed by using the `reset` command. A console message is now printed when trying to change a read-only config variable. Removing the special handling for these two config variables is additionally useful so the console does not need to keep a pointer to config values and manager.
Use a `CHeap` for the config variables, their help texts and the previous values of string config variables to avoid many separate allocations as well usage of static variables. Also use the heap to store the unknown commands instead of using `std::string`s.
Properly trigger command chain when resetting config variables with the `reset` command and when resetting game settings on map loading. Closes#7461.
Format default value for color variables as RGB/RGBA hex with dollar sign prefix. Closes#5523.
Add log message when using `reset` with a variable that does not exist. Use `log_error` instead of `dbg_msg` when saving config file fails.
Support unlimited number of config save callbacks instead of at most 16. The code also becomes more readable by using an `std::vector` instead of a fixed-size array and a separate num variable.
Consistently name `MACRO_CONFIG_*` parameters when declaring the macros.
Add `IConsole::CMDLINE_LENGTH` constant to represent the maximum length of the console input and thereby reduce usage of magic numbers for buffer sizes.
Add a templated `CHeap::Allocate` function to simplify memory allocation of objects using `CHeap`. The function uses perfect forwarding to construct objects with the specified arguments.
Apply the name bans system also to player clans, meaning players joining with banned clan names are kicked and changing the clan to a banned name while ingame has no effect.
Additionally, trim UTF-8 whitespace from beginning and end of clan. This was already done for player names but not for clans.
Closes#7516.
Unify all code for name bans in new class `CNameBans` in the existing `name_ban.cpp/h` files. The previously global function `IsNameBanned` is now the member function `CNameBans::IsBanned`. The existing name ban tests are extended for the `CNameBans` class.
Move `CNameBan` constructor definition to source file to avoid including `system.h` in the header file. Use `bool` instead of `int` for `m_IsSubstring`. Reorder `CNameBan` constructor arguments and remove unnecessary default value.
The contents of `variables.h` are moved to `config_variables.h` instead of being included with the preprocessor. The file `variables.h` is removed, so all config variables can be found in a single file instead of being spread over two files without any clear structure. The original declaration order of config variables is preserved. The unnecessary header guard `GAME_VARIABLES_H` from `variables.h` is removed, as the comment `// This file can be included several times.` already serves the same purpose of silencing the header guard check.
A comment is added at the end of `config_variables.h` to mark the location where modders should ideally declare all of their own config variables to avoid merge conflicts with us in the future.
Closes#7472.
Interfaces should not have member variables, so the variable is moved to `CConsole`. Only a getter `IConsole::Cheated` is added because the cheated state of the console is never reset.
So other interfaces/components can check which console commands are active. In particular this will be used to refactor the config manager. The respective setter function already exists.
After you issue a command in the client console or rcon, the command
will first be printed to the console prefixed with a '>' symbol.
Cherry-pick of https://github.com/teeworlds/teeworlds/pull/3185
Due to swapped `str_copy` arguments, the old value for string game variables was being overridden by the current value instead of the other way around in `CConsole::ResetGameSettings`.
There are currently no string game settings affected by this.
Handling color settings the same as int settings in `CConsole::ResetGameSettings` is not correct, as this causes the color variable data to be cast to int variable data.
There are currently no color game settings affected by this.
Call expected server callback functions to simulate clients dynamically connecting and disconnecting when changing the `dbg_dummies` variable. This makes the debug dummies more useful for debugging. Previously, the debug dummies were considered invalid clients, whereas they are now considered to be ingame, so they should behave mostly like real clients being connected to the server. The debug dummies also have correct client names now, e.g. "Debug dummy 42".
The game server code is cleaned up by moving all special handling for debug dummies to the engine server function `CServer::UpdateDebugDummies`.
The left/right direction inputs for debug dummies are now properly added to the client input array, so their input handling should be consistent with normal clients, which fixes some inconsistent prediction with debug dummies.
Greyscale images with alpha channel (i.e. channel count = 2) were incorrectly handled as RGBA images, causing the client to crash when loading such images. Now the images can successfully be loaded with the image loader, but the client still only supports loading RGB and RGBA images like before.
The image data is freed when the image format is unsupported, but `CImageInfo::m_pData` would still point to the freed memory, so double-frees were possible.
Gets rid of more CGameControllerDDRace casts.
Those did not show up during compile time only during runtime
of another active controller when asan is active.
Also update server browser filtering/sorting when changing the community/country/type filter config variables with the console.
Clean the filter config variables when they are changed instead of only when the community filter is rendered.
Ensure that community/country/type filters do not exclude all allowed elements, which can happen when a previously selected community is not available anymore or when arbitrary community filter values are set with the console.
Allows to do this
```C++
for(const CPlayer *pPlayer : GameServer()->m_apPlayers)
{
if(!pPlayer)
continue;
if(!pPlayer->GetCharacter())
continue;
// your code that does not change the character state
}
```
Initialize nontrivial types with a constructor instead. Make the
compiler aware that some of our constructors are indeed trivial.
This allows `mem_zero` calls to actually always zero the memory.
Partially replaces #5690.
POD types are just memset. Other types are either destructed if not
trivial and/or constructed if not trivial. Types need to have a default
constructor.
Virtual classes can be mem_zeroed only if they already have been
constructed, otherwise it is UB.
Zeroing the entire ringbuffer memory is unnecessary and inefficient. Only the first item in the ringbuffer has to be initialized properly.
It's unlikely that existing code depends on allocated memory being zeroed, as recycled ringbuffer items where never zeroed.
Previously, the client would hang due to recursive usage of the console backlog lock when a log line is printed via the logger functions while already owning the backlog lock. This could happen when the text render causes log messages to be printed while the console backlog is rendered.
This is fixed by introducing a separate pending backlog to which new log lines are initially added and which is protected by a lock. The pending backlog entries are pumped into the normal backlog before the normal backlog is used, so accesses to the normal backlog do not need to be locked anymore. This means the console backlog lock is not owned when calling any functions that could print log messages, which should prevent the dead lock.
When creating a non ddrace controller and it uses `IGameController::GetMaskForPlayerWorldEvent`
it will crash:
#0 0x00007ffff72ac83c in ?? () from /usr/lib/libc.so.6
#1 0x00007ffff725c668 in raise () from /usr/lib/libc.so.6
#2 0x00007ffff72444b8 in abort () from /usr/lib/libc.so.6
#3 0x00007ffff749ca6f in __gnu_cxx::__verbose_terminate_handler () at /usr/src/debug/gcc/gcc/libstdc++-v3/libsupc++/vterminate.cc:95
#4 0x00007ffff74b011c in __cxxabiv1::__terminate (handler=<optimized out>) at /usr/src/debug/gcc/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48
#5 0x00007ffff74b0189 in std::terminate () at /usr/src/debug/gcc/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58
#6 0x00007ffff74b03ed in __cxxabiv1::__cxa_throw (obj=<optimized out>, tinfo=0x7ffff766c0e8 <typeinfo for std::out_of_range>, dest=0x7ffff74c85c0 <std::out_of_range::~out_of_range()>) at /usr/src/debug/gcc/gcc/libstdc++-v3/libsupc++/eh_throw.cc:98
#7 0x00007ffff74a025f in std::__throw_out_of_range_fmt (__fmt=<optimized out>) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/functexcept.cc:101
#8 0x00005555555bd4a3 in std::bitset<64ul>::_M_check (this=0x7fffffffbb90, __position=0xffffffffffffffff, __s=0x5555557a9881 "bitset::reset") at /usr/include/c++/13.2.1/bitset:823
#9 0x00005555555f83e0 in std::bitset<64ul>::reset (this=0x7fffffffbb90, __position=0xffffffffffffffff) at /usr/include/c++/13.2.1/bitset:1196
#10 0x000055555560262a in IGameController::GetMaskForPlayerWorldEvent (this=0x555555b113d0, Asker=0x0, ExceptID=0xffffffff) at /home/chiller/Desktop/git/ddnet/src/game/server/gamecontroller.cpp:728
#11 0x000055555560be0f in CPlayer::TryRespawn (this=0x55555592e500 <gs_PoolDataCPlayer>) at /home/chiller/Desktop/git/ddnet/src/game/server/player.cpp:695
#12 0x000055555560a1a6 in CPlayer::Tick (this=0x55555592e500 <gs_PoolDataCPlayer>) at /home/chiller/Desktop/git/ddnet/src/game/server/player.cpp:249
#13 0x00005555555e174b in CGameContext::OnTick (this=0x7ffff477d010) at /home/chiller/Desktop/git/ddnet/src/game/server/gamecontext.cpp:964
#14 0x00005555555a7e34 in CServer::Run (this=0x7ffff57d5010) at /home/chiller/Desktop/git/ddnet/src/engine/server/server.cpp:2893
#15 0x0000555555592a2b in main (argc=0x1, argv=0x7fffffffd178) at /home/chiller/Desktop/git/ddnet/src/engine/server/main.cpp:197
Also increase usage of the `GetDDRaceTeam()` method.
Instead of reimplementing it in place everywhere.
move `m_Teams` from the ddrace controller to `IGameController`
so the ddrace controller casts can go away
This will enable creating another controller instead of the ddrace
controller. Which is useful for community forks.
Also make `m_Teams` private and define a getter for it.
This makes future refactors smoother.
On Unix, the encoding of filenames is unspecified, although UTF-8 is likely used in most cases. Detecting and converting from several possible encodings to UTF-8 would be too much effort, considering that most systems already use UTF-8 per default. Therefore, any filenames which are not valid UTF-8 will be ignored when listing directories with `fs_listdir(_fileinfo)`, `fs_storage_path` will fail if the storage location is not valid UTF-8 and `fs_getcwd` will fail if the current working directory is not valid UTF-8. Paths specified in `storage.cfg` must also be valid UTF-8.
On Windows, we already ensure that all filenames are converted to UTF-8.
The check for multiple storage locations was using the base path from the previous invocation of the file dialog instead of using the new base path.
Closes#7463.
When the `CGameContext::SendChatTeam` function is used to send a chat message to all members of a DDTeam (e.g. on completed /swap chat command), it was not checked whether the target players are online but only whether they belong to the specified team according to the teams core. However, the default team for unconnected/cleared players is 0 in the teams core, which is the same for players in team 0, so chat messages were being sent to client IDs not corresponding to connected clients when chat messages where supposed to be sent to players in team 0. This was causing the server to crash with the assertion error "erroneous client id" specifically when the server is started with `sv_max_clients` being less than the default, maximum 64.
Closes#7450.
Simplify selecting envelope point colors by showing a color picker button that opens a color picker popup to change the color of the selected envelope point. The existing editbox to change only the selected channel's value is kept, as the color picker popup does not support the same precision to specify the individual color channel values.
Closes#7317.
When using ctrl+s to test the current envelope it should not activate
the scale mode. This causes unexpected envelope changes on ctrl+s based
envelope fine tuning testing.
Use `CLock` and `CLockScope` instead of `std::mutex` and add clang thread-safety analysis annotations everywhere except for usages in engine graphics and video, as those usages also involve `std::condition_variable`.
Fix lock not being unlocked on all code paths in `CFutureLogger::Log`, which is caught by the static analysis.
Replace usages of platform specific `lock_*` functions with `std::mutex` through the wrapper class `CLock`. Move lock classes to `base/lock.h`.
The `CLock` wrapper class is only necessary because the clang thread-safety attributes are not available for `std::mutex` except when explicitly using libc++.
Round to nearest integer instead of truncating in `f2fx` to ensure correct round-trip with `fx2f`.
Add test to ensure correct round-trip with maximum `0.0005f` absolute error.
After the error message popup is shown for graphics assertions, the client window was destroyed but the process was not terminated properly. Now the graphics assertion error is handled like a normal assertion error, as those are also shown in an error message popup and correctly cause the client to break into the debugger or terminate.
However, calling `dbg_assert` while already owning the lock that `WaitForIdle` waits on will cause a deadlock, so error handling must be delayed until after the lock is released.
The buffer size for assertion messages is increased, as it was not sufficient for some graphics assertions.
The `ICommandProcessor::GetError` and `ICommandProcessor::GetWarning` functions are marked as `const`.
Add buttons for selecting the color mode (RGBA, HSVA, HSLA) in color picker popups in menu and editor. Previously, the color picker popups always showed the color components in HSVA. Now the mode can be switched so the components are shown in either RGBA or HSLA. The hex color code is always RGBA, same as before.
In the editor, the RGBA mode is used per default, to prevent any loss of information due to color conversions, as the map format stores RGBA values. In the menus, the HSVA mode is the default, same as before, although the config actually stores HSLA values.
The HSVA color picker controls (1D slider for hue, 2D picker for saturation and value) are still shown for all modes.
As many color conversions as possible are avoided by only converting between color formats when necessary. Switching between color modes should not change the selected color. Changing the RGBA hex value in the editor will set the exact value also when another color mode is selected. However, changing the color with the other controls in HSVA/HSLA mode will cause a conversion and possible loss of information. The conversion directly from RGBA to HSVA and vice versa is also explicitly avoided, as this internally converts to HSLA first, which is done separately already.
Closes#7409.
Previously, the client would crash with an assertion when writing more than 1024 items, 1024 data items or 64 extended item types to a map file. This arbitrary limitation is removed by using `std::vector`s, so much larger maps can be written. This was only a limitation when writing map files. Old clients can correctly read the map files having more items/data but will crash when the map is saved in the editor.
Remove the DDNet and KoG tabs and replace them with a community filter, which works like the country and type filters. Community information (ID, name, icon SHA256, countries, types, servers, ranked maps) is loaded dynamically from the DDNet info json.
The official checkmark icon is replaced with community icons. The icons are downloaded to the `communityicons` folder in the config directory from a URL specified in the DDNet info json. The icons are only re-downloaded when their SHA256 has changed.
Per default, the Internet tab with all communities is selected. When starting the client for the first time, only the DDNet community is selected. The community, country and type filters can also be used on the Favorites tab now. The LAN tab remains unchanged.
The country and type filters are refactored. Previously, using these filters changed the total number of servers and players that were displayed, as the filter was implemented as a separate step. Now the community, country and type filters work like the other browser filters. This also has the benefit that the server list and DDNet info json are not reloaded each time these filters are changed, as updating the local filtering/sorting is enough now.
The check for finished maps is made more efficient by using an `std::unordered_set` instead of linear search.
Closes#5654.
Some calls to `LoadTextureRaw` where passing the image format also in place of the texture load flags. Since the image format would be RGBA most of the time, this was interpreted as the flag `IGraphics::TEXLOAD_NOMIPMAPS` causing various textures (all sprites textures, assets when shown in menus, menu images, menu theme icons) to be loaded without mipmaps.
This is fixed by passing `0` as the texture load flags and by replacing uses of `LoadPNG` and `LoadTextureRaw` with `LoadTexture`.
Rename `InvalidTexture` to `NullTexture` to avoid confusion because the null texture is not invalid. The function `CTextureHandle::IsNullTexture` is added to make it easier to check the result of using `IGraphics::LoadTexture`, which returns the null texture on error instead of an invalid texture handle. An assertion is added to ensure that `IsNullTexture` works correctly.
The handle returned by `LoadTextureRaw` is either valid or invalid (i.e. `-1`) but never the invalid texture itself.
Additionally, ensure that the `LoadTexture` function returns the invalid texture also when `LoadTextureRaw` fails.
Load theme icons individually for all themes that have been loaded instead of doing a separate scan of the `themes` folder for the icons.
Fix screen occasionally flashing black when opening the general settings. This was caused by `UpdateAndSwap` randomly being called when theme loading takes longer than 1/60 seconds, which sometimes happens on the first start of the client after rebooting the machine. Now the loading popup is correctly rendered when theme loading takes longer than 500ms, which is consistent with the behavior when loading other files.
Minor improvements to log messages.
Using `CMenus::PopupWarning` will immediately set the popup and override the current warning, which can hide warnings when multiple are shown at the same time. Now all warnings are added to the queue with `IClient::AddWarning`.
Add assertions to prevent map items and data that are too large to be represented by the map format from being written to maps. Additionally, ensure that the size of the whole map file is not too large to be represented by the map header.
Prevent `malloc` of size 0, which is implementation defined and should be avoided, when adding items without data, which happens for example when adding an empty array of envelope points.
Show a warning popup when a map image or sound cannot be loaded for any reason. Only one generic warning popup is shown for images and sounds individually.
The image name is only required for external images. For embedded images it was only used in log messages. This fixes rendering with various maps that have embedded images with invalid names.
Parallax Zoom improves the appearance of maps visually when zooming.
Contrary to initial tests, it does not interfere with certain map
locations such as the shop on the map Timeshop.
The default value appears to be correct for all existing maps.
The value in the map file is non-trivial to manage, and provides little
benefit. See https://github.com/ddnet/ddnet/issues/6196 for further
discussion.
Limit number of sounds being loaded in the client to 64, instead of writing sample indices out of bounds.
Check if sound indices are out of bounds. It was only checked whether the sound index is -1 but no other bounds checking was performed.
Check if image indices are out of bounds. It was not checked for all negative image indices, only -1 was considered.
Add popup message in the editor when trying to add more than 64 sounds, same as for images.
Limit number of images in `map_convert_07` tool, instead of writing out of bounds.
Add easter, halloween and xmas to `enum ETimeSeason` and `time_season` function. This unifies the logic for detecting these events and seasons in one function. This allows adding support for special easter, halloween and xmas theme maps in the future. The `localtime` function is not used outside `system.c` anymore. The code for detecting easter is taken from upstream.
Check whether the demo file has been closed due to a playback error when calling `DoTick` in loops, to prevent crashes on operating systems with assertions for correct C library usage. On Windows, `warning: Invalid parameter passed to C runtime function` was printed to the debug console in this case.
Ensure server password can fit username and password separated by colon, so there is no discrepancy where some passwords work in rcon but not for reserved slots.
There is no need to limit the length of server password, rcon username, rcon password and rcon commands when packing them into their respective messages. The source buffers for these strings are already limited in length and the message packer ensures that the maximum packet size is not exceeded.
Add parameter `int Conn` to `SendInfo` and `SendReady` functions and use existing `SendEnterGame` function to reduce duplicate code for sending the same messages for main and dummy connections.
Use `m_aCurrentDemoSelectionName` and `m_DemolistStorageType` for the demo render popup instead of using `m_DemolistSelectedIndex`, which can be invalid when the demo render popup is not opened from the demo browser.
Closes#7347.
The host lookup job and the engine interface are independent so they are moved to separate files.
The include of `engine.h` in `client.h` is therefore unnecessary and other includes also had to be adjusted because of this.
The variable `m_VersionServeraddr` is unused and therefore removed. The host lookup job is currently not used on the client-side.
Previously, the IME candidate window was aligned with the top-right corner of the text bounding box (when rendering the text until the caret offset). This does not work correctly for text spanning multiple lines, causing the IME candidate window to be displayed at the X position of the longest line instead. Additionally, text clipping in the chat was not considered, as `CLineInput` is not aware of the clipping implemented in `CChat`, causing the IME candidate window to be moved up too far.
This is fixed by getting the correct rendered position of the caret offset using `m_CursorRenderedPosition`. Vertical alignment is also changed so only one line of text is considered, which makes the behavior more consistent with Windows' native IME candidate window and avoids larger changes in `CLineInput` to make it aware of clipping.
Handle the return values of all uses of the `io_read`, `io_skip` and `io_tell` functions in `CDemoPlayer`, to handle truncated demo files and other unexpected file reading and seeking errors during demo playback.
Show more detailed error message popups when demos cannot be loaded due to errors and when demo playback is stopped unexpectedly due to errors. Previously, only a generic message "Error loading demo" was shown when loading failed and no error message was shown when demo playback is stopped due to errors.
Add checks to ensure that the ticks read from demo chunk headers are in the valid range (cf. `MIN_TICK` and `MAX_TICK` constants). Playing demos with invalid ticks is prevented entirely, as the invalid ticks would cause issues in other places. The server never uses ticks outside the valid range, so invalid ticks should never occur in correctly recorded demos.
Additionally, checks are added to detect if a tickmarker chunk with a tick delta occurs before a tickmarker chunk defining an initial tick. The tick delta is only meaningful when an initial tick has already been defined, so if this is not the case the demo is also considered invalid.
Make the title of warnings adjustable, with the default title being "Warning" to preserve existing code.
Make auto-hiding configurable, so the automatic closing of warning popups after 10 seconds can be toggled.
The function returns 0 on success and -1 on error, as it delegates to `io_seek`, instead of returning the number of bytes skipped, which the documentation previously suggested. The return type is changed from `unsigned` to `int`, as this is also the type of `io_seek` and this better handles -1 as a return value.
We only show the string value directly in the UI instead of using the demotype enum literals. There also should not be any reason to change any logic depending on whether the current demo is a server- or client-demo.
The SHA256 was effectively not optional anymore when recording demos, as it and the SHA256 extension UUID were always written to the demo file without checking for `nullptr`. Therefore the SHA256 is now passed by const reference instead of by pointer and redundant checks for `nullptr` are removed.
We already use `CClient::LoadMapSearch` to load maps for demo playback, so maps in the `maps` folder are already considered. Using the map CRC is deprecated, we do not want to check it.
Using an `std::vector` is simpler and more readable than first allocating a linked list on a heap and later copying the list to an array.
The variable `m_SeekablePoints` is removed from `CPlaybackInfo`, as it does not need to be exposed outside of `CDemoPlayer` and can be replaced with the size of the vector.
The client/server jobpools were previously only using a fixed number of 2 threads. Now the pools use `2 * hardware-concurrency + 2` threads, which should provide better performance overall, as we expect threads to often wait on I/O.
The player info snapshot item (`CNetObj_PlayerInfo`) has its own `m_ClientID` member variable in addition to the generic snapshot item ID. The snapshot item ID was only used to set `m_Snap.m_LocalClientID` but without being checked for invalid values. Now it is checked that both IDs are identical and only `m_ClientID` is used consistently.
The map version was only checked if the version item is present, which is different from how client and editor load maps. Now a missing version item is considered an unsupported version. Additional log messages are also added to the tools.
Previously all demo players checked `IVideo::Current` to render a video, which would cause issues when rendering a demo while a demo slicing background job is running. Now video rendering can be toggled for each demo player individually and is only enabled for the main demo player.
Use member instead of static variables for demo player snapshot data. The static variables would otherwise cause issues when multiple demo players are playing at the same time, especially demo players used in background jobs for replay demo slicing. This hopefully closes#7068.
There is no reason to slice a demo while currently rendering it and it may cause issues because multiple demo players would access the same `IVideo` instance.
Use composition instead of inheritance for demo player listener to avoid temporarily storing a pointer to a local variable in a member variable.
Fix demo player file not being closed when demo recorder file cannot be opened during demo slicing.
Add assertions to check that demo recording/playback is not started when already running.
Add assertions to check that demo recording/playback is stopped before the respective demo recorder/player is destroyed.
The filename editbox and buttons of the demo render popup were rendered excessively large on Android. While too small buttons could be an issue with smaller screens, this should not be implemented solely this popup, if Android support is revived in the future, as it makes the UI layout code harder to maintain.
The TODO in the `Dilate` function is removed, as the code already appears to be safe without additional checks. The variable `k` is at most `(w * h - 1) * BPP`, as `ix` and `iy` are clamped to maximum `w - 1` and `h - 1` respectively. Because `p < BPP - 1` the index `k + p` is therefore always valid for the buffers. (The caller must ensure that the source and destination buffers are of size `w * h * BPP`.)
The entire `CEditorImage` was being overwritten when loading external images, which was causing the already loaded image name to be cleared, due to the changed order of operations (regression from #7008). This is fixed by using `CImageInfo` to load the image and only copying the relevant members to the `CEditorImage`.
This class is slightly more light-weight than a CEditorComponent
and its naming makes it more natural to inherit for envelope points,
proof-mode positions etc.
Improve layout of demo browser buttons, search and checkbox. Use icons for most buttons. Decrease size of UI elements.
Move demo details from below the file browser to a side panel on the right, which is the same size as the server browser side panel. Use ellipsis to truncate the SHA256 instead of rendering only half of it with reduced font size. Show "map not included" instead of "0.00 KiB" for the map size of demos that don't include a map.
Remove the "Markers" column, as it is not very useful to see for all demos and sort by.
Closes#7275.
When using the demo filter and the selected demo name does not match any visible demo item, temporarily reset the selected demo index instead of keeping an incorrect demo index. This makes the behavior consistent with the server browser.
The popup to show the completed demo rendering was also shown when the demo to be rendered could not be loaded or if the demo render popup was cancelled. Now the popup is only shown when the demo rendering was successful.
The layout of the popup is made consistent with other message popups. Long text is wrapped over multiple lines instead of decreasing the font size.
Simplify the usage of datafile reader and writer by adding utility functions to read and write zero-terminated UTF-8 strings.
Improve validation of string data read from datafiles. It is ensure that string data is null-terminated, has no internal NUL-characters and is valid UTF-8.
Fix loading of external sounds in the editor. The wrong path variable was being used, so the sound files would not be loaded from correct folder.
Add tests for new datafile reader/writer functions.
When `IMap::Load` fails, other components will continue to use the old map. However, if `IMap::Load` failed after the map was already successfully read with the datafile reader then other components kept their pointers to the old, invalid datafile reader items and data, causing random crashes in collision code. This is fixed by using a separate datafile reader to read the new map and only applying the datafile reader globally when loading was entirely successfully.
An error message is added for the case that a map has an unsupported version, which is currently the only case where a map can fail to load after the datafile was read successfully.
In particular, the block maps `blmapPepe`, `blmapV5` and `blmapDT-UPTU` did not have a version map item and were fixed separately.
Closes#7218. Regression from #5737.
Add error message in editor when loading a map that has an unsupported version.
Ensure error messages are not closed immediately when loading a map fails.
Remove unnecessary indentation by returning early.
The pixel size (bytes per pixel) always has to be 4 for the `Dilate` function to work correctly. This is already checked before calling the function, so the redundant argument which is always `4` can be removed.
Store client IDs of all victims for team killmessages instead of storing only the first victim ID, so the render info for all victims can be properly restored when skins are updated.
Ensure all killmessages are properly initialized.
The wrong color channel count was being used for loading images that use an indexed color palette, which was causing the loading to fail with the error "bytes in row incorrect". Now the correct color channel count is retrieved using the libpng API.
Closes#7157.
Avoid duplicate `SetColor` calls in loop.
Avoid `QuadsDrawTL` calls by batching quads together before drawing.
Use `SetColor` instead of `SetColorVertex`.
Remove unnecessary check for duplicate menu images. Listing directories with the storage now prevents duplicates, so this additional check is not needed anymore.
Ensure menu images are in RGBA format.
Ensure menu image names are not truncated.
Minor code format improvements.
The server list was being resorted every frame when the server details of a favorite server were being rendered, which was causing the FPS to drop by a factor of 5.
Use config manager to reset `ui_page` to the default, instead of using `CMenus::PAGE_DDNET` directly (which is the default).
Check current type of serverbrowser instead of checking the current `ui_page` against `CMenus::PAGE_DDNET` and `CMenus::PAGE_KOG`.
Using `dbg_stress 1` now only does the following (in debug build):
- Randomly send inputs.
- Randomly send chat messages.
- Randomly connect/disconnect to server configured with `dbg_stress_server` (`localhost` by default).
Previously it also did the following, which is not useful for this debugging feature and only complicates the code unnecessarily:
- Cause images and sounds not to be loaded.
- Render only every tenth frame.
- Always use inactive graphics refresh rate.
Instead of keeping track of a permanently empty `CSnapshot` object in client and server separately, add `CSnapshot::EmptySnapshot` to access a singleton empty `CSnapshot`.
Mark pointer parameters of snapshot functions as `const` when possible.
This mostly reverts #6937 by making our `IOHANDLE` effectively `FILE *` on all systems again. We still use `CreateFileW` to open a `HANDLE` initially so we can specify the necessary flag so the file can be moved/deleted while open, which we can't do with the `FILE *` based `fopen` functions on Windows. This brings back the automatic I/O buffering on Windows, causing significantly less system calls when saving files. Closes#7226.
Simplify the handling of free texture indices by using `-1` only for indices which are currently in use, whereas the size of the vector is now used to indicate the last free index. Otherwise the assertions incorrectly detect the last texture index always being in use because `-1` was used for both states.
Previously, if the demo header strings did not contain zero-termination, the client would render the strings and any following non-zero memory from the demo header.
Now, demos will not be loaded, if any string in the header is not zero-terminated or not valid UTF-8.
When using `auth_remove`, the key indices for the default helper, mod and admin passwords were not properly adjusted, causing the wrong passwords to be used for the username-less logins.
The key indices for connected clients were also not properly adjusted, causing the wrong identity to be shown for currently authenticated clients when using the `status` command.
Closes#6427.
Most variables used in the sound engine were static globals, as they are used in the static sound mixing function. The global variables are replaced by member variables, by passing the sound interface as user-data for the SDL mixing callback. The `Mix` function is made a public member function of `ISound` instead of being exposed using `ISoundMixFunc GetSoundMixFunc()`.
This allows to remove the direct dependency of the engine sound on the engine video, by instead passing the sound mixing function as a lambda to the engine video in the engine client.
The old WavPack reader function interface does support passing a user-data pointer to the callback function, so global variables are still used here.
Respect the intratick when displaying the player position, speed and angle, to fix this information always being shown for the next tick. See #6417. This does not resolve the issue yet, as there are more HUD and player elements that need to make use of the intratick.
Fix highlighted text of server browser entries not being refresh correctly when switching tabs.
This also reduces lag when switching tabs, as the UI elements for all tabs are now cached and don't need to be recreated when switching.
Regression from #7203.
Replace existing hard-coded support for two "networks" with support for a dynamic list of "communities" which are indexed by a string-ID, though right now the DDNet and KoG communities are still hard-coded. The communities now also support an arbitrary number of associated countries, types and servers. This is a refactoring to prepare for getting the list of communities dynamically from the server and removing the DDNet and KoG tabs from the serverbrowser.
New UI elements were being created for every server info after refreshing the server list. At the same time, old UI elements were not being deleted when the server info objects are deleted. The use of `mutable` for this purpose was also rather unclean.
Now, a separate `std::vector` of UI elements is kept for all server browser entries, instead of associating the UI elements directly with the server info.
Move the "Filter", "Info" and "Friends" tabs to the top, above the tab content. Use icons instead of text for the tabs. Use animator to animate the tabs on mouse-over. Closes#6613.
Make spacings, corners and font sizes used in the filter, details and friends tabs more consistent.
Remove some unnecessary dark UI rect backgrounds.
Improve alignment of the number of friends with the heart icon for entries in the server list.
Improve layout of countries and types filters. Make the filters scrollable when there are many entries.
Refactor most of the server browser in preparation for replacing the DDNet and KoG tabs with a community filter, which will work like the countries and types filters. Split rendering of different server browser sections into multiple functions to improve readability. Reduce duplicate code for the countries and types filters.
Remove `Is` from the getter names for the same reason that removing `Get` from the name is preferred. The word `Is` was inconsistently used as a prefix in `CScrollRegion` but as an infix in `CListBox`.
- Remove unnecessary variable `Page`.
- Use `IGraphics::CORNER_NONE` instead of `0` and instead of the inconsistent-looking `CORNER_BR` for the KoG-button.
- Simplify UI rect layout.
The world tuning is a part of the world. This way the entities implementation
use the same API as available on the client side.
This change is a step toward unified/shared world logic for client and server.
Make the skipping duration adjustable with a dropdown menu. The dropdown menu includes the durations 1s, 5s, 10s, 30s, 1m, 5m and 10m. The default duration is 5s. Skipping durations longer than the current demo are not shown. The dropdown menu is only shown if two or more durations would be shown.
Add buttons for skipping the duration, which was previously only possible with the hotkeys.
Add Ctrl+Left/Right hotkeys for skipping to chapters.
Add Shift+Left/Right hotkeys for adjusting the skipping time.
The Left/Right arrow keys and the J/L keys work identically for all hotkeys now.
Ignore ctrl, shift and alt keys for demo speed changes with the mouse wheel, to better support actions like zooming being bound to alt+mousewheel etc.
Also handle keypad enter key for play/pause like the normal return key.
Use arrow up/down icon for speed adjustment buttons, so that the "backward/forward" icons can be used for duration skipping instead.
Closes#7064.
The DDTeam colors were previously generated in HSL by taking the team index and multiplying it by 360/64° to calculate the hue, which results in team colors being evenly distributed over the entire color range like a rainbow. However, this causes colors of adjacent teams to be very similar and therefore hard to distinguish.
Now, the hue is calculated by multiplying the team index with the golden angle (~137.50776°) and taking the modulo 360° of that. Due to the properties of the golden angle, this can generate never repeating sequences of unique colors where the adjacent colors are very distinct.
Duplicate code is reduced by adding the `CGameClient::GetDDTeamColor` function.
Reduce the space reserved for the label by the space for the dropdown icon instead of rendering the label behind the icon.
This is more noticeable with smaller dropdown menu buttons, which will be used in the future.
1. Regardless of the pause the message is CL_SETTEAM and there is no
reason to match it against other messages.
2. Another implementation can save the wanted team and apply it later.
When the buffer of a lineinput is modified externally, the cursor offset and selection are not updated, which causes them to be rendered wrong and also causes the assertion error "Selection and cursor offset got desynchronized" when changing the selection of a lineinput.
Check if maximum number of lines has been reached before starting a new line, to prevent the text cursor from reporting the wrong number of lines and text height in that case.
Don't truncate console lines at 255 bytes anymore. Especially lines containing many Unicode characters would be adversely affected by this limitation.
Instead, truncate console lines after 10 wrapped lines are rendered. Rendering too many lines at once currently breaks the console scrolling. Rendering an ellipsis is currently not possible when rendering text with a maximum line count.
Increase buffer sizes to handle long (esp. invalid) command inputs.
Closes#7132.
If the player slots update the 0.7 clients have to be informed
about it. Otherwise the client can block the join button
if the outdated playerslots are filled already.
Use `WaitForPipeDrain` to deterministically wait for the pipe to drain instead of using `Start-Sleep`.
Use `Dispose` instead of `Close` to properly flush and close the pipe stream.
Add error handling for connection timeout and I/O errors.
Handle `ERROR_BROKEN_PIPE` separately when peeking at pipe, as this happens when the pipe is disconnected immediately after connecting it or after reading the previous message.
Don't ignore `ERROR_BAD_PIPE` anymore, as the pipe should never be in a disconnected (i.e. bad) state at this point of the function.
Use `enum EImageFormat` type for image format literals and variables.
Add `PixelSize` function to get the number of bytes/color channels per pixel for a specified image format.
Remove unused store format argument of texture loading functions. All textures are automatically being stored as RGBA, so the argument was unused. Also remove the therefore unused `FORMAT_AUTO`.
Rename variables consistently to `PixelSize` and use `size_t`, instead of mixing different names like `BPP` and `ColorChannelCount`.
Validate image format loaded from maps using `CImageInfo::ImageFormatFromInt`. Add `FORMAT_ERROR` to represent invalid formats.
Remove redundant `PixelSize` parameter from graphics backends and commands, which can be derived from the texture format.
Fix memory leak when RGB image data is being converted to RGBA format when saving map in editor.
For some tooltips, the associated UI element ID was not being set as hot item, which is required for tooltips.
The tooltip for the "Dummy settings" checkbox was only present on the tee settings page but not on the player settings page.
Closes#7107.
This config variable was only settable in the server console but only read in the client, so it was effectively unusable. It also has no use case right now.
This makes it more obvious where text is localized. This class was also broken for localized strings with context, since the member variable `m_ContextHash` was uninitialized.
The log message is otherwise shown multiple times when starting the client.
Now it's only shown when the `record` command is used manually, i.e. not for automatically recorded demos anymore.
When the text cursor/selection mode is set to calculate, values of `-1` are used when the selection is empty. These values were not being handled anymore due to a regression from #7028. This was causing the selection to be set to the last position instead, which was causing text to subsequently be inserted there instead of at the cursor position.
An assertion is added to ensure that the selection cannot be desynchronized from the cursor position anymore.
Closes#7099.
CGameClient::OnPredict() says "don't predict anything if we are paused"
and yet we predict different stuff based on CGameClient::Predict() result
which leads to flickering here and there (e.g. for projectiles and characters).
Render a pause/play icon in the center of the screen when pausing/unpausing while the menu is not active.
The icon fades in and out over 0.5 seconds and slightly increases in size over that time.
When starting demo rendering with initial pause, the pause indicator is rendered continuous until playback is first started, to ensure that the initial pause state is communicated clearly to the user. The initial pause indicator is not included in the rendered demo, but pausing and unpausing later during demo rendering will cause it to be included in the video, same as other UI elements. Closes#7044.
The config variable `cl_demo_show_pause` (`0/1`, default `1`) is added to hide the pause indicator entirely, for example to render a demo with multiple pauses without the indicator.
The pause indicator and also the existing speed indicator are not rendered (anymore) while the menu is active, as the menu already contains this information.
Add more efficient function for formatting integer values as strings.
A benchmark shows that using this function is significantly faster than using `str_format`. It is faster by a factor of 220 with Clang 15.0 O2 (https://quick-bench.com/q/BlNoLnlyqxipf4jvsFTUxKMHDJU) and by a factor of 11 with GCC 12.2 O2 (https://quick-bench.com/q/Fxf9lDCTqXBF4pIa_IyZ5R0IqYg).
This increases FPS in the editor by ~25% when many numbers are rendered for switch/tele/speedup/tune layers or with "Show Info" being enabled.
The additional static analysis for `std::to_chars` revealed that the wrong size was used in `CHud` for `aScoreTeam[TEAM_RED]` and `aScoreTeam[TEAM_BLUE]`.
This requires incrementing the macOS deployment target from 10.13 to 10.15.
When connecting to the SQLite database fails, e.g. because the `.sqlite` file is corrupted, the server would crash with the assertion "Tried connecting while the connection is in use" when a player joins and performs any action.
This is fixed by resetting the use-flag when connecting to the SQLite database fails, which is the same behavior as for the MySQL database connection.
It was not actually necessary to clear the brushes to prevent the crashes. The crashes were fixed by not storing the texture handles for the layers anymore.
Closes#7024.
Add a button to manually reload the entities background map instead of automatically reloading it when it's changed. As the background map was only reloaded every 10 seconds, sometimes changing the background map quickly had no effect.
Improve the layout of the DDNet settings menu. Align labels and UI elements and reduce unused empty space.