├── pch.cpp
├── BetterChat.rc
├── .gitignore
├── plugins
├── BetterChat.dll
├── BetterChat.exp
├── BetterChat.lib
└── BetterChat.pdb
├── fmt
├── include
│ └── fmt
│ │ ├── posix.h
│ │ ├── locale.h
│ │ ├── ostream.h
│ │ ├── ranges.h
│ │ ├── os.h
│ │ └── color.h
└── src
│ ├── format.cc
│ └── os.cc
├── vcpkg.json
├── BetterChat.vcxproj.user
├── version.h
├── IMGUI
├── imgui_timeline.h
├── imgui_additions.cpp
├── imgui_additions.h
├── imgui_searchablecombo.h
├── imgui_impl_dx11.h
├── imgui_stdlib.h
├── imgui_impl_win32.h
├── imgui_rangeslider.h
├── imgui_stdlib.cpp
├── imgui_timeline.cpp
├── imconfig.h
├── imgui_searchablecombo.cpp
├── imgui_impl_win32.cpp
└── imstb_rectpack.h
├── update_version.ps1
├── pch.h
├── resource.h
├── BetterChat.sln
├── LICENSE
├── BakkesMod.props
├── logging.h
├── README.md
├── .github
└── workflows
│ └── build.yml
├── BetterChat.vcxproj.filters
├── BetterChat.vcxproj
├── BetterChat.h
└── BetterChatGUI.cpp
/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/BetterChat.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JulienML/BetterChat/HEAD/BetterChat.rc
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | .vscode/
3 | build/
4 | vcpkg_installed/
5 |
6 | README BakkesPlugins.md
--------------------------------------------------------------------------------
/plugins/BetterChat.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JulienML/BetterChat/HEAD/plugins/BetterChat.dll
--------------------------------------------------------------------------------
/plugins/BetterChat.exp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JulienML/BetterChat/HEAD/plugins/BetterChat.exp
--------------------------------------------------------------------------------
/plugins/BetterChat.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JulienML/BetterChat/HEAD/plugins/BetterChat.lib
--------------------------------------------------------------------------------
/plugins/BetterChat.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JulienML/BetterChat/HEAD/plugins/BetterChat.pdb
--------------------------------------------------------------------------------
/fmt/include/fmt/posix.h:
--------------------------------------------------------------------------------
1 | #include "os.h"
2 | #warning "fmt/posix.h is deprecated; use fmt/os.h instead"
3 |
--------------------------------------------------------------------------------
/vcpkg.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
3 | "dependencies": [
4 | "nlohmann-json"
5 | ]
6 | }
--------------------------------------------------------------------------------
/BetterChat.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/version.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define VERSION_MAJOR 3
3 | #define VERSION_MINOR 1
4 | #define VERSION_PATCH 0
5 | #define VERSION_BUILD 530
6 |
7 | #define stringify(a) stringify_(a)
8 | #define stringify_(a) #a
9 |
10 |
--------------------------------------------------------------------------------
/IMGUI/imgui_timeline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | namespace ImGui {
3 |
4 | bool BeginTimeline(const char* str_id, float max_time);
5 | bool TimelineEvent(const char* str_id, float times[2]);
6 | void EndTimeline(float current_time = -1);
7 |
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/update_version.ps1:
--------------------------------------------------------------------------------
1 | (Get-Content -path $args[0] -Raw) |
2 | ForEach-Object {
3 | $defstr="#define VERSION_BUILD ";
4 | $regex="$defstr(?\d*)";
5 | if($_ -match $regex) {
6 | $_ = $_ -replace $regex,"$($defstr)$(([int]$matches["BuildVersion"])+1)"
7 | }
8 | $_
9 | } |
10 | Out-File $args[0] -encoding ascii -nonewline
--------------------------------------------------------------------------------
/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIN32_LEAN_AND_MEAN
4 | #define _CRT_SECURE_NO_WARNINGS
5 | #include "bakkesmod/plugin/bakkesmodplugin.h"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "IMGUI/imgui.h"
13 | #include "IMGUI/imgui_stdlib.h"
14 | #include "IMGUI/imgui_searchablecombo.h"
15 | #include "IMGUI/imgui_rangeslider.h"
16 |
17 | #include "logging.h"
--------------------------------------------------------------------------------
/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by TemplateChanges.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/IMGUI/imgui_additions.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "imgui_additions.h"
3 |
4 | namespace ImGui {
5 | bool Combo(const char* label, int* currIndex, std::vector& values)
6 | {
7 | if (values.empty()) { return false; }
8 | return Combo(label, currIndex, vector_getter,
9 | static_cast(&values), values.size());
10 | }
11 |
12 | bool ListBox(const char* label, int* currIndex, std::vector& values)
13 | {
14 | if (values.empty()) { return false; }
15 | return ListBox(label, currIndex, vector_getter,
16 | static_cast(&values), values.size());
17 | }
18 | }
--------------------------------------------------------------------------------
/IMGUI/imgui_additions.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include "imgui.h"
5 | #include "imgui_internal.h"
6 |
7 | namespace ImGui
8 | {
9 | static auto vector_getter = [](void* vec, int idx, const char** out_text)
10 | {
11 | auto& vector = *static_cast*>(vec);
12 | if (idx < 0 || idx >= static_cast(vector.size())) { return false; }
13 | *out_text = vector.at(idx).c_str();
14 | return true;
15 | };
16 | bool Combo(const char* label, int* currIndex, std::vector& values);
17 | bool ListBox(const char* label, int* currIndex, std::vector& values);
18 | }
--------------------------------------------------------------------------------
/IMGUI/imgui_searchablecombo.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "imgui.h"
3 |
4 | #include // isprint
5 | #include // vector<>
6 | #include // string
7 | #include // transform
8 |
9 | namespace ImGui
10 | {
11 | IMGUI_API bool BeginSearchableCombo(const char* label, const char* preview_value, char* input, int input_size, const char* input_preview_value, ImGuiComboFlags flags = 0);
12 | IMGUI_API void EndSearchableCombo();
13 | IMGUI_API bool SearchableCombo(const char* label, int* current_item, std::vector items, const char* default_preview_text, const char* input_preview_value, int popup_max_height_in_items = -1);
14 | } // namespace ImGui
--------------------------------------------------------------------------------
/BetterChat.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.34031.279
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BetterChat", "BetterChat.vcxproj", "{4D053DE5-3F47-432D-BE43-BDD54680D990}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|x64 = Release|x64
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {4D053DE5-3F47-432D-BE43-BDD54680D990}.Release|x64.ActiveCfg = Release|x64
14 | {4D053DE5-3F47-432D-BE43-BDD54680D990}.Release|x64.Build.0 = Release|x64
15 | EndGlobalSection
16 | GlobalSection(SolutionProperties) = preSolution
17 | HideSolutionNode = FALSE
18 | EndGlobalSection
19 | GlobalSection(ExtensibilityGlobals) = postSolution
20 | SolutionGuid = {3056B556-37ED-439C-880E-56BECECA3365}
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 JulienML
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/BakkesMod.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | $(registry:HKEY_CURRENT_USER\Software\BakkesMod\AppPath@BakkesModPath)
6 |
7 |
8 |
9 | $(BakkesModPath)\bakkesmodsdk\include;%(AdditionalIncludeDirectories)
10 |
11 |
12 | $(BakkesModPath)\bakkesmodsdk\lib;%(AdditionalLibraryDirectories)
13 | pluginsdk.lib;%(AdditionalDependencies)
14 |
15 |
16 | "$(BakkesModPath)\bakkesmodsdk\bakkesmod-patch.exe" "$(TargetPath)"
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/IMGUI/imgui_impl_dx11.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer for DirectX11
2 | // This needs to be used along with a Platform Binding (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
7 |
8 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
9 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
10 | // https://github.com/ocornut/imgui
11 |
12 | #pragma once
13 |
14 | struct ID3D11Device;
15 | struct ID3D11DeviceContext;
16 |
17 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
18 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
19 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
20 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
21 |
22 | // Use if you want to reset your rendering device without losing ImGui state.
23 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
24 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
--------------------------------------------------------------------------------
/IMGUI/imgui_stdlib.h:
--------------------------------------------------------------------------------
1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
2 | // This is also an example of how you may wrap your own similar types.
3 |
4 | // Compatibility:
5 | // - std::string support is only guaranteed to work from C++11.
6 | // If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
7 |
8 | // Changelog:
9 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
10 |
11 | #pragma once
12 |
13 | #include
14 |
15 | namespace ImGui
16 | {
17 | // ImGui::InputText() with std::string
18 | // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
19 | IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
20 | IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
21 | IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
22 | }
23 |
--------------------------------------------------------------------------------
/IMGUI/imgui_impl_win32.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Binding for Windows (standard windows API for 32 and 64 bits applications)
2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
3 |
4 | // Implemented features:
5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core imgui)
6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 |
10 | #pragma once
11 |
12 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
13 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
14 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
15 |
16 | // Configuration: Disable gamepad support or linking with xinput.lib
17 | #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
18 | #define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
19 |
20 | // Handler for Win32 messages, update mouse/keyboard data.
21 | // You may or not need this for your implementation, but it can serve as reference for handling inputs.
22 | // Intentionally commented out to avoid dragging dependencies on types. You can COPY this line into your .cpp code instead.
23 | #if 0
24 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
25 | #endif
--------------------------------------------------------------------------------
/IMGUI/imgui_rangeslider.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "imgui.h"
3 | namespace ImGui
4 | {
5 | IMGUI_API bool RangeSliderScalar(const char* label, ImGuiDataType data_type, void* p_data1, void* p_data2, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
6 | IMGUI_API bool RangeSliderScalarN(const char* label, ImGuiDataType data_type, void* p_data1, void* p_data2, int components, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
7 | IMGUI_API bool RangeSliderFloat(const char* label, float* v1, float* v2, float v_min, float v_max, const char* format = "(%.3f, %.3f)", float power = 1.0f); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for power curve sliders
8 | IMGUI_API bool RangeSliderFloat2(const char* label, float v1[2], float v2[2], float v_min, float v_max, const char* format = "(%.3f, %.3f)", float power = 1.0f);
9 | IMGUI_API bool RangeSliderFloat3(const char* label, float v1[3], float v2[3], float v_min, float v_max, const char* format = "(%.3f, %.3f)", float power = 1.0f);
10 | IMGUI_API bool RangeSliderFloat4(const char* label, float v1[4], float v2[4], float v_min, float v_max, const char* format = "(%.3f, %.3f)", float power = 1.0f);
11 | IMGUI_API bool RangeSliderAngle(const char* label, float* v_rad1, float* v_rad2, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "(%d, %d) deg");
12 | IMGUI_API bool RangeSliderInt(const char* label, int* v1, int* v2, int v_min, int v_max, const char* format = "(%d, %d)");
13 | IMGUI_API bool RangeSliderInt2(const char* label, int v1[2], int v2[2], int v_min, int v_max, const char* format = "(%d, %d)");
14 | IMGUI_API bool RangeSliderInt3(const char* label, int v1[3], int v2[3], int v_min, int v_max, const char* format = "(%d, %d)");
15 | IMGUI_API bool RangeSliderInt4(const char* label, int v1[4], int v2[4], int v_min, int v_max, const char* format = "(%d, %d)");
16 | IMGUI_API bool RangeVSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data1, void* p_data2, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
17 | IMGUI_API bool RangeVSliderFloat(const char* label, const ImVec2& size, float* v1, float* v2, float v_min, float v_max, const char* format = "(%.3f, %.3f)", float power = 1.0f);
18 | IMGUI_API bool RangeVSliderInt(const char* label, const ImVec2& size, int* v1, int* v2, int v_min, int v_max, const char* format = "(%d, %d)");
19 |
20 | } // namespace ImGui
--------------------------------------------------------------------------------
/logging.h:
--------------------------------------------------------------------------------
1 | // ReSharper disable CppNonExplicitConvertingConstructor
2 | #pragma once
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "bakkesmod/wrappers/cvarmanagerwrapper.h"
9 |
10 | extern std::shared_ptr _globalCvarManager;
11 | constexpr bool DEBUG_LOG = false;
12 |
13 |
14 | struct FormatString
15 | {
16 | std::string_view str;
17 | std::source_location loc{};
18 |
19 | FormatString(const char* str, const std::source_location& loc = std::source_location::current()) : str(str), loc(loc)
20 | {
21 | }
22 |
23 | FormatString(const std::string&& str, const std::source_location& loc = std::source_location::current()) : str(str), loc(loc)
24 | {
25 | }
26 |
27 | [[nodiscard]] std::string GetLocation() const
28 | {
29 | return std::format("[{} ({}:{})]", loc.function_name(), loc.file_name(), loc.line());
30 | }
31 | };
32 |
33 | struct FormatWstring
34 | {
35 | std::wstring_view str;
36 | std::source_location loc{};
37 |
38 | FormatWstring(const wchar_t* str, const std::source_location& loc = std::source_location::current()) : str(str), loc(loc)
39 | {
40 | }
41 |
42 | FormatWstring(const std::wstring&& str, const std::source_location& loc = std::source_location::current()) : str(str), loc(loc)
43 | {
44 | }
45 |
46 | [[nodiscard]] std::wstring GetLocation() const
47 | {
48 | auto basic_string = std::format("[{} ({}:{})]", loc.function_name(), loc.file_name(), loc.line());
49 | return std::wstring(basic_string.begin(), basic_string.end());
50 | }
51 | };
52 |
53 |
54 | template
55 | void LOG(std::string_view format_str, Args&&... args)
56 | {
57 | _globalCvarManager->log(std::vformat(format_str, std::make_format_args(args...)));
58 | }
59 |
60 | template
61 | void LOG(std::wstring_view format_str, Args&&... args)
62 | {
63 | _globalCvarManager->log(std::vformat(format_str, std::make_wformat_args(args...)));
64 | }
65 |
66 |
67 | template
68 | void DEBUGLOG(const FormatString& format_str, Args&&... args)
69 | {
70 | if constexpr (DEBUG_LOG)
71 | {
72 | auto text = std::vformat(format_str.str, std::make_format_args(args...));
73 | auto location = format_str.GetLocation();
74 | _globalCvarManager->log(std::format("{} {}", text, location));
75 | }
76 | }
77 |
78 | template
79 | void DEBUGLOG(const FormatWstring& format_str, Args&&... args)
80 | {
81 | if constexpr (DEBUG_LOG)
82 | {
83 | auto text = std::vformat(format_str.str, std::make_wformat_args(args...));
84 | auto location = format_str.GetLocation();
85 | _globalCvarManager->log(std::format(L"{} {}", text, location));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BetterChat [](https://opensource.org/licenses/MIT)
2 |
3 | **BetterChat** is a plugin that works with **BakkesMod**, allowing you to choose which quickchats you want to disallow at which points in the game (after a goal, after a save, etc.). There is also an anti-spam function. At the end of the game, you get the toxicity score of each player (i.e. a recap of the number of blocked messages for each player).
4 |
5 | In this way, you can make the usual toxic Rocket League chat more respectful and focus on your gameplay.
6 |
7 | **If you have any suggestions to improve the plugin, don't hesitate to create an [Issue](https://github.com/JulienML/BetterChat/issues) or a [Pull Request](https://github.com/JulienML/BetterChat/pulls)!**
8 |
9 | # Table of contents
10 |
11 | * [Installation](#installation)
12 | * [Configuration](#configuration)
13 | * [Anti-Spam](#anti-spam)
14 | * [Chat Filter](#chat-filter)
15 |
16 | # Installation
17 |
18 | - Install [BakkesMod](https://www.bakkesmod.com/download.php).
19 | - Launch Rocket League and make sure BakkesMod is working.
20 | - Install [BetterChat](https://bakkesplugins.com/plugins/view/416) plugin.
21 |
22 | You are ready to use the plugin :)
23 |
24 | # Configuration
25 |
26 | You can configure the plugin easily by pressing F2 -> Plugins -> BetterChat Plugin.
27 |
28 | Here, you can create as many configurations as you want and assign them to the different gamemodes:
29 |
30 | 
31 |
32 | Each configuration is composed of two features: an Anti-Spam and a Message Filter.
33 |
34 | ## Anti-Spam
35 |
36 | | Without Anti-Spam | With Anti-Spam |
37 | | :-------------: |:-------------:|
38 | |  |  |
39 |
40 | In the Anti-Spam section, you can set the delay between two identical quickchat from the same player.
41 |
42 | ## Message Filter
43 |
44 | | Without the Message Filter | With the Message Filter |
45 | | :-------------: |:-------------:|
46 | |  |  |
47 |
48 | In the Message Filter section, you can allow/disallow the quickchat you want at the moment you want by pressing the corresponding button:
49 |
50 | 
51 |
52 | At the bottom, you can configure the position of the toxicity scores at the end of the game:
53 |
54 | 
55 |
--------------------------------------------------------------------------------
/fmt/src/format.cc:
--------------------------------------------------------------------------------
1 | // Formatting library for C++
2 | //
3 | // Copyright (c) 2012 - 2016, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 | #include "pch.h"
8 | #include "fmt/format-inl.h"
9 |
10 | FMT_BEGIN_NAMESPACE
11 | namespace detail {
12 |
13 | template
14 | int format_float(char* buf, std::size_t size, const char* format, int precision,
15 | T value) {
16 | #ifdef FMT_FUZZ
17 | if (precision > 100000)
18 | throw std::runtime_error(
19 | "fuzz mode - avoid large allocation inside snprintf");
20 | #endif
21 | // Suppress the warning about nonliteral format string.
22 | int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
23 | return precision < 0 ? snprintf_ptr(buf, size, format, value)
24 | : snprintf_ptr(buf, size, format, precision, value);
25 | }
26 | } // namespace detail
27 |
28 | template struct FMT_INSTANTIATION_DEF_API detail::basic_data;
29 |
30 | // Workaround a bug in MSVC2013 that prevents instantiation of format_float.
31 | int (*instantiate_format_float)(double, int, detail::float_specs,
32 | detail::buffer&) = detail::format_float;
33 |
34 | #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
35 | template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
36 | template FMT_API std::locale detail::locale_ref::get() const;
37 | #endif
38 |
39 | // Explicit instantiations for char.
40 |
41 | template FMT_API std::string detail::grouping_impl(locale_ref);
42 | template FMT_API char detail::thousands_sep_impl(locale_ref);
43 | template FMT_API char detail::decimal_point_impl(locale_ref);
44 |
45 | template FMT_API void detail::buffer::append(const char*, const char*);
46 |
47 | template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
48 | detail::buffer&, string_view,
49 | basic_format_args);
50 |
51 | template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
52 | detail::buffer&);
53 | template FMT_API int detail::snprintf_float(long double, int,
54 | detail::float_specs,
55 | detail::buffer&);
56 | template FMT_API int detail::format_float(double, int, detail::float_specs,
57 | detail::buffer&);
58 | template FMT_API int detail::format_float(long double, int, detail::float_specs,
59 | detail::buffer&);
60 |
61 | // Explicit instantiations for wchar_t.
62 |
63 | template FMT_API std::string detail::grouping_impl(locale_ref);
64 | template FMT_API wchar_t detail::thousands_sep_impl(locale_ref);
65 | template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
66 |
67 | template FMT_API void detail::buffer::append(const wchar_t*,
68 | const wchar_t*);
69 | FMT_END_NAMESPACE
70 |
--------------------------------------------------------------------------------
/fmt/include/fmt/locale.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - std::locale support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_LOCALE_H_
9 | #define FMT_LOCALE_H_
10 |
11 | #include
12 |
13 | #include "format.h"
14 |
15 | FMT_BEGIN_NAMESPACE
16 |
17 | namespace detail {
18 | template
19 | typename buffer_context::iterator vformat_to(
20 | const std::locale& loc, buffer& buf,
21 | basic_string_view format_str,
22 | basic_format_args>> args) {
23 | using af = arg_formatter::iterator, Char>;
24 | return vformat_to(std::back_inserter(buf), to_string_view(format_str),
25 | args, detail::locale_ref(loc));
26 | }
27 |
28 | template
29 | std::basic_string vformat(
30 | const std::locale& loc, basic_string_view format_str,
31 | basic_format_args>> args) {
32 | basic_memory_buffer buffer;
33 | detail::vformat_to(loc, buffer, format_str, args);
34 | return fmt::to_string(buffer);
35 | }
36 | } // namespace detail
37 |
38 | template >
39 | inline std::basic_string vformat(
40 | const std::locale& loc, const S& format_str,
41 | basic_format_args>> args) {
42 | return detail::vformat(loc, to_string_view(format_str), args);
43 | }
44 |
45 | template >
46 | inline std::basic_string format(const std::locale& loc,
47 | const S& format_str, Args&&... args) {
48 | return detail::vformat(
49 | loc, to_string_view(format_str),
50 | detail::make_args_checked(format_str, args...));
51 | }
52 |
53 | template ::value, char_t>>
56 | inline OutputIt vformat_to(
57 | OutputIt out, const std::locale& loc, const S& format_str,
58 | format_args_t, Char> args) {
59 | using af = detail::arg_formatter;
60 | return vformat_to(out, to_string_view(format_str), args,
61 | detail::locale_ref(loc));
62 | }
63 |
64 | template ::value&&
66 | detail::is_string::value)>
67 | inline OutputIt format_to(OutputIt out, const std::locale& loc,
68 | const S& format_str, Args&&... args) {
69 | detail::check_format_string(format_str);
70 | using context = format_context_t>;
71 | format_arg_store as{args...};
72 | return vformat_to(out, loc, to_string_view(format_str),
73 | basic_format_args(as));
74 | }
75 |
76 | FMT_END_NAMESPACE
77 |
78 | #endif // FMT_LOCALE_H_
79 |
--------------------------------------------------------------------------------
/IMGUI/imgui_stdlib.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
2 | // This is also an example of how you may wrap your own similar types.
3 |
4 | // Compatibility:
5 | // - std::string support is only guaranteed to work from C++11.
6 | // If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
7 |
8 | // Changelog:
9 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
10 | #include "pch.h"
11 | #include "imgui.h"
12 | #include "imgui_stdlib.h"
13 |
14 | struct InputTextCallback_UserData
15 | {
16 | std::string* Str;
17 | ImGuiInputTextCallback ChainCallback;
18 | void* ChainCallbackUserData;
19 | };
20 |
21 | static int InputTextCallback(ImGuiInputTextCallbackData* data)
22 | {
23 | InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData;
24 | if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
25 | {
26 | // Resize string callback
27 | // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
28 | std::string* str = user_data->Str;
29 | IM_ASSERT(data->Buf == str->c_str());
30 | str->resize(data->BufTextLen);
31 | data->Buf = (char*)str->c_str();
32 | }
33 | else if (user_data->ChainCallback)
34 | {
35 | // Forward to user callback, if any
36 | data->UserData = user_data->ChainCallbackUserData;
37 | return user_data->ChainCallback(data);
38 | }
39 | return 0;
40 | }
41 |
42 | bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
43 | {
44 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
45 | flags |= ImGuiInputTextFlags_CallbackResize;
46 |
47 | InputTextCallback_UserData cb_user_data;
48 | cb_user_data.Str = str;
49 | cb_user_data.ChainCallback = callback;
50 | cb_user_data.ChainCallbackUserData = user_data;
51 | return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
52 | }
53 |
54 | bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
55 | {
56 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
57 | flags |= ImGuiInputTextFlags_CallbackResize;
58 |
59 | InputTextCallback_UserData cb_user_data;
60 | cb_user_data.Str = str;
61 | cb_user_data.ChainCallback = callback;
62 | cb_user_data.ChainCallbackUserData = user_data;
63 | return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
64 | }
65 |
66 | bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
67 | {
68 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
69 | flags |= ImGuiInputTextFlags_CallbackResize;
70 |
71 | InputTextCallback_UserData cb_user_data;
72 | cb_user_data.Str = str;
73 | cb_user_data.ChainCallback = callback;
74 | cb_user_data.ChainCallbackUserData = user_data;
75 | return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
76 | }
77 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build BakkesMod Plugin
2 |
3 | on:
4 | push:
5 | branches: [ main, master ]
6 | pull_request:
7 | branches: [ main, master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: windows-latest
12 |
13 | steps:
14 | - name: Checkout repository
15 | uses: actions/checkout@v4
16 |
17 |
18 | - name: Checkout BakkesMod SDK
19 | uses: actions/checkout@v4
20 | with:
21 | repository: bakkesmodorg/BakkesModSDK
22 | path: bakkesmod\bakkesmodsdk
23 |
24 |
25 | - name: Check for vcpkg manifest
26 | id: vcpkg_check
27 | shell: pwsh
28 | run: |
29 | $manifest = Test-Path "$env:GITHUB_WORKSPACE/vcpkg.json"
30 | Write-Host "vcpkg manifest present: $manifest"
31 | echo "vcpkg_manifest=$manifest" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
32 |
33 | - name: Checkout vcpkg
34 | if: steps.vcpkg_check.outputs.vcpkg_manifest == 'True'
35 | uses: actions/checkout@v4
36 | with:
37 | repository: microsoft/vcpkg
38 | path: vcpkg
39 |
40 | - name: Bootstrap vcpkg
41 | if: steps.vcpkg_check.outputs.vcpkg_manifest == 'True'
42 | run: |
43 | .\vcpkg\bootstrap-vcpkg.bat
44 |
45 | - name: Integrate vcpkg
46 | if: steps.vcpkg_check.outputs.vcpkg_manifest == 'True'
47 | run: |
48 | .\vcpkg\vcpkg.exe integrate install
49 |
50 |
51 | - name: Setup MSBuild
52 | uses: microsoft/setup-msbuild@v2
53 |
54 | - name: Find solution file
55 | id: find_sln
56 | shell: pwsh
57 | run: |
58 | $sln = Get-ChildItem -Path $env:GITHUB_WORKSPACE -Filter *.sln -Recurse | Select-Object -First 1
59 | if ($null -eq $sln) { Write-Error 'No .sln file found!'; exit 1 }
60 | Write-Host "sln path: $($sln.FullName)"
61 | echo "SOLUTION_PATH=$($sln.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Append
62 |
63 | - name: Build
64 | run: msbuild /m /p:Configuration=Release /p:BakkesModPath=$env:GITHUB_WORKSPACE\bakkesmod /p:PostBuildEventUseInBuild=false $env:SOLUTION_PATH
65 |
66 |
67 | - name: Prepare build artifacts
68 | run: |
69 | # Create artifacts/plugins directory
70 | New-Item -ItemType Directory -Force -Path "artifacts/plugins"
71 |
72 | if (Test-Path "plugins") {
73 | Get-ChildItem -Path "plugins" -Include "*.dll", "*.pdb" -Recurse | ForEach-Object {
74 | Copy-Item $_.FullName -Destination "artifacts/plugins" -Force
75 | }
76 | }
77 |
78 | if (Test-Path "data") {
79 | Copy-Item -Path "data" -Destination "artifacts/data" -Recurse -Force
80 | }
81 |
82 | Write-Host "Artifacts contents:"
83 | Get-ChildItem -Path "artifacts" -Recurse
84 |
85 | - name: Create release archive
86 | run: |
87 | # Create zip file with timestamp
88 | $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
89 | $zipName = "${{ github.event.repository.name }}-$timestamp.zip"
90 |
91 | if (Test-Path "artifacts") {
92 | Compress-Archive -Path "artifacts\*" -DestinationPath $zipName
93 | echo "RELEASE_ZIP=$zipName" >> $env:GITHUB_ENV
94 | } else {
95 | Write-Error "No artifacts found to archive"
96 | exit 1
97 | }
98 |
99 | - name: Upload build artifacts
100 | uses: actions/upload-artifact@v4
101 | with:
102 | name: ${{ github.event.repository.name }}
103 | path: ${{ env.RELEASE_ZIP }}
104 | retention-days: 30
--------------------------------------------------------------------------------
/IMGUI/imgui_timeline.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "imgui_timeline.h"
3 | // cpp
4 | #include "imgui.h"
5 | #include "imgui_internal.h"
6 | // https://github.com/ocornut/imgui/issues/76
7 |
8 | namespace ImGui {
9 |
10 | static float s_max_timeline_value;
11 |
12 |
13 | bool BeginTimeline(const char* str_id, float max_time)
14 | {
15 | s_max_timeline_value = max_time;
16 | return BeginChild(str_id);
17 | }
18 |
19 |
20 | static const float TIMELINE_RADIUS = 6;
21 |
22 |
23 | bool TimelineEvent(const char* str_id, float values[2])
24 | {
25 | ImGuiWindow* win = GetCurrentWindow();
26 | const ImU32 inactive_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_Button]);
27 | const ImU32 active_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_ButtonHovered]);
28 | const ImU32 line_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorActive]);
29 | bool changed = false;
30 | ImVec2 cursor_pos = win->DC.CursorPos;
31 |
32 | // @r-lyeh {
33 | Button(str_id, ImVec2(120, 0)); // @todo: enable/disable track channel here
34 | SameLine();
35 | cursor_pos += ImVec2(0, GetTextLineHeightWithSpacing() / 3);
36 | // }
37 |
38 | for (int i = 0; i < 2; ++i)
39 | {
40 | ImVec2 pos = cursor_pos;
41 | pos.x += win->Size.x * values[i] / s_max_timeline_value + TIMELINE_RADIUS;
42 | pos.y += TIMELINE_RADIUS;
43 |
44 | SetCursorScreenPos(pos - ImVec2(TIMELINE_RADIUS, TIMELINE_RADIUS));
45 | PushID(i);
46 | InvisibleButton(str_id, ImVec2(2 * TIMELINE_RADIUS, 2 * TIMELINE_RADIUS));
47 | if (IsItemActive() || IsItemHovered())
48 | {
49 | ImGui::SetTooltip("%f", values[i]);
50 | ImVec2 a(pos.x, GetWindowContentRegionMin().y + win->Pos.y + win->Scroll.y);
51 | ImVec2 b(pos.x, GetWindowContentRegionMax().y + win->Pos.y + win->Scroll.y);
52 | win->DrawList->AddLine(a, b, line_color);
53 | }
54 | if (IsItemActive() && IsMouseDragging(0))
55 | {
56 | values[i] += GetIO().MouseDelta.x / win->Size.x * s_max_timeline_value;
57 | changed = true;
58 | }
59 | PopID();
60 | win->DrawList->AddCircleFilled(
61 | pos, TIMELINE_RADIUS, IsItemActive() || IsItemHovered() ? active_color : inactive_color);
62 | }
63 |
64 | ImVec2 start = cursor_pos;
65 | start.x += win->Size.x * values[0] / s_max_timeline_value + 2 * TIMELINE_RADIUS;
66 | start.y += TIMELINE_RADIUS * 0.5f;
67 | ImVec2 end = start + ImVec2(win->Size.x * (values[1] - values[0]) / s_max_timeline_value - 2 * TIMELINE_RADIUS,
68 | TIMELINE_RADIUS);
69 |
70 | PushID(-1);
71 | SetCursorScreenPos(start);
72 | InvisibleButton(str_id, end - start);
73 | if (IsItemActive() && IsMouseDragging(0))
74 | {
75 | values[0] += GetIO().MouseDelta.x / win->Size.x * s_max_timeline_value;
76 | values[1] += GetIO().MouseDelta.x / win->Size.x * s_max_timeline_value;
77 | changed = true;
78 | }
79 | PopID();
80 |
81 | SetCursorScreenPos(cursor_pos + ImVec2(0, GetTextLineHeightWithSpacing()));
82 |
83 | win->DrawList->AddRectFilled(start, end, IsItemActive() || IsItemHovered() ? active_color : inactive_color);
84 |
85 | if (values[0] > values[1])
86 | {
87 | float tmp = values[0];
88 | values[0] = values[1];
89 | values[1] = tmp;
90 | }
91 | if (values[1] > s_max_timeline_value) values[1] = s_max_timeline_value;
92 | if (values[0] < 0) values[0] = 0;
93 | return changed;
94 | }
95 |
96 |
97 | void EndTimeline(float t)
98 | {
99 | ImGuiWindow* win = GetCurrentWindow();
100 |
101 | // @r-lyeh {
102 | if (t >= 0) {
103 | if (t > s_max_timeline_value) t = s_max_timeline_value; t /= s_max_timeline_value;
104 | const ImU32 line_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorActive]);
105 | ImVec2 a(win->Pos.x + GetWindowContentRegionMin().x + t * GetWindowContentRegionWidth(), GetWindowContentRegionMin().y + win->Pos.y + win->Scroll.y);
106 | ImVec2 b(win->Pos.x + GetWindowContentRegionMin().x + t * GetWindowContentRegionWidth(), GetWindowContentRegionMax().y + win->Pos.y + win->Scroll.y);
107 | win->DrawList->AddLine(a, b, line_color);
108 | }
109 | // }
110 |
111 | ImU32 color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_Button]);
112 | ImU32 line_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_Border]);
113 | ImU32 text_color = ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_Text]);
114 | float rounding = GImGui->Style.ScrollbarRounding;
115 | ImVec2 start(GetWindowContentRegionMin().x + win->Pos.x,
116 | GetWindowContentRegionMax().y - GetTextLineHeightWithSpacing() + win->Pos.y + win->Scroll.y);
117 | ImVec2 end = GetWindowContentRegionMax() + win->Pos + ImVec2(0, win->Scroll.y);
118 |
119 | win->DrawList->AddRectFilled(start, end, color, rounding);
120 |
121 | const int LINE_COUNT = 5;
122 | const ImVec2 text_offset(0, GetTextLineHeightWithSpacing());
123 | for (int i = 0; i <= LINE_COUNT; ++i)
124 | {
125 | ImVec2 a = GetWindowContentRegionMin() + win->Pos; // @r-lyeh: - ImVec2(TIMELINE_RADIUS, 0);
126 | a.x += i * (GetWindowContentRegionWidth() - 1) / LINE_COUNT; // @r-lyeh: -1
127 | ImVec2 b = a;
128 | b.y = start.y;
129 | win->DrawList->AddLine(a, b, line_color);
130 | char tmp[256];
131 | ImFormatString(tmp, sizeof(tmp), "%.2f", i * s_max_timeline_value / LINE_COUNT);
132 | win->DrawList->AddText(b, text_color, tmp);
133 | }
134 |
135 | EndChild();
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/BetterChat.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {396e4dda-4fe2-4588-9756-a364a57aa8c1}
18 |
19 |
20 | {ae0c99c9-78de-41f1-8c8d-e6eb860af833}
21 |
22 |
23 | {d46c4711-0bdc-484c-bb4c-5526d80f7f5e}
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | imgui\implementation
35 |
36 |
37 | imgui\implementation
38 |
39 |
40 | imgui\implementation
41 |
42 |
43 | imgui\implementation
44 |
45 |
46 | imgui\implementation
47 |
48 |
49 | imgui\implementation
50 |
51 |
52 | imgui\implementation
53 |
54 |
55 | imgui\implementation
56 |
57 |
58 | imgui\implementation
59 |
60 |
61 | imgui\implementation
62 |
63 |
64 | imgui\implementation
65 |
66 |
67 | Source Files
68 |
69 |
70 | Source Files
71 |
72 |
73 | Source Files
74 |
75 |
76 | Source Files
77 |
78 |
79 |
80 |
81 | Header Files
82 |
83 |
84 | Header Files
85 |
86 |
87 | imgui\headers
88 |
89 |
90 | imgui\headers
91 |
92 |
93 | imgui\headers
94 |
95 |
96 | imgui\headers
97 |
98 |
99 | imgui\headers
100 |
101 |
102 | imgui\headers
103 |
104 |
105 | imgui\headers
106 |
107 |
108 | imgui\headers
109 |
110 |
111 | imgui\headers
112 |
113 |
114 | imgui\headers
115 |
116 |
117 | imgui\headers
118 |
119 |
120 | imgui\headers
121 |
122 |
123 | imgui\headers
124 |
125 |
126 | Header Files
127 |
128 |
129 | Header Files
130 |
131 |
132 | Header Files
133 |
134 |
135 |
136 |
137 | Resource Files
138 |
139 |
140 |
--------------------------------------------------------------------------------
/fmt/include/fmt/ostream.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - std::ostream support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_OSTREAM_H_
9 | #define FMT_OSTREAM_H_
10 |
11 | #include
12 |
13 | #include "format.h"
14 |
15 | FMT_BEGIN_NAMESPACE
16 |
17 | template class basic_printf_parse_context;
18 | template class basic_printf_context;
19 |
20 | namespace detail {
21 |
22 | template class formatbuf : public std::basic_streambuf {
23 | private:
24 | using int_type = typename std::basic_streambuf::int_type;
25 | using traits_type = typename std::basic_streambuf::traits_type;
26 |
27 | buffer& buffer_;
28 |
29 | public:
30 | formatbuf(buffer& buf) : buffer_(buf) {}
31 |
32 | protected:
33 | // The put-area is actually always empty. This makes the implementation
34 | // simpler and has the advantage that the streambuf and the buffer are always
35 | // in sync and sputc never writes into uninitialized memory. The obvious
36 | // disadvantage is that each call to sputc always results in a (virtual) call
37 | // to overflow. There is no disadvantage here for sputn since this always
38 | // results in a call to xsputn.
39 |
40 | int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
41 | if (!traits_type::eq_int_type(ch, traits_type::eof()))
42 | buffer_.push_back(static_cast(ch));
43 | return ch;
44 | }
45 |
46 | std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
47 | buffer_.append(s, s + count);
48 | return count;
49 | }
50 | };
51 |
52 | template struct test_stream : std::basic_ostream {
53 | private:
54 | // Hide all operator<< from std::basic_ostream.
55 | void_t<> operator<<(null<>);
56 | void_t<> operator<<(const Char*);
57 |
58 | template ::value &&
59 | !std::is_enum::value)>
60 | void_t<> operator<<(T);
61 | };
62 |
63 | // Checks if T has a user-defined operator<< (e.g. not a member of
64 | // std::ostream).
65 | template class is_streamable {
66 | private:
67 | template
68 | static bool_constant&>()
69 | << std::declval()),
70 | void_t<>>::value>
71 | test(int);
72 |
73 | template static std::false_type test(...);
74 |
75 | using result = decltype(test(0));
76 |
77 | public:
78 | static const bool value = result::value;
79 | };
80 |
81 | // Write the content of buf to os.
82 | template
83 | void write_buffer(std::basic_ostream& os, buffer& buf) {
84 | const Char* buf_data = buf.data();
85 | using unsigned_streamsize = std::make_unsigned::type;
86 | unsigned_streamsize size = buf.size();
87 | unsigned_streamsize max_size = to_unsigned(max_value());
88 | do {
89 | unsigned_streamsize n = size <= max_size ? size : max_size;
90 | os.write(buf_data, static_cast(n));
91 | buf_data += n;
92 | size -= n;
93 | } while (size != 0);
94 | }
95 |
96 | template
97 | void format_value(buffer& buf, const T& value,
98 | locale_ref loc = locale_ref()) {
99 | formatbuf format_buf(buf);
100 | std::basic_ostream output(&format_buf);
101 | #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
102 | if (loc) output.imbue(loc.get());
103 | #endif
104 | output << value;
105 | output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
106 | buf.resize(buf.size());
107 | }
108 |
109 | // Formats an object of type T that has an overloaded ostream operator<<.
110 | template
111 | struct fallback_formatter::value>>
112 | : private formatter, Char> {
113 | FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx)
114 | -> decltype(ctx.begin()) {
115 | return formatter, Char>::parse(ctx);
116 | }
117 | template >::value)>
120 | auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
121 | return ctx.begin();
122 | }
123 |
124 | template
125 | auto format(const T& value, basic_format_context& ctx)
126 | -> OutputIt {
127 | basic_memory_buffer buffer;
128 | format_value(buffer, value, ctx.locale());
129 | basic_string_view str(buffer.data(), buffer.size());
130 | return formatter, Char>::format(str, ctx);
131 | }
132 | template
133 | auto format(const T& value, basic_printf_context& ctx)
134 | -> OutputIt {
135 | basic_memory_buffer buffer;
136 | format_value(buffer, value, ctx.locale());
137 | return std::copy(buffer.begin(), buffer.end(), ctx.out());
138 | }
139 | };
140 | } // namespace detail
141 |
142 | template
143 | void vprint(std::basic_ostream& os, basic_string_view format_str,
144 | basic_format_args>> args) {
145 | basic_memory_buffer buffer;
146 | detail::vformat_to(buffer, format_str, args);
147 | detail::write_buffer(os, buffer);
148 | }
149 |
150 | /**
151 | \rst
152 | Prints formatted data to the stream *os*.
153 |
154 | **Example**::
155 |
156 | fmt::print(cerr, "Don't {}!", "panic");
157 | \endrst
158 | */
159 | template ::value, char_t>>
161 | void print(std::basic_ostream& os, const S& format_str, Args&&... args) {
162 | vprint(os, to_string_view(format_str),
163 | detail::make_args_checked(format_str, args...));
164 | }
165 | FMT_END_NAMESPACE
166 |
167 | #endif // FMT_OSTREAM_H_
168 |
--------------------------------------------------------------------------------
/BetterChat.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | x64
7 |
8 |
9 |
10 | 16.0
11 | {4d053de5-3f47-432d-be43-bdd54680d990}
12 | BetterChat
13 | 10.0
14 |
15 |
16 |
17 | DynamicLibrary
18 | true
19 | v142
20 | Unicode
21 |
22 |
23 | DynamicLibrary
24 | false
25 | v143
26 | true
27 | Unicode
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 | $(SolutionDir)plugins\
46 | $(SolutionDir)build\.intermediates\$(Configuration)\
47 |
48 |
49 | false
50 | $(SolutionDir)plugins\
51 | $(SolutionDir)build\.intermediates\$(Configuration)\
52 |
53 |
54 | true
55 |
56 |
57 | true
58 |
59 |
60 |
61 | Level3
62 | true
63 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
64 | true
65 | Use
66 | pch.h
67 | MultiThreadedDebug
68 |
69 |
70 | Console
71 | true
72 |
73 |
74 |
75 |
76 | Level3
77 | true
78 | true
79 | true
80 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
81 | true
82 | Use
83 | pch.h
84 | MultiThreaded
85 | stdcpp20
86 | true
87 | $(ProjectDir)fmt\include;%(AdditionalIncludeDirectories)
88 |
89 |
90 | Console
91 | true
92 | true
93 | true
94 |
95 |
96 | powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | Create
116 | Create
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/IMGUI/imconfig.h:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI
3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
5 | //-----------------------------------------------------------------------------
6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/branch with your modifications to imconfig.h)
7 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
8 | // If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include
9 | // the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
10 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
11 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
12 | //-----------------------------------------------------------------------------
13 |
14 | #pragma once
15 |
16 | //---- Define assertion handler. Defaults to calling assert().
17 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
18 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
19 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
20 |
21 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
22 | // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
23 | //#define IMGUI_API __declspec( dllexport )
24 | //#define IMGUI_API __declspec( dllimport )
25 |
26 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
27 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
28 |
29 | //---- Disable all of Dear ImGui or don't implement standard windows.
30 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
31 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
32 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
33 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable debug/metrics window: ShowMetricsWindow() will be empty.
34 |
35 | //---- Don't implement some functions to reduce linkage requirements.
36 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
37 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
38 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
39 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
40 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
41 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
42 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
43 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
44 |
45 | //---- Include imgui_user.h at the end of imgui.h as a convenience
46 | //#define IMGUI_INCLUDE_IMGUI_USER_H
47 |
48 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
49 | //#define IMGUI_USE_BGRA_PACKED_COLOR
50 |
51 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
52 | // By default the embedded implementations are declared static and not available outside of imgui cpp files.
53 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
54 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
55 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
56 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
57 |
58 | //---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
59 | // Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
60 | // #define IMGUI_USE_STB_SPRINTF
61 |
62 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
63 | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
64 | /*
65 | #define IM_VEC2_CLASS_EXTRA \
66 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
67 | operator MyVec2() const { return MyVec2(x,y); }
68 |
69 | #define IM_VEC4_CLASS_EXTRA \
70 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
71 | operator MyVec4() const { return MyVec4(x,y,z,w); }
72 | */
73 |
74 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
75 | // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bit indices).
76 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
77 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
78 | //#define ImDrawIdx unsigned int
79 |
80 | //---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
81 | //struct ImDrawList;
82 | //struct ImDrawCmd;
83 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
84 | //#define ImDrawCallback MyImDrawCallback
85 |
86 | //---- Debug Tools: Macro to break in Debugger
87 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
88 | //#define IM_DEBUG_BREAK IM_ASSERT(0)
89 | //#define IM_DEBUG_BREAK __debugbreak()
90 |
91 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
92 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
93 | // This adds a small runtime cost which is why it is not enabled by default.
94 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
95 |
96 | //---- Debug Tools: Enable slower asserts
97 | //#define IMGUI_DEBUG_PARANOID
98 |
99 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
100 | /*
101 | namespace ImGui
102 | {
103 | void MyFunction(const char* name, const MyMatrix44& v);
104 | }
105 | */
106 |
107 | #define IMGUI_DEFINE_MATH_OPERATORS
--------------------------------------------------------------------------------
/BetterChat.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "bakkesmod/plugin/bakkesmodplugin.h"
4 | #include "bakkesmod/plugin/pluginwindow.h"
5 | #include "bakkesmod/plugin/PluginSettingsWindow.h"
6 |
7 | #include "version.h"
8 |
9 | #include
10 | #include
11 | #include
12 | constexpr auto plugin_version = stringify(VERSION_MAJOR) "." stringify(VERSION_MINOR) "." stringify(VERSION_PATCH);
13 |
14 | class BetterChat: public BakkesMod::Plugin::BakkesModPlugin, public BakkesMod::Plugin::PluginSettingsWindow
15 | {
16 | // Quickchats id <=> Quickchats texts
17 | std::map idQuickchats = {
18 | {"Group1Message1", "I got it!"}, // Je l'ai !
19 | {"Group1Message2", "Need boost!"}, // Besoin de turbo !
20 | {"Group1Message3", "Take the shot!"}, // Prends-le !
21 | {"Group1Message4", "Defending."}, // Je d�fends.
22 | {"Group1Message5", "Go for it!"}, // Vas-y !
23 | {"Group1Message6", "Centering!"}, // Centre !
24 | {"Group1Message7", "All yours."}, // Il est pour toi.
25 | {"Group1Message8", "In position."}, // En position.
26 | {"Group1Message9", "Incoming!"}, // En approche !
27 | {"Group1Message10", "Faking."}, // La feinte.
28 | {"Group1Message11", "Bumping!"}, // Impact !
29 | {"Group1Message12", "On your left!"}, // Sur ta gauche !
30 | {"Group1Message13", "On your right!"}, // Sur ta droite !
31 | {"Group1Message14", "Passing!"}, // La passe !
32 | {"Group1Message15", "Rotating Up!"}, // Je monte !
33 | {"Group1Message16", "Rotating back!"}, // Je recule !
34 | {"Group1Message17", "You have time!"}, // Tu as le temps !
35 |
36 | {"Group2Message1", "Nice shot!"}, // Beau tir !
37 | {"Group2Message2", "Great pass!"}, // Belle passe !
38 | {"Group2Message3", "Thanks!"}, // Merci !
39 | {"Group2Message4", "What a save!"}, // Quel arr�t !
40 | {"Group2Message5", "Nice one!"}, // Bien vu !
41 | {"Group2Message6", "What a play!"}, // Quelle intensit� !
42 | {"Group2Message7", "Great clear!"}, // Beau d�gagement !
43 | {"Group2Message8", "Nice block!"}, // Super blocage !
44 | {"Group2Message9", "Nice bump!"}, // Bel impact !
45 | {"Group2Message10", "Nice demo!"}, // Jolie d�mo !
46 | {"Group2Message11", "We got this."}, // On assure !
47 |
48 | {"Group3Message1", "OMG!"}, // Oh mon dieu !
49 | {"Group3Message2", "Noooo!"}, // Noooon !
50 | {"Group3Message3", "Wow!"}, // Wow !
51 | {"Group3Message4", "Close one..."}, // C'�tait pas loin...
52 | {"Group3Message5", "No way!"}, // Pas possible !
53 | {"Group3Message6", "Holy cow!"}, // S�rieux ?!
54 | {"Group3Message7", "Whew."}, // Waouh.
55 | {"Group3Message8", "Siiiick!"}, // Truc de ouf !
56 | {"Group3Message9", "Calculated."}, // C'est pr�vu.
57 | {"Group3Message10", "Savage!"}, // Sauvage !
58 | {"Group3Message11", "Okay."}, // Ok.
59 | {"Group3Message12", "Yes!"}, // Oui !
60 |
61 | {"Group4Message1", "$#@%!"}, // $#@%!
62 | {"Group4Message2", "No problem."}, // Pas de probl�mes.
63 | {"Group4Message3", "Whoops..."}, // Oups...
64 | {"Group4Message4", "Sorry!"}, // D�sol� !
65 | {"Group4Message5", "My bad..."}, // Pardon...
66 | {"Group4Message6", "Oops!"}, // Oups !
67 | {"Group4Message7", "My fault."}, // Ma faute.
68 |
69 | {"Group5Message1", "gg"}, // gg
70 | {"Group5Message2", "Well played."}, // Bien jou�.
71 | {"Group5Message3", "That was fun!"}, // C'�tait cool !
72 | {"Group5Message4", "Rematch!"}, // On remet �a !
73 | {"Group5Message5", "One. More. Game."}, // Encore. Une. Partie.
74 | {"Group5Message6", "What a game!"}, // Quelle partie !
75 | {"Group5Message7", "Nice moves!"}, // Super d�placements !
76 | {"Group5Message8", "Everybody dance!"}, // Que tout le monde dance !
77 | {"Group5Message9", "Party Up?"}, // On groupe ?
78 |
79 | {"Group6Message4", "This is Rocket League!"}, // �a c'est Rocket League !
80 | };
81 |
82 | // Structs
83 | struct BetterChatParams {
84 | bool antispam;
85 | bool chatfilter;
86 | int antispam_delay;
87 | bool nowrittenmsg;
88 | bool writtenmsgastoxic;
89 | int aftersavetime;
90 | bool owngoal;
91 | bool unwanted_pass;
92 | bool toxicityscores;
93 | };
94 |
95 | struct StatTickerParams {
96 | uintptr_t Receiver;
97 | uintptr_t Victim;
98 | uintptr_t StatEvent;
99 | };
100 |
101 | struct FHUDChatMessage
102 | {
103 | void* PRI;
104 | void* Team;
105 | wchar_t* PlayerName;
106 | uint8_t PlayerNamePadding[0x8];
107 | wchar_t* Message;
108 | uint8_t MessagePadding[0x8];
109 | uint8_t ChatChannel;
110 | unsigned long bPreset : 1;
111 | };
112 |
113 | struct FString
114 | {
115 | public:
116 | using ElementType = const wchar_t;
117 | using ElementPointer = ElementType*;
118 |
119 | private:
120 | ElementPointer ArrayData;
121 | int32_t ArrayCount;
122 | int32_t ArrayMax;
123 |
124 | public:
125 | FString()
126 | {
127 | ArrayData = nullptr;
128 | ArrayCount = 0;
129 | ArrayMax = 0;
130 | }
131 |
132 | FString(ElementPointer other)
133 | {
134 | ArrayData = nullptr;
135 | ArrayCount = 0;
136 | ArrayMax = 0;
137 |
138 | ArrayMax = ArrayCount = *other ? (wcslen(other) + 1) : 0;
139 |
140 | if (ArrayCount > 0)
141 | {
142 | ArrayData = other;
143 | }
144 | }
145 |
146 | ~FString() {}
147 |
148 | public:
149 | std::string ToString() const
150 | {
151 | if (!IsValid())
152 | {
153 | std::wstring wideStr(ArrayData);
154 | std::string str(wideStr.begin(), wideStr.end());
155 | return str;
156 | }
157 |
158 | return std::string("null");
159 | }
160 |
161 | bool IsValid() const
162 | {
163 | return !ArrayData;
164 | }
165 |
166 | FString operator=(ElementPointer other)
167 | {
168 | if (ArrayData != other)
169 | {
170 | ArrayMax = ArrayCount = *other ? (wcslen(other) + 1) : 0;
171 |
172 | if (ArrayCount > 0)
173 | {
174 | ArrayData = other;
175 | }
176 | }
177 |
178 | return *this;
179 | }
180 |
181 | bool operator==(const FString& other)
182 | {
183 | return (!wcscmp(ArrayData, other.ArrayData));
184 | }
185 | };
186 |
187 | FString FS(const std::string& s) {
188 | wchar_t* p = new wchar_t[s.size() + 1];
189 | for (std::string::size_type i = 0; i < s.size(); ++i)
190 | p[i] = s[i];
191 |
192 | p[s.size()] = '\0';
193 | return FString(p);
194 | }
195 |
196 | struct FSceNpOnlineId
197 | {
198 | uint64_t Data[0x2]; // 0x0000 (0x0010) [0x0000000000000000]
199 | uint8_t Term; // 0x0010 (0x0001) [0x0000000000000000]
200 | uint8_t Dummy[0x3]; // 0x0011 (0x0003) [0x0000000000000000]
201 | };
202 |
203 | struct FSceNpId
204 | {
205 | struct FSceNpOnlineId Handle; // 0x0000 (0x0018) [0x0000000000000002] (CPF_Const)
206 | uint64_t Opt; // 0x0018 (0x0008) [0x0000000000000002] (CPF_Const)
207 | uint64_t Reserved; // 0x0020 (0x0008) [0x0000000000000002] (CPF_Const)
208 | };
209 |
210 | struct FUniqueNetId
211 | {
212 | uint64_t Uid; // 0x0000 (0x0008) [0x0000000000000000]
213 | struct FSceNpId NpId; // 0x0008 (0x0028) [0x0000000000000000]
214 | struct FString EpicAccountId; // 0x0030 (0x0010) [0x0000000000400000] (CPF_NeedCtorLink)
215 | uint8_t Platform; // 0x0040 (0x0001) [0x0000000000000000]
216 | uint8_t SplitscreenID; // 0x0041 (0x0001) [0x0000000000000000]
217 | };
218 |
219 | struct FGFxChatMessage {
220 | int32_t Team;
221 | class FString PlayerName;
222 | class FString Message;
223 | uint8_t ChatChannel;
224 | bool bLocalPlayer : 1;
225 | struct FUniqueNetId SenderID;
226 | uint8_t MessageType;
227 | class FString TimeStamp;
228 | };
229 |
230 | //Functions
231 |
232 | void resetWhitelist();
233 |
234 | // -- JSON functions --
235 | void jsonFileExists();
236 | void createConfigInJson(std::string configName);
237 | void deleteConfigInJson(std::string configName);
238 | std::list getConfigsListInJson();
239 | std::map getConfigByGamemodeInJson();
240 | void editConfigByGamemodeInJson(std::string gamemode, std::string config);
241 | std::map readMapInJson(std::string config, std::string category);
242 | void toggleQuickchatInJson(std::string config, std::string category, std::string idMsg);
243 | BetterChatParams getParamsInJson(std::string config);
244 | void editParamInJson(std::string config, std::string param, std::variant value);
245 |
246 | virtual void onLoad();
247 | virtual void onUnload();
248 |
249 | void handleMsg(bool cancel, std::string playerName);
250 |
251 | void onNewGame();
252 | void setConfig();
253 | void refreshConfig();
254 | void gameBegin();
255 | void gameEnd();
256 | void chatMessageEvent(ActorWrapper caller, void* args);
257 | void onStatTickerMessage(ServerWrapper caller, void* args);
258 | void hitBall(CarWrapper car, void* params);
259 | void addKickoffMessages();
260 | void onTimerUpdate();
261 | void onGoal();
262 | void onOvertimeStarted();
263 |
264 | void gameDestroyed();
265 | void ShowToxicityScores(CanvasWrapper canvas);
266 |
267 | // Interface
268 | void RenderSettings() override;
269 | std::string GetPluginName() override;
270 | void SetImGuiContext(uintptr_t ctx) override;
271 | };
--------------------------------------------------------------------------------
/IMGUI/imgui_searchablecombo.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "imgui_searchablecombo.h"
3 | #include "imgui_internal.h"
4 |
5 | static float CalcMaxPopupHeightFromItemCount(int items_count)
6 | {
7 | ImGuiContext& g = *GImGui;
8 | if (items_count <= 0)
9 | return FLT_MAX;
10 | return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
11 | }
12 |
13 | /* Modified version of BeginCombo from imgui.cpp at line 9172,
14 | * to include a input field to be able to filter the combo values. */
15 | bool ImGui::BeginSearchableCombo(const char* label, const char* preview_value, char* input, int input_size, const char* input_preview_value, ImGuiComboFlags flags)
16 | {
17 | // Always consume the SetNextWindowSizeConstraint() call in our early return paths
18 | ImGuiContext& g = *GImGui;
19 | bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;
20 | g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
21 |
22 | ImGuiWindow* window = GetCurrentWindow();
23 | if (window->SkipItems)
24 | return false;
25 |
26 | IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
27 |
28 | const ImGuiStyle& style = g.Style;
29 | const ImGuiID id = window->GetID(label);
30 |
31 | const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
32 | const ImVec2 label_size = CalcTextSize(label, NULL, true);
33 | const float expected_w = CalcItemWidth();
34 | const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
35 | const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
36 | const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
37 |
38 | bool hovered, held;
39 | bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
40 | bool popup_open = IsPopupOpen(id);
41 |
42 | const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
43 | const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
44 |
45 | if (popup_open || (pressed || g.NavActivateId == id))
46 | {
47 | ImGuiID activeId = g.ActiveId;
48 | if (popup_open)
49 | g.ActiveId = id;
50 | else
51 | g.NavInputId = id;
52 | InputTextEx(label, input_preview_value, input, input_size, frame_bb.Max - frame_bb.Min, ImGuiInputTextFlags_NoUndoRedo);
53 | g.ActiveId = activeId;
54 | if (!(flags & ImGuiComboFlags_NoArrowButton))
55 | {
56 | ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
57 | ImU32 text_col = GetColorU32(ImGuiCol_Text);
58 | window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
59 | if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x)
60 | RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
61 | }
62 | }
63 | else
64 | {
65 | ItemSize(total_bb, style.FramePadding.y);
66 | if (!ItemAdd(total_bb, id, &frame_bb))
67 | return false;
68 | }
69 |
70 | if ((pressed || g.NavActivateId == id) && !popup_open)
71 | {
72 | if (window->DC.NavLayerCurrent == 0)
73 | window->NavLastIds[0] = id;
74 | OpenPopupEx(id);
75 | popup_open = true;
76 | }
77 |
78 | if (!popup_open)
79 | {
80 | RenderNavHighlight(frame_bb, id);
81 | if (!(flags & ImGuiComboFlags_NoPreview))
82 | window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Left);
83 | if (!(flags & ImGuiComboFlags_NoArrowButton))
84 | {
85 | ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
86 | ImU32 text_col = GetColorU32(ImGuiCol_Text);
87 | window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
88 | if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x)
89 | RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
90 | }
91 | RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
92 |
93 | if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
94 | RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f));
95 | if (label_size.x > 0)
96 | RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
97 |
98 | return false;
99 | }
100 |
101 | if (has_window_size_constraint)
102 | {
103 | g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
104 | g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
105 | }
106 | else
107 | {
108 | if ((flags & ImGuiComboFlags_HeightMask_) == 0)
109 | flags |= ImGuiComboFlags_HeightRegular;
110 | IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
111 | int popup_max_height_in_items = -1;
112 | if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
113 | else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
114 | else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
115 | SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
116 | }
117 |
118 | char name[16];
119 | ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
120 |
121 | // Peak into expected window size so we can position it
122 | if (ImGuiWindow* popup_window = FindWindowByName(name))
123 | if (popup_window->WasActive)
124 | {
125 | ImVec2 size_expected = CalcWindowExpectedSize(popup_window);
126 | if (flags & ImGuiComboFlags_PopupAlignLeft)
127 | popup_window->AutoPosLastDirection = ImGuiDir_Left;
128 | ImRect r_outer = GetWindowAllowedExtentRect(popup_window);
129 | ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
130 | SetNextWindowPos(pos);
131 | }
132 |
133 | // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx()
134 | ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;
135 |
136 | // Horizontally align ourselves with the framed text
137 | PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y));
138 | bool ret = Begin(name, NULL, window_flags);
139 | PopStyleVar();
140 | if (!ret)
141 | {
142 | EndPopup();
143 | IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
144 | return false;
145 | }
146 |
147 | return true;
148 | }
149 |
150 |
151 | // Just so you can end your BeginSearchableCombo with EndSearchableCombo.
152 | void ImGui::EndSearchableCombo()
153 | {
154 | EndCombo();
155 | }
156 |
157 |
158 | /* Modified version of Combo from imgui.cpp at line 9343,
159 | * to include a input field to be able to filter the combo values. */
160 | bool ImGui::SearchableCombo(const char* label, int* current_item, std::vector items, const char* default_preview_text, const char* input_preview_value, int popup_max_height_in_items)
161 | {
162 | ImGuiContext& g = *GImGui;
163 |
164 | const char* preview_text = NULL;
165 | if (*current_item >= (int)items.size())
166 | *current_item = 0;
167 | if (*current_item >= 0 && *current_item < (int)items.size())
168 | preview_text = items[*current_item].c_str();
169 | else
170 | preview_text = default_preview_text;
171 |
172 | // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
173 | if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
174 | SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
175 |
176 | const int input_size = 64;
177 | char input_buffer[input_size] = "";
178 | if (!BeginSearchableCombo(label, preview_text, input_buffer, input_size, input_preview_value, ImGuiComboFlags_None))
179 | return false;
180 |
181 | // Display items
182 | // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
183 | int matched_items = 0;
184 | bool value_changed = false;
185 | for (int i = 0; i < (int)items.size(); i++)
186 | {
187 | char buffer[input_size] = "";
188 | ImStrncpy(buffer, input_buffer, input_size);
189 | std::string input(buffer);
190 | std::string item = items[i];
191 |
192 | std::transform(item.begin(), item.end(), item.begin(),
193 | [](unsigned char c) { return (unsigned char)std::tolower(c); });
194 | std::transform(input.begin(), input.end(), input.begin(),
195 | [](unsigned char c) { return (unsigned char)std::tolower(c); });
196 |
197 | if (item.find(input, 0) == std::string::npos)
198 | continue;
199 |
200 | matched_items++;
201 | PushID((void*)(intptr_t)i);
202 | const bool item_selected = (i == *current_item);
203 | const char* item_text = items[i].c_str();
204 | if (Selectable(item_text, item_selected))
205 | {
206 | value_changed = true;
207 | *current_item = i;
208 | }
209 | if (item_selected)
210 | SetItemDefaultFocus();
211 | PopID();
212 | }
213 | if (matched_items == 0)
214 | ImGui::Selectable("No maps found", false, ImGuiSelectableFlags_Disabled);
215 |
216 | EndSearchableCombo();
217 |
218 | return value_changed;
219 | }
--------------------------------------------------------------------------------
/fmt/src/os.cc:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - optional OS-specific functionality
2 | //
3 | // Copyright (c) 2012 - 2016, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | // Disable bogus MSVC warnings.
9 | #if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
10 | # define _CRT_SECURE_NO_WARNINGS
11 | #endif
12 | #include "pch.h"
13 | #include "fmt/os.h"
14 |
15 | #include
16 |
17 | #if FMT_USE_FCNTL
18 | # include
19 | # include
20 |
21 | # ifndef _WIN32
22 | # include
23 | # else
24 | # ifndef WIN32_LEAN_AND_MEAN
25 | # define WIN32_LEAN_AND_MEAN
26 | # endif
27 | # include
28 | # include
29 |
30 | # define O_CREAT _O_CREAT
31 | # define O_TRUNC _O_TRUNC
32 |
33 | # ifndef S_IRUSR
34 | # define S_IRUSR _S_IREAD
35 | # endif
36 |
37 | # ifndef S_IWUSR
38 | # define S_IWUSR _S_IWRITE
39 | # endif
40 |
41 | # ifdef __MINGW32__
42 | # define _SH_DENYNO 0x40
43 | # endif
44 | # endif // _WIN32
45 | #endif // FMT_USE_FCNTL
46 |
47 | #ifdef _WIN32
48 | # include
49 | #endif
50 |
51 | #ifdef fileno
52 | # undef fileno
53 | #endif
54 |
55 | namespace {
56 | #ifdef _WIN32
57 | // Return type of read and write functions.
58 | using RWResult = int;
59 |
60 | // On Windows the count argument to read and write is unsigned, so convert
61 | // it from size_t preventing integer overflow.
62 | inline unsigned convert_rwcount(std::size_t count) {
63 | return count <= UINT_MAX ? static_cast(count) : UINT_MAX;
64 | }
65 | #else
66 | // Return type of read and write functions.
67 | using RWResult = ssize_t;
68 |
69 | inline std::size_t convert_rwcount(std::size_t count) { return count; }
70 | #endif
71 | } // namespace
72 |
73 | FMT_BEGIN_NAMESPACE
74 |
75 | #ifdef _WIN32
76 | detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
77 | if (int error_code = convert(s)) {
78 | FMT_THROW(windows_error(error_code,
79 | "cannot convert string from UTF-16 to UTF-8"));
80 | }
81 | }
82 |
83 | int detail::utf16_to_utf8::convert(wstring_view s) {
84 | if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
85 | int s_size = static_cast(s.size());
86 | if (s_size == 0) {
87 | // WideCharToMultiByte does not support zero length, handle separately.
88 | buffer_.resize(1);
89 | buffer_[0] = 0;
90 | return 0;
91 | }
92 |
93 | int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, nullptr, 0,
94 | nullptr, nullptr);
95 | if (length == 0) return GetLastError();
96 | buffer_.resize(length + 1);
97 | length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0],
98 | length, nullptr, nullptr);
99 | if (length == 0) return GetLastError();
100 | buffer_[length] = 0;
101 | return 0;
102 | }
103 |
104 | void windows_error::init(int err_code, string_view format_str,
105 | format_args args) {
106 | error_code_ = err_code;
107 | memory_buffer buffer;
108 | detail::format_windows_error(buffer, err_code, vformat(format_str, args));
109 | std::runtime_error& base = *this;
110 | base = std::runtime_error(to_string(buffer));
111 | }
112 |
113 | void detail::format_windows_error(detail::buffer& out, int error_code,
114 | string_view message) FMT_NOEXCEPT {
115 | FMT_TRY {
116 | wmemory_buffer buf;
117 | buf.resize(inline_buffer_size);
118 | for (;;) {
119 | wchar_t* system_message = &buf[0];
120 | int result = FormatMessageW(
121 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
122 | error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message,
123 | static_cast(buf.size()), nullptr);
124 | if (result != 0) {
125 | utf16_to_utf8 utf8_message;
126 | if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
127 | format_to(std::back_inserter(out), "{}: {}", message, utf8_message);
128 | return;
129 | }
130 | break;
131 | }
132 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
133 | break; // Can't get error message, report error code instead.
134 | buf.resize(buf.size() * 2);
135 | }
136 | }
137 | FMT_CATCH(...) {}
138 | format_error_code(out, error_code, message);
139 | }
140 |
141 | void report_windows_error(int error_code,
142 | fmt::string_view message) FMT_NOEXCEPT {
143 | report_error(detail::format_windows_error, error_code, message);
144 | }
145 | #endif // _WIN32
146 |
147 | buffered_file::~buffered_file() FMT_NOEXCEPT {
148 | if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
149 | report_system_error(errno, "cannot close file");
150 | }
151 |
152 | buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
153 | FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())),
154 | nullptr);
155 | if (!file_)
156 | FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
157 | }
158 |
159 | void buffered_file::close() {
160 | if (!file_) return;
161 | int result = FMT_SYSTEM(fclose(file_));
162 | file_ = nullptr;
163 | if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
164 | }
165 |
166 | // A macro used to prevent expansion of fileno on broken versions of MinGW.
167 | #define FMT_ARGS
168 |
169 | int buffered_file::fileno() const {
170 | int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
171 | if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
172 | return fd;
173 | }
174 |
175 | #if FMT_USE_FCNTL
176 | file::file(cstring_view path, int oflag) {
177 | int mode = S_IRUSR | S_IWUSR;
178 | # if defined(_WIN32) && !defined(__MINGW32__)
179 | fd_ = -1;
180 | FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
181 | # else
182 | FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
183 | # endif
184 | if (fd_ == -1)
185 | FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
186 | }
187 |
188 | file::~file() FMT_NOEXCEPT {
189 | // Don't retry close in case of EINTR!
190 | // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
191 | if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
192 | report_system_error(errno, "cannot close file");
193 | }
194 |
195 | void file::close() {
196 | if (fd_ == -1) return;
197 | // Don't retry close in case of EINTR!
198 | // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
199 | int result = FMT_POSIX_CALL(close(fd_));
200 | fd_ = -1;
201 | if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
202 | }
203 |
204 | long long file::size() const {
205 | # ifdef _WIN32
206 | // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
207 | // is less than 0x0500 as is the case with some default MinGW builds.
208 | // Both functions support large file sizes.
209 | DWORD size_upper = 0;
210 | HANDLE handle = reinterpret_cast(_get_osfhandle(fd_));
211 | DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
212 | if (size_lower == INVALID_FILE_SIZE) {
213 | DWORD error = GetLastError();
214 | if (error != NO_ERROR)
215 | FMT_THROW(windows_error(GetLastError(), "cannot get file size"));
216 | }
217 | unsigned long long long_size = size_upper;
218 | return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
219 | # else
220 | using Stat = struct stat;
221 | Stat file_stat = Stat();
222 | if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
223 | FMT_THROW(system_error(errno, "cannot get file attributes"));
224 | static_assert(sizeof(long long) >= sizeof(file_stat.st_size),
225 | "return type of file::size is not large enough");
226 | return file_stat.st_size;
227 | # endif
228 | }
229 |
230 | std::size_t file::read(void* buffer, std::size_t count) {
231 | RWResult result = 0;
232 | FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
233 | if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
234 | return detail::to_unsigned(result);
235 | }
236 |
237 | std::size_t file::write(const void* buffer, std::size_t count) {
238 | RWResult result = 0;
239 | FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
240 | if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
241 | return detail::to_unsigned(result);
242 | }
243 |
244 | file file::dup(int fd) {
245 | // Don't retry as dup doesn't return EINTR.
246 | // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
247 | int new_fd = FMT_POSIX_CALL(dup(fd));
248 | if (new_fd == -1)
249 | FMT_THROW(system_error(errno, "cannot duplicate file descriptor {}", fd));
250 | return file(new_fd);
251 | }
252 |
253 | void file::dup2(int fd) {
254 | int result = 0;
255 | FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
256 | if (result == -1) {
257 | FMT_THROW(system_error(errno, "cannot duplicate file descriptor {} to {}",
258 | fd_, fd));
259 | }
260 | }
261 |
262 | void file::dup2(int fd, error_code& ec) FMT_NOEXCEPT {
263 | int result = 0;
264 | FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
265 | if (result == -1) ec = error_code(errno);
266 | }
267 |
268 | void file::pipe(file& read_end, file& write_end) {
269 | // Close the descriptors first to make sure that assignments don't throw
270 | // and there are no leaks.
271 | read_end.close();
272 | write_end.close();
273 | int fds[2] = {};
274 | # ifdef _WIN32
275 | // Make the default pipe capacity same as on Linux 2.6.11+.
276 | enum { DEFAULT_CAPACITY = 65536 };
277 | int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
278 | # else
279 | // Don't retry as the pipe function doesn't return EINTR.
280 | // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
281 | int result = FMT_POSIX_CALL(pipe(fds));
282 | # endif
283 | if (result != 0) FMT_THROW(system_error(errno, "cannot create pipe"));
284 | // The following assignments don't throw because read_fd and write_fd
285 | // are closed.
286 | read_end = file(fds[0]);
287 | write_end = file(fds[1]);
288 | }
289 |
290 | buffered_file file::fdopen(const char* mode) {
291 | // Don't retry as fdopen doesn't return EINTR.
292 | #if defined(__MINGW32__) && defined(_POSIX_)
293 | FILE* f = ::fdopen(fd_, mode);
294 | #else
295 | FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
296 | #endif
297 | if (!f)
298 | FMT_THROW(
299 | system_error(errno, "cannot associate stream with file descriptor"));
300 | buffered_file bf(f);
301 | fd_ = -1;
302 | return bf;
303 | }
304 |
305 | long getpagesize() {
306 | # ifdef _WIN32
307 | SYSTEM_INFO si;
308 | GetSystemInfo(&si);
309 | return si.dwPageSize;
310 | # else
311 | long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
312 | if (size < 0) FMT_THROW(system_error(errno, "cannot get memory page size"));
313 | return size;
314 | # endif
315 | }
316 | #endif // FMT_USE_FCNTL
317 | FMT_END_NAMESPACE
318 |
--------------------------------------------------------------------------------
/fmt/include/fmt/ranges.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - experimental range support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 | //
8 | // Copyright (c) 2018 - present, Remotion (Igor Schulz)
9 | // All Rights Reserved
10 | // {fmt} support for ranges, containers and types tuple interface.
11 |
12 | #ifndef FMT_RANGES_H_
13 | #define FMT_RANGES_H_
14 |
15 | #include
16 | #include
17 |
18 | #include "format.h"
19 |
20 | // output only up to N items from the range.
21 | #ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
22 | # define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
23 | #endif
24 |
25 | FMT_BEGIN_NAMESPACE
26 |
27 | template struct formatting_base {
28 | template
29 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
30 | return ctx.begin();
31 | }
32 | };
33 |
34 | template
35 | struct formatting_range : formatting_base {
36 | static FMT_CONSTEXPR_DECL const size_t range_length_limit =
37 | FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
38 | // range.
39 | Char prefix;
40 | Char delimiter;
41 | Char postfix;
42 | formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
43 | static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
44 | static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
45 | };
46 |
47 | template
48 | struct formatting_tuple : formatting_base {
49 | Char prefix;
50 | Char delimiter;
51 | Char postfix;
52 | formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
53 | static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
54 | static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
55 | };
56 |
57 | namespace detail {
58 |
59 | template
60 | OutputIterator copy(const RangeT& range, OutputIterator out) {
61 | for (auto it = range.begin(), end = range.end(); it != end; ++it)
62 | *out++ = *it;
63 | return out;
64 | }
65 |
66 | template
67 | OutputIterator copy(const char* str, OutputIterator out) {
68 | while (*str) *out++ = *str++;
69 | return out;
70 | }
71 |
72 | template
73 | OutputIterator copy(char ch, OutputIterator out) {
74 | *out++ = ch;
75 | return out;
76 | }
77 |
78 | /// Return true value if T has std::string interface, like std::string_view.
79 | template class is_like_std_string {
80 | template
81 | static auto check(U* p)
82 | -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
83 | template static void check(...);
84 |
85 | public:
86 | static FMT_CONSTEXPR_DECL const bool value =
87 | is_string::value || !std::is_void(nullptr))>::value;
88 | };
89 |
90 | template
91 | struct is_like_std_string> : std::true_type {};
92 |
93 | template struct conditional_helper {};
94 |
95 | template struct is_range_ : std::false_type {};
96 |
97 | #if !FMT_MSC_VER || FMT_MSC_VER > 1800
98 | template
99 | struct is_range_<
100 | T, conditional_t().begin()),
102 | decltype(std::declval().end())>,
103 | void>> : std::true_type {};
104 | #endif
105 |
106 | /// tuple_size and tuple_element check.
107 | template class is_tuple_like_ {
108 | template
109 | static auto check(U* p) -> decltype(std::tuple_size::value, int());
110 | template static void check(...);
111 |
112 | public:
113 | static FMT_CONSTEXPR_DECL const bool value =
114 | !std::is_void(nullptr))>::value;
115 | };
116 |
117 | // Check for integer_sequence
118 | #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
119 | template
120 | using integer_sequence = std::integer_sequence;
121 | template using index_sequence = std::index_sequence;
122 | template using make_index_sequence = std::make_index_sequence;
123 | #else
124 | template struct integer_sequence {
125 | using value_type = T;
126 |
127 | static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
128 | };
129 |
130 | template using index_sequence = integer_sequence;
131 |
132 | template
133 | struct make_integer_sequence : make_integer_sequence {};
134 | template
135 | struct make_integer_sequence : integer_sequence {};
136 |
137 | template
138 | using make_index_sequence = make_integer_sequence;
139 | #endif
140 |
141 | template
142 | void for_each(index_sequence, Tuple&& tup, F&& f) FMT_NOEXCEPT {
143 | using std::get;
144 | // using free function get(T) now.
145 | const int _[] = {0, ((void)f(get(tup)), 0)...};
146 | (void)_; // blocks warnings
147 | }
148 |
149 | template
150 | FMT_CONSTEXPR make_index_sequence::value> get_indexes(
151 | T const&) {
152 | return {};
153 | }
154 |
155 | template void for_each(Tuple&& tup, F&& f) {
156 | const auto indexes = get_indexes(tup);
157 | for_each(indexes, std::forward(tup), std::forward(f));
158 | }
159 |
160 | template ::type>::value)>
162 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
163 | return add_space ? " {}" : "{}";
164 | }
165 |
166 | template ::type>::value)>
168 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
169 | return add_space ? " \"{}\"" : "\"{}\"";
170 | }
171 |
172 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
173 | return add_space ? " \"{}\"" : "\"{}\"";
174 | }
175 | FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
176 | return add_space ? L" \"{}\"" : L"\"{}\"";
177 | }
178 |
179 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
180 | return add_space ? " '{}'" : "'{}'";
181 | }
182 | FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
183 | return add_space ? L" '{}'" : L"'{}'";
184 | }
185 |
186 | } // namespace detail
187 |
188 | template struct is_tuple_like {
189 | static FMT_CONSTEXPR_DECL const bool value =
190 | detail::is_tuple_like_::value && !detail::is_range_::value;
191 | };
192 |
193 | template
194 | struct formatter::value>> {
195 | private:
196 | // C++11 generic lambda for format()
197 | template struct format_each {
198 | template void operator()(const T& v) {
199 | if (i > 0) {
200 | if (formatting.add_prepostfix_space) {
201 | *out++ = ' ';
202 | }
203 | out = detail::copy(formatting.delimiter, out);
204 | }
205 | out = format_to(out,
206 | detail::format_str_quoted(
207 | (formatting.add_delimiter_spaces && i > 0), v),
208 | v);
209 | ++i;
210 | }
211 |
212 | formatting_tuple& formatting;
213 | size_t& i;
214 | typename std::add_lvalue_reference().out())>::type out;
216 | };
217 |
218 | public:
219 | formatting_tuple formatting;
220 |
221 | template
222 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
223 | return formatting.parse(ctx);
224 | }
225 |
226 | template
227 | auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
228 | auto out = ctx.out();
229 | size_t i = 0;
230 | detail::copy(formatting.prefix, out);
231 |
232 | detail::for_each(values, format_each{formatting, i, out});
233 | if (formatting.add_prepostfix_space) {
234 | *out++ = ' ';
235 | }
236 | detail::copy(formatting.postfix, out);
237 |
238 | return ctx.out();
239 | }
240 | };
241 |
242 | template struct is_range {
243 | static FMT_CONSTEXPR_DECL const bool value =
244 | detail::is_range_::value && !detail::is_like_std_string::value &&
245 | !std::is_convertible>::value &&
246 | !std::is_constructible, T>::value;
247 | };
248 |
249 | template
250 | struct formatter::value>> {
252 | formatting_range formatting;
253 |
254 | template
255 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
256 | return formatting.parse(ctx);
257 | }
258 |
259 | template
260 | typename FormatContext::iterator format(const RangeT& values,
261 | FormatContext& ctx) {
262 | auto out = detail::copy(formatting.prefix, ctx.out());
263 | size_t i = 0;
264 | auto it = values.begin();
265 | auto end = values.end();
266 | for (; it != end; ++it) {
267 | if (i > 0) {
268 | if (formatting.add_prepostfix_space) *out++ = ' ';
269 | out = detail::copy(formatting.delimiter, out);
270 | }
271 | out = format_to(out,
272 | detail::format_str_quoted(
273 | (formatting.add_delimiter_spaces && i > 0), *it),
274 | *it);
275 | if (++i > formatting.range_length_limit) {
276 | out = format_to(out, " ... ");
277 | break;
278 | }
279 | }
280 | if (formatting.add_prepostfix_space) *out++ = ' ';
281 | return detail::copy(formatting.postfix, out);
282 | }
283 | };
284 |
285 | template struct tuple_arg_join : detail::view {
286 | const std::tuple& tuple;
287 | basic_string_view sep;
288 |
289 | tuple_arg_join(const std::tuple& t, basic_string_view s)
290 | : tuple{t}, sep{s} {}
291 | };
292 |
293 | template
294 | struct formatter, Char> {
295 | template
296 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
297 | return ctx.begin();
298 | }
299 |
300 | template
301 | typename FormatContext::iterator format(
302 | const tuple_arg_join& value, FormatContext& ctx) {
303 | return format(value, ctx, detail::make_index_sequence{});
304 | }
305 |
306 | private:
307 | template
308 | typename FormatContext::iterator format(
309 | const tuple_arg_join& value, FormatContext& ctx,
310 | detail::index_sequence) {
311 | return format_args(value, ctx, std::get(value.tuple)...);
312 | }
313 |
314 | template
315 | typename FormatContext::iterator format_args(
316 | const tuple_arg_join&, FormatContext& ctx) {
317 | // NOTE: for compilers that support C++17, this empty function instantiation
318 | // can be replaced with a constexpr branch in the variadic overload.
319 | return ctx.out();
320 | }
321 |
322 | template
323 | typename FormatContext::iterator format_args(
324 | const tuple_arg_join& value, FormatContext& ctx,
325 | const Arg& arg, const Args&... args) {
326 | using base = formatter::type, Char>;
327 | auto out = ctx.out();
328 | out = base{}.format(arg, ctx);
329 | if (sizeof...(Args) > 0) {
330 | out = std::copy(value.sep.begin(), value.sep.end(), out);
331 | ctx.advance_to(out);
332 | return format_args(value, ctx, args...);
333 | }
334 | return out;
335 | }
336 | };
337 |
338 | /**
339 | \rst
340 | Returns an object that formats `tuple` with elements separated by `sep`.
341 |
342 | **Example**::
343 |
344 | std::tuple t = {1, 'a'};
345 | fmt::print("{}", fmt::join(t, ", "));
346 | // Output: "1, a"
347 | \endrst
348 | */
349 | template
350 | FMT_CONSTEXPR tuple_arg_join join(const std::tuple& tuple,
351 | string_view sep) {
352 | return {tuple, sep};
353 | }
354 |
355 | template
356 | FMT_CONSTEXPR tuple_arg_join