1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
// Everything the menu owns: what is switched on, what the last frame saw, and
// the keys bound to it.
//
// The shape mirrors the Rust client deliberately, so the saved config file is
// the same format and a config written by either build means the same thing.
//
// One design note worth keeping: modules are addressed through a table rather
// than a giant switch. Each entry knows its label, its config key, and how to
// reach its bool, which is what lets the menu, the keybinds and the config file
// all iterate the same list instead of repeating it three times.
#pragma once
#include <windows.h>
#include <array>
#include <cstdint>
#include <string>
#include <vector>
namespace lodestone::state {
// ---------------------------------------------------------------------------
// modes
// ---------------------------------------------------------------------------
enum class AimMode { Camera, Silent };
enum class FlyMode { Vanilla, Smooth, Glide, Teleport, Creative };
enum class SpeedMode { Vanilla, Strafe, Bhop };
enum class AuraTarget { Nearest, Weakest, Angle };
enum class BoxStyle { Full, Corners, Filled };
enum class TotemMode { Legit, Instant };
inline const char* label_of(AimMode m) {
switch (m) {
case AimMode::Camera: return "Camera";
case AimMode::Silent: return "Silent";
}
return "?";
}
inline const char* label_of(TotemMode m) {
switch (m) {
case TotemMode::Legit: return "Legit";
case TotemMode::Instant: return "Instant";
}
return "?";
}
inline const char* label_of(FlyMode m) {
switch (m) {
case FlyMode::Vanilla: return "Vanilla";
case FlyMode::Smooth: return "Smooth";
case FlyMode::Glide: return "Glide";
case FlyMode::Teleport: return "Teleport";
case FlyMode::Creative: return "Creative";
}
return "?";
}
inline const char* label_of(SpeedMode m) {
switch (m) {
case SpeedMode::Vanilla: return "Vanilla";
case SpeedMode::Strafe: return "Strafe";
case SpeedMode::Bhop: return "Bhop";
}
return "?";
}
inline const char* label_of(AuraTarget m) {
switch (m) {
case AuraTarget::Nearest: return "Nearest";
case AuraTarget::Weakest: return "Weakest";
case AuraTarget::Angle: return "Angle";
}
return "?";
}
inline const char* label_of(BoxStyle m) {
switch (m) {
case BoxStyle::Full: return "Full";
case BoxStyle::Corners: return "Corners";
case BoxStyle::Filled: return "Filled";
}
return "?";
}
using Colour = std::array<float, 4>;
// ---------------------------------------------------------------------------
// config
// ---------------------------------------------------------------------------
struct Combat {
bool kill_aura = false;
AuraTarget aura_target = AuraTarget::Nearest;
float aura_range = 3.5f;
float aura_cps = 10.0f;
bool aura_cooldown = true;
bool aura_rotate = true;
bool aura_through_walls = false;
bool aura_players = true;
bool aura_mobs = true;
bool aura_animals = false;
bool aimbot = false;
AimMode aim_mode = AimMode::Silent;
float aim_fov = 60.0f;
float aim_speed = 0.35f;
bool trigger_bot = false;
float trigger_delay = 0.05f;
bool auto_dodge = false;
float dodge_range = 8.0f;
float dodge_speed = 0.25f;
bool dodge_arrows = true;
bool dodge_cliffs = true;
bool reach = false;
float reach_distance = 3.5f;
bool auto_clicker = false;
float click_cps = 12.0f;
float click_jitter = 0.3f;
bool criticals = false;
float crit_hop = 0.2f;
bool sprint_reset = false;
bool hitbox = false;
float hitbox_expand = 0.2f;
bool bow_aimbot = false;
bool backtrack = false;
float backtrack_ms = 120.0f;
bool auto_totem = false;
/// How eagerly the totem goes across. Inventory timing is one of the
/// cheapest things for a server to check, and a totem that appears the same
/// millisecond every hit lands is the clearest tell there is — so Legit
/// waits until the health is genuinely dangerous and takes a human beat
/// about it, while Instant goes as fast as the container click can.
TotemMode totem_mode = TotemMode::Instant;
bool auto_shield = false;
/// Breaks the end crystals near you — the half of crystal PvP that deals
/// the damage. Placing needs a face to build on beside the target, which is
/// a separate problem.
bool auto_crystal = false;
float crystal_range = 5.0f;
float crystal_delay = 0.1f;
/// The mace's damage scales with how far you have fallen, so it is worth
/// nothing on the ground and everything on the way down.
bool auto_mace = false;
bool anti_knockback = false;
float kb_horizontal = 0.0f;
float kb_vertical = 0.0f;
};
struct Movement {
bool fly = false;
FlyMode fly_mode = FlyMode::Smooth;
float fly_speed = 0.4f;
float fly_step = 2.0f;
float fly_step_interval = 0.25f;
bool fly_anti_kick = true;
float fly_dip_interval = 1.5f;
bool speed = false;
SpeedMode speed_mode = SpeedMode::Strafe;
float speed_value = 0.3f;
bool bhop = false;
bool sprint = false;
bool no_fall = false;
bool noclip = false;
bool jesus = false;
bool spider = false;
float spider_power = 0.3f;
bool step = false;
float step_height = 1.2f;
bool jump_power = false;
float jump_multiplier = 1.5f;
bool jetpack = false;
float jetpack_power = 0.5f;
bool freecam = false;
float freecam_speed = 1.0f;
bool blink = false;
bool safewalk = false;
bool timer = false;
float timer_speed = 1.0f;
/// Keep within what the server will re-simulate without snapping you back.
bool speed_limit = true;
};
struct Esp {
bool players = false;
bool mobs = false;
bool animals = false;
bool items = false;
bool containers = false;
bool xray = false;
float block_radius = 24.0f;
std::vector<bool> xray_selected;
bool base_finder = false;
float base_chunk_radius = 8.0f;
bool gizmo_esp = false;
bool show_invis = true;
bool show_ping = true;
bool show_threat = true;
bool show_gear = true;
bool server_ghost = false;
bool player_radar = false;
bool boxes = true;
bool tracers = false;
bool nametags = true;
bool health_bars = true;
float distance = 96.0f;
BoxStyle box_style = BoxStyle::Full;
bool box_fill = false;
Colour color_player{0.94f, 0.38f, 0.43f, 1.0f};
Colour color_mob{0.93f, 0.63f, 0.33f, 1.0f};
Colour color_animal{0.49f, 0.85f, 0.55f, 1.0f};
Colour color_item{0.47f, 0.75f, 0.93f, 1.0f};
Colour color_threat{1.0f, 0.33f, 0.33f, 1.0f};
Colour color_invis{0.75f, 0.55f, 1.0f, 1.0f};
};
struct Building {
bool no_cooldown = false;
bool fast_place = false;
bool block_reach = false;
float block_reach_dist = 4.5f;
bool air_place = false;
float place_delay = 0.05f;
bool auto_build = false;
};
struct Visuals {
bool fullbright = false;
bool no_culling = false;
bool view_distance = false;
float view_distance_chunks = 16.0f;
bool fast_chunks = false;
float fast_chunks_rate = 60.0f;
bool no_fog = false;
bool no_weather = false;
bool no_hurt_cam = false;
bool no_bob = false;
bool fov = false;
float fov_value = 90.0f;
bool watermark = false;
bool hud_coords = false;
bool hud_modules = false;
};
struct Misc {
bool auto_respawn = false;
bool hide_from_capture = false;
bool packet_log = false;
};
struct Config {
Combat combat;
Movement movement;
Esp esp;
Building building;
Visuals visuals;
Misc misc;
float ui_scale = 1.0f;
/// The one accent the whole UI is themed around — #B7CDD4 by default.
Colour accent{0.718f, 0.804f, 0.831f, 1.0f};
/// Win32 virtual-key that opens the menu (Insert), rebindable.
uint32_t menu_key = 0x2D;
};
// ---------------------------------------------------------------------------
// the module table
// ---------------------------------------------------------------------------
/// Reaching a module's flag. A function rather than a member pointer because
/// the flags live in different nested structs.
using Flag = bool& (*)(Config&);
struct Module {
const char* category; ///< which nav pane it lives under
const char* label; ///< shown in the menu
const char* key; ///< stable name in the config file
Flag flag;
};
/// The nav rail, in order. Kept beside the table so the two cannot drift.
inline const std::vector<const char*>& categories() {
static const std::vector<const char*> all = {"Combat", "Movement", "World", "ESP",
"Visuals", "Misc", "Settings"};
return all;
}
#define LODE_FLAG(path) \
+[](Config& c) -> bool& { return c.path; }
/// Every toggle, in menu order. The menu, the keybinds and the config file all
/// walk this one list.
inline const std::vector<Module>& modules() {
static const std::vector<Module> table = {
// combat
{"Combat", "Kill Aura", "kill_aura", LODE_FLAG(combat.kill_aura)},
{"Combat", "Aimbot", "aimbot", LODE_FLAG(combat.aimbot)},
{"Combat", "Trigger Bot", "trigger_bot", LODE_FLAG(combat.trigger_bot)},
{"Combat", "Auto Dodge", "auto_dodge", LODE_FLAG(combat.auto_dodge)},
{"Combat", "Reach", "reach", LODE_FLAG(combat.reach)},
{"Combat", "Auto Clicker", "auto_clicker", LODE_FLAG(combat.auto_clicker)},
{"Combat", "Criticals", "criticals", LODE_FLAG(combat.criticals)},
{"Combat", "Sprint Reset", "sprint_reset", LODE_FLAG(combat.sprint_reset)},
{"Combat", "Hitbox", "hitbox", LODE_FLAG(combat.hitbox)},
{"Combat", "Bow Aimbot", "bow_aimbot", LODE_FLAG(combat.bow_aimbot)},
{"Combat", "Backtrack", "backtrack", LODE_FLAG(combat.backtrack)},
{"Combat", "Auto Totem", "auto_totem", LODE_FLAG(combat.auto_totem)},
{"Combat", "Auto Crystal", "auto_crystal", LODE_FLAG(combat.auto_crystal)},
{"Combat", "Auto Mace", "auto_mace", LODE_FLAG(combat.auto_mace)},
{"Combat", "Auto Shield", "auto_shield", LODE_FLAG(combat.auto_shield)},
{"Combat", "Anti Knockback", "anti_knockback", LODE_FLAG(combat.anti_knockback)},
// movement
{"Movement", "Fly", "fly", LODE_FLAG(movement.fly)},
{"Movement", "Speed", "speed", LODE_FLAG(movement.speed)},
{"Movement", "Bhop", "bhop", LODE_FLAG(movement.bhop)},
{"Movement", "Auto Sprint", "sprint", LODE_FLAG(movement.sprint)},
{"Movement", "No Fall", "no_fall", LODE_FLAG(movement.no_fall)},
{"Movement", "Noclip", "noclip", LODE_FLAG(movement.noclip)},
{"Movement", "Jesus", "jesus", LODE_FLAG(movement.jesus)},
{"Movement", "Spider", "spider", LODE_FLAG(movement.spider)},
{"Movement", "Step", "step", LODE_FLAG(movement.step)},
{"Movement", "High Jump", "jump_power", LODE_FLAG(movement.jump_power)},
{"Movement", "Jetpack", "jetpack", LODE_FLAG(movement.jetpack)},
{"Movement", "Freecam", "freecam", LODE_FLAG(movement.freecam)},
{"Movement", "Blink", "blink", LODE_FLAG(movement.blink)},
{"Movement", "Safewalk", "safewalk", LODE_FLAG(movement.safewalk)},
{"Movement", "Timer", "timer", LODE_FLAG(movement.timer)},
// world
{"World", "No Cooldown", "no_cooldown", LODE_FLAG(building.no_cooldown)},
{"World", "Fast Place", "fast_place", LODE_FLAG(building.fast_place)},
{"World", "Block Reach", "block_reach", LODE_FLAG(building.block_reach)},
{"World", "Air Place", "air_place", LODE_FLAG(building.air_place)},
{"World", "Auto Build", "auto_build", LODE_FLAG(building.auto_build)},
// esp
{"ESP", "Players", "esp_players", LODE_FLAG(esp.players)},
{"ESP", "Mobs", "esp_mobs", LODE_FLAG(esp.mobs)},
{"ESP", "Animals", "esp_animals", LODE_FLAG(esp.animals)},
{"ESP", "Items", "esp_items", LODE_FLAG(esp.items)},
{"ESP", "Containers", "esp_containers", LODE_FLAG(esp.containers)},
{"ESP", "Base Finder", "base_finder", LODE_FLAG(esp.base_finder)},
{"ESP", "X-Ray", "xray", LODE_FLAG(esp.xray)},
{"ESP", "Player Radar", "player_radar", LODE_FLAG(esp.player_radar)},
{"ESP", "3D Boxes", "gizmo_esp", LODE_FLAG(esp.gizmo_esp)},
{"ESP", "Boxes", "esp_boxes", LODE_FLAG(esp.boxes)},
{"ESP", "Tracers", "esp_tracers", LODE_FLAG(esp.tracers)},
{"ESP", "Nametags", "esp_nametags", LODE_FLAG(esp.nametags)},
{"ESP", "Health Bars", "esp_health", LODE_FLAG(esp.health_bars)},
{"ESP", "Show Invisible", "show_invis", LODE_FLAG(esp.show_invis)},
{"ESP", "Show Ping", "show_ping", LODE_FLAG(esp.show_ping)},
{"ESP", "Show Threat", "show_threat", LODE_FLAG(esp.show_threat)},
{"ESP", "Show Gear", "show_gear", LODE_FLAG(esp.show_gear)},
{"ESP", "Server Ghost", "server_ghost", LODE_FLAG(esp.server_ghost)},
// visuals
{"Visuals", "Fullbright", "fullbright", LODE_FLAG(visuals.fullbright)},
{"Visuals", "No Culling", "no_culling", LODE_FLAG(visuals.no_culling)},
{"Visuals", "Extend View", "view_distance", LODE_FLAG(visuals.view_distance)},
{"Visuals", "Fast Chunks", "fast_chunks", LODE_FLAG(visuals.fast_chunks)},
{"Visuals", "No Fog", "no_fog", LODE_FLAG(visuals.no_fog)},
{"Visuals", "No Weather", "no_weather", LODE_FLAG(visuals.no_weather)},
{"Visuals", "No Hurt Cam", "no_hurt_cam", LODE_FLAG(visuals.no_hurt_cam)},
{"Visuals", "No Bob", "no_bob", LODE_FLAG(visuals.no_bob)},
{"Visuals", "Custom FOV", "fov", LODE_FLAG(visuals.fov)},
{"Visuals", "Watermark", "watermark", LODE_FLAG(visuals.watermark)},
{"Visuals", "HUD Coords", "hud_coords", LODE_FLAG(visuals.hud_coords)},
{"Visuals", "HUD Modules", "hud_modules", LODE_FLAG(visuals.hud_modules)},
// misc
{"Misc", "Auto Respawn", "auto_respawn", LODE_FLAG(misc.auto_respawn)},
{"Misc", "Hide From Capture", "hide_capture", LODE_FLAG(misc.hide_from_capture)},
{"Misc", "Packet Log", "packet_log", LODE_FLAG(misc.packet_log)},
};
return table;
}
#undef LODE_FLAG
// ---------------------------------------------------------------------------
// what the last frame saw
// ---------------------------------------------------------------------------
enum class TargetKind { Player, Mob, Animal, Item, Other };
struct Vec3 {
double x = 0, y = 0, z = 0;
};
struct Target {
Vec3 min, max;
TargetKind kind = TargetKind::Other;
std::string name;
std::string held;
std::vector<std::string> effects;
int armor = 0;
int ping = -1;
float health = 0.0f;
float max_health = 0.0f;
float distance = 0.0f;
bool invisible = false;
/// Its own reach already covers you — the one thing worth seeing first.
bool can_reach_you = false;
};
struct GameState {
bool in_world = false;
bool single_player = false;
Vec3 pos, eye, camera;
float yaw = 0, pitch = 0;
float camera_yaw = 0, camera_pitch = 0;
float fov = 70.0f;
bool on_ground = false;
bool sprinting = false;
bool screen_open = false;
float health = 0.0f;
/// Counts down from 10 after damage lands, so a rise means a hit just
/// arrived. That edge is what the totem and the shield react to — far
/// earlier and more reliably than watching health alone.
int hurt_time = 0;
float fps = 0.0f;
int loaded_chunks = 0;
std::vector<Target> targets;
std::string server_brand;
/// The local player's skin: the GL texture the game already has resident,
/// and whether the model is the slim variant. 0 means "not resolved".
uint32_t skin_texture = 0;
bool skin_slim = false;
std::string player_name;
};
// ---------------------------------------------------------------------------
// keybinds and the shared state
// ---------------------------------------------------------------------------
enum class BindKind { Module, Panic, MenuToggle };
struct BindTarget {
BindKind kind = BindKind::Module;
/// Index into `modules()` when kind is Module.
size_t module = 0;
bool operator==(const BindTarget&) const = default;
};
struct Bind {
uint32_t key = 0;
BindTarget target;
};
/// Framework-neutral input, translated from Win32 by the window hook and
/// drained by the menu each frame.
struct UiInput {
enum class Kind { MouseMove, MouseButton, Wheel, Key, Char } kind{};
float x = 0, y = 0;
uint8_t button = 0;
bool down = false;
uint32_t vk = 0;
unsigned int codepoint = 0;
};
struct Shared {
bool menu_open = false;
bool eject = false;
Config cfg;
GameState game;
std::vector<UiInput> events;
std::vector<Bind> binds;
std::vector<std::string> missing;
std::string status;
/// Set while waiting for the next key press to bind something.
bool binding_active = false;
BindTarget binding;
/// Turn everything off at once.
void panic_off() {
for (const auto& m : modules()) m.flag(cfg) = false;
}
/// A key press. Returns true if it was ours and the game should not see it.
bool handle_key(uint32_t vk) {
if (binding_active) {
binding_active = false;
// Escape clears a bind rather than setting one.
if (vk == 0x1B) return true;
if (binding.kind == BindKind::MenuToggle) {
cfg.menu_key = vk;
return true;
}
std::erase_if(binds, [&](const Bind& b) { return b.key == vk || b.target == binding; });
binds.push_back(Bind{vk, binding});
return true;
}
for (const auto& b : binds) {
if (b.key != vk) continue;
switch (b.target.kind) {
case BindKind::Module: {
bool& f = modules()[b.target.module].flag(cfg);
f = !f;
break;
}
case BindKind::Panic: panic_off(); break;
case BindKind::MenuToggle: break; // lives in cfg.menu_key
}
return true;
}
return false;
}
};
/// A lock built on a critical section rather than std::mutex.
///
/// The mingw toolchain here is the win32-threads build, whose libstdc++ ships
/// without <mutex>, <thread> and friends. That is no loss: a critical section
/// is exactly what this wants, and going the other way — the posix-threads
/// toolchain — would drag libwinpthread into a DLL that currently needs nothing
/// but the system libraries.
class Lock {
public:
Lock() { InitializeCriticalSection(&cs_); }
~Lock() { DeleteCriticalSection(&cs_); }
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
void enter() { EnterCriticalSection(&cs_); }
void leave() { LeaveCriticalSection(&cs_); }
private:
CRITICAL_SECTION cs_{};
};
class Guard {
public:
explicit Guard(Lock& l) : lock_(l) { lock_.enter(); }
~Guard() { lock_.leave(); }
Guard(const Guard&) = delete;
Guard& operator=(const Guard&) = delete;
private:
Lock& lock_;
};
/// The one instance, and the lock around it. The render thread writes it and
/// the window procedure reads it, so every touch goes through `with`.
inline Lock g_lock;
inline Shared g_shared;
template <typename F>
inline auto with(F&& f) -> decltype(f(g_shared)) {
Guard guard(g_lock);
return f(g_shared);
}
} // namespace lodestone::state