From 1d566f23329b756aa3ef57be7b53525d949af14a Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Thu, 9 Nov 2023 20:09:45 +0000 Subject: [PATCH] More stuff (#8) * Merge * feat(netsync): add CPedAttachData * feat(netsync): add CPlayerHealthData --------- --- classes.cpp | 3 + network/sync/ped/CPedAttachData.hpp | 13 ++ network/sync/player/CPlayerHealthData.hpp | 21 +++ rage/datBitBuffer.hpp | 192 ++++++++++++++++++++++ rdr2.rcnet | Bin 16597 -> 16932 bytes 5 files changed, 229 insertions(+) create mode 100644 network/sync/ped/CPedAttachData.hpp create mode 100644 network/sync/player/CPlayerHealthData.hpp create mode 100644 rage/datBitBuffer.hpp diff --git a/classes.cpp b/classes.cpp index 798f004..c42bf7d 100644 --- a/classes.cpp +++ b/classes.cpp @@ -4,11 +4,13 @@ #include "base/fwRefAwareBaseImpl.hpp" #include "entity/fwEntity.hpp" #include "network/sync/object/CObjectCreationData.hpp" +#include "network/sync/ped/CPedAttachData.hpp" #include "network/sync/ped/CPedCreationData.hpp" #include "network/sync/ped/CPedTaskTreeData.hpp" #include "network/sync/physical/CPhysicalAttachData.hpp" #include "network/sync/pickup/CPickupCreationData.hpp" #include "network/sync/player/CPlayerAppearanceData.hpp" +#include "network/sync/player/CPlayerHealthData.hpp" #include "network/sync/vehicle/CVehicleCreationData.hpp" #include "network/sync/vehicle/CVehicleProximityMigrationData.hpp" #include "network/sync/CProjectBaseSyncDataNode.hpp" @@ -31,6 +33,7 @@ #include "ped/CPed.hpp" #include "rage/atArray.hpp" #include "rage/atPlayerBits.hpp" +#include "rage/datBitBuffer.hpp" #include "rage/joaat.hpp" #include "rage/rlJson.hpp" #include "rage/rlMetric.hpp" diff --git a/network/sync/ped/CPedAttachData.hpp b/network/sync/ped/CPedAttachData.hpp new file mode 100644 index 0000000..202c84a --- /dev/null +++ b/network/sync/ped/CPedAttachData.hpp @@ -0,0 +1,13 @@ +#pragma once +#include + +class CPedAttachData +{ +public: + char pad_0000[32]; //0x0000 + uint16_t m_AttachObjectId; //0x0020 + char pad_0022[15]; //0x0022 + bool m_IsAttached; //0x0031 + char pad_0032[14]; //0x0032 +}; //Size: 0x0040 +static_assert(sizeof(CPedAttachData) == 0x40); \ No newline at end of file diff --git a/network/sync/player/CPlayerHealthData.hpp b/network/sync/player/CPlayerHealthData.hpp new file mode 100644 index 0000000..9bcf163 --- /dev/null +++ b/network/sync/player/CPlayerHealthData.hpp @@ -0,0 +1,21 @@ +#pragma once +#include + +#pragma pack(push, 8) +class CPlayerHealthData +{ +public: + uint32_t m_Unused; //0x0000 + bool m_BulletProof; //0x0004 + bool m_FlameProof; //0x0005 + bool m_ExplosionProof; //0x0006 + bool m_CollisionProof; //0x0007 + bool m_MeleeProof; //0x0008 + bool m_SmokeProof; //0x0009 + bool m_SteamProof; //0x000A + bool m_Godmode; //0x000B +private: + char m_Pad[4]; +}; //Size: 0x0010 +static_assert(sizeof(CPlayerHealthData) == 0x10); +#pragma pack(pop) \ No newline at end of file diff --git a/rage/datBitBuffer.hpp b/rage/datBitBuffer.hpp new file mode 100644 index 0000000..95317da --- /dev/null +++ b/rage/datBitBuffer.hpp @@ -0,0 +1,192 @@ +#pragma once +#include + +namespace rage +{ + class datBitBuffer + { + public: + datBitBuffer(void* data, uint32_t size, bool read = false) + { + m_Data = data; + m_BitOffset = 0; + m_MaxBit = size * 8; + m_BitsRead = 0; + m_CurBit = 0; + m_HighestBitsRead = 0; + m_ErrorCallback = nullptr; + m_FlagBits = read ? 1 : 0; + } + + static void ReadBitsSingle(uint8_t* data, int* out, int size, int offset) + { + int v5; // r11d + int v6; // ebx + uint8_t* v7; // r14 + char v8; // cl + int v9; // r11d + unsigned int v10; // r8d + int v11; // esi + __int64 v12; // r9 + + v5 = offset; + v6 = 1; + v7 = &data[offset >> 3]; + v8 = offset & 7; + if (size > 0) + v5 = size + offset - 1; + v9 = (v5 >> 3) - (offset >> 3); + v10 = (unsigned __int8)(*v7 << v8); + v11 = 8; + if (size > 8) + { + v12 = 1i64; + do + { + if (v12 > v9) + break; + ++v6; + v10 = (v10 << 8) | (v7[v12++] << v8); + v11 += 8; + } while (v11 < size); + } + if (v6 <= v9) + v10 |= v7[v6] >> (8 - v8); + *out = v10 >> (((size + 7) & 0xF8) - size); + } + + static void WriteBitsSingle(uint8_t* data, int value, int size, int offset) + { + uint8_t* v4; // r10 + int v5; // r9d + unsigned int v6; // r11d + uint8_t* v7; // r10 + unsigned int v8; // r11d + int v9; // ebx + __int64 v10; // rdx + char v11; // cl + + v4 = &data[(__int64)offset >> 3]; + v5 = offset & 7; + v6 = value << (32 - size); + *v4 = ((v6 >> 24) >> v5) | *v4 & ~((unsigned int)(-1 << (32 - size)) >> 24 >> v5); + v7 = v4 + 1; + v8 = v6 << (8 - v5); + v9 = -1 << (32 - size) << (8 - v5); + if (8 - v5 < size) + { + v10 = ((unsigned int)(size - (8 - v5) - 1) >> 3) + 1; + do + { + v11 = (v8 >> 24) | *v7 & ~(v9 >> 24); + v8 <<= 8; + *v7++ = v11; + v9 <<= 8; + --v10; + } while (v10); + } + } + + inline bool IsReadBuffer() + { + return m_FlagBits & 1; + } + + inline bool IsSizeCalculator() + { + return m_FlagBits & 2; + } + + void Seek(int bits, bool read) + { + m_BitsRead += bits; + + if (read) + { + if (m_HighestBitsRead > m_CurBit) + m_CurBit = m_HighestBitsRead; + } + else + { + if (m_BitsRead > m_CurBit) + m_CurBit = m_BitsRead; + } + } + + inline bool ReadDword(int* out, int size) + { + if (IsSizeCalculator()) + return false; + + if (m_BitsRead + size > (IsReadBuffer() ? m_MaxBit : m_CurBit)) + return false; + + ReadBitsSingle(static_cast(m_Data), out, size, m_BitsRead + m_BitOffset); + Seek(size, true); + return true; + } + + inline bool WriteDword(int val, int size) + { + if (IsReadBuffer()) + return false; + + if (m_BitsRead + size > m_MaxBit) + return false; + + if (!IsSizeCalculator()) + WriteBitsSingle(static_cast(m_Data), val, size, m_BitsRead + m_BitOffset); + Seek(size, false); + return true; + } + + inline bool ReadQword(uint64_t* out, int size) + { + if (size <= 32) + return ReadDword(reinterpret_cast(out), size); + + return ReadDword(reinterpret_cast(out), 32) && !ReadDword(reinterpret_cast(out) + 1, size - 32); + } + + inline bool WriteQword(uint64_t value, int size) + { + if (size <= 32) + return WriteDword(value, size); + + int low = (int)(value) & 0xFFFFFFFF; + int high = (int)((uint64_t)value >> 32); + + return WriteDword(low, 32) && WriteDword(high, size - 32); + } + + // unsigned + template + T Read(int size) + { + static_assert(sizeof(T) <= 8); + + uint64_t data{}; + ReadQword(&data, size); + return T(data); + } + + // unsigned + template + void Write(T data, int size) + { + static_assert(sizeof(T) <= 8); + + WriteQword(uint64_t(data), size); + } + + public: + void* m_Data; //0x0000 + uint32_t m_BitOffset; //0x0008 + uint32_t m_MaxBit; //0x000C + uint32_t m_BitsRead; //0x0010 + uint32_t m_CurBit; //0x0014 + uint32_t m_HighestBitsRead; //0x0018 + void* m_ErrorCallback; //0x0020 + uint8_t m_FlagBits; //0x0028 + }; +} \ No newline at end of file diff --git a/rdr2.rcnet b/rdr2.rcnet index eddc6d2d358a6f0d25e47306b4839680272460ff..f70fa38a91c4c9e418909fa6918f7eb7d2c14f7a 100644 GIT binary patch literal 16932 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 SDxPEe-DF#K+nxnsXZJUs`=I0i literal 16597 zcmeI43tSUdzQ;ktR#DMfr7Du`cGb1C(3Y|&kBqI`>Ze*`yO%~QFjCjDTQtD}CO{te zB5P^E$97S9MEfA#izQK(<(&ajii!|ziUA`;h$O_k33<(A=Ir2Yx3*XB7VBNv&jr4p z&pGG+pUezD{&UWm|D4Q*wSJQy_wn(0)aUr`*U*Em-K)1S2X`203GBRPz{ zW4o!h_i(VX?u0IVwL9bw!O@>Y<>1=}-#l1yJ|Xq61s&Q>oU)o_Qrck52nVaj<0M!>y~Ih(5UQ9owqR%q~@Yq9@J+yfAR30CR(gM)j!l z=2nePPUSyN=!dT?6{RTU%n%4O=n9ki)Jc~LiQXWf0oERnvC~GOnJ(B`^ZBU8ed~yo zW;;@0fjln$C6ihN*gI{qctWAS)vCc17OF=}5UL;q8&M!sDbNmfL5UC_)dvEUVDiz< z&!WJsUOn37&qtp8-7>v(=m=&(;<&_6!!qca*l}U0FcIPG1YSMNC~&pWsND1`6&2n= zy-me*ZT6yv@v~xQ`&FG>$k|y9lqo{O-Nqtp7GbX(j_m`6a2K=EitcfVXO+{Hk1As5 zJ>l6PdYQC-{RftW6l4fDtn+kbmU}xho%wxrofOwvsoP1IwKkJU71|^9Zv)#pTE1`x#7^y1_S2vho;Qb1zAIc9Z1O|OuG2x&w zFy~E=jmTHg0j^!Z3}fpS;GXu1rJ`^~5|9@gylGcr=%`(f5}riwfBLio;$CxX$Y^_uXpSRx{6T3-Gtc&T;k$^!U%O%te5R+P@gZ7S6W<4 zhl*S**lY4=ih)PK)WrlLyf=AhRmxzBC?#AdWn-Ul@$FC(I|l7I0tVaLqJ+@X`tqbU zL&nZ{o#qwk`nLRviWNzJE>^W`&Xg2*%Bkqh9-BTSuR#OT5UjUKffvyV)IxIz_bf}R z*Z1JM!VvEJjdgV~P3$vK&%#oV{8I{1kB4)dUhT-Lgud7lpcc07x}`w89-09XP z&=eOdLdsQ|BS9GC8EM%BIH(zagU_)?6>+Yfew=bVo`;=|lABz}SCEm_$#da^wsEH& zQ~U+TKuz5CD3RrSW0d-GgwDk3^)|=VtOxE>6lTwSmMZ-E>1~;Ca{8z9qTXv>4O(JR zpwtx#xem8JOKuY|d$u!r=pxPUHkM6GDRmuWv#(|aq5`sdiqC#aP}P}p9g0m&uPR@= zJhXY!?9SKHu4X|^l(NjPXco96vrk?{ZhNJRtiC#xzjK~ZIT?#=;k_<_=X_gTv;~`x%wKPJ<7YnTtnrHXu}N#1YdW=-U+{)@G#FP74xgUQE2H>FQ{;v2)UQ)=TTc z1aG$Y$6xL9mYNDh7}y5*pt+$_i2xL@3UaljC`H1?mgRjW8PC*S7t>qjG$aVABfZ1n z2vAY|Skr#~gJp7^rp6?8m@wRn~r(+-A%^1H0 znP#N##-EnJDU7G6u>sDCW?pI4QfGeE7UTx?tz2xQuX(F~ZQ!e?#AEVg3Rj{ z-=*65+sTwNf2_Kh_pAgCFe;~E)#rF$NZ`s7vJ-nw{m|PLlStAvqHvu352eE5KQk5AL9Gpjs1ak zgx9JmvpY(@j;}ph$tcg~WE~CDZqVkpw+Fvj8>UQ_W?`(q!5b=|$2G+M@PWsqwI9ub z|1>6MI|Bv+X8&w#!JPh+bF7Wg;)8Ku{XXL53C6zye-3@`GW@3pf}b-04VZm5Y%=fu zz!LIW{c(R@Y@pX?;IEPWwVv#+6YF`Oll^su9{rf?%)cf(^LslN|Fj<4f2w5iSa>`c z`GxOaemi zV*a>z(ioYF!gEHDB}4qzFN5PJK;%mxbq}GOjEjH1gL@P>dPGWEL3mOlt}sBH;o(6| zv7C}9DmEy(22HIyW;%YUPM`&)*S{VV)mE%nwr}eP;<9ok(fNJ02H^lBTG61;Hz621 zJ)M^6HutZZ=1~pYTzxl4k(u-BK0v4KjS=~KYK)- zE%90poA)YFDmT&;6}O#8^P0U(JLaeE+nCOha%b_*Cr0DWhLOEchkFN0uiA{O`x&_V z(Dk;$n^fMfT(+m`3Mm)3-Zf^;>h~$oVeEUCDy5G114l5r#_UJlCbs-;c%Ajnv2$V< z%O}$=MEv9?Ihnk%ENcn-wX&&Yhg0^5ZXO#y&GNvQ#d2}*yhY{Njd6p9d|7;L-T7s- zpte~TTe~t&4LWDh`j<4}F{&a_@h(<$AH*Y0Q!IrRybI|+H6#p48g^9in__i)D+M#- zJ;R=waABi#KWtJy9|0sle*vPv99comie|NJQKy&l)VjcqXv?m+<%Ua2Mqp>O&Y?%W zo+B>gkiphdrRX4jO*Q0o1ad#BqzfYW;e=IVpqS2ey!f#yEj@E*R{ZcQ)DF)lNr|+e znzpo@lGmD~(x;(a{WLo8WN^d3w%%Ce*FpHbhy`9YLMy9)57~%aX&EhkVEewY!|V4~ zTj1rdpp^@O&wVt~%0B`(0<`Jdy@I|_Y1T3?6Kz`h`?kP?W@u$S@X-@~pJ6|2P+oO` zi&(dcbEMpmowIX|KI4#>Ar33By$FAnow-KYwyH6%(T;tww9P_ewb!W23Rq;0ZYi;T z-o@fae$5Oy(U_Gxto03}hunC7(Dw&6vQevL<)-rPD4vkOX&n|HrFZ6i6wJI-UPOYu zxc|6%y3+e@tu{&)iOjF`bfk4W5Eq+$<-Yf;eH8P5K<6YVmH*s72-@CZ8SNwHc8e!r zcVy_kOW(f!eJ1yw)gL8y@5rm&ne+Y59AQ*W#~dx9Ag)0M82S}7!R;PWdj@-!|#&w$wlUs(7z$XU#qEtkH_#@&&ayQBJp z1l)TPc!sm$M_IY=jG5iynOIjc5^bal@LS&|;C^f*N6eETaurC;Bb3u|@q84H7(w10 z;&q_MJyY<9$-HFb1n8PzLV^2J zV9Mwdz6E0>dIT9KWRDIEbio7@3fz|hl+lNUx5mhV%V4}fE_^{@zX>K3xGx2^Hj}xR zRPru(Ozb6;xVPI_WG6S4z@6Y4nUY^Y z?#Le-^pc-@Fb;C1ZwZ(iRtl=+d+_%OB{jg=?jg^tJ6y*%k!x^ECL9xz+($5wE8WQ` zP1BDtQU}qwC%|~&_9!xG1est$f%{P4-0fwPxdeSo>?7#ogbzpWgg%&HLV^2J;P!Lq z*(f|F$Q5DZgk_^op+m16mi_yMYr{u@HmbGHKVioyiy=-~lN70)3 zbyPla6US2Hs5!gpJ;N7ln4;H!nOEiUoO;I*O@0s)jG%$SMvlj=wXe>q?~J_a8F;Ti z8RS{sn{U;J`}~(b#6M!A9~3#XlKIIEbbiSnphLEN%u@Y_6WXLzN1zlys@5-N=gYhD>sRz zAJ%4k9L@;Lock$c zTd&v!i}Hz3%chyz>Mz>+hd=qU`29o70?)v$cJ(p=w8&|wcTv0Q%hGNx5X5r}Kwe&;buAu3W6kUF-$e@Tn#$;TS^L)Wz zuiX*?aXA2|gaC(`g2n4rshc4w2OZ@3(d0ySeT-&v?e*S82+%8TnQ8}7!lvdqcJIQy zgB9&EuWO;#AkN^iBRwq(_X(xP9mPzKDkv1m7Bn`Q1aQ3x;uHAQtw69 zhRub1{KS{U#itB1bGr~a+nrxZml@xfq?>gRvA$sJqUU@?D-(iK?ji+0%X6y*t7+7)_ynWiuA@xEF}h*Agh}2cHNRhcjs6kRH)l=&a1t71DY9 zos0cxn<}Bk#{!8@9t#T^4BQ-sR{KR#hYVbBY@PaVjqClmON3b^&9eCA7S{pe^4;)p zM{?UAycb