Skip to content

Commit 720d0ac

Browse files
feat(vmtpp): add VMT library
1 parent 6795542 commit 720d0ac

File tree

12 files changed

+1040
-3
lines changed

12 files changed

+1040
-3
lines changed

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ option(SOURCEPP_USE_MDLPP "Build mdlpp library" ${SOURC
2424
option(SOURCEPP_USE_STEAMPP "Build steampp library" ${SOURCEPP_LIBS_START_ENABLED})
2525
option(SOURCEPP_USE_TOOLPP "Build toolpp library" ${SOURCEPP_LIBS_START_ENABLED})
2626
option(SOURCEPP_USE_VCRYPTPP "Build vcryptpp library" ${SOURCEPP_LIBS_START_ENABLED})
27+
option(SOURCEPP_USE_VMTPP "Build vmtpp library" ${SOURCEPP_LIBS_START_ENABLED})
2728
option(SOURCEPP_USE_VPKPP "Build vpkpp library" ${SOURCEPP_LIBS_START_ENABLED})
2829
option(SOURCEPP_USE_VTFPP "Build vtfpp library" ${SOURCEPP_LIBS_START_ENABLED})
2930

@@ -54,6 +55,9 @@ endif()
5455
if(SOURCEPP_USE_TOOLPP)
5556
set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "" FORCE)
5657
endif()
58+
if(SOURCEPP_USE_VMTPP)
59+
set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "" FORCE)
60+
endif()
5761
if(SOURCEPP_USE_VPKPP)
5862
set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "" FORCE)
5963
endif()
@@ -194,6 +198,7 @@ add_sourcepp_library(mdlpp ) # sourcepp::mdlpp
194198
add_sourcepp_library(steampp C PYTHON ) # sourcepp::steampp
195199
add_sourcepp_library(toolpp PYTHON ) # sourcepp::toolpp
196200
add_sourcepp_library(vcryptpp C CSHARP PYTHON ) # sourcepp::vcryptpp
201+
add_sourcepp_library(vmtpp ) # sourcepp::vmtpp
197202
add_sourcepp_library(vpkpp C CSHARP NO_TEST ) # sourcepp::vpkpp
198203
add_sourcepp_library(vtfpp PYTHON BENCH) # sourcepp::vtfpp
199204

@@ -257,7 +262,7 @@ endif()
257262

258263
# Print options
259264
print_options(OPTIONS
260-
USE_BSPPP USE_DMXPP USE_GAMEPP USE_KVPP USE_MDLPP USE_STEAMPP USE_TOOLPP USE_VCRYPTPP USE_VPKPP USE_VTFPP
265+
USE_BSPPP USE_DMXPP USE_GAMEPP USE_KVPP USE_MDLPP USE_STEAMPP USE_TOOLPP USE_VCRYPTPP USE_VMTPP USE_VPKPP USE_VTFPP
261266
BUILD_BENCHMARKS BUILD_C_WRAPPERS BUILD_CSHARP_WRAPPERS BUILD_PYTHON_WRAPPERS BUILD_WITH_OPENCL BUILD_WITH_TBB BUILD_WITH_THREADS BUILD_TESTS BUILD_WIN7_COMPAT
262267
LINK_STATIC_MSVC_RUNTIME
263268
VPKPP_SUPPORT_VPK_V54)

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
128128
<td align="center">❌</td>
129129
</tr>
130130
<tr><!-- empty row to disable github striped bg color --></tr>
131+
<tr>
132+
<td rowspan="1"><code>vmtpp</code></td>
133+
<td><a href="https://developer.valvesoftware.com/wiki/VMT">VMT</a></td>
134+
<td align="center">✅</td>
135+
<td align="center">❌</td>
136+
<td rowspan="1" align="center"></td>
137+
</tr>
138+
<tr><!-- empty row to disable github striped bg color --></tr>
131139
<tr>
132140
<td rowspan="29"><code>vpkpp</code></td>
133141
<td>007 v1.1, v1.3 (007 - Nightfire)</td>
@@ -321,7 +329,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
321329
Libraries not starred should be considered stable, and their existing interfaces will not change much if at all. Note that wrappers
322330
only exist for stable libraries.
323331

324-
(&dagger;) Many text-based formats in Source are close to (if not identical to) KeyValues v1, such as [VMT](https://developer.valvesoftware.com/wiki/VMT) and [VMF](https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)).
332+
(&dagger;) Many text-based formats in Source are close to (if not identical to) KeyValues v1, such as [RES](https://developer.valvesoftware.com/wiki/Resource_list_(Source)), [VDF](https://developer.valvesoftware.com/wiki/VDF), and [VMF](https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)).
325333

326334
## Wrappers
327335

docs/index.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
114114
<td align="center">✅</td>
115115
<td align="center">❌</td>
116116
</tr>
117+
<tr>
118+
<td rowspan="1"><code>vmtpp</code></td>
119+
<td><a href="https://developer.valvesoftware.com/wiki/VMT">VMT</a></td>
120+
<td align="center">✅</td>
121+
<td align="center">❌</td>
122+
<td rowspan="1" align="center"></td>
123+
</tr>
117124
<tr>
118125
<td rowspan="15"><code>vpkpp</code></td>
119126
<td>007 v1.1, v1.3 (007 - Nightfire)</td>
@@ -280,7 +287,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
280287
Libraries not starred should be considered stable, and their existing interfaces will not change much if at all. Note that wrappers
281288
only exist for stable libraries.
282289

283-
(&dagger;) Many text-based formats in Source are close to (if not identical to) KeyValues v1, such as [VMT](https://developer.valvesoftware.com/wiki/VMT) and [VMF](https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)).
290+
(&dagger;) Many text-based formats in Source are close to (if not identical to) KeyValues v1, such as [RES](https://developer.valvesoftware.com/wiki/Resource_list_(Source)), [VDF](https://developer.valvesoftware.com/wiki/VDF), and [VMF](https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)).
284291

285292
## Wrappers
286293

include/vmtpp/EntityAccess.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#pragma once
2+
3+
#include <sourcepp/Math.h>
4+
5+
namespace vmtpp {
6+
7+
/// Expose an interface to read values from the entity the VMT is attached to for material proxies.
8+
class IEntityAccess {
9+
public:
10+
virtual ~IEntityAccess() = default;
11+
12+
/// "The number of seconds the current map has been running on the server for."
13+
[[nodiscard]] virtual uint64_t getCurrentTime() const = 0;
14+
15+
[[nodiscard]] virtual float getRenderAlpha() const = 0;
16+
17+
[[nodiscard]] virtual float getAnimationProgress() const = 0;
18+
19+
/// "The distance in units between the current player and the origin of the entity that the material is applied to."
20+
[[nodiscard]] virtual float getDistanceToCurrentPlayer() const = 0;
21+
22+
[[nodiscard]] virtual int getCurrentPlayerTeam() const = 0;
23+
24+
[[nodiscard]] virtual int getTeam() const = 0;
25+
26+
/// "The dot product of the current player's view angle and the relative origin of the material's entity."
27+
[[nodiscard]] virtual float getCurrentPlayerViewDotProduct() const = 0;
28+
29+
[[nodiscard]] virtual float getCurrentPlayerSpeed() const = 0;
30+
31+
[[nodiscard]] virtual sourcepp::math::Vec3f getCurrentPlayerPosition() const = 0;
32+
33+
[[nodiscard]] virtual float getSpeed() const = 0;
34+
35+
[[nodiscard]] virtual sourcepp::math::Vec3f getOrigin() const = 0;
36+
37+
/// "A static random number associated with the entity the material is applied to."
38+
[[nodiscard]] virtual float getRandomNumber() const = 0;
39+
40+
[[nodiscard]] virtual float getHealth() const = 0;
41+
42+
[[nodiscard]] virtual bool isNPC() const = 0;
43+
44+
[[nodiscard]] virtual bool isViewModel() const = 0;
45+
46+
[[nodiscard]] virtual sourcepp::math::Vec3f getWorldDimensionsMinimum() const = 0;
47+
48+
[[nodiscard]] virtual sourcepp::math::Vec3f getWorldDimensionsMaximum() const = 0;
49+
50+
[[nodiscard]] virtual sourcepp::math::Vec3f getCurrentPlayerCrosshairColor() const = 0;
51+
};
52+
53+
class EntityAccessEmpty : public IEntityAccess {
54+
public:
55+
EntityAccessEmpty();
56+
57+
[[nodiscard]] uint64_t getCurrentTime() const override;
58+
59+
[[nodiscard]] float getRenderAlpha() const override;
60+
61+
[[nodiscard]] float getAnimationProgress() const override;
62+
63+
[[nodiscard]] float getDistanceToCurrentPlayer() const override;
64+
65+
[[nodiscard]] int getCurrentPlayerTeam() const override;
66+
67+
[[nodiscard]] int getTeam() const override;
68+
69+
[[nodiscard]] float getCurrentPlayerViewDotProduct() const override;
70+
71+
[[nodiscard]] float getCurrentPlayerSpeed() const override;
72+
73+
[[nodiscard]] sourcepp::math::Vec3f getCurrentPlayerPosition() const override;
74+
75+
[[nodiscard]] float getSpeed() const override;
76+
77+
[[nodiscard]] sourcepp::math::Vec3f getOrigin() const override;
78+
79+
[[nodiscard]] float getRandomNumber() const override;
80+
81+
[[nodiscard]] float getHealth() const override;
82+
83+
[[nodiscard]] bool isNPC() const override;
84+
85+
[[nodiscard]] bool isViewModel() const override;
86+
87+
[[nodiscard]] sourcepp::math::Vec3f getWorldDimensionsMinimum() const override;
88+
89+
[[nodiscard]] sourcepp::math::Vec3f getWorldDimensionsMaximum() const override;
90+
91+
[[nodiscard]] sourcepp::math::Vec3f getCurrentPlayerCrosshairColor() const override;
92+
93+
private:
94+
float random;
95+
};
96+
97+
} // namespace vmtpp

include/vmtpp/Proxy.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <unordered_map>
5+
6+
namespace vmtpp {
7+
8+
class IEntityAccess;
9+
10+
namespace Proxy {
11+
12+
// We're going to try to implement proxies in a way that's distinct from but still roughly
13+
// comparable to the SDK, so it's easy to compare functionality and get a nice reference!
14+
15+
struct Data {
16+
std::string name;
17+
std::unordered_map<std::string, std::string> variables;
18+
};
19+
20+
using Function = void(*)(Data&, std::unordered_map<std::string, std::string>&, const IEntityAccess&);
21+
22+
Function add(const std::string& name, Function proxy);
23+
24+
Function get(const std::string& name);
25+
26+
void exec(Data& data, std::unordered_map<std::string, std::string>& vmtVariables, const IEntityAccess& entity);
27+
28+
void remove(const std::string& name);
29+
30+
} // namespace Proxy
31+
32+
} // namespace vmtpp
33+
34+
#define VMTPP_MATERIAL_PROXY(name, proxy) \
35+
vmtpp::Proxy::Function VMTPP_MATERIAL_PROXY_##name = vmtpp::Proxy::add(#name, proxy)

include/vmtpp/VMT.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#include <initializer_list>
4+
#include <string>
5+
#include <string_view>
6+
#include <unordered_map>
7+
#include <vector>
8+
9+
#include "EntityAccess.h"
10+
#include "Proxy.h"
11+
12+
namespace vmtpp {
13+
14+
namespace Value {
15+
16+
enum class Type {
17+
INT,
18+
FLOAT,
19+
VEC3,
20+
COLOR,
21+
};
22+
23+
[[nodiscard]] Type getProbableType(std::string_view value);
24+
25+
[[nodiscard]] Type getProbableTypeBasedOnAssociatedValues(std::string_view value, std::initializer_list<std::string_view> others);
26+
27+
[[nodiscard]] int toInt(std::string_view value);
28+
29+
[[nodiscard]] std::string fromInt(int value);
30+
31+
[[nodiscard]] float toFloat(std::string_view value);
32+
33+
[[nodiscard]] std::string fromFloat(float value);
34+
35+
[[nodiscard]] sourcepp::math::Vec3f toVec3(std::string_view value);
36+
37+
[[nodiscard]] std::string fromVec3(sourcepp::math::Vec3f value);
38+
39+
[[nodiscard]] sourcepp::math::Vec4f toColor(std::string_view value);
40+
41+
[[nodiscard]] std::string fromColor(sourcepp::math::Vec4f value);
42+
43+
} // namespace Value
44+
45+
class VMT {
46+
public:
47+
explicit VMT(std::string_view vmt, const IEntityAccess& entityAccess_ = EntityAccessEmpty{}, int dxLevel = 98, int shaderDetailLevel = 3, std::string_view shaderFallbackSuffix = "DX9");
48+
49+
[[nodiscard]] std::string_view getShader() const;
50+
51+
[[nodiscard]] bool hasCompileFlag(std::string_view flag) const;
52+
53+
[[nodiscard]] const std::vector<std::string>& getCompileFlags() const;
54+
55+
[[nodiscard]] bool hasVariable(std::string_view key) const;
56+
57+
[[nodiscard]] std::string_view getVariable(std::string_view key) const;
58+
59+
[[nodiscard]] std::string_view operator[](std::string_view key) const;
60+
61+
void update();
62+
63+
private:
64+
const IEntityAccess& entityAccess;
65+
std::string shader;
66+
std::vector<std::string> compileFlags;
67+
std::unordered_map<std::string, std::string> variables;
68+
std::vector<Proxy::Data> proxies;
69+
};
70+
71+
} // namespace vmtpp

include/vmtpp/vmtpp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
/*
4+
* This header is just included so consumers of this library can
5+
* include it the same way as any of the other SourcePP libraries.
6+
*/
7+
8+
#include "EntityAccess.h"
9+
#include "Proxy.h"
10+
#include "VMT.h"

src/vmtpp/EntityAccess.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include <vmtpp/EntityAccess.h>
2+
3+
#include <chrono>
4+
5+
using namespace sourcepp;
6+
using namespace vmtpp;
7+
8+
EntityAccessEmpty::EntityAccessEmpty() {
9+
// MLP:FIM S09E20 04:58
10+
static float randomNumberGeneratorWinkWink = 0.f;
11+
this->random = randomNumberGeneratorWinkWink++;
12+
}
13+
14+
uint64_t EntityAccessEmpty::getCurrentTime() const {
15+
return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
16+
}
17+
18+
float EntityAccessEmpty::getRenderAlpha() const {
19+
return 1.f;
20+
}
21+
22+
float EntityAccessEmpty::getAnimationProgress() const {
23+
return 0.f;
24+
}
25+
26+
float EntityAccessEmpty::getDistanceToCurrentPlayer() const {
27+
return 0.f;
28+
}
29+
30+
int EntityAccessEmpty::getCurrentPlayerTeam() const {
31+
return 0;
32+
}
33+
34+
int EntityAccessEmpty::getTeam() const {
35+
return 0;
36+
}
37+
38+
float EntityAccessEmpty::getCurrentPlayerViewDotProduct() const {
39+
return 0.f;
40+
}
41+
42+
float EntityAccessEmpty::getCurrentPlayerSpeed() const {
43+
return 0.f;
44+
}
45+
46+
math::Vec3f EntityAccessEmpty::getCurrentPlayerPosition() const {
47+
return {};
48+
}
49+
50+
float EntityAccessEmpty::getSpeed() const {
51+
return 0.f;
52+
}
53+
54+
math::Vec3f EntityAccessEmpty::getOrigin() const {
55+
return {};
56+
}
57+
58+
float EntityAccessEmpty::getRandomNumber() const {
59+
return this->random;
60+
}
61+
62+
float EntityAccessEmpty::getHealth() const {
63+
return 0.f;
64+
}
65+
66+
bool EntityAccessEmpty::isNPC() const {
67+
return false;
68+
}
69+
70+
bool EntityAccessEmpty::isViewModel() const {
71+
return false;
72+
}
73+
74+
math::Vec3f EntityAccessEmpty::getWorldDimensionsMinimum() const {
75+
return {};
76+
}
77+
78+
math::Vec3f EntityAccessEmpty::getWorldDimensionsMaximum() const {
79+
return {};
80+
}
81+
82+
math::Vec3f EntityAccessEmpty::getCurrentPlayerCrosshairColor() const {
83+
return {1.f, 1.f, 1.f};
84+
}

0 commit comments

Comments
 (0)