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.