Skip to content
This repository was archived by the owner on Nov 12, 2025. It is now read-only.

Commit d702741

Browse files
committed
0.8.0
Move around file organization *again*, this time with backwards compatible re-exports * Added ICVar bindings * Added IMaterial / IMaterialSystem bindings * Fix offsets in pretty much all interfaces (mostly engine though) * Add GetGameDirectory, GetLevelName, IsPlayingDemo, IsRecordingDemo, IsPaused to engine interface * Add engine example to show off how to use the engine interface. * Make previously ignored tests compile * util::dump_stack now returns a string instead of printing to stdout * Add Vector and Angle types (Currently meant for interfaces, not lua values)
1 parent bc0e77b commit d702741

File tree

25 files changed

+1031
-562
lines changed

25 files changed

+1031
-562
lines changed

Cargo.toml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
[package]
22
name = "rglua"
3-
description = "Rust tooling for garrysmod development with the LuaJIT api"
4-
version = "0.7.1"
3+
description = "Toolkit for garrysmod development with the source sdk and luajit api"
4+
version = "0.8.0"
55
authors = ["Vurv <[email protected]>"]
66
keywords = ["glua", "garrysmod", "lua", "gmod"]
7+
categories = ["api-bindings", "external-ffi-bindings", "development-tools::ffi", "game-development", "accessibility"]
78
readme = "README.md"
89
license = "MIT"
910
edition = "2021"
@@ -15,9 +16,14 @@ libloading = "0.7.2"
1516
once_cell = "1.8.0"
1617
thiserror = "1.0.30"
1718

19+
derive_more = { version = "0.99.17", optional = true }
20+
1821
vtables = { version = "0.1.0", optional = true }
1922
vtables_derive = { version = "0.1.0", optional = true }
2023

2124
[features]
22-
default = ["interfaces"]
23-
interfaces = ["vtables", "vtables_derive"]
25+
default = ["interfaces", "userdata"]
26+
27+
interfaces = ["vtables", "vtables_derive"]
28+
29+
userdata = ["derive_more"]

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
# 🌑 ``rglua`` [![cratesio](https://img.shields.io/crates/v/rglua.svg)](https://crates.io/crates/rglua) ![Build Status](https://www.travis-ci.com/Vurv78/rglua.svg?branch=main) [![License](https://img.shields.io/github/license/Vurv78/rglua?color=red)](https://opensource.org/licenses/Apache-2.0) [![github/Vurv78](https://img.shields.io/discord/824727565948157963?label=Discord&logo=discord&logoColor=ffffff&labelColor=7289DA&color=2c2f33)](https://discord.gg/epJFC6cNsw)
22

3-
This is a crate that contains bindings for using the lua c api in garrysmod through bindings using the rust libloading library.
4-
Can be used for either binary modules or just manual injections into gmod, like with [Autorun-rs](https://github.com/Vurv78/Autorun-rs)
3+
This is a crate that allows interop with the luajit c api as well as the source sdk through libloading and vtable bindings.
4+
You can then use these for binary modules or manually injected code, like with [Autorun-rs](https://github.com/Vurv78/Autorun-rs)
55

6-
This works by finding a ``lua_shared.dll`` file relative to the currently running program, so you need to make sure your file is either in ``GarrysMod/bin/`` or ``GarrysMod/garrysmod/bin`` for srcds servers. The library will panic if the file is not found.
7-
8-
More information on binary modules can be found on the garrysmod wiki: [Creating Binary Modules](https://wiki.facepunch.com/gmod/Creating_Binary_Modules) and an example [can be found here.](https://github.com/Vurv78/rglua/tree/master/examples/is_even)
6+
More information on binary modules can be found on the garrysmod wiki: [Creating Binary Modules](https://wiki.facepunch.com/gmod/Creating_Binary_Modules) and examples [can be found here.](https://github.com/Vurv78/rglua/tree/master/examples)
97
## Usage
108
If you are targeting 32 bit make sure to install the toolchain and build to it:
119
```bash

examples/engine/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "gmod_engine"
3+
description = "Binary module that accesses engine.dll"
4+
version = "0.1.0"
5+
edition = "2021"
6+
publish = false
7+
8+
[lib]
9+
crate-type = ["cdylib"]
10+
11+
[dependencies]
12+
rglua = { path = "../.." }
13+
anyhow = "1.0.51"

examples/engine/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ⚙️ ``iengine``
2+
Binary module that adds engine functions from IEngineClientV015 to the ``iengine`` library
3+
4+
## iengine.concmd(command: string)
5+
Runs a concommand on yourself, internally calls ``ExecuteClientCmd``
6+
7+
## iengine.getResolution() -> number, number
8+
Returns your screen resolution, internally using ``GetScreenSize``
9+
10+
## iengine.getGameDirectory() -> string
11+
Returns the absolute location of your garrysmod dir, internally using ``GetGameDirectory``
12+
13+
## iengine.getLevel() -> string
14+
Returns the current level/map name, internally using ``GetLevelName``
15+
16+
## iengine.isRecording() -> boolean
17+
Returns ``true`` if you are recording a demo, else ``false``, internally using ``IsRecordingDemo``
18+
19+
## iengine.isPaused() -> boolean
20+
Returns ``true`` if the game is paused, else ``false``, internally using ``IsPaused``

examples/engine/src/lib.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use rglua::interface::{get_from_interface, get_interface_handle, EngineClient};
2+
use rglua::prelude::*;
3+
4+
use anyhow::bail;
5+
6+
fn get_iface() -> anyhow::Result<&'static EngineClient> {
7+
let handle = unsafe { get_interface_handle("engine.dll")? };
8+
let iface = get_from_interface("VEngineClient015", handle)? as *mut EngineClient;
9+
match unsafe { iface.as_ref() } {
10+
Some(iface) => Ok(iface),
11+
None => bail!("Failed to get interface"),
12+
}
13+
}
14+
15+
extern "C" fn concmd(l: LuaState) -> i32 {
16+
match get_iface() {
17+
Ok(iface) => {
18+
iface.ExecuteClientCmd( luaL_checklstring(l, 1, 0) );
19+
}
20+
Err(e) => printgm!(l, "{}", e)
21+
}
22+
0
23+
}
24+
25+
extern "C" fn get_resolution(l: LuaState) -> i32 {
26+
match get_iface() {
27+
Ok(iface) => unsafe {
28+
let (w, h): (*mut _, *mut _) = (&mut 0, &mut 0);
29+
iface.GetScreenSize(w, h);
30+
lua_pushinteger(l, *w as isize);
31+
lua_pushinteger(l, *h as isize);
32+
return 2;
33+
},
34+
Err(e) => {
35+
printgm!(l, "Failed to get interface: {}", e);
36+
}
37+
}
38+
0
39+
}
40+
41+
extern "C" fn get_directory(l: LuaState) -> i32 {
42+
match get_iface() {
43+
Ok(iface) => {
44+
let dir = iface.GetGameDirectory();
45+
lua_pushstring(l, dir);
46+
return 1;
47+
},
48+
Err(e) => {
49+
printgm!(l, "Failed to get interface: {}", e);
50+
}
51+
}
52+
0
53+
}
54+
55+
extern "C" fn get_level(l: LuaState) -> i32 {
56+
match get_iface() {
57+
Ok(iface) => {
58+
let level = iface.GetLevelName();
59+
lua_pushstring(l, level);
60+
return 1;
61+
},
62+
Err(e) => {
63+
printgm!(l, "Failed to get interface: {}", e);
64+
}
65+
}
66+
0
67+
}
68+
69+
extern "C" fn is_recording(l: LuaState) -> i32 {
70+
match get_iface() {
71+
Ok(iface) => {
72+
let demo = iface.IsRecordingDemo();
73+
lua_pushboolean(l, demo as i32);
74+
return 1;
75+
},
76+
Err(e) => {
77+
printgm!(l, "Failed to get interface: {}", e);
78+
}
79+
}
80+
0
81+
}
82+
83+
extern "C" fn is_paused(l: LuaState) -> i32 {
84+
match get_iface() {
85+
Ok(iface) => {
86+
let paused = iface.IsPaused();
87+
lua_pushboolean(l, paused as i32);
88+
return 1;
89+
},
90+
Err(e) => {
91+
printgm!(l, "Failed to get interface: {}", e);
92+
}
93+
}
94+
0
95+
}
96+
97+
#[no_mangle]
98+
extern "C" fn gmod13_open(l: LuaState) -> i32 {
99+
printgm!(l, "Loaded engine module!");
100+
101+
let lib = reg! [
102+
"concmd" => concmd,
103+
"getResolution" => get_resolution,
104+
"getGameDirectory" => get_directory,
105+
"getLevel" => get_level,
106+
"isRecording" => is_recording,
107+
"isPaused" => is_paused
108+
];
109+
110+
luaL_register(l, cstr!("iengine"), lib.as_ptr());
111+
0
112+
}
113+
114+
#[no_mangle]
115+
extern "C" fn gmod13_close(_: LuaState) -> i32 {
116+
0
117+
}

src/globals.rs

Lines changed: 0 additions & 96 deletions
This file was deleted.

src/interface/common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#[repr(C)]
2+
#[allow(non_snake_case)]
23
pub struct PlayerInfo {
34
unknown: u64,
45
xuid: u64,
@@ -16,4 +17,4 @@ pub struct PlayerInfo {
1617
customFiles: [u64; 4],
1718
filesDownloaded: u8,
1819
pad: [i8; 304],
19-
}
20+
}

src/interface/cvar.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use super::prelude::*;
2+
3+
#[repr(C)]
4+
pub struct ConCommandBase {
5+
pub base_vtable: *mut c_void, // 0
6+
pub next: *mut ConCommandBase, // 4
7+
pub registered: bool, // 8
8+
pub name: *const c_char, // 12
9+
pub help_string: *const c_char, // 16
10+
pub flags: c_int, // 20
11+
}
12+
13+
iface! {
14+
/// VEngineCvar007
15+
/// vstdlib.dll
16+
pub abstract struct ICVar {};
17+
}
18+
19+
impl ICVar {
20+
#[virtual_index(1)]
21+
pub fn RegisterConCommand(&self, pCommandBase: *mut ConCommandBase) {}
22+
23+
#[virtual_index(2)]
24+
pub fn UnregisterConCommand(&self, pCommandBase: *mut ConCommandBase) {}
25+
26+
#[virtual_index(11)]
27+
pub fn GetCommands(&self) -> *mut ConCommandBase {}
28+
}

0 commit comments

Comments
 (0)