bun-memory 1.1.24 → 1.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,107 @@
1
+ // ! Warning:
2
+ // ! This benchmark may take 1-2+ minutes. It repeatedly traverses the entire entity list in
3
+ // ! Counter-Strike 2, storing it into `EntityClassInfoNames`…
4
+
5
+ import Memory from 'bun-memory';
6
+
7
+ // Get the latest client_dll.json and offsets.json from:
8
+ // https://github.com/a2x/cs2-dumper/tree/main/output
9
+
10
+ import ClientDLLJSON from './offsets/client_dll.json';
11
+ import OffsetsJSON from './offsets/offsets.json';
12
+
13
+ // Load the needed offsets as bigints… It's ugly but… IntelliSense! 🫠…
14
+ const Client = {
15
+ ...Object.fromEntries(Object.entries(ClientDLLJSON['client.dll'].classes).map(([class_, { fields }]) => [class_, Object.fromEntries(Object.entries(fields).map(([field, value]) => [field, BigInt(value)]))])),
16
+ Other: Object.fromEntries(Object.entries(OffsetsJSON['client.dll']).map(([key, value]) => [key, BigInt(value)])),
17
+ } as {
18
+ [Class in keyof (typeof ClientDLLJSON)['client.dll']['classes']]: { [Field in keyof (typeof ClientDLLJSON)['client.dll']['classes'][Class]['fields']]: bigint };
19
+ } & { Other: { [K in keyof (typeof OffsetsJSON)['client.dll']]: bigint } };
20
+
21
+ // Open a handle to cs2.exe…
22
+ const cs2 = new Memory('cs2.exe');
23
+
24
+ // Get the base for client.dll…
25
+ const ClientPtr = cs2.modules['client.dll']?.base;
26
+
27
+ // Make sure client.dll is loaded…
28
+ if (ClientPtr === undefined) {
29
+ throw new TypeError('ClientPtr must not be undefined.');
30
+ }
31
+
32
+ // Warmup…
33
+ console.log('Warming up…');
34
+
35
+ for (let i = 0; i < 1e6; i++) {
36
+ const GlobalVarsPtr = cs2.u64(ClientPtr + Client.Other.dwGlobalVars);
37
+ /* */ const CurTime = cs2.f32(GlobalVarsPtr + 0x30n);
38
+ }
39
+
40
+ // Create caches and scratches to optimize performance…
41
+ const Cache_Names = new Map<bigint, string>();
42
+
43
+ const EntityChunkScratch = new BigUint64Array(0xf000 / 0x08);
44
+ const EntityListScratch = new BigUint64Array(0x200 / 0x08);
45
+
46
+ // Start the test…
47
+ console.log('Starting the test…');
48
+
49
+ const performance1 = performance.now();
50
+
51
+ const EntityListPtr = cs2.u64(ClientPtr + Client.Other.dwEntityList);
52
+
53
+ for (let i = 0; i < 1e6; i++) {
54
+ const EntityClassInfoNames = new Map<string, bigint[]>();
55
+ const EntityClassInfoPtrs = new Map<bigint, bigint[]>();
56
+
57
+ // Traverse the entity list…
58
+ cs2.read(EntityListPtr + 0x10n, EntityListScratch);
59
+
60
+ for (let i = 0; i < 0x40; i++) {
61
+ const EntityChunkPtr = EntityListScratch[i];
62
+
63
+ if (EntityChunkPtr === 0n) {
64
+ continue;
65
+ }
66
+
67
+ cs2.read(EntityChunkPtr, EntityChunkScratch);
68
+
69
+ for (let j = 0, l = 0; j < 0x200; j++, l += 0x0f) {
70
+ const BaseEntityPtr = EntityChunkScratch[l];
71
+
72
+ if (BaseEntityPtr === 0n) {
73
+ continue;
74
+ }
75
+
76
+ const EntityClassInfoPtr = EntityChunkScratch[l + 0x01];
77
+
78
+ let BaseEntityPtrs = EntityClassInfoPtrs.get(EntityClassInfoPtr);
79
+
80
+ if (BaseEntityPtrs === undefined) {
81
+ BaseEntityPtrs = [];
82
+
83
+ EntityClassInfoPtrs.set(EntityClassInfoPtr, BaseEntityPtrs);
84
+ }
85
+
86
+ BaseEntityPtrs.push(BaseEntityPtr);
87
+ }
88
+
89
+ for (const [EntityClassInfoPtr, BaseEntityPtrs] of EntityClassInfoPtrs) {
90
+ let Name = Cache_Names.get(EntityClassInfoPtr);
91
+
92
+ if (Name === undefined) {
93
+ const SchemaClassInfoDataPtr = cs2.u64(EntityClassInfoPtr + 0x30n);
94
+ /* */ const NamePtr = cs2.u64(SchemaClassInfoDataPtr + 0x08n);
95
+ /* */ Name = cs2.cString(NamePtr, 0x2a).toString();
96
+
97
+ Cache_Names.set(EntityClassInfoPtr, Name);
98
+ }
99
+
100
+ EntityClassInfoNames.set(Name, BaseEntityPtrs);
101
+ }
102
+ }
103
+ }
104
+
105
+ const performance2 = performance.now();
106
+
107
+ console.log('Test completed in %fms…', (performance2 - performance1).toFixed(2));
@@ -1,7 +1,7 @@
1
1
  import { FFIType, dlopen } from 'bun:ffi';
2
2
  import { sleep } from 'bun';
3
3
 
4
- import Memory from '../index.ts';
4
+ import Memory from 'bun-memory';
5
5
 
6
6
  // Get the latest client_dll.json and offsets.json from:
7
7
  // https://github.com/a2x/cs2-dumper/tree/main/output
@@ -21,21 +21,12 @@ const {
21
21
  });
22
22
 
23
23
  // Load the needed offsets as bigints…
24
- const { C_BaseEntity, C_BasePlayerPawn, C_BasePlayerWeapon, C_CSPlayerPawn, C_CSPlayerPawnBase, C_CSWeaponBaseGun, CBasePlayerController, CCSPlayer_WeaponServices, CCSWeaponBaseVData } = Object.fromEntries(
25
- Object.entries(ClientDLLJSON['client.dll'].classes).map(([class_, { fields }]) => [class_, Object.fromEntries(Object.entries(fields).map(([field, value]) => [field, BigInt(value)]))])
26
- ) as {
27
- [C in keyof (typeof ClientDLLJSON)['client.dll']['classes']]: { [F in keyof (typeof ClientDLLJSON)['client.dll']['classes'][C]['fields']]: bigint };
28
- };
29
-
30
- // Load the needed offsets as bigints…
31
- const {
32
- 'client.dll': { dwEntityList, dwGlobalVars, dwLocalPlayerController, dwLocalPlayerPawn },
33
- 'engine2.dll': {},
34
- } = Object.fromEntries(
35
- Object.entries(OffsetsJSON).map(([name, section]) => [name, Object.fromEntries(Object.entries(section).map(([key, value]) => [key, BigInt(value as number)]))]) //
36
- ) as {
37
- [M in keyof typeof OffsetsJSON]: { [K in keyof (typeof OffsetsJSON)[M]]: bigint };
38
- };
24
+ const Client = {
25
+ ...Object.fromEntries(Object.entries(ClientDLLJSON['client.dll'].classes).map(([class_, { fields }]) => [class_, Object.fromEntries(Object.entries(fields).map(([field, value]) => [field, BigInt(value)]))])),
26
+ Other: Object.fromEntries(Object.entries(OffsetsJSON['client.dll']).map(([key, value]) => [key, BigInt(value)])),
27
+ } as {
28
+ [Class in keyof (typeof ClientDLLJSON)['client.dll']['classes']]: { [Field in keyof (typeof ClientDLLJSON)['client.dll']['classes'][Class]['fields']]: bigint };
29
+ } & { Other: { [K in keyof (typeof OffsetsJSON)['client.dll']]: bigint } };
39
30
 
40
31
  // Open a handle to cs2.exe…
41
32
  const cs2 = new Memory('cs2.exe');
@@ -46,23 +37,6 @@ const ClientPtr = cs2.modules['client.dll']?.base;
46
37
  if (ClientPtr === undefined) {
47
38
  throw new TypeError('ClientPtr must not be undefined.');
48
39
  }
49
- // !
50
-
51
- console.time('test');
52
-
53
- // while (true) {
54
- // for (const pointer of pointers) {
55
- // const cString = cs2.cString(pointer, 32).toString();
56
-
57
- // if (cString.length > 32) {
58
- // console.log(cString);
59
- // }
60
- // }
61
- // }
62
-
63
- console.timeEnd('test');
64
-
65
- // !
66
40
 
67
41
  // Create a cache for class name strings… 🫠…
68
42
  const Cache_Names = new Map<bigint, string>();
@@ -74,26 +48,26 @@ async function tick(ClientPtr: bigint) {
74
48
  ticks++;
75
49
 
76
50
  // Read relevant info from memory…
77
- const GlobalVarsPtr = cs2.u64(ClientPtr + dwGlobalVars);
51
+ const GlobalVarsPtr = cs2.u64(ClientPtr + Client.Other.dwGlobalVars);
78
52
  /* */ const CurTime = cs2.f32(GlobalVarsPtr + 0x30n);
79
53
 
80
- const Local_PlayerControllerPtr = cs2.u64(ClientPtr + dwLocalPlayerController);
81
- /* */ const Local_TickBase = cs2.u32(Local_PlayerControllerPtr + CBasePlayerController.m_nTickBase);
82
-
83
- const Local_PlayerPawnPtr = cs2.u64(ClientPtr + dwLocalPlayerPawn);
84
- /* */ const Local_FlashOverlayAlpha = cs2.f32(Local_PlayerPawnPtr + C_CSPlayerPawnBase.m_flFlashOverlayAlpha);
85
- /* */ const Local_IDEntIndex = cs2.i32(Local_PlayerPawnPtr + C_CSPlayerPawn.m_iIDEntIndex);
86
- /* */ const Local_IsScoped = cs2.i32(Local_PlayerPawnPtr + C_CSPlayerPawn.m_bIsScoped);
87
- /* */ const Local_Player_WeaponServicesPtr = cs2.u64(Local_PlayerPawnPtr + C_BasePlayerPawn.m_pWeaponServices);
88
- /* */ const Local_NextAttack = cs2.f32(Local_Player_WeaponServicesPtr + CCSPlayer_WeaponServices.m_flNextAttack);
89
- /* */ const Local_TeamNum = cs2.u8(Local_PlayerPawnPtr + C_BaseEntity.m_iTeamNum);
90
- /* */ const Local_WeaponBasePtr = cs2.u64(Local_PlayerPawnPtr + C_CSPlayerPawn.m_pClippingWeapon);
91
- /* */ const Local_Clip1 = cs2.i32(Local_WeaponBasePtr + C_BasePlayerWeapon.m_iClip1);
92
- /* */ const Local_NextPrimaryAttackTick = cs2.u32(Local_WeaponBasePtr + C_BasePlayerWeapon.m_nNextPrimaryAttackTick);
93
- /* */ const Local_WeaponBaseVDataPtr = cs2.u64(Local_WeaponBasePtr + C_BaseEntity.m_nSubclassID + 0x08n);
94
- /* */ const Local_IsFullAuto = cs2.bool(Local_WeaponBaseVDataPtr + CCSWeaponBaseVData.m_bIsFullAuto);
95
- /* */ const Local_WeaponType = cs2.i32(Local_WeaponBaseVDataPtr + CCSWeaponBaseVData.m_WeaponType);
96
- /* */ const Local_ZoomLevel = cs2.i32(Local_WeaponBasePtr + C_CSWeaponBaseGun.m_zoomLevel);
54
+ const Local_PlayerControllerPtr = cs2.u64(ClientPtr + Client.Other.dwLocalPlayerController);
55
+ /* */ const Local_TickBase = cs2.u32(Local_PlayerControllerPtr + Client.CBasePlayerController.m_nTickBase);
56
+
57
+ const Local_PlayerPawnPtr = cs2.u64(ClientPtr + Client.Other.dwLocalPlayerPawn);
58
+ /* */ const Local_FlashOverlayAlpha = cs2.f32(Local_PlayerPawnPtr + Client.C_CSPlayerPawnBase.m_flFlashOverlayAlpha);
59
+ /* */ const Local_IDEntIndex = cs2.i32(Local_PlayerPawnPtr + Client.C_CSPlayerPawn.m_iIDEntIndex);
60
+ /* */ const Local_IsScoped = cs2.i32(Local_PlayerPawnPtr + Client.C_CSPlayerPawn.m_bIsScoped);
61
+ /* */ const Local_Player_WeaponServicesPtr = cs2.u64(Local_PlayerPawnPtr + Client.C_BasePlayerPawn.m_pWeaponServices);
62
+ /* */ const Local_NextAttack = cs2.f32(Local_Player_WeaponServicesPtr + Client.CCSPlayer_WeaponServices.m_flNextAttack);
63
+ /* */ const Local_TeamNum = cs2.u8(Local_PlayerPawnPtr + Client.C_BaseEntity.m_iTeamNum);
64
+ /* */ const Local_WeaponBasePtr = cs2.u64(Local_PlayerPawnPtr + Client.C_CSPlayerPawn.m_pClippingWeapon);
65
+ /* */ const Local_Clip1 = cs2.i32(Local_WeaponBasePtr + Client.C_BasePlayerWeapon.m_iClip1);
66
+ /* */ const Local_NextPrimaryAttackTick = cs2.u32(Local_WeaponBasePtr + Client.C_BasePlayerWeapon.m_nNextPrimaryAttackTick);
67
+ /* */ const Local_WeaponBaseVDataPtr = cs2.u64(Local_WeaponBasePtr + Client.C_BaseEntity.m_nSubclassID + 0x08n);
68
+ /* */ const Local_IsFullAuto = cs2.bool(Local_WeaponBaseVDataPtr + Client.CCSWeaponBaseVData.m_bIsFullAuto);
69
+ /* */ const Local_WeaponType = cs2.i32(Local_WeaponBaseVDataPtr + Client.CCSWeaponBaseVData.m_WeaponType);
70
+ /* */ const Local_ZoomLevel = cs2.i32(Local_WeaponBasePtr + Client.C_CSWeaponBaseGun.m_zoomLevel);
97
71
 
98
72
  // Conditions where we should not fire…
99
73
  if (CurTime < Local_NextAttack) {
@@ -113,7 +87,7 @@ async function tick(ClientPtr: bigint) {
113
87
  // Weapon types: https://swiftlys2.net/sdk/cs2/types/csweapontype
114
88
 
115
89
  // Get the entity that we're aiming at from the entity list…
116
- const EntityListPtr = cs2.u64(ClientPtr + dwEntityList);
90
+ const EntityListPtr = cs2.u64(ClientPtr + Client.Other.dwEntityList);
117
91
  /* */ const EntityChunkPtr = cs2.u64(EntityListPtr + (BigInt(Local_IDEntIndex) >> 0x09n) * 0x08n + 0x10n);
118
92
  /* */ const BaseEntityPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) * 0x78n);
119
93
  /* */ const EntityClassInfoPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) * 0x78n + 0x08n);
@@ -134,7 +108,7 @@ async function tick(ClientPtr: bigint) {
134
108
  }
135
109
 
136
110
  const PlayerPawnPtr = BaseEntityPtr;
137
- /* */ const TeamNum = cs2.u8(PlayerPawnPtr + BigInt(C_BaseEntity.m_iTeamNum));
111
+ /* */ const TeamNum = cs2.u8(PlayerPawnPtr + Client.C_BaseEntity.m_iTeamNum);
138
112
 
139
113
  if (TeamNum === Local_TeamNum) {
140
114
  return;
@@ -148,7 +122,7 @@ async function tick(ClientPtr: bigint) {
148
122
  // If the gun is automatic, hold the trigger until we're no longer aiming at them…
149
123
  do {
150
124
  await sleep(random() * Delay + Delay);
151
- } while (Local_IDEntIndex === cs2.u32(Local_PlayerPawnPtr + C_CSPlayerPawn.m_iIDEntIndex) && Local_IsFullAuto);
125
+ } while (Local_IDEntIndex === cs2.u32(Local_PlayerPawnPtr + Client.C_CSPlayerPawn.m_iIDEntIndex) && Local_IsFullAuto);
152
126
 
153
127
  // Release the trigger…
154
128
  mouse_event(0x04, 0x00, 0x00, 0x00, 0n);
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "url": "git://github.com/obscuritysrl/bun-memory.git"
23
23
  },
24
24
  "type": "module",
25
- "version": "1.1.24",
25
+ "version": "1.1.26",
26
26
  "main": "./index.ts",
27
27
  "keywords": [
28
28
  "bun",
@@ -46,5 +46,9 @@
46
46
  ],
47
47
  "engines": {
48
48
  "bun": ">=1.1.0"
49
+ },
50
+ "scripts": {
51
+ "run:benchmark": "bun ./example/benchmark.ts",
52
+ "run:trigger-bot": "bun ./example/trigger-bot.ts"
49
53
  }
50
54
  }