Commit graph

1077 commits

Author SHA1 Message Date
bors[bot] dd09c59710
Merge #6269
6269: Fix ddnet.org change in UUIDs r=def- a=heinrich5991

One case was a ddnet.tw UUID's string being changed (but the UUID was not), and the other case is a ddnet.tw UUID's string being changed in one place but not in another in documentation.

Fixes the commit c479230d71.

CC #5312

## 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: heinrich5991 <heinrich5991@gmail.com>
2023-01-12 16:45:27 +00:00
heinrich5991 f2530cfbf2 Add forgotten call 2023-01-12 16:18:03 +01:00
heinrich5991 a0221c3038 Fix ddnet.org change in UUIDs
One case was a ddnet.tw UUID's string being changed (but the UUID was
not), and the other case is a ddnet.tw UUID's string being changed in
one place but not in another in documentation.

Fixes the commit c479230d71.

CC #5312
2023-01-12 15:38:17 +01:00
Robert Müller 179e3b1c4c Register application separately to specify its displayed name
The application itself must also be registered in a separate registry key, so its displayed name can be set.

See: https://learn.microsoft.com/en-us/windows/win32/shell/app-registration
2023-01-02 17:35:16 +01:00
Robert Müller 6e28ca6fe4 Extract method IStorage::GetBinaryPathAbsolute 2023-01-02 15:29:43 +01:00
bors[bot] b252f2e344
Merge #6199
6199: Register protocol and file extensions on client launch on Windows r=def- a=Robyt3

When launching the client on Windows, associate the protocol `ddnet` and the file extensions `.map` and `.demo` with the client executable.

See #6072.

## 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>
2023-01-02 12:58:15 +00:00
Robert Müller a3e48bef27 Prevent temporary demo file from being deleted multiple times
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.
2022-12-30 14:20:42 +01:00
Robert Müller a61eec8f1e Add DDNet settings button to unregister protocol and file extensions
Add a button to the Miscellaneous DDNet settings to manually unregister the protocol and file extension handlers.
2022-12-29 18:03:08 +01:00
Robert Müller db3d1f19a9 Register protocol and file extensions on client launch on Windows
When launching the client on Windows, associate the protocol `ddnet` and the file extensions `.map` and `.demo` with the client executable.
2022-12-29 18:03:08 +01:00
bors[bot] f230ad0bdc
Merge #6191
6191: Use own defines of format specifiers for MinGW (fixes #6187) r=Jupeyy a=Chairn

Counter proposition to #6188. Redefines our own specifiers

## 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: Chairn <chairn.nq@hotmail.fr>
2022-12-28 20:59:17 +00:00
Chairn 3132c96a80 Use own defines of format specifiers for MinGW (fixes #6187) 2022-12-25 21:18:05 +01:00
Dennis Felsing 779b44fde5 Support .demo and .map files being dragged into client
Only tested on macOS, but should work everywhere
2022-12-24 01:06:06 +01:00
Dennis Felsing bfe4ced662 Automatically register ddnet:// url handler on macOS
Works automatically on first time running client. Whenever you click on
a URL it is automatically opened in the current client, same as writing
"connect ip:port" into F1.

See https://hublog.hubmed.org/archives/001154 and
https://wiki.libsdl.org/SDL2/SDL_DropEvent
2022-12-24 00:26:35 +01:00
Robert Müller a0553f2d40 Fix editor smooth zooming when joining/reloading game
Using `IClient::LocalTime` for smooth zooming in the editor causes the zoom to behave incorrectly when joining a game, as the local time is reset when joining a game.
This is fixed by adding a separate `IClient::GlobalTime` which is only set once when the client launches and never resets.
2022-12-15 18:18:06 +01:00
Robert Müller 144a69266c Fix client attempting to delete user directory when stopping replay demo
When the client stops a replay demo and tries to remove the temporary file when being disconnected, it's not checked whether a recording of a replay demo has ever been started.
In this case the filename is empty, which leads to the client trying to delete the user's directory, which will fail with an error message, as it's a folder and cannot be deleted with the function designed for deleting files.

This is fixed by calling the function `DemoRecorder_Stop` to delete the temporary demo file, as this function already makes sure that the filename is not empty.
2022-12-11 15:05:31 +01:00
Robert Müller 6d8fad775d Encapsulate m_ResortServerBrowser inside CServerBrowser
The variable `m_ResortServerBrowser` was only used in the client to pass it to the server browser. For better separation of concerns, this variable is moved inside `CServerBrowser` and the function `RequestResort` should be called to set it to `true`.

The existing variable `m_SortOnNextUpdate` is replaced with this, as it served the same purpose already. The variable name from upstream is used to reduce conflicts.
2022-12-05 23:15:35 +01:00
bors[bot] cf6e89c319
Merge #6035
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>
2022-12-05 20:00:07 +00:00
Robert Müller ca58bba82f Remove redundant bitwise operand
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
                         ^
```
2022-11-29 23:32:28 +01:00
Robert Müller 2e2cb47674 Fix client crash when launching with screenshot command
The client crashes when launching with `screenshot` in the command line, as the graphics are not available when the command is executed.
This is fixed by storing the command, so it's executed when everything is ready.
2022-11-29 23:08:52 +01:00
Dennis Felsing 9912e44a9a Also remove appended / 2022-11-29 18:18:12 +01:00
Dennis Felsing 3fcf497850 Remove // in ddnet:// url handler 2022-11-29 18:15:09 +01:00
Robert Müller 7ae5b1474a Add TYPE_ALL_OR_ABSOLUTE and TYPE_SAVE_OR_ABSOLUTE storage types
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.
2022-11-20 16:07:40 +01:00
Robert Müller 04be9d6e72 Add IInput::ShiftIsPressed and IInput::AltIsPressed
To avoid duplicate code when checking for both right and left shift or alt keys.
2022-11-15 21:17:55 +01:00
Robert Müller 7185f028f1 Reduce duplicate code by using loop for snapshot types 2022-11-12 20:31:44 +01:00
Robert Müller c988a71d3e Fix aliasing warnings in CClient::DemoPlayer_Play
Fix warnings with `-fstrict-aliasing` and `-Wstrict-aliasing=2` by using char array instead of array of char pointers:

```
src/engine/client/client.cpp: In member function 'virtual const char* CClient::DemoPlayer_Play(const char*, int)':
src/engine/client/client.cpp:3858:123: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
 3858 |         m_aapSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pSnap = (CSnapshot *)m_aaapDemorecSnapshotData[SNAP_CURRENT][0];
      |                                                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
src/engine/client/client.cpp:3859:126: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
 3859 |         m_aapSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)m_aaapDemorecSnapshotData[SNAP_CURRENT][1];
      |                                                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
src/engine/client/client.cpp:3864:117: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
 3864 |         m_aapSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_pSnap = (CSnapshot *)m_aaapDemorecSnapshotData[SNAP_PREV][0];
      |                                                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
src/engine/client/client.cpp:3865:120: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
 3865 |         m_aapSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_pAltSnap = (CSnapshot *)m_aaapDemorecSnapshotData[SNAP_PREV][1];
      |                                                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
```

Snapshot data during demo playback was being stored in an array of `char *` instead of an array of `char`, which caused above aliasing warnings and used 8 times more memory for the snapshot storage than being necessary.
2022-11-12 20:27:45 +01:00
bors[bot] 06e3eb5641
Merge #6017
6017: Minor refactoring of demo related code r=def- a=Robyt3

Extracted from #6016.

## 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>
2022-11-06 22:00:54 +00:00
bors[bot] b21ba35225
Merge #5599
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>
2022-11-06 21:40:48 +00:00
Robert Müller bbf36a226c Remove dead code 2022-11-06 16:25:25 +01:00
Robert Müller c2d2093c89 Use . for object access instead of getting a pointer first 2022-11-06 16:25:25 +01:00
Robert Müller 84c9506d3c Use loop for demo recorders to reduce duplicate code 2022-11-06 16:25:24 +01:00
Robert Müller a62bf7c334 Write log files to storage unless given as absolute path 2022-11-05 16:30:24 +01:00
Robert Müller c0da3b93e4 Fix IME not being deactivated when editor is closed
Previously the IME was not deactivated when the editor is closed, so `SDL_TEXTINPUT` events where still being reported ingame after exiting the editor.
2022-10-21 21:31:21 +02:00
Robert Müller 75326e8393 Fix text input not working when entering editor with bind
When entering the editor with a custom bind (e.g. `bind e "cl_editor 1"`) or when opening it from the console while also immediately closing the console (e.g. with `cl_editor 1; toggle_local_console`), the IME state was not properly set to active, so SDL did not report any `SDL_TEXTINPUT` events, leading to editboxes in the editor not receiving any text.

The is fixed by always enabling the IME state when entering the editor, which was previously only done when using the Ctrl+Shift+E hotkey or coincidentally when the editor is activated while the IME is already active, i.e. when the menu or console is open.

Closes #5095.
2022-10-21 21:20:10 +02:00
heinrich5991 dcd76fd3e1 Add support for Rust code in DDNet
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
```
2022-10-19 23:46:06 +02:00
bors[bot] 6c3d0e999b
Merge #5933 #5941
5933: Inline `Is(GameType)` functions and remove support for legacy 64 player info protocol r=def- a=heinrich5991

## 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)


5941: Get away from vector for skins r=def- a=Jupeyy

most of the time it uses the index just to get the skin, downloaded skins change the index. Now its simply a heap object and downloaded skins load directly. Also the loading might be a bit faster bcs it had a loop lookup .Also O(1) lookup

not 100% tested. also fixes a bug with favorite skins hopefully
## 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: heinrich5991 <heinrich5991@gmail.com>
Co-authored-by: Jupeyy <jupjopjap@gmail.com>
2022-10-12 22:08:17 +00:00
Robert Müller 4bb549b68e Initialize the Windows COM library on all threads
Use threading model `COINIT_APARTMENTTHREADED` on threads that own a window (the main client thread) and `COINIT_MULTITHREADED` on all other threads.

Add assertions to ensure that the COM library is initialized successfully and only once per thread.

References:

- https://learn.microsoft.com/en-us/windows/win32/learnwin32/initializing-the-com-library
- https://learn.microsoft.com/en-us/windows/win32/com/single-threaded-apartments
- https://learn.microsoft.com/en-us/windows/win32/com/multithreaded-apartments

Yet another attempt at solving #5744.
2022-10-12 17:18:57 +02:00
heinrich5991 a595936fb5 Remove chat timeout code fallback heuristic
KoG is now on the newest version, we no longer need this.
2022-10-12 16:12:02 +02:00
heinrich5991 150485e3b0 Remove support for legacy 64 player info protocol
It was only being used for "Leak IP" favorites and LAN servers. Since
KoG has upgraded to latest DDNet, there aren't much servers left that
don't understand the new 64 player info protocol.

Keywords: fstd, dtsf
2022-10-12 16:12:02 +02:00
heinrich5991 a97a597592 Inline Is(GameType) functions
They are used for two purposes, coloring gametypes in the serverbrowser
and enabling backward compatibility. These are independent, we shouldn't
add more stuff to the backward compatibility, hence I split them up and
inlined them.
2022-10-11 16:05:46 +02:00
def c2d1118c90 Only announce servers using Steam/Discord integration which are registered 2022-10-09 16:16:54 +02:00
ChillerDragon 9982a7bad3 Constify snap more (inspired by upstream)
Incorporate const added in those upstream commits:
d86d576217
e6b8518b49
2022-10-09 15:12:12 +02:00
ChillerDragon b2285855f5 Remove unused SnapInvalidateItem
suggested by @Robyt3 <3
2022-10-09 15:11:58 +02:00
Robert Müller 5825d5eb7f Fix map file argument not opening editor with absolute paths 2022-09-23 19:54:12 +02:00
def 9f4e883906 Remove cl_http_map_download 2022-09-18 01:03:15 +02:00
Learath f91a3069c3 Let CKernel clean-up. Use unused CSound::Shutdown 2022-09-16 16:50:19 +02:00
heinrich5991 716e8cd7f4 Add HTTPS map download URL field for game servers
This allows every game server to provide its own HTTPS server for map
downloads. Since the ingame protocol for downloading map data is very
inefficient, this is desirable. Previously, only servers hosted by DDNet
could benefit from this.

Security concerns:
- Attackers can find out whether a given HTTPS GET request matches a
  known answer.

  This isn't deemed to be problematic as no cookies for authentication
  are sent and only the whole response can be matched.

- Sending requests to honeypot URLs to get people in legal trouble.

  This seems to be already possible with HTML image embeds, so it can't
  be that bad™.

- Downloading huge files, filling up a player's disk. The players might
  cancel when seeing huge files.

  There's a generous limit of 1 GiB per map file.

- Downloading huge files transparently compressed with gzip. See above.

Fixes #5812.
2022-09-15 02:08:35 +02:00
heinrich5991 cb2614ff5c Treat manual aborts the same way as errors for map downloads 2022-09-15 02:08:34 +02:00
Robert Müller fe38caa7b4 Handle path/link arguments using the console argument parser
Add `IConsole::SetUnknownCommandCallback` to set a callback for unknown commands. The callback is used to handle connect links, .demo and .map files when parsing command line arguments.

This will allow paths/links to be passed at any argument position instead of only the first one.

And this fixes the command `play xyz.demo` not working due to `play ` being considered part of the path.
2022-08-30 22:17:04 +02:00
Robert Müller 13961db6a8 Allow demo/map arguments to be relative paths, allow using play
When passing .demo or .map paths as command line arguments, first check if the path can be found in the storage and then try resolving an absolute path.

Also delay execution of the `play` command until the client is ready so the command can be used from the command line. Although it doesn't work if there is only one argument, as this interferes with the .demo file handling.
2022-08-30 21:51:34 +02:00
def c479230d71 Use new ddnet.org domain 2022-08-30 10:09:06 +02:00
Robert Müller 63d0c8e170 Improve error message when map for demo cannot be found
Previously the playback did not start and no error messages was shown, when the map file cannot be found and no map data is embedded in the demo file.

Minor refactoring: Replace instances of `return pError` with semantically identical `return nullptr` to improve readability.
2022-08-25 17:57:04 +02:00
Robert Müller 37cadc5c09 Add CWindowsComLifecycle RAII wrapper for Windows COM library 2022-08-21 10:34:37 +02:00
Robert Müller 967c92f5d6 Encapsulate CGraph member variables
Make the member variables private and add `SetMin` to replace a usage of the member variables in `CDebugHud`. For completeness/symmetry, `SetMax` is also added.
2022-08-12 16:13:23 +02:00
Robert Müller 8c88005a42 Rename variables Array to aLineItems / aColorVertices 2022-08-12 16:13:03 +02:00
Robert Müller 11e60d32f0 Reuse CGraph::InsertAt in Add to reduce duplicate code 2022-08-12 16:13:03 +02:00
Robert Müller 44ca1f0d7b Use size_t for indices, replace unused return value with assert
The return value of `CGraph::InsertAt` was not checked. All uses of the function pass a correct index, so the return value is replaced with an assertion.
2022-08-12 16:13:03 +02:00
Robert Müller 3daa177830 Remove restriction for CGraph::MAX_VALUES to be a power of two
By using `% MAX_VALUES` instead of `& (MAX_VALUES - 1)` to wrap the index. Both work the same, but the latter only does for powers of two.
2022-08-12 16:13:03 +02:00
Robert Müller 8e0a935d5c Combine CGraph::ScaleMin and ScaleMax into Scale
As the methods are always called at the same time, they can be combined. This also improves the performance, as the array only needs to be iterated once.
2022-08-12 16:12:55 +02:00
bors[bot] e8667b6075
Merge #5658
5658: Fix game freezing up on duplicate snapshot r=def- a=Fireball-Teeworlds

If a duplicate snapshot is received (for the same tick), we add both to the SnapshotStorage and end up with the same snapshot as both Cur and Prev. This results in GameInfraTick returning "inf" and results in "NaN" downstream in a few places, getting the CollLine logic stuck.

Some debug info (tcpdump, gdb, perf): https://gist.github.com/Fireball-Teeworlds/ad0016d2551a2e4d4cb5691023493856

Apparently this doesn't really happen in the wild, unless you have a buggy network stack. In which case it happens frequently enough to pinpoint the issue :D

 (fixes #5657)

## 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
- [X] Considered possible null pointers and out of bounds array indexing
- [X] Changed no physics that affect existing maps
- [X] 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: Fireball <fireball.teeworlds@gmail.com>
2022-07-26 13:46:40 +00:00
Fireball 9689301410 Fix game freezing up on duplicate snapshot
If a duplicate snapshot is received (for the same tick), we add both to the SnapshotStorage and end up with the same snapshot as both Cur and Prev. This results in GameInfraTick returning "inf" and results in "NaN" downstream in a few places, getting the CollLine logic stuck.

Apparently this doesn't really happen in the wild, unless you have a buggy network stack. In which case it happens frequently enough to pinpoint the issue :D
2022-07-24 21:57:05 +01:00
Robert Müller 3863d41623 Validate snapshot size and member variables and demo snapshots
Add `CSnapshot::IsValid` to check if a snapshot unpacked from a snapshot delta or demo is valid:
- ensure number of items and data size are not negative
- ensure that the actual size of the snapshot matches the size derived from its member variables
- ensure item offsets are within the valid range
- ensure item sizes are not negative

Add `CSnapshot::TotalSize` and `CSnapshot::OffsetSize` utility functions.

Minor improvements to related error messages.

Fixes buffer overflow:

```
==47744==ERROR: AddressSanitizer: global-buffer-overflow on address 0x558618e3767f at pc 0x558614b9bdfb bp 0x7ffe58a32cd0 sp 0x7ffe58a32cc0
READ of size 4 at 0x558618e3767f thread T0
    0x558614b9bdfa in CSnapshotItem::Type() const src/engine/shared/snapshot.h:16
    0x558615c3c911 in CSnapshot::GetItemType(int) const src/engine/shared/snapshot.cpp:29
    0x558614aebaba in CClient::UnpackAndValidateSnapshot(CSnapshot*, CSnapshot*) src/engine/client/client.cpp:2264
    0x558614af87cb in CClient::OnDemoPlayerSnapshot(void*, int) src/engine/client/client.cpp:2598
    0x558615b9db1a in CDemoPlayer::DoTick() src/engine/shared/demo.cpp:659
    0x558615babd3f in CDemoPlayer::Update(bool) src/engine/shared/demo.cpp:1007
    0x558614afb08b in CClient::Update() src/engine/client/client.cpp:2686
    0x558614b1d9eb in CClient::Run() src/engine/client/client.cpp:3296
    0x558614b8e64f in main src/engine/client/client.cpp:4761
```

And fixes a buffer overflow that manifests itself as an internal ASan error:

```
=================================================================
==4755==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_descriptions.cc:79 "((0 && "Address is not in memory and not in shadow?")) != (0)" (0x0, 0x0)
    0x7f0bf5f368be in AsanCheckFailed ../../../../src/libsanitizer/asan/asan_rtl.cc:72
    0x7f0bf5f54eee in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cc:77
    0x7f0bf5e4cb6f in GetShadowKind ../../../../src/libsanitizer/asan/asan_descriptions.cc:79
    0x7f0bf5e4cb6f in __asan::GetShadowAddressInformation(unsigned long, __asan::ShadowAddressDescription*) ../../../../src/libsanitizer/asan/asan_descriptions.cc:95
    0x7f0bf5e4cb6f in __asan::GetShadowAddressInformation(unsigned long, __asan::ShadowAddressDescription*) ../../../../src/libsanitizer/asan/asan_descriptions.cc:92
    0x7f0bf5e4e386 in __asan::AddressDescription::AddressDescription(unsigned long, unsigned long, bool) ../../../../src/libsanitizer/asan/asan_descriptions.cc:440
    0x7f0bf5e50e94 in __asan::ErrorGeneric::ErrorGeneric(unsigned int, unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long) ../../../../src/libsanitizer/asan/asan_errors.cc:380
    0x7f0bf5f35f4d in __asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) ../../../../src/libsanitizer/asan/asan_report.cc:460
    0x7f0bf5e86f5e in __interceptor_memset ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:762
    0x558234873f1d in mem_zero src/base/system.cpp:213
    0x55823481fc27 in CSnapshotBuilder::NewItem(int, int, int) src/engine/shared/snapshot.cpp:675
    0x55823481be65 in CSnapshotDelta::UnpackDelta(CSnapshot*, CSnapshot*, void const*, int) src/engine/shared/snapshot.cpp:380
    0x558234776641 in CDemoPlayer::DoTick() src/engine/shared/demo.cpp:631
    0x5582347861a9 in CDemoPlayer::Update(bool) src/engine/shared/demo.cpp:1007
    0x5582336d4c7d in CClient::Update() src/engine/client/client.cpp:2695
    0x5582336f75dd in CClient::Run() src/engine/client/client.cpp:3305
    0x558233768241 in main src/engine/client/client.cpp:4770
```
2022-07-24 18:00:39 +02:00
Alexander Akulich 1f264a042d CClient::DemoPlayer_Play: Load map info into m_CurrentServerInfo
This e.g. allows better heuristic in GetGameInfo() (from gameclient.cpp)
2022-07-14 23:38:20 +03:00
heinrich5991 994324b059 Warn about pnglite-incompatible PNGs on load
This allows a larger range of PNGs to be loaded while still maintaining
backward compatibility with older clients by annoying the user.

This warning can be enabled by the `warn-pnglite-incompatible-images`
key in the https://info2.ddnet.tw/info JSON, if the key is not there or
the JSON hasn't been obtained yet, the warning is disabled. Since the
JSON is cached across restarts, it'll be effective for initially loaded
images from the second start.
2022-07-14 18:22:46 +02:00
heinrich5991 7c984df17a Fix UDP connectivity check
The nonsensical index of `m_aNetClients` was introduced during my
rebasing of #5205.

Fixes #5618.
2022-07-11 20:48:28 +02:00
bors[bot] a3001f3bd1
Merge #5205
5205: Allow multiple addresses per server in the serverbrowser r=def- a=heinrich5991

Support is incomplete for `leak_ip_address_to_all_servers` (will only
ping the first address of each server) and for the `leak_ip` setting
(which will also only ping the first address of each server).

Fixes #5158.

## 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 if it works standalone, system.c especially
- [ ] 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: heinrich5991 <heinrich5991@gmail.com>
2022-07-10 23:31:21 +00:00
Robert Müller a971a16ed5 Fix readability-duplicate-include 2022-07-10 21:57:13 +02:00
Robert Müller ec4175277e Fix readability-container-data-pointer 2022-07-10 21:42:57 +02:00
heinrich5991 8996d152ab Allow multiple connect addresses
This allows the client to connect to servers that have both an IPv4 and
an IPv6 address, even if the client is only connected to one of the two.
The one faster to answer will be picked.

Timeout codes are now generated based on *all* of the server's
addresses.

Fixes #5158.
2022-07-10 16:57:10 +02:00
heinrich5991 a9bf09f769 Move websocket address handling out of the client 2022-07-10 16:53:12 +02:00
heinrich5991 6600024f24 Allow multiple addresses per server in the serverbrowser
Support is incomplete for `leak_ip_address_to_all_servers` (will only
ping the first address of each server) and for the `leak_ip` setting
(which will also only ping the first address of each server).
2022-07-10 16:52:07 +02:00
Alexander Akulich 6d9284adc1 Port some code to str_copy() template 2022-07-09 19:40:58 +03:00
Chairn a69dc599a9 Huge variable naming format
Fix pointer and pointer array variable naming

Huge renaming to match our rules

Used regex: (?!(return|delete)\b)\b\w+ (m_|ms_|g_|gs_|s_)[^a]\w+\[
            (?!(return|delete)\b)\b\w+ (?!(m_|ms_|g_|gs_|s_))[^a]\w+\[

Further format static variables

Format almost all pointer names accordingly

Used regex: (?!(return)\b)\b\w+
\*(?!(m_p|p|s_p|m_ap|s_ap|g_p|g_ap|ap|gs_ap|ms_ap|gs_p|ms_p))\w+\b[^:\(p]

clang-format

Fix CI fail

Fix misnamed non pointer as pointer and non array as array

Used regex: (?!(return|delete)\b)\b\w+ (m_|ms_|g_|gs_|s_)p\w+\b
            (?!return\b)\b\w+ (ms_|m_|g_|gs_|s_)a\w+\b[^\[]

clang-format

Revert to SCREAMING_SNAKE_CASE and reinstate dead code
2022-07-08 18:01:29 +02:00
Dennis Felsing ef9299c88d Also make gameclient aware that snapshots have been purged (fixes #5571)
Recreates SnapEntities internally
2022-07-06 15:42:05 +02:00
heinrich5991 e026bce50f Fix out of bounds read in checksum stuff 2022-07-05 10:26:05 +02:00
bors[bot] b79bb7e62a
Merge #5547
5547: Minor tweaks to keep ODR across translation units r=def- a=Jupeyy

<!-- What is the motivation for the changes of this pull request -->

## 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 if it works standalone, system.c especially
- [ ] 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: Jupeyy <jupjopjap@gmail.com>
2022-07-02 13:06:20 +00:00
Jupeyy 7250be6a95 Rename typedef 2022-07-02 14:43:41 +02:00
Robert Müller 8ee821c2f0 Remove unused #include <windows.h> in engine client 2022-07-02 14:02:42 +02:00
bors[bot] 5e7ec64292
Merge #5486
5486: Switch to loading screen, when map creation takes too long r=def- a=Jupeyy

Same as #4941 

It doesn't directly fix the issue described in #5478, it does however not trigger it anymore. it's still a bug in our code unrelated  to this. This just triggered the UB from the issue as  `@ardadem` confirmed, SDL received a SDL_QUIT (`[2022-06-23 20:26:31][test]: sdl closed my client, but why xd`)

Now we have a confirmed case that making the window unresponsive can create weird behavior. Similar to the other pr switch to a loading screen after 500ms (this time without menu background map tho, since the menu background map calls the same code).

We really need some fancy loading screen for such situations, even tho they are rare xD

## 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 if it works standalone, system.c especially
- [ ] 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: Jupeyy <jupjopjap@gmail.com>
2022-06-30 14:36:58 +00:00
Chairn 96e9364fb0 Fix more unsafe define 2022-06-29 23:52:03 +02:00
c0d3d3v 59436b5e6d
Add default values to extended Net Objects 2022-06-27 01:11:19 +02:00
c0d3d3v f819afed6c
Print also extended NetObj and NetMsg Names
Show External NetObjects in Snapshot stats
2022-06-27 01:10:37 +02:00
c0d3d3v 00f28f2c8e
Unpack all 64 Parts of a splitted Snapshot 2022-06-27 01:10:37 +02:00
Jupeyy b62894dad4 Switch to loading screen, when map creation takes too long 2022-06-26 11:56:56 +02:00
Dennis Felsing af1f0de5fb
Merge pull request #5453 from Robyt3/Joystick-Close-Before-SDL-Quit
Fix segfault in `SDL_JoystickClose` on client quit
2022-06-20 23:47:59 +02:00
Robert Müller 3f1f94c9d8 Fix segfault in SDL_JoystickClose on client quit
Instead of closing the joysticks manually, use `SDL_QuitSubSystem(SDL_INIT_JOYSTICK)` to quit the entire subsystem, which will also close all joysticks correctly.

The engine input destructor is replaced with a `Shutdown` method so we can control when it is called, i.e. before calling `SDL_Quit`, which forcefully quits all subsystems.

`CJoystick::Close` is removed as we don't need to close joysticks manually anymore.
2022-06-18 11:57:57 +02:00
Robert Müller 23cce5415e Organize engine-client includes 2022-06-17 17:46:43 +02:00
Robert Müller 32707f6354 Remove unused CVideo constructor argument, organize includes 2022-06-17 17:39:26 +02:00
Robert Müller 93536b8977 Use io_read_all to load font files 2022-06-16 10:19:36 +02:00
bors[bot] b8a82f71aa
Merge #5429
5429: More vector naming format r=heinrich5991 a=Chairn

Following of https://github.com/ddnet/ddnet/pull/5391

## 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 if it works standalone, system.c especially
- [ ] 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: Chairn <chairn.nq@hotmail.fr>
2022-06-15 17:41:08 +00:00
Chairn c9345e7d32 More vector naming format 2022-06-15 19:37:37 +02:00
Robert Müller eb7e210fc1 Separate editor update and render to fix slow joystick input 2022-06-15 17:37:22 +02:00
bors[bot] caf889d04a
Merge #5406
5406: Remove namespace tw r=Jupeyy a=heinrich5991

It didn't have a clear role, it just acted as a distinguisher between
two functions with the same name.

Rename `tw::time_get` to `time_get_nanoseconds` and delete the old
`time_get_nanoseconds`. Move `CCmdlineFix` and the typed
`net_socket_read_wait` function to the global namespace.

## 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 if it works standalone, system.c especially
- [ ] 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: heinrich5991 <heinrich5991@gmail.com>
2022-06-14 17:46:17 +00:00
Robert Müller 92699de86c Add log_set_loglevel instead of depending on engine config 2022-06-13 23:21:41 +02:00
heinrich5991 b3a3604c36 Remove namespace tw
It didn't have a clear role, it just acted as a distinguisher between
two functions with the same name.

Rename `tw::time_get` to `time_get_nanoseconds` and delete the old
`time_get_nanoseconds`. Move `CCmdlineFix` and the typed
`net_socket_read_wait` function to the global namespace.
2022-06-13 18:07:29 +02:00
Chairn 01edaec628 Format vector variables names (fixes #5209) 2022-06-11 21:38:49 +02:00
bors[bot] 37780cbe6f
Merge #5106
5106: Fix dummy intended tick sent to server r=def- a=sjrc6

fixes https://github.com/ddnet/ddnet/issues/5044

Currently the dummy gives the server the wrong IntendedTick aka PredTick which (I think) makes it impossible for the server to correctly order inputs if they come early (i.e. if you're playing with high prediction margin).

Currently with dummy copy if you switch dummy with high prediction margin it will almost always desync, with this change it doesn't desync. 

The only reason dummy works at all is because it relies on this code in the server to change the tick that was sent to be the current game tick, if you remove it then dummy hammer and dummy copy breaks but normal players are unaffected.

e9b59e72ff/src/engine/server/server.cpp (L1632-L1633) 

I marked this PR as draft because it seems to cause some unexpected side effects:

with this change if you use dummy copy in solo part your dummy will be visually delayed, this doesn't change anything but it's different from how it was before and I don't understand why. 

the sound effects from hooking with dummy copy are also not as synced as they are with the wrong tick being sent (not sure why) 

I also didn't test all dummy mechanics or any advanced dummy binds which might somehow rely on the broken behavior. 


With wrong tick sent to server:

https://user-images.githubusercontent.com/22122579/168413464-92a3a44b-3b75-4894-8fb0-54e64ff421fa.mp4

With correct tick:

https://user-images.githubusercontent.com/22122579/168413459-eb6f299c-260a-4ddb-9972-3dea504aef41.mp4






## 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 if it works standalone, system.c especially
- [ ] 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: Tater <Mr.Potatooh@gmail.com>
2022-06-09 21:52:19 +00:00
Dennis Felsing 2fceb1aa27 Paginate bans (partially fixes #3691)
20 elements per page, we have too many bot bans
2022-06-08 23:48:32 +02:00
Robert Müller e6bd84d4fd Extract CCmdlineFix to call cmdline_fix and cmdline_free automatically 2022-06-06 12:46:58 +02:00
trml 2b48c376d6 Fix input getter for dummy 2022-06-06 04:17:55 +02:00
trml 455b17e957 Update prediction to use new input handling 2022-06-02 22:35:10 +02:00
bors[bot] 760cb99574
Merge #5271
5271: Time out for POST requests too (hopefully fixes #5198) r=heinrich5991 a=def-

Untested because the issue is sporadic. But I think it makes sense to have a timeout even if this is not the root cause.

## 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 if it works standalone, system.c especially
- [ ] 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: def <dennis@felsin9.de>
2022-05-31 08:01:38 +00:00
Robert Müller 91d2ba1865 Organize game-client includes 2022-05-29 21:24:43 +02:00
Robert Müller 4b36584ca1 Organize engine-client includes 2022-05-29 21:24:43 +02:00
def 3e60cd83d0 Time out for POST requests too (hopefully fixes #5198) 2022-05-29 19:15:36 +02:00
def a3c1a4c540 Prevent users from setting port 1-1023
Following user report that they set cl_port 1 and it didn't work
2022-05-28 13:42:28 +02:00
bors[bot] e7140caf8b
Merge #5064
5064: Add HTTP masterserver registering and HTTP masterserver r=def- a=heinrich5991

Registering
-----------

The idea is that game servers push their server info to the
masterservers every 15 seconds or when the server info changes, but not
more than once per second.

The game servers do not support the old registering protocol anymore,
the backward compatibility is handled by the masterserver.

The register call is a HTTP POST to a URL like
`https://master1.ddnet.tw/ddnet/15/register` and looks like this:
```http
POST /ddnet/15/register HTTP/1.1
Address: tw-0.6+udp://connecting-address.invalid:8303
Secret: 81fa3955-6f83-4290-818d-31c0906b1118
Challenge-Secret: 81fa3955-6f83-4290-818d-31c0906b1118:tw0.6/ipv6
Info-Serial: 0

{
	"max_clients": 64,
	"max_players": 64,
	"passworded": false,
	"game_type": "TestDDraceNetwork",
	"name": "My DDNet server",
	"map": {
		"name": "dm1",
		"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
		"size": 5805
	},
	"version": "0.6.4, 16.0.3",
	"clients": []
}
```

The `Address` header declares that the server wants to register itself as
a `tw-0.6+udp` server, i.e. a server speaking a Teeworlds-0.6-compatible
protocol.

The free-form `Secret` header is used as a server identity, the server
list will be deduplicated via this secret.

The free-form `Challenge-Secret` is sent back via UDP for a port forward
check.  This might have security implications as the masterserver can be
asked to send a UDP packet containing some user-controlled bytes. This
is somewhat mitigated by the fact that it can only go to an
attacker-controlled IP address.

The `Info-Serial` header is an integer field that should increase each
time the server info (in the body) changes. The masterserver uses that
field to ensure that it doesn't use old server infos.

The body is a free-form JSON object set by the game server. It should
contain certain keys in the correct form to be accepted by clients. The
body is optional if the masterserver already confirmed the reception of
the info with the given `Info-Serial`.

Not shown in this payload is the `Connless-Token` header that is used
for Teeworlds 0.7 style communication.

Also not shown is the `Challenge-Token` that should be included once the
server receives the challenge token via UDP.

The masterserver responds with a `200 OK` with a body like this:

```
{"status":"success"}
```

The `status` field can be `success` if the server was successfully
registered on the masterserver, `need_challenge` if the masterserver
wants the correct `Challenge-Token` header before the register process
is successful, `need_info` if the server sent an empty body but the
masterserver doesn't actually know the server info.

It can also be `error` if the request was malformed, only in this case
an HTTP status code except `200 OK` is sent.

Synchronization
---------------

The masterserver keeps state and outputs JSON files every second.

```json
{
	"servers": [
		{
			"addresses": [
				"tw-0.6+udp://127.0.0.1:8303",
				"tw-0.6+udp://[::1]:8303"
			],
			"info_serial": 0,
			"info": {
				"max_clients": 64,
				"max_players": 64,
				"passworded": false,
				"game_type": "TestDDraceNetwork",
				"name": "My DDNet server",
				"map": {
					"name": "dm1",
					"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
					"size": 5805
				},
				"version": "0.6.4, 16.0.3",
				"clients": []
			}
		}
	]
}
```

`servers.json` (or configured by `--out`) is a server list that is
compatible with DDNet 15.5+ clients. It is a JSON object containing a
single key `servers` with a list of game servers. Each game server is
represented by a JSON object with an `addresses` key containing a list
of all known addresses of the server and an `info` key containing the
free-form server info sent by the game server. The free-form `info` JSON
object re-encoded by the master server and thus canonicalized and
stripped of any whitespace characters outside strings.

```json
{
	"kind": "mastersrv",
	"now": 1816002,
	"secrets": {
		"tw-0.6+udp://127.0.0.1:8303": {
			"ping_time": 1811999,
			"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
		},
		"tw-0.6+udp://[::1]:8303": {
			"ping_time": 1811999,
			"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
		}
	},
	"servers": {
		"42d8f991-f2fa-46e5-a9ae-ebcc93846feb": {
			"info_serial": 0,
			"info": {
				"max_clients": 64,
				"max_players": 64,
				"passworded": false,
				"game_type": "TestDDraceNetwork",
				"name": "My DDNet server",
				"map": {
					"name": "dm1",
					"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
					"size": 5805
				},
				"version": "0.6.4, 16.0.3",
				"clients": []
			}
		}
	}
}
```

`--write-dump` outputs a JSON file compatible with `--read-dump-dir`,
this can be used to synchronize servers across different masterservers.
`--read-dump-dir` is also used to ingest servers from the backward
compatibility layer that pings each server for their server info using
the old protocol.

The `kind` field describe that this is `mastersrv` output and not from a
`backcompat`. This is used for prioritizing `mastersrv` information over
`backcompat` information.

The `now` field contains an integer describing the current time in
milliseconds relative an unspecified epoch that is fixed for each JSON
file. This is done instead of using the current time as the epoch for
better compression of non-changing data.

`secrets` is a map from each server address and to a JSON object
containing the last ping time (`ping_time`) in milliseconds relative to
the same epoch as before, and the server secret (`secret`) that is used
to unify server infos from different addresses of the same logical
server.

`servers` is a map from the aforementioned `secret`s to the
corresponding `info_serial` and `info`.

```json
[
	"tw-0.6+udp://127.0.0.1:8303",
	"tw-0.6+udp://[::1]:8303"
]
```

`--write-addresses` outputs a JSON file containing all addresses
corresponding to servers that are registered to HTTP masterservers. It
does not contain the servers that are obtained via backward
compatibility measures.

This file can be used by an old-style masterserver to also list
new-style servers without the game servers having to register there.

An implementation of this can be found at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_6_backcompat
for Teeworlds 0.5/0.6 masterservers and at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_7_backcompat
for Teeworlds 0.7 masterservers.

All these JSON files can be sent over the network in an efficient way
using https://github.com/heinrich5991/twmaster-collect. It establishes a
zstd-compressed TCP connection authenticated by a string token that is
sent in plain-text. It watches the specified file and transmits it every
time it changes. Due to the zstd-compression, the data sent over the
network is similar to the size of a diff.

Implementation
--------------

The masterserver implementation was done in Rust.

The current gameserver register implementation doesn't support more than
one masterserver for registering.

Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
2022-05-20 17:01:20 +00:00
heinrich5991 6b65ccb945 Add HTTP masterserver registering and HTTP masterserver
Registering
-----------

The idea is that game servers push their server info to the
masterservers every 15 seconds or when the server info changes, but not
more than once per second.

The game servers do not support the old registering protocol anymore,
the backward compatibility is handled by the masterserver.

The register call is a HTTP POST to a URL like
`https://master1.ddnet.tw/ddnet/15/register` and looks like this:
```json
POST /ddnet/15/register HTTP/1.1
Address: tw-0.6+udp://connecting-address.invalid:8303
Secret: 81fa3955-6f83-4290-818d-31c0906b1118
Challenge-Secret: 81fa3955-6f83-4290-818d-31c0906b1118:tw0.6/ipv6
Info-Serial: 0

{
	"max_clients": 64,
	"max_players": 64,
	"passworded": false,
	"game_type": "TestDDraceNetwork",
	"name": "My DDNet server",
	"map": {
		"name": "dm1",
		"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
		"size": 5805
	},
	"version": "0.6.4, 16.0.3",
	"clients": []
}
```

The `Address` header declares that the server wants to register itself as
a `tw-0.6+udp` server, i.e. a server speaking a Teeworlds-0.6-compatible
protocol.

The free-form `Secret` header is used as a server identity, the server
list will be deduplicated via this secret.

The free-form `Challenge-Secret` is sent back via UDP for a port forward
check.  This might have security implications as the masterserver can be
asked to send a UDP packet containing some user-controlled bytes. This
is somewhat mitigated by the fact that it can only go to an
attacker-controlled IP address.

The `Info-Serial` header is an integer field that should increase each
time the server info (in the body) changes. The masterserver uses that
field to ensure that it doesn't use old server infos.

The body is a free-form JSON object set by the game server. It should
contain certain keys in the correct form to be accepted by clients. The
body is optional if the masterserver already confirmed the reception of
the info with the given `Info-Serial`.

Not shown in this payload is the `Connless-Token` header that is used
for Teeworlds 0.7 style communication.

Also not shown is the `Challenge-Token` that should be included once the
server receives the challenge token via UDP.

The masterserver responds with a `200 OK` with a body like this:

```
{"status":"success"}
```

The `status` field can be `success` if the server was successfully
registered on the masterserver, `need_challenge` if the masterserver
wants the correct `Challenge-Token` header before the register process
is successful, `need_info` if the server sent an empty body but the
masterserver doesn't actually know the server info.

It can also be `error` if the request was malformed, only in this case
an HTTP status code except `200 OK` is sent.

Synchronization
---------------

The masterserver keeps state and outputs JSON files every second.

```json
{
	"servers": [
		{
			"addresses": [
				"tw-0.6+udp://127.0.0.1:8303",
				"tw-0.6+udp://[::1]:8303"
			],
			"info_serial": 0,
			"info": {
				"max_clients": 64,
				"max_players": 64,
				"passworded": false,
				"game_type": "TestDDraceNetwork",
				"name": "My DDNet server",
				"map": {
					"name": "dm1",
					"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
					"size": 5805
				},
				"version": "0.6.4, 16.0.3",
				"clients": []
			}
		}
	]
}
```

`servers.json` (or configured by `--out`) is a server list that is
compatible with DDNet 15.5+ clients. It is a JSON object containing a
single key `servers` with a list of game servers. Each game server is
represented by a JSON object with an `addresses` key containing a list
of all known addresses of the server and an `info` key containing the
free-form server info sent by the game server. The free-form `info` JSON
object re-encoded by the master server and thus canonicalized and
stripped of any whitespace characters outside strings.

```json
{
	"kind": "mastersrv",
	"now": 1816002,
	"secrets": {
		"tw-0.6+udp://127.0.0.1:8303": {
			"ping_time": 1811999,
			"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
		},
		"tw-0.6+udp://[::1]:8303": {
			"ping_time": 1811999,
			"secret": "42d8f991-f2fa-46e5-a9ae-ebcc93846feb"
		}
	},
	"servers": {
		"42d8f991-f2fa-46e5-a9ae-ebcc93846feb": {
			"info_serial": 0,
			"info": {
				"max_clients": 64,
				"max_players": 64,
				"passworded": false,
				"game_type": "TestDDraceNetwork",
				"name": "My DDNet server",
				"map": {
					"name": "dm1",
					"sha256": "0b0c481d77519c32fbe85624ef16ec0fa9991aec7367ad538bd280f28d8c26cf",
					"size": 5805
				},
				"version": "0.6.4, 16.0.3",
				"clients": []
			}
		}
	}
}
```

`--write-dump` outputs a JSON file compatible with `--read-dump-dir`,
this can be used to synchronize servers across different masterservers.
`--read-dump-dir` is also used to ingest servers from the backward
compatibility layer that pings each server for their server info using
the old protocol.

The `kind` field describe that this is `mastersrv` output and not from a
`backcompat`. This is used for prioritizing `mastersrv` information over
`backcompat` information.

The `now` field contains an integer describing the current time in
milliseconds relative an unspecified epoch that is fixed for each JSON
file. This is done instead of using the current time as the epoch for
better compression of non-changing data.

`secrets` is a map from each server address and to a JSON object
containing the last ping time (`ping_time`) in milliseconds relative to
the same epoch as before, and the server secret (`secret`) that is used
to unify server infos from different addresses of the same logical
server.

`servers` is a map from the aforementioned `secret`s to the
corresponding `info_serial` and `info`.

```json
[
	"tw-0.6+udp://127.0.0.1:8303",
	"tw-0.6+udp://[::1]:8303"
]
```

`--write-addresses` outputs a JSON file containing all addresses
corresponding to servers that are registered to HTTP masterservers. It
does not contain the servers that are obtained via backward
compatibility measures.

This file can be used by an old-style masterserver to also list
new-style servers without the game servers having to register there.

An implementation of this can be found at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_6_backcompat
for Teeworlds 0.5/0.6 masterservers and at
https://github.com/heinrich5991/teeworlds/tree/mastersrv_7_backcompat
for Teeworlds 0.7 masterservers.

All these JSON files can be sent over the network in an efficient way
using https://github.com/heinrich5991/twmaster-collect. It establishes a
zstd-compressed TCP connection authenticated by a string token that is
sent in plain-text. It watches the specified file and transmits it every
time it changes. Due to the zstd-compression, the data sent over the
network is similar to the size of a diff.

Implementation
--------------

The masterserver implementation was done in Rust.

The current gameserver register implementation doesn't support more than
one masterserver for registering.
2022-05-20 08:58:32 +02:00
Robert Müller 2ebaa76194 Remove cl_show_console and -c / --console cmdline options 2022-05-19 21:24:19 +02:00
Jupeyy 3c597aff95 Switch to nanoseconds 2022-05-18 18:05:41 +02:00
heinrich5991 4fb050ccb7 Use STUN to determine UDP connectivity and show diagnostics
These diagnostics are supposed to guide the user to problem resolution.
They're displayed if no packet is received from the server within one
second of connecting.

No message if we don't have STUN servers.

"Trying to determine UDP connectivity..." if no answer has been received
from the STUN server yet and it hasn't timed out yet.

"UDP seems to be filtered." if the STUN request has timed out.

"UDP and TCP IP addresses seem to be different. Try disabling VPN,
proxy or network accelerators." if the STUN request has returned an IP
address different from the one obtained via HTTP from info2.ddnet.tw.

"No answer from server yet." otherwise, if the STUN request has returned
no interesting data, indicating that it's likely the game server's
fault.
2022-05-18 09:21:31 +02:00
heinrich5991 407644deef Change IClient::ServerAddress to give the actual server address
Previously, it'd take the string entered by the user, before applying
its transformations. Add `IClient::ConnectAddressString` for the old
behavior.
2022-05-18 09:20:53 +02:00
bors[bot] 47874fb57f
Merge #5085
5085: New DDRace HUD r=def- a=C0D3D3V

If you want to test this PR, you have to test it on a Server that includes this PR too.

Textures are made by Ravie 

Here a showcase video with most parts shown: https://youtu.be/gPTVj-s3pgc 

Added to the new HUD
- A display of the weapons available to the player
- The weapon the player is carrying is highlighted
- Indicators for the special abilities of the player (Endless Hook, Endless Jumps, Jetpack, Teleport Weapons)
- Indicators for abilities taken away from the player (Deep/Life Freeze, No Hook, No Weapons collision, No Collision)
- Control indicators for dummy controls (dummy hammer, dummy copy) (bottom right)
- Jump indicator (max 10 jumps ar displayed, and greyed out as soon as a jump is used) 
- Ninja status bar that indicates how long a player is capable of using ninja (next to the ninja sword)
- Freeze status bar that indicates the thawing time of a player (below player)
- Movement Information can be displayed in a clean way above the mini score HUD (Position, Speed, Target Angle)
- Indicator if you are in practice mode

The complete HUD also works for players you spectate

I Added a new NetObj since the predicted values are not perfect and would make the display of the information a lot less good: DDNetCharacterDisplayInfo that contains the following information
```
NetIntRange("m_JumpedTotal", -2, 255),
NetTick("m_NinjaActivationTick"),
NetTick("m_FreezeTick"),
NetBool("m_IsInFreeze"),
NetBool("m_IsInPracticeMode"),

NetIntAny("m_TargetX"),  # used for the Movement Information display
NetIntAny("m_TargetY"),
NetIntAny("m_RampValue"),
```
So if someone has an idea what data we could also need in the client for making the display more nice, now is the right moment to add more data to this network object.

A few screenshots:
Assets Tab:
![grafik](https://user-images.githubusercontent.com/14315968/167703792-f0fa86be-159d-4e11-baf4-9539cee38aae.png)
HUD Settings:
![grafik](https://user-images.githubusercontent.com/14315968/167704336-dc7a314e-5603-40a2-98b4-9c03377906dd.png)
Mini Debug HUD:
![grafik](https://user-images.githubusercontent.com/14315968/168302791-c377d93e-33a2-4eb2-9d8d-b78f0808a009.png)
Speed.X is calculated using the players ramp vaule


## Checklist

- [x] Tested the change ingame
- [x] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [x] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [x] 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: c0d3d3v <c0d3d3v@mag-keinen-spam.de>
Co-authored-by: Jupeyy <jupjopjap@gmail.com>
2022-05-16 22:23:08 +00:00
bors[bot] a041ff8aed
Merge #5069
5069: Some HTTP fixes factored out of the HTTP masterserver PR r=def- a=heinrich5991

CC #5064

Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
2022-05-15 22:20:11 +00:00
Robert Müller 53f4001fb1 Fix stringop-overflow warning
In function 'str_copy',
    inlined from 'GetServerInfo' at src\engine\client\client.cpp:951:11,
    inlined from 'GetServerInfo' at src\engine\client\client.cpp:946:6:
src\base\system.cpp:2524:16: warning: 'strncat' specified bound 13 equals source length [-Wstringop-overflow=]
 2524 |         strncat(dst, src, dst_size - 1);
      |                ^
2022-05-15 19:45:14 +02:00
Tater 3380fd8122 Fix dummy intended tick sent to server 2022-05-14 01:07:36 -05:00
heinrich5991 40bd85b552 Refactor HTTP code to no longer use inheritance
This gives us the same API interface for all different request types
(HEAD, GET, POST).
2022-05-13 09:16:15 +02:00
heinrich5991 1b233ab95c Add the HTTP client methods to the server 2022-05-13 09:04:39 +02:00
c0d3d3v fa2ac1bb64
Merge branch 'master' into New_HUD
* master: (87 commits)
  Remove base/tl/string.h
  Replace remaining usage of base/tl/string with std::string
  Remove unused includes of base/tl/string.h
  Store localized strings in a CHeap instead of using tl/string.h
  Mark methods as const
  Add CHeap::StoreString method
  Rules are chat responses too
  Add margins to demo slice popup, decrease error font size, UI scaling
  Remove redundant parameters which are overridden later
  Use Margin instead of both VMargin and HMargin
  Move variable declaration
  Only output messages intended for chat to the user of a chat command
  Remove unused chat response variables
  Don't print the first "Waiting for score threads to complete"
  fix usage of undefined behavior for default eyes
  remove duplicate HOOK_RETRACTED assignment
  do not send swap request notification to complete team 0
  make swap messages more personal
  Move ninja shield to other position (fixes #5047)
  do not release the hooks if you swap
  ...
2022-05-10 19:03:09 +02:00
Tater 488b781f79 fix usage of undefined behavior for default eyes
fix using the same buffer as dest and source.
2022-05-01 03:04:10 -05:00
heinrich5991 fa4bcd5ec0 Unify logging infrastructure between IConsole and dbg_msg
This makes the "black console window" less important on Windows (or
anywhere else, for that matter), lets you see logs from other threads in
the f1 console, and removes the distinction between `IConsole::Print`
and `dbg_msg`.
2022-04-29 15:21:26 +02:00
bors[bot] 7a7e291dcf
Merge #4509
4509: Switch new players to DDNet config dir, support Teeworlds as fallback r=heinrich5991 a=def-

This way new players will get DDNet directory, old ones can switch
directory if they want, or keep using the old one.

If we ever enforce a switch in a future version, this will make it
easier since older DDNet versions will also support the DDNet directory
already.

<!-- What is the motivation for the changes of this pull request -->

## 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 if it works standalone, system.c especially
- [ ] 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: def <dennis@felsin9.de>
Co-authored-by: Dennis Felsing <dennis@felsin9.de>
2022-04-28 11:53:12 +00:00
Tater 70311d5d4f Add option for default eyes when joining server 2022-04-26 19:47:38 -05:00
def 790c1cc0aa Switch new players to DDNet config dir, support Teeworlds as fallback
This way new players will get DDNet directory, old ones can switch
directory if they want, or keep using the old one.

If we ever enforce a switch in a future version, this will make it
easier since older DDNet versions will also support the DDNet directory
already.
2022-04-25 09:50:45 +02:00
c0d3d3v a9c8b344a2
Player position, speed and angle can now be displayed in the HUD.
- Added RenderMovementInformation() to the HUD
- Use m_Width instead of recalculating the display width each time in hud.cpp
- Reworked Debug HUD:
    - Display velspeed.x*ramp and velspeed.y instead of velspeed*ramp
    - Show unit of speed
    - The graph for the velspeed.x*ramp behavior (if dbg_tuning is active) is now nicer and usable. A second graph zooming in on the turning point has been added.
    - The velspeed.x*ramp graph will be redrawn only when new tuning parameters are added
- The target angle used to draw the tees is now calculated using the m_TargetX, m_TargetY in DDNetCharacterDisplayInfo if available.
- Added m_TargetX, m_TargetY and m_RampValue to DDNetCharacterDisplayInfo Snap (m_RampValue has a precision of one thousandth)
- Added CGraph::InsertAt() to create static Graphs
- Added "assets/hud" to initial created Directories
- Added Settings to hide Dummy Action HUD and Player Movement HUD cl_showhud_dummy_actions, cl_showhud_player_position, cl_showhud_player_speed, cl_showhud_player_angle
- Added Pointer to m_PrevExtendedDisplayInfo, for calculation of interpolated Angle in Player Rendering
- Added GetDigitsIndex(int Value, float Max); to hud.cpp
2022-04-14 13:42:19 +02:00
ChillerDrgon 18ca71ae55 Close sockets 2022-04-14 11:50:10 +02:00
Robert Müller 60230f4eb7 Move/Merge variable declarations with assignments in CClient 2022-04-08 19:49:00 +02:00
Robert Müller 1daefbdeb2 Use bool instead of int 2022-04-08 19:40:28 +02:00
Jupeyy f7e3662cd7 Keep DDNet window responsive for loading tasks 2022-04-02 17:03:23 +02:00
Dennis Felsing 843acf6a5a Use std::size instead of sizeof(a) / sizeof(a[0]) 2022-03-30 18:55:04 +02:00
Jupeyy bb1ed45c3d Emscripten support 2022-03-25 12:42:18 +01:00
Dennis Felsing 6600bc622b Fix some Windows build warnings 2022-03-21 16:34:47 +01:00
Jupeyy e572704963 Multithreaded video rendering 2022-03-20 18:03:33 +01:00
Jupeyy e54da1b396 Cleanup backend a bit for vulkan 2022-03-20 18:03:25 +01:00
def 8134f9fa55 Enable -Wshadow=local
> Warn when a local variable shadows another local variable or parameter.

Found one actual bug in graphics_threaded.cpp

Should reduce confusion in the future when reading source code
2022-03-20 13:24:34 +01:00
simpygirl 18386e135f Use pFilename instead of Filename 2022-03-14 05:56:44 +01:00
simpygirl 5e6283a807 Add optional save_replay parameter, filename 2022-03-13 15:17:44 +01:00
Dennis Felsing 9032f12cf3 Use ipv4 for info2.ddnet.tw requests 2022-03-07 15:01:37 +01:00
bors[bot] 3f222b46f8
Merge #4783
4783: Some network refactoring r=def- a=heinrich5991

In preparation to the proxy code, I refactored the network code a little, unifying its interface across operating systems and making our use of recvmmsg invisible to the caller.

## 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 if it works standalone, system.c especially
- [ ] 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: heinrich5991 <heinrich5991@gmail.com>
2022-03-05 21:59:57 +00:00
heinrich5991 3211b1de67 Remove unused Flags argument in network code 2022-03-04 19:33:06 +01:00
heinrich5991 9af5870b3e Remove some redundant variable, spell out the condition instead 2022-03-04 19:20:36 +01:00
Jupeyy c9094eb76f Fix dummy connect on some vanilla servers 2022-03-02 09:11:37 +01:00
bors[bot] 03fc4d8f6e
Merge #4758
4758: Fix logging into rcon with dummy r=def- a=heinrich5991

Fixes #4721.

<!-- What is the motivation for the changes of this pull request -->

## 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 if it works standalone, system.c especially
- [ ] 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: heinrich5991 <heinrich5991@gmail.com>
2022-02-23 21:28:28 +00:00
heinrich5991 eff9abf769 Fix logging into rcon with dummy
Fixes #4721.
2022-02-23 20:42:08 +01:00
Jupeyy 4330ff83cf Add exception handling for Windows 2022-02-18 11:35:06 +01:00
Robert Müller 89f126cf8d Remove obsolete ignore_convention comment 2022-02-16 20:54:11 +01:00
Dennis Felsing dbfc62d2c0 Add modernize-deprecated-headers 2022-02-15 00:22:52 +01:00
Dennis Felsing 68e4eb21d5 Add modernize-use-bool-literals 2022-02-15 00:12:52 +01:00
ChillerDrgon 064ba50230 Add secure_random_uninit 2022-02-14 12:06:31 +01:00
Dennis Felsing 720268af6a Fix compilation error in client.cpp
src/engine/client/client.cpp:3861:47: error: ‘INT_MAX’ was not declared in this scope
 3861 |         if(Start < 0 || Length < 0 || Start > INT_MAX - Length)
      |                                               ^~~~~~~
src/engine/client/client.cpp:81:1: note: ‘INT_MAX’ is defined in header ‘<climits>’; did you forget to ‘#include <climits>’?
2022-02-08 18:35:55 +01:00
Alexander Akulich d7a4c37f11 engine/client: Replace the game hardcoded name with a macro variable 2022-02-06 22:25:34 +03:00