When the demo recording is not stopped properly (e.g. client crashes during recording), the timeline markers and the demo length are not updated.
The length is always set to zero when starting the recording, but uninitialized memory is written for the timeline markers, which causes these demos to likely show the maximum number of markers with some markers possibly being outside the ticks that the demo contains.
This is fixed by initially setting all timeline marker data to zero when starting the recording.
The include of `base/system.h` in `src/engine/shared/protocol.h` is not required and only used transitively in `teamscore.h` for `dbg_assert`.
To avoid adding back the include in `teamscore.h`, the function definitions are moved to the cpp file. Both definitions are moved for consistency.
```
src/engine/shared/snapshot.cpp:219:18: runtime error: signed integer overflow: -2011501152 + -1594687485 cannot be represented in type 'int'
0 0x5593cbc3534c in CSnapshotDelta::UndiffItem(int const*, int*, int*, int, int*) src/engine/shared/snapshot.cpp:219
1 0x5593cbc3852d in CSnapshotDelta::UnpackDelta(CSnapshot*, CSnapshot*, void const*, int) src/engine/shared/snapshot.cpp:442
2 0x5593cbb881a6 in CDemoPlayer::DoTick() src/engine/shared/demo.cpp:624
3 0x5593cbb9a907 in CDemoPlayer::Update(bool) src/engine/shared/demo.cpp:1016
4 0x5593ca9f44da in CClient::Update() src/engine/client/client.cpp:2628
5 0x5593caa199dd in CClient::Run() src/engine/client/client.cpp:3220
6 0x5593caa970f3 in main src/engine/client/client.cpp:4717
7 0x7fe086d04d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
8 0x7fe086d04e3f in __libc_start_main_impl ../csu/libc-start.c:392
9 0x5593ca55e6f4 in _start (build-demofuzz/DDNet+0x24936f4)
```
```
src/engine/shared/snapshot.cpp:693:28: runtime error: left shift of negative value -1
0 0x55cae1608071 in CSnapshotBuilder::NewItem(int, int, int) src/engine/shared/snapshot.cpp:686
1 0x55cae1603fe0 in CSnapshotDelta::UnpackDelta(CSnapshot*, CSnapshot*, void const*, int) src/engine/shared/snapshot.cpp:390
2 0x55cae15544c6 in CDemoPlayer::DoTick() src/engine/shared/demo.cpp:624
3 0x55cae1566c27 in CDemoPlayer::Update(bool) src/engine/shared/demo.cpp:1016
4 0x55cae03c07fa in CClient::Update() src/engine/client/client.cpp:2628
5 0x55cae03e5cfd in CClient::Run() src/engine/client/client.cpp:3220
6 0x55cae0463413 in main src/engine/client/client.cpp:4717
7 0x7fbc7d855d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
8 0x7fbc7d855e3f in __libc_start_main_impl ../csu/libc-start.c:392
9 0x55cadff2aa14 in _start (build-demofuzz/DDNet+0x2493a14)
```
Instead of using hardcoded tick offsets, use the current/previous/next tick values from the demo info.
This fixes seeking the next tick not working for demos where the difference between the current and the next tick was greater than 3.
Each time the client disconnected or stopped a demo, it tried to delete the previous temporary replay file, which causes an error message "could not delete file" to be shown in the console.
This is prevented by clearing the current filename of the demo recorder after deleting the file.
When slicing a demo, also copy the demo markers that are within the sliced segment to the new demo.
This also fixes timeline markers not being added to replay demos, as the replay demos are always created by slicing.
Closes#6116.
6101: Remove check for `pResponseToken`, which isn't used on this code path r=def- a=Robyt3
Closes#6100.
## Checklist
- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)
Co-authored-by: Robert Müller <robytemueller@gmail.com>
6035: Fix various issues reported by cppcheck static analyser r=def- a=Robyt3
After generating `compile_commands.json` with cmake, I ran [cppcheck](https://cppcheck.sourceforge.io/) like this:
```
cppcheck --project=compile_commands.json -DWIN64 --suppressions-list=cppcheck.supp --enable=all 2>cppcheck.log
```
With these suppressions in `cppcheck.supp`:
```
cstyleCast
useStlAlgorithm
unusedFunction
variableScope
noExplicitConstructor
useInitializationList
noConstructor
uninitMemberVar
uninitMemberVarPrivate
uninitDerivedMemberVar
uninitStructMember
uninitvar
shadowFunction
memleakOnRealloc
internalAstError
virtualCallInConstructor
unknownMacro
noOperatorEq
noCopyConstructor
```
Many of these occur too often or are false positives.
Here is a list of all remaining non-suppressed issues reported by cppcheck: [cppcheck.log](https://github.com/ddnet/ddnet/files/9997663/cppcheck.log)
And here is a list of all remaining issues including the suppressed ones: [cppcheck_all.log](https://github.com/ddnet/ddnet/files/9997662/cppcheck_all.log)
I couldn't get cppcheck's command line argument to ignore the external folders to work correctly, so I manually removed those entries from the files.
## Checklist
- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)
Co-authored-by: Robert Müller <robytemueller@gmail.com>
According to cppchecker's `constParameter` error:
```
src\engine\gfx\image_manipulation.cpp:7:58: style: Parameter 'pSrc' can be declared as pointer to const [constParameter]
static void Dilate(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest, unsigned char AlphaThreshold = TW_DILATE_ALPHA_THRESHOLD)
^
src\engine\gfx\image_manipulation.cpp:58:67: style: Parameter 'pSrc' can be declared as pointer to const [constParameter]
static void CopyColorValues(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest)
^
src\engine\shared\network_conn.cpp:241:42: style: Parameter 'Addr' can be declared as reference to const [constParameter]
void CNetConnection::DirectInit(NETADDR &Addr, SECURITY_TOKEN SecurityToken, SECURITY_TOKEN Token, bool Sixup)
^
src\base\system.cpp:4060:71: style: Parameter 'random' can be declared as pointer to const [constParameter]
void generate_password(char *buffer, unsigned length, unsigned short *random, unsigned random_length)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:263:38: style: Parameter 'AllocatedMemory' can be declared as reference to const [constParameter]
void Free(SMemoryHeapQueueElement &AllocatedMemory)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:1708:47: style: Parameter 'ImgExtent' can be declared as reference to const [constParameter]
static size_t ImageMipLevelCount(VkExtent3D &ImgExtent)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:2801:29: style: Parameter 'Image' can be declared as reference to const [constParameter]
void ImageBarrier(VkImage &Image, size_t MipMapBase, size_t MipMapCount, size_t LayerBase, size_t LayerCount, VkFormat Format, VkImageLayout OldLayout, VkImageLayout NewLayout)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6495:46: style: Parameter 'ExecBuffer' can be declared as reference to const [constParameter]
void Cmd_Clear(SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand)
^
src\game\client\components\skins.cpp:83:72: style: Parameter 'pImg' can be declared as pointer to const [constParameter]
static void CheckMetrics(CSkin::SSkinMetricVariable &Metrics, uint8_t *pImg, int ImgWidth, int ImgX, int ImgY, int CheckWidth, int CheckHeight)
^
src\game\client\prediction\entities\character.h:106:37: style: Parameter 'pNewInput' can be declared as pointer to const [constParameter]
void SetInput(CNetObj_PlayerInput *pNewInput)
^
src\game\client\prediction\gameworld.cpp:245:106: style: Parameter 'pNotThis' can be declared as pointer to const [constParameter]
CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, CCharacter *pNotThis, int CollideWith, class CCharacter *pThisOnly)
^
src\game\client\prediction\gameworld.cpp:245:151: style: Parameter 'pThisOnly' can be declared as pointer to const [constParameter]
CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, CCharacter *pNotThis, int CollideWith, class CCharacter *pThisOnly)
^
src\game\client\prediction\gameworld.cpp:283:116: style: Parameter 'pNotThis' can be declared as pointer to const [constParameter]
std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, class CEntity *pNotThis)
^
src\game\client\ui.cpp:522:180: style: Parameter 'pReadCursor' can be declared as pointer to const [constParameter]
void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps, int StrLen, CTextCursor *pReadCursor)
^
src\game\client\ui_scrollregion.cpp:23:86: style: Parameter 'pParams' can be declared as pointer to const [constParameter]
void CScrollRegion::Begin(CUIRect *pClipRect, vec2 *pOutOffset, CScrollRegionParams *pParams)
^
src\game\server\scoreworker.h:239:29: style: Parameter 'aTimeCp' can be declared as const array [constParameter]
void Set(float Time, float aTimeCp[NUM_CHECKPOINTS])
^
src\game\server\score.cpp:135:80: style: Parameter 'aTimeCp' can be declared as const array [constParameter]
void CScore::SaveScore(int ClientID, float Time, const char *pTimestamp, float aTimeCp[NUM_CHECKPOINTS], bool NotEligible)
^
src\game\server\teeinfo.cpp:40:57: style: Parameter 'pUseCustomColors' can be declared as pointer to const [constParameter]
CTeeInfo::CTeeInfo(const char *apSkinPartNames[6], int *pUseCustomColors, int *pSkinPartColors)
^
src\game\server\teeinfo.cpp:40:80: style: Parameter 'pSkinPartColors' can be declared as pointer to const [constParameter]
CTeeInfo::CTeeInfo(const char *apSkinPartNames[6], int *pUseCustomColors, int *pSkinPartColors)
^
```
According to cppcheck's `badBitmaskCheck` error:
```
src\engine\client\client.cpp:422:26: style: Operator '|' with one operand equal to zero is redundant. [badBitmaskCheck]
Packer.AddInt((0 << 1) | (pMsg->m_System ? 1 : 0)); // NETMSG_EX, NETMSGTYPE_EX
^
src\engine\shared\snapshot.cpp:40:45: style: Operator '|' with one operand equal to zero is redundant. [badBitmaskCheck]
int TypeItemIndex = GetItemIndex((0 << 16) | InternalType); // NETOBJTYPE_EX
^
src\engine\server\server.cpp:777:26: style: Operator '|' with one operand equal to zero is redundant. [badBitmaskCheck]
Packer.AddInt((0 << 1) | (pMsg->m_System ? 1 : 0)); // NETMSG_EX, NETMSGTYPE_EX
^
```
According to cppcheck's `unsignedLessThanZero` error:
```
src\engine\shared\datafile.cpp:129:13: style: Checking if unsigned expression 'Bytes' is less than zero. [unsignedLessThanZero]
if(Bytes <= 0)
^
```
The assigned values are never used, so the assignments can be removed or variable scopes can be reduced.
According to cppcheck's `unreadVariable` error.
When stored commands (`CFGFLAG_STORE`) were executed with `CConsole::StoreCommands(false)`, the associated chained commands were not properly executed, if they were chained after the command has been stored (e.g. in `CMenus::OnInit`).
Storing the command saves the current callback and userdata, which were overridden by the chain callback and userdata, but the stored callback and userdata were not updated.
This is fixed by storing a pointer to the command itself, which will be updated when it is chained.
From teeworlds/teeworlds#2572.
The client crashes when trying to unpack a packet that has the sixup flag set, as `CNetClient` does not pass pointers for the output parameters `pSecurityToken` and `pResponseToken` to `CNetBase::UnpackPacket`.
Since the client does not handle sixup packets, checks are added to return an error and ignore the packet instead of crashing due to a null pointer access.
This was found by fuzzing the data returned by `net_udp_recv` with radamsa.
```
==6200==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f8d0fb8ba56 bp 0x7ffcbf67c7f0 sp 0x7ffcbf67c7a8 T0)
==6200==The signal is caused by a WRITE memory access.
==6200==Hint: address points to the zero page.
0 0x7f8d0fb8ba56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x563a7e250fbe in mem_copy src/base/system.cpp:208
2 0x563a7e1bc6b6 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:263
3 0x563a7e1bf57e in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:100
4 0x563a7cfa76a2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x563a7cfb7cf6 in CClient::Update() src/engine/client/client.cpp:2838
6 0x563a7cfcfe47 in CClient::Run() src/engine/client/client.cpp:3214
7 0x563a7d04c631 in main src/engine/client/client.cpp:4702
8 0x7f8d0faf0d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f8d0faf0e3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x563a7cb28754 in _start (build-asan/DDNet+0x2472754)
==8315==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f4accfe5a56 bp 0x7ffcf1318530 sp 0x7ffcf13184e8 T0)
==8315==The signal is caused by a WRITE memory access.
==8315==Hint: address points to the zero page.
0 0x7f4accfe5a56 (/lib/x86_64-linux-gnu/libc.so.6+0xc4a56)
1 0x560413603200 in mem_copy src/base/system.cpp:208
2 0x56041356d9c7 in CNetBase::UnpackPacket(unsigned char*, int, CNetPacketConstruct*, bool&, int*, int*) src/engine/shared/network.cpp:224
3 0x5604135717c0 in CNetClient::Recv(CNetChunk*) src/engine/shared/network_client.cpp:104
4 0x5604123597e2 in CClient::PumpNetwork() src/engine/client/client.cpp:2546
5 0x560412369e36 in CClient::Update() src/engine/client/client.cpp:2838
6 0x560412381f87 in CClient::Run() src/engine/client/client.cpp:3214
7 0x5604123fe771 in main src/engine/client/client.cpp:4702
8 0x7f4accf4ad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
9 0x7f4accf4ae3f in __libc_start_main_impl ../csu/libc-start.c:392
10 0x560411eda894 in _start (build-asan/DDNet+0x2472894)
```
Demo seeking for percent positions and relative time was choppy, when the first and last ticks of the demo are very large but close together (e.g. with 1308908156 to 1308905658, which are close to integer limit).
During the calculation of `WantedTick` both operands were promoted to `float`s, which caused the information of the smaller operand, i.e. the seeked percentage or relative time, to be mostly lost, so seeking was very inaccurate.
This is fixed by rounding the `float` operand to `int` before adding it to another `int`.
The types are translated to `TYPE_ALL`/`TYPE_SAVE` respectively if a given path is relative and to `TYPE_ABSOLUTE` if a path is absolute.
These types are only supported with the `OpenFile`, `ReadFile`, `ReadFileStr` and `GetCompletePath` methods.
This reduces duplicate code when calling the methods.
5599: Add support for Rust code in DDNet r=def- a=heinrich5991
The glue is done using the [cxx crate](https://cxx.rs/) on the Rust side.
As a proof-of-concept, only a small console command (`rust_version`) printing the currently used Rust version was added.
You can generate and open the Rust documentation using `DDNET_TEST_NO_LINK=1 cargo doc --open`.
You can run the Rust tests using `cmake --build <build dir> --target run_rust_tests`, they're automatically included in the `run_tests` target as well.
Rust tests don't work on Windows in debug mode on Windows because Rust cannot currently link with the debug version of the C stdlib on Windows: https://github.com/rust-lang/rust/issues/39016.
---
The stuff in `src/rust-bridge` is generated using
```
cxxbridge src/engine/shared/rust_version.rs --output src/rust-bridge/engine/shared/rust_version.cpp --output src/rust-bridge/engine/shared/rust_version.h
cxxbridge src/engine/console.rs --output src/rust-bridge/cpp/console.cpp --output src/rust-bridge/cpp/console.h
```
Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This function searches in all subfolder of the given folder and fills the given `std::vector` with all files with the given filename.
A `std::set` is used to prevent duplicate entries when a file with the same path is present in multiple storage locations. In that case we only need the path once, as we only use it against the highest priority storage location anyway.
5770: Fix physics change by weak hook fix (fixes#5769) r=def- a=fokkonaut
<!-- What is the motivation for the changes of this pull request -->
fixes#5769
## Checklist
- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)
Co-authored-by: fokkonaut <35420825+fokkonaut@users.noreply.github.com>
Co-authored-by: Jupeyy <jupjopjap@gmail.com>
Slicing a demo opened from command line with an absolute path did not work, as the game only tried to load the source demo from storage instead of using the given absolute path.
The glue is done using the [cxx crate](https://cxx.rs/) on the Rust
side.
As a proof-of-concept, only a small console command (`rust_version`)
printing the currently used Rust version was added.
You can generate and open the Rust documentation using
`DDNET_TEST_NO_LINK=1 cargo doc --open`.
You can run the Rust tests using `cmake --build <build dir> --target
run_rust_tests`, they're automatically included in the `run_tests`
target as well.
Rust tests don't work on Windows in debug mode on Windows because Rust
cannot currently link with the debug version of the C stdlib on Windows:
https://github.com/rust-lang/rust/issues/39016.
---
The stuff in `src/rust-bridge` is generated using
```
cxxbridge src/engine/shared/rust_version.rs --output src/rust-bridge/engine/shared/rust_version.cpp --output src/rust-bridge/engine/shared/rust_version.h
cxxbridge src/engine/console.rs --output src/rust-bridge/cpp/console.cpp --output src/rust-bridge/cpp/console.h
```
Pass the original string to the unknown command callback instead of the parsed command, as the latter ends at the first whitespace, which breaks for unknown commands (filenames) containing spaces.
Closes#5902.