1+ #pragma once
2+
3+ #include " CoreMinimal.h"
4+ #include " VarObDelegates.h"
5+ #include " VarObTraits.h"
6+
7+ #define VO_VAL 0
8+ #define VO_KEY 1
9+ #define VO_CHK 2
10+
11+ template <int N>
12+ struct ChunkN
13+ {
14+ uint32 Data[N];
15+
16+ ChunkN<N> operator ^(const ChunkN<N>& Rhs)
17+ {
18+ ChunkN<N> tmp;
19+ for (int i = 0 ; i < N; i++)
20+ {
21+ tmp.Data [i] = Data[i] ^ Rhs.Data [i];
22+ }
23+ return tmp;
24+ }
25+
26+ ChunkN<N> operator ^(const int32& Rhs)
27+ {
28+ ChunkN<N> tmp;
29+ for (int i = 0 ; i < N; i++)
30+ {
31+ tmp.Data [i] = Data[i] ^ Rhs;
32+ }
33+ return tmp;
34+ }
35+
36+ ChunkN<N>& operator ^=(const ChunkN<N>& Rhs)
37+ {
38+ for (int i = 0 ; i < N; i++)
39+ {
40+ Data[i] ^= Rhs.Data [i];
41+ }
42+ return *this ;
43+ }
44+
45+ bool operator ==(const ChunkN<N>& Rhs)
46+ {
47+ for (int i = 0 ; i < N; i++)
48+ {
49+ if (Data[i] != Rhs.Data [i])
50+ {
51+ return false ;
52+ }
53+ }
54+ return true ;
55+ }
56+
57+ void GenRand ()
58+ {
59+ for (int i = 0 ; i < N; i++)
60+ {
61+ Data[i] = static_cast <uint32>(FMath::RandHelper (0x7fff ));
62+ }
63+ }
64+ };
65+
66+ template <typename T>
67+ class TVarOb
68+ {
69+ private:
70+
71+ using ChunkX = ChunkN<(sizeof (T)-1 )/4 +1 >;
72+ ChunkX Data[3 ] = {};
73+
74+ inline void MemMangle ()
75+ {
76+ uint8* DataPtr = reinterpret_cast <uint8*>(Data);
77+ for (uint8 I = 0 ; I < sizeof (ChunkX) * 3 ; I += 3 )
78+ {
79+ uint8 Tmp = DataPtr[I];
80+ DataPtr[I] = DataPtr[I + 2 ];
81+ DataPtr[I + 2 ] = Tmp;
82+ }
83+ }
84+
85+ inline void Check (bool bCondition)
86+ {
87+ if (bCondition == false )
88+ {
89+ FVarObDelegates::OnVariableCheatDetected.Broadcast ();
90+ }
91+ }
92+
93+ public:
94+
95+
96+ TVarOb (T v = 0 )
97+ {
98+ static_assert (TVarObSupportedType<T>::Value, " Unsupported Type" );
99+
100+ Data[VO_KEY].GenRand ();
101+ Data[VO_VAL] = *(ChunkX*)&v;
102+ Data[VO_CHK] = (Data[VO_VAL] ^ VO_MASK);
103+
104+ Data[VO_VAL] ^= Data[VO_KEY];
105+ MemMangle ();
106+ }
107+
108+ TVarOb (TVarOb& v)
109+ {
110+ FMemory::Memcpy (Data, v.Data , sizeof (ChunkX) * 3 );
111+ }
112+
113+ TVarOb& operator =(T& v)
114+ {
115+ static_assert (TVarObSupportedType<T>::Value, " Unsupported Type" );
116+
117+ Data[VO_KEY].GenRand ();
118+ Data[VO_VAL] = *(ChunkX*)&v;
119+ Data[VO_CHK] = (Data[VO_VAL] ^ VO_MASK);
120+
121+ Data[VO_VAL] ^= Data[VO_KEY];
122+ MemMangle ();
123+
124+ return *this ;
125+ }
126+
127+ operator T ()
128+ {
129+ MemMangle ();
130+ ChunkX Tmp = Data[VO_VAL] ^ Data[VO_KEY];
131+ Check (Tmp == (Data[VO_CHK] ^ VO_MASK));
132+ MemMangle ();
133+ return *(T*)&Tmp;
134+ }
135+
136+ #define VO_BINARY_OP (_op ) TVarOb& operator _op (const T& Rhs) \
137+ { \
138+ MemMangle (); \
139+ ChunkX Tmp = Data[VO_VAL] ^ Data[VO_KEY]; \
140+ Check (Tmp == (Data[VO_CHK] ^ VO_MASK)); \
141+ T Res = *(T*)&Tmp; \
142+ Res _op Rhs; \
143+ Data[VO_KEY].GenRand (); \
144+ Data[VO_VAL] = *(ChunkX*)&Res; \
145+ Data[VO_CHK] = (Data[VO_VAL] ^ VO_MASK); \
146+ Data[VO_VAL] ^= Data[VO_KEY]; \
147+ MemMangle (); \
148+ return *this ; \
149+ } \
150+
151+ #define VO_UNARY_OP (_op ) TVarOb& operator _op () \
152+ { \
153+ MemMangle (); \
154+ ChunkX Tmp = Data[VO_VAL] ^ Data[VO_KEY]; \
155+ Check (Tmp == (Data[VO_CHK] ^ VO_MASK)); \
156+ T v = *(T*)&Tmp; \
157+ v _op; \
158+ Data[VO_KEY].GenRand (); \
159+ Data[VO_VAL] = *(ChunkX*)&v; \
160+ Data[VO_CHK] = (Data[VO_VAL] ^ VO_MASK); \
161+ Data[VO_VAL] ^= Data[VO_KEY]; \
162+ MemMangle (); \
163+ return *this ; \
164+ } \
165+ TVarOb operator _op (int ) \
166+ { \
167+ TVarOb Tmp (*this ); \
168+ operator _op (); \
169+ return Tmp; \
170+ } \
171+
172+ VO_BINARY_OP (*=)
173+ VO_BINARY_OP (/=)
174+ VO_BINARY_OP (%=)
175+ VO_BINARY_OP (-=)
176+ VO_BINARY_OP (+=)
177+ VO_BINARY_OP (^=)
178+ VO_BINARY_OP (<<)
179+ VO_BINARY_OP (>>)
180+
181+ VO_UNARY_OP (++)
182+ VO_UNARY_OP (--)
183+ };
0 commit comments