Skip to content

Commit

Permalink
Add PatternPool class as a more optimal storage for compile-time code…
Browse files Browse the repository at this point in the history
… patterns

PatternPool allows iterating over the patterns and results in lower binary code size.
Clang 15 and 16 are no longer supported due to their bugs which result in build error after this commit.
  • Loading branch information
danielkrupinski committed Oct 28, 2024
1 parent 19ac65c commit 1eacf0d
Show file tree
Hide file tree
Showing 187 changed files with 1,592 additions and 2,244 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ jobs:
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
compiler: [g++-11, g++-12, g++-13, g++-14, clang++-15, clang++-16, clang++-17, clang++-18, clang++-19]
compiler: [g++-11, g++-12, g++-13, g++-14, clang++-17, clang++-18, clang++-19]
configuration: [Debug, Release]
exclude:
- os: ubuntu-22.04
compiler: g++-13
- os: ubuntu-22.04
compiler: g++-14
- os: ubuntu-22.04
compiler: clang++-16
- os: ubuntu-22.04
compiler: clang++-17
- os: ubuntu-22.04
Expand All @@ -28,8 +26,6 @@ jobs:
compiler: g++-11
- os: ubuntu-24.04
compiler: g++-12
- os: ubuntu-24.04
compiler: clang++-15

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Cross-platform (Windows, Linux) game hack for **Counter-Strike 2** with GUI and
#### Linux

* **CMake 3.24** or newer
* **g++ 11 or newer** or **clang++ 15 or newer**
* **g++ 11 or newer** or **clang++ 17 or newer**

### Compiling from source

Expand Down
1 change: 1 addition & 0 deletions Source/CS2/Panorama/CUIEngine.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <Platform/Macros/IsPlatform.h>
#include "CPanoramaSymbol.h"

namespace cs2
{
Expand Down
3 changes: 3 additions & 0 deletions Source/CS2/Panorama/StyleProperties.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#pragma once

#include <CS2/Classes/Color.h>
#include <CS2/Classes/CUtlString.h>
#include <CS2/Panorama/CUILength.h>
#include <CS2/Panorama/StyleEnums.h>
#include <Platform/Macros/PlatformSpecific.h>

#include "CStyleSymbol.h"

namespace cs2
{

Expand Down
18 changes: 9 additions & 9 deletions Source/FeatureHelpers/ConVarAccessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

#include <optional>

#include <GameDependencies/ConVarDeps.h>
#include <GameDependencies/ConVars.h>

struct ConVarAccessorState {
std::optional<bool> mp_teammates_are_enemies;
};

template <typename HookContext>
struct ConVarAccessor {
explicit ConVarAccessor(const ConVars& conVars, const ConVarDeps& conVarDeps, ConVarAccessorState& state) noexcept
: conVars{conVars}
, conVarDeps{conVarDeps}
explicit ConVarAccessor(HookContext& hookContext, const ConVars& conVars, ConVarAccessorState& state) noexcept
: hookContext{hookContext}
, conVars{conVars}
, state{state}
{
}
Expand All @@ -29,7 +29,7 @@ struct ConVarAccessor {
if (!conVar)
return false;

if (!conVarDeps.offsetToConVarValue || !conVarIsBool(conVar))
if (!hookContext.tier0PatternSearchResults().template get<OffsetToConVarValue>() || !conVarIsBool(conVar))
return false;

state.mp_teammates_are_enemies = readConVarValue<bool>(conVar);
Expand All @@ -49,19 +49,19 @@ struct ConVarAccessor {
[[nodiscard]] T readConVarValue(cs2::ConVar* conVar) const noexcept
{
T value;
std::memcpy(&value, conVarDeps.offsetToConVarValue.of(conVar).get(), sizeof(value));
std::memcpy(&value, hookContext.tier0PatternSearchResults().template get<OffsetToConVarValue>().of(conVar).get(), sizeof(value));
return value;
}

[[nodiscard]] bool conVarIsBool(cs2::ConVar* conVar) const noexcept
{
if (!conVarDeps.offsetToConVarValueType)
if (!hookContext.tier0PatternSearchResults().template get<OffsetToConVarValueType>())
return true;

return cs2::ConVarValueType{*conVarDeps.offsetToConVarValueType.of(conVar).get()} == cs2::ConVarValueType::boolean;
return cs2::ConVarValueType{*hookContext.tier0PatternSearchResults().template get<OffsetToConVarValueType>().of(conVar).get()} == cs2::ConVarValueType::boolean;
}

HookContext& hookContext;
const ConVars& conVars;
const ConVarDeps& conVarDeps;
ConVarAccessorState& state;
};
2 changes: 1 addition & 1 deletion Source/Features/Sound/Details/SoundVisualizationFeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class SoundVisualizationFeature {

auto&& transformFactory = hookContext.panoramaTransformFactory();
PanoramaTransformations{
transformFactory.scale(SoundVisualization<SoundType>::getScale(soundInClipSpace.z, ViewToProjectionMatrix{hookContext.gameDependencies().viewToProjectionMatrix}.getFovScale())),
transformFactory.scale(SoundVisualization<SoundType>::getScale(soundInClipSpace.z, ViewToProjectionMatrix{hookContext.clientPatternSearchResults().template get<ViewToProjectionMatrixPointer>()}.getFovScale())),
transformFactory.translate(deviceCoordinates.getX(), deviceCoordinates.getY())
}.applyTo(panel);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class PlayerInfoPanel {

[[nodiscard]] float getFovScale() const noexcept
{
return ViewToProjectionMatrix{hookContext.gameDependencies().viewToProjectionMatrix}.getFovScale();
return ViewToProjectionMatrix{hookContext.clientPatternSearchResults().template get<ViewToProjectionMatrixPointer>()}.getFovScale();
}

template <typename... PanelTypes>
Expand Down
19 changes: 7 additions & 12 deletions Source/GameClasses/BaseEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ class BaseEntity {

[[nodiscard]] decltype(auto) renderComponent() const noexcept
{
return hookContext.template make<RenderComponent>(deps().offsetToRenderComponent.of(entity).valueOr(nullptr));
return hookContext.template make<RenderComponent>(hookContext.clientPatternSearchResults().template get<OffsetToRenderComponent>().of(entity).valueOr(nullptr));
}

[[nodiscard]] decltype(auto) gameSceneNode() const noexcept
{
return hookContext.template make<GameSceneNode>(deps().offsetToGameSceneNode.of(entity).valueOr(nullptr));
return hookContext.template make<GameSceneNode>(hookContext.clientPatternSearchResults().template get<OffsetToGameSceneNode>().of(entity).valueOr(nullptr));
}

template <typename F>
Expand Down Expand Up @@ -70,27 +70,27 @@ class BaseEntity {

[[nodiscard]] auto hasOwner() const noexcept
{
return deps().offsetToOwnerEntity.of(entity).toOptional().notEqual(cs2::CEntityHandle{cs2::INVALID_EHANDLE_INDEX});
return hookContext.clientPatternSearchResults().template get<OffsetToOwnerEntity>().of(entity).toOptional().notEqual(cs2::CEntityHandle{cs2::INVALID_EHANDLE_INDEX});
}

[[nodiscard]] TeamNumber teamNumber() const noexcept
{
return TeamNumber{deps().offsetToTeamNumber.of(entity).valueOr({})};
return TeamNumber{hookContext.clientPatternSearchResults().template get<OffsetToTeamNumber>().of(entity).valueOr({})};
}

[[nodiscard]] auto vData() const noexcept
{
return deps().offsetToVData.of(entity).toOptional();
return hookContext.clientPatternSearchResults().template get<OffsetToVData>().of(entity).toOptional();
}

[[nodiscard]] auto health() const noexcept
{
return deps().offsetToHealth.of(entity).toOptional();
return hookContext.clientPatternSearchResults().template get<OffsetToHealth>().of(entity).toOptional();
}

[[nodiscard]] std::optional<bool> isAlive() const noexcept
{
const auto lifestate = deps().offsetToLifeState.of(entity).get();
const auto lifestate = hookContext.clientPatternSearchResults().template get<OffsetToLifeState>().of(entity).get();
if (lifestate)
return LifeState{*lifestate} == LifeState::Alive;
return {};
Expand All @@ -102,11 +102,6 @@ class BaseEntity {
}

private:
[[nodiscard]] const auto& deps() const noexcept
{
return hookContext.gameDependencies().entityDeps;
}

[[nodiscard]] auto invokeWithGameSceneNodeOwner(auto& f) const noexcept
{
return [&f](auto&& gameSceneNode) { f(gameSceneNode.owner()); };
Expand Down
4 changes: 2 additions & 2 deletions Source/GameClasses/BaseWeapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ class BaseWeapon {
[[nodiscard]] auto getName() const noexcept
{
const auto vData = static_cast<cs2::CCSWeaponBaseVData*>(hookContext.template make<BaseEntity>(baseWeapon).vData().valueOr(nullptr));
return hookContext.gameDependencies().weaponVDataDeps.offsetToWeaponName.of(vData).valueOr(nullptr);
return hookContext.clientPatternSearchResults().template get<OffsetToWeaponName>().of(vData).valueOr(nullptr);
}

[[nodiscard]] auto clipAmmo() const noexcept
{
return hookContext.gameDependencies().weaponDeps.offsetToClipAmmo.of(baseWeapon).toOptional();
return hookContext.clientPatternSearchResults().template get<OffsetToClipAmmo>().of(baseWeapon).toOptional();
}

private:
Expand Down
8 changes: 4 additions & 4 deletions Source/GameClasses/EntitySystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ class EntitySystem {
private:
[[nodiscard]] cs2::CGameEntitySystem* entitySystem() const noexcept
{
if (hookContext.gameDependencies().entitySystemDeps.entitySystem)
return *hookContext.gameDependencies().entitySystemDeps.entitySystem;
if (hookContext.clientPatternSearchResults().template get<EntitySystemPointer>())
return *hookContext.clientPatternSearchResults().template get<EntitySystemPointer>();
return nullptr;
}

[[nodiscard]] auto getEntityList() const noexcept
{
return hookContext.gameDependencies().entitySystemDeps.entityListOffset.of(entitySystem()).get();
return hookContext.clientPatternSearchResults().template get<EntityListOffset>().of(entitySystem()).get();
}

[[nodiscard]] auto getHighestEntityIndex() const noexcept
{
const auto highestEntityIndex = hookContext.gameDependencies().entitySystemDeps.highestEntityIndexOffset.of(entitySystem()).get();
const auto highestEntityIndex = hookContext.clientPatternSearchResults().template get<HighestEntityIndexOffset>().of(entitySystem()).get();
if (highestEntityIndex && highestEntityIndex->isValid())
return *highestEntityIndex;
return cs2::kMaxValidEntityIndex;
Expand Down
10 changes: 2 additions & 8 deletions Source/GameClasses/FileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <CS2/Classes/FileSystem.h>
#include "FileNameSymbolTable.h"
#include <GameDependencies/FileSystemDeps.h>

template <typename HookContext>
class FileSystem {
Expand All @@ -14,21 +13,16 @@ class FileSystem {

[[nodiscard]] decltype(auto) fileNames() const noexcept
{
return hookContext.template make<FileNameSymbolTable>(deps().fileNamesOffset.of(fileSystem()).get());
return hookContext.template make<FileNameSymbolTable>(hookContext.fileSystemPatternSearchResults().template get<FileNamesOffset>().of(fileSystem()).get());
}

private:
[[nodiscard]] cs2::CBaseFileSystem* fileSystem() const noexcept
{
if (const auto fileSystemPointer = hookContext.gameDependencies().fileSystem)
if (const auto fileSystemPointer = hookContext.soundSystemPatternSearchResults().template get<FileSystemPointer>())
return *fileSystemPointer;
return nullptr;
}

[[nodiscard]] const auto& deps() const noexcept
{
return hookContext.gameDependencies().fileSystemDeps;
}

HookContext& hookContext;
};
11 changes: 2 additions & 9 deletions Source/GameClasses/GameRules.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

#include <optional>

#include <GameDependencies/GameRulesDeps.h>

template <typename HookContext>
class GameRules {
public:
Expand All @@ -15,12 +13,12 @@ class GameRules {

[[nodiscard]] auto roundStartTime() const noexcept
{
return deps().roundStartTimeOffset.of(gameRules).toOptional();
return hookContext.clientPatternSearchResults().template get<RoundStartTimeOffset>().of(gameRules).toOptional();
}

[[nodiscard]] auto roundRestartTime() const noexcept
{
return deps().offsetToRoundRestartTime.of(gameRules).toOptional();
return hookContext.clientPatternSearchResults().template get<OffsetToRoundRestartTime>().of(gameRules).toOptional();
}

[[nodiscard]] bool hasScheduledRoundRestart() const noexcept
Expand All @@ -34,11 +32,6 @@ class GameRules {
}

private:
[[nodiscard]] const auto& deps() const noexcept
{
return hookContext.gameDependencies().gameRulesDeps;
}

HookContext& hookContext;
cs2::C_CSGameRules* gameRules;
};
13 changes: 4 additions & 9 deletions Source/GameClasses/GameSceneNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ class GameSceneNode {

[[nodiscard]] auto absOrigin() const noexcept
{
return deps().offsetToAbsOrigin.of(gameSceneNode).toOptional();
return hookContext->clientPatternSearchResults().template get<OffsetToAbsOrigin>().of(gameSceneNode).toOptional();
}

[[nodiscard]] decltype(auto) owner() const noexcept
{
return hookContext->template make<BaseEntity>(static_cast<cs2::C_BaseEntity*>(deps().offsetToOwner.of(gameSceneNode).valueOr(nullptr)));
return hookContext->template make<BaseEntity>(static_cast<cs2::C_BaseEntity*>(hookContext->clientPatternSearchResults().template get<OffsetToGameSceneNodeOwner>().of(gameSceneNode).valueOr(nullptr)));
}

template <typename F>
Expand All @@ -39,17 +39,12 @@ class GameSceneNode {
private:
[[nodiscard]] decltype(auto) child() const noexcept
{
return hookContext->template make<GameSceneNode<HookContext>>(deps().offsetToChild.of(gameSceneNode).valueOr(nullptr));
return hookContext->template make<GameSceneNode<HookContext>>(hookContext->clientPatternSearchResults().template get<OffsetToChildGameSceneNode>().of(gameSceneNode).valueOr(nullptr));
}

[[nodiscard]] decltype(auto) nextSibling() const noexcept
{
return hookContext->template make<GameSceneNode<HookContext>>(deps().offsetToNextSibling.of(gameSceneNode).valueOr(nullptr));
}

[[nodiscard]] const auto& deps() const noexcept
{
return hookContext->gameDependencies().gameSceneNodeDeps;
return hookContext->template make<GameSceneNode<HookContext>>(hookContext->clientPatternSearchResults().template get<OffsetToNextSiblingGameSceneNode>().of(gameSceneNode).valueOr(nullptr));
}

HookContext* hookContext;
Expand Down
7 changes: 1 addition & 6 deletions Source/GameClasses/HostageServices.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,10 @@ class HostageServices {

[[nodiscard]] bool hasCarriedHostage() const noexcept
{
return hookContext.template make<EntitySystem>().getEntityFromHandle(deps().offsetToCarriedHostage.of(hostageServices).valueOr(cs2::CEntityHandle{cs2::INVALID_EHANDLE_INDEX})) != nullptr;
return hookContext.template make<EntitySystem>().getEntityFromHandle(hookContext.clientPatternSearchResults().template get<OffsetToCarriedHostage>().of(hostageServices).valueOr(cs2::CEntityHandle{cs2::INVALID_EHANDLE_INDEX})) != nullptr;
}

private:
[[nodiscard]] const auto& deps() const noexcept
{
return hookContext.gameDependencies().hostageServicesDeps;
}

HookContext& hookContext;
cs2::CCSPlayer_HostageServices* hostageServices;
};
2 changes: 1 addition & 1 deletion Source/GameClasses/Hud/HudContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct HudContext {

[[nodiscard]] auto panel() noexcept
{
auto&& hud = hookContext.gameDependencies().hudDeps.hud;
auto&& hud = hookContext.clientPatternSearchResults().template get<HudPanelPointer>();
if (hud && *hud)
return hookContext.template make<PanoramaUiPanel>((*hud)->uiPanel);
return hookContext.template make<PanoramaUiPanel>(nullptr);
Expand Down
3 changes: 2 additions & 1 deletion Source/GameClasses/MemAlloc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <CS2/Classes/IMemAlloc.h>
#include <MemoryPatterns/PatternTypes/MemAllocPatternTypes.h>
#include <Platform/Macros/FunctionAttributes.h>

template <typename HookContext>
Expand All @@ -16,7 +17,7 @@ class MemAlloc {
if (!deps().thisptr || !*deps().thisptr)
return nullptr;

if (const auto fn = deps().alloc.of((*deps().thisptr)->vmt).get())
if (const auto fn = hookContext.clientPatternSearchResults().template get<OffsetAllocVirtualMethod>().of((*deps().thisptr)->vmt).get())
return (*fn)(*deps().thisptr, size);

return nullptr;
Expand Down
17 changes: 0 additions & 17 deletions Source/GameClasses/OffsetTypes/EntityOffset.h

This file was deleted.

Loading

0 comments on commit 1eacf0d

Please sign in to comment.