Compare commits

...

23 Commits
master ... luau

Author SHA1 Message Date
1cae51ecb9 Idea, Vector.new(X?, Y?, Z?, W?) instead of Vector2.new, Vector3.new, Vector4.new 2024-01-23 22:42:53 -05:00
d9b6085d7f need to patch a bug related to some NEG_X and Y values, start metatable work 2024-01-23 00:11:15 -05:00
33cf9f0561 f32 instead because glam 2024-01-22 23:28:48 -05:00
40745c4f6f roblox sandbox maybe 2024-01-22 23:28:21 -05:00
e40e960ef2 Provide optional values for Vector.new libraries Vector4.new() -> 0,0,0,0 2024-01-22 15:05:23 -05:00
76ca43a645 debug "warn" global for StrafeLua 2024-01-22 14:20:23 -05:00
b5f7a8cc6f Add color_print crate and implement it into the Lua error handler 2024-01-22 13:50:42 -05:00
88ad707f39 Error handler so strafe client wont panic on a Lua error 2024-01-22 13:42:52 -05:00
66eea1f106 added properties for Vector3 & Vector4:
Vector3.ZERO
Vector3.ONE
Vector3.NEG_ZERO
Vector3.NEG_ONE
Vector3.NEG_X
Vector3.NEG_Y
@Vector4:
Vector4.ZERO
Vector4.ONE
Vector4.NEG_ZERO
Vector4.NEG_ONE
Vector4.NEG_X
Vector4.NEG_Y
2024-01-22 12:22:16 -05:00
a51001a875 added properties for Vector2:
Vector2.ZERO
Vector2.ONE
Vector2.NEG_ZERO
Vector2.NEG_ONE
Vector2.NEG_X
Vector2.NEG_Y
2024-01-21 22:44:58 -05:00
d2782012ac _VERSION=StrafeLuau 0.9.0, Luau 0.606 2024-01-21 20:38:27 -05:00
63c8f0f4f5 Vector.new, add vector types 4,3,2,& 1; Lua error handling needed 2024-01-21 20:26:20 -05:00
46a16d1169 cargo update 2024-01-21 20:24:36 -05:00
2f4e1d64dc typemap for luau analyzer, rename "tests" to "luau" and move tests into it 2024-01-21 17:40:10 -05:00
f21ec098db lifetimes massacred 2024-01-21 00:59:31 -05:00
41b9aafd54 Luau: Vector3(x,y,z) 2024-01-20 23:17:55 -05:00
bf0ed47ceb Temporary return solution
fighting the borrow checker
2024-01-20 23:09:26 -05:00
fdf0205c98 Vector test and the test folder 2024-01-20 22:28:07 -05:00
5327b201c7 first luau.rs commit, this one doesn't work 2024-01-20 20:19:42 -05:00
99b9c527b4 add luau module to main
WIP implementation method
2024-01-20 20:19:10 -05:00
6e703075e9 add luau-jit
cargo add mlua --features luau-jit
2024-01-19 14:37:45 -05:00
53545ab5a2 Update smallvec, built and ran tested
WAYLAND_DISPLAY= mangohud cargo run
2024-01-19 14:24:28 -05:00
dd4f0b9245 update wgpu and slap lifetimes on everything until it works 2024-01-18 14:26:08 -08:00
11 changed files with 519 additions and 297 deletions

463
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,10 +7,12 @@ edition = "2021"
[dependencies] [dependencies]
bytemuck = { version = "1.13.1", features = ["derive"] } bytemuck = { version = "1.13.1", features = ["derive"] }
color-print = "0.3.5"
configparser = "3.0.2" configparser = "3.0.2"
ddsfile = "0.5.1" ddsfile = "0.5.1"
glam = "0.24.1" glam = "0.24.1"
lazy-regex = "3.0.2" lazy-regex = "3.0.2"
mlua = { version = "0.9.4", features = ["luau-jit"] }
obj = "0.10.2" obj = "0.10.2"
parking_lot = "0.12.1" parking_lot = "0.12.1"
pollster = "0.3.0" pollster = "0.3.0"
@ -20,8 +22,8 @@ rbx_reflection_database = "0.2.7"
rbx_xml = "0.13.1" rbx_xml = "0.13.1"
vbsp = "0.5.0" vbsp = "0.5.0"
vmdl = "0.1.1" vmdl = "0.1.1"
wgpu = "0.18.0" wgpu = "0.19.0"
winit = { version = "0.29.2", features = ["rwh_05"] } winit = { version = "0.29.2" }
#[profile.release] #[profile.release]
#lto = true #lto = true

View File

@ -0,0 +1,52 @@
type workspace = {[string]: {number}}
type Service = {}
export type exports = {[string]: {workspace | number | {}}}
local workspace: workspace = {}
local RS = {
RenderStepped = {},
Stepped = {},
Heartbeat = {}
}
local game = setmetatable({
Workspace = workspace,
Players = {},
RunService = RS
}, {
__index = function(self,i)
return rawget(self,i)
end,
__newindex = function(self,i,_)
--Roblox actually does this
local t = type(i)
return t == "Object" and "Unable to assign property Game. Property is read only" or `Unable to assign property Game. Object expected, got {t}`
end,
__metatable = "This metatable is locked."
})
function game:GetService(service: string): Service
return self[service]
end
function game:service(service: string): Service
return self:GetService(service)
end
function game:FindService(service: string): boolean | Service
return self[service] and self[service]
end
local tick = os.clock() --just be better (Roblox wants you to use this instead of "tick" anyways because of Wine)
local task = {
wait = {},
delay = {},
defer = {}
}
local exports: exports = {
game = game, Game = game,
workspace = workspace, Workspace = workspace,
tick = tick,
task = task
}
return exports

20
luau/tests/Vector.lua Normal file
View File

@ -0,0 +1,20 @@
local vec2 = Vector.new(1,2)
local vec3 = Vector.new(1,2,3)
local vec4 = Vector.new(1,2,3,4)
local function InspectVectorTable(Vector: {[string]: number})
local aye: {string} = {"{"}
for k,v in Vector do
table.insert(aye, `{tostring(k)}={tostring(v)}`)
end
table.insert(aye, "}")
return table.concat(aye, " ")
end
print("----StrafeLua----")
warn(_VERSION)
print(`Vector.new = {InspectVectorTable(Vector.new())}`)
print(`vec2 = {InspectVectorTable(vec2)}`)
print(`vec3 = {InspectVectorTable(vec3)}`)
print(`vec4 = {InspectVectorTable(vec4)}`)
print("-----------------")

48
luau/typemap.lua Normal file
View File

@ -0,0 +1,48 @@
--A type map for the luau analyzer
type f32 = number
type struct_Vector2 = {x: f32, y: f32}
type struct_Vector3 = struct_Vector2 & {z: f32}
type struct_Vector4 = struct_Vector3 & {w: f32}
export type warn = (message: string) -> ()
export type Vector2 = {
new: (x: f32?, y: f32?) -> struct_Vector2,
ONE: struct_Vector2,
ZERO: struct_Vector2,
NEG_ZERO: struct_Vector2,
NEG_ONE: struct_Vector2,
NEG_X: struct_Vector2,
NEG_Y: struct_Vector2,
}
export type Vector3 = {
new: (x: f32?, y: f32?, z: f32?) -> struct_Vector3,
ONE: struct_Vector3,
ZERO: struct_Vector3,
NEG_ZERO: struct_Vector3,
NEG_ONE: struct_Vector3,
NEG_X: struct_Vector3,
NEG_Y: struct_Vector3,
}
export type Vector4 = {
new: (x: f32?, y: f32?, z: f32?, w: f32?) -> struct_Vector4,
ONE: struct_Vector4,
ZERO: struct_Vector4,
NEG_ZERO: struct_Vector4,
NEG_ONE: struct_Vector4,
NEG_X: struct_Vector4,
NEG_Y: struct_Vector4,
}
local Vector2: Vector2 = Vector2
local Vector3: Vector3 = Vector3
local Vector4: Vector4 = Vector4
local warn: warn = warn
return {
Vector2 = Vector2,
Vector3 = Vector3,
Vector4 = Vector4,
warn = warn
}

View File

@ -203,6 +203,7 @@ impl GraphicsState{
label: Some(format!("Texture{}",texture_id).as_str()), label: Some(format!("Texture{}",texture_id).as_str()),
view_formats: &[], view_formats: &[],
}, },
wgpu::util::TextureDataOrder::LayerMajor,
&image.data, &image.data,
); );
texture.create_view(&wgpu::TextureViewDescriptor { texture.create_view(&wgpu::TextureViewDescriptor {
@ -700,6 +701,7 @@ impl GraphicsState{
label: Some("Skybox Texture"), label: Some("Skybox Texture"),
view_formats: &[], view_formats: &[],
}, },
wgpu::util::TextureDataOrder::LayerMajor,
&skybox_image.data, &skybox_image.data,
); );
@ -740,6 +742,7 @@ impl GraphicsState{
label: Some("Squid Texture"), label: Some("Squid Texture"),
view_formats: &[], view_formats: &[],
}, },
wgpu::util::TextureDataOrder::LayerMajor,
&image.data, &image.data,
); );

View File

@ -18,7 +18,7 @@ WorkerDescription{
pub fn new<'a>( pub fn new<'a>(
mut graphics:crate::graphics::GraphicsState, mut graphics:crate::graphics::GraphicsState,
mut config:wgpu::SurfaceConfiguration, mut config:wgpu::SurfaceConfiguration,
surface:wgpu::Surface, surface:wgpu::Surface<'a>,
device:wgpu::Device, device:wgpu::Device,
queue:wgpu::Queue, queue:wgpu::Queue,
)->crate::compat_worker::INWorker<'a,Instruction>{ )->crate::compat_worker::INWorker<'a,Instruction>{

95
src/luau.rs Normal file
View File

@ -0,0 +1,95 @@
use mlua::{Lua as Luau, Result};
use glam::{Vec2, Vec3, Vec4, Quat};
use color_print::cprintln;
const STRAFE_VERSION: &str = env!("CARGO_PKG_VERSION");
struct StrafeluaGlobals {
vm: Luau,
}
trait Luavm {
fn new_vm(isolated: bool) -> StrafeluaGlobals {
let vm = Luau::new();
vm.sandbox(isolated).unwrap();
if isolated {
//Prevent bad actors
vm.globals().set("getfenv", mlua::Nil).unwrap(); //Deprecated in Luau but not removed *yet*
vm.globals().set("setfenv", mlua::Nil).unwrap(); //same with this
vm.globals().set("loadstring", mlua::Nil).unwrap();
};
let luau_version: String = vm.globals().get("_VERSION").unwrap();
vm.globals().set("_VERSION", format!("StrafeLuau {}, {}", STRAFE_VERSION, luau_version)).unwrap();
StrafeluaGlobals {vm}
}
fn warn(&self) -> mlua::Function;
fn vector(&self) -> mlua::Table;
}
impl Luavm for StrafeluaGlobals {
//Debug stuff
fn warn(&self) -> mlua::Function {
return self.vm.create_function(|_, message: mlua::String| {
match Some(message) {
Some(lua_string) => cprintln!("<yellow>{}</yellow>", lua_string.to_str().unwrap()),
None => println!("Nothing provided to warn"),
};
Ok(())
}).unwrap();
}
fn vector(&self) -> mlua::Table {
let field_vector = self.vm.create_table().unwrap();
field_vector.set("new", self.vm.create_function(|this: &Luau, (x,y,z,w): (Option<mlua::Number>, Option<mlua::Number>, Option<mlua::Number>, Option<mlua::Number>)| {
let vector = this.create_table().unwrap();
vector.set("x", x.unwrap_or(0.0)).unwrap();
vector.set("y", y.unwrap_or(0.0)).unwrap();
vector.set("z", z.unwrap_or(0.0)).unwrap();
vector.set("w", w.unwrap_or(0.0)).unwrap();
Ok(vector)
}).unwrap()).unwrap();
let vector_one2 = self.vm.create_table().unwrap();
vector_one2.set("x", 1.0).unwrap();
vector_one2.set("y", 1.0).unwrap();
vector_one2.set("z", 0.0).unwrap();
vector_one2.set("w", 0.0).unwrap();
field_vector.set("one2", vector_one2).unwrap();
let vector_one3 = self.vm.create_table().unwrap();
vector_one3.set("x", 1.0).unwrap();
vector_one3.set("y", 1.0).unwrap();
vector_one3.set("z", 1.0).unwrap();
vector_one3.set("w", 0.0).unwrap();
field_vector.set("one3", vector_one3).unwrap();
let vector_one4 = self.vm.create_table().unwrap();
vector_one4.set("x", 1.0).unwrap();
vector_one4.set("y", 1.0).unwrap();
vector_one4.set("z", 1.0).unwrap();
vector_one4.set("w", 1.0).unwrap();
field_vector.set("one4", vector_one4).unwrap();
return field_vector
}
}
/// Prevent strafe client from panicking when there is a Lua error related to syntax or anything else Lua related
pub fn error_wrapper(execute_result: Result<()>) {
match execute_result {
Ok(t) => t,
Err(e) => cprintln!("[StrafeLua ERROR]: <red>{}</red>", e),
}
}
pub fn new_state(isolated: bool) -> Result<Luau> {
let strafelua = StrafeluaGlobals::new_vm(isolated);
strafelua.vm.globals().set("warn", strafelua.warn()).unwrap();
strafelua.vm.globals().set("Vector", strafelua.vector()).unwrap();
Ok(strafelua.vm)
}

View File

@ -1,5 +1,6 @@
mod bvh; mod bvh;
mod aabb; mod aabb;
mod luau;
mod model; mod model;
mod setup; mod setup;
mod window; mod window;
@ -117,6 +118,31 @@ pub fn default_models()->model::IndexedModelInstances{
} }
fn main(){ fn main(){
let context=setup::setup(format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")).as_str()); let strafelua_vm = luau::new_state(true).expect("Failed to load strafe lua");
context.start();//creates and runs a window context luau::error_wrapper(strafelua_vm.load(r#"
local vec2 = Vector.new(1,2)
local vec3 = Vector.new(1,2,3)
local vec4 = Vector.new(1,2,3,4)
local function InspectVectorTable(Vector: {[string]: number})
local aye: {string} = {"{"}
for k,v in Vector do
table.insert(aye, `{tostring(k)}={tostring(v)}`)
end
table.insert(aye, "}")
return table.concat(aye, " ")
end
print("----StrafeLua----")
warn(_VERSION)
print(`Vector.new = {InspectVectorTable(Vector.new())}`)
print(`vec2 = {InspectVectorTable(vec2)}`)
print(`vec3 = {InspectVectorTable(vec3)}`)
print(`vec4 = {InspectVectorTable(vec4)}`)
print("-----------------")
"#).exec());
//Lua syntax error!: SyntaxError { message: "[string \"src/main.rs:122:18\"]:7: Expected ')' (to close '(' at column 7), got ','", incomplete_input: false }
//we got our first lua syntax error, todo: make an error handler in luau.rs
setup::setup_and_start(format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")));
} }

View File

@ -46,21 +46,21 @@ fn create_instance()->SetupContextPartial1{
} }
} }
impl SetupContextPartial1{ impl SetupContextPartial1{
fn create_surface(self,window:&winit::window::Window)->Result<SetupContextPartial2,wgpu::CreateSurfaceError>{ fn create_surface<'a>(self,window:&'a winit::window::Window)->Result<SetupContextPartial2<'a>,wgpu::CreateSurfaceError>{
Ok(SetupContextPartial2{ Ok(SetupContextPartial2{
backends:self.backends, backends:self.backends,
surface:unsafe{self.instance.create_surface(window)}?, surface:self.instance.create_surface(window)?,
instance:self.instance, instance:self.instance,
}) })
} }
} }
struct SetupContextPartial2{ struct SetupContextPartial2<'a>{
backends:wgpu::Backends, backends:wgpu::Backends,
instance:wgpu::Instance, instance:wgpu::Instance,
surface:wgpu::Surface, surface:wgpu::Surface<'a>,
} }
impl SetupContextPartial2{ impl<'a> SetupContextPartial2<'a>{
fn pick_adapter(self)->SetupContextPartial3{ fn pick_adapter(self)->SetupContextPartial3<'a>{
let adapter; let adapter;
//TODO: prefer adapter that implements optional features //TODO: prefer adapter that implements optional features
@ -122,13 +122,13 @@ impl SetupContextPartial2{
} }
} }
} }
struct SetupContextPartial3{ struct SetupContextPartial3<'a>{
instance:wgpu::Instance, instance:wgpu::Instance,
surface:wgpu::Surface, surface:wgpu::Surface<'a>,
adapter:wgpu::Adapter, adapter:wgpu::Adapter,
} }
impl SetupContextPartial3{ impl<'a> SetupContextPartial3<'a>{
fn request_device(self)->SetupContextPartial4{ fn request_device(self)->SetupContextPartial4<'a>{
let optional_features=optional_features(); let optional_features=optional_features();
let required_features=required_features(); let required_features=required_features();
@ -140,8 +140,8 @@ impl SetupContextPartial3{
.request_device( .request_device(
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
label: None, label: None,
features: (optional_features & self.adapter.features()) | required_features, required_features: (optional_features & self.adapter.features()) | required_features,
limits: needed_limits, required_limits: needed_limits,
}, },
trace_dir.ok().as_ref().map(std::path::Path::new), trace_dir.ok().as_ref().map(std::path::Path::new),
)) ))
@ -156,15 +156,15 @@ impl SetupContextPartial3{
} }
} }
} }
struct SetupContextPartial4{ struct SetupContextPartial4<'a>{
instance:wgpu::Instance, instance:wgpu::Instance,
surface:wgpu::Surface, surface:wgpu::Surface<'a>,
adapter:wgpu::Adapter, adapter:wgpu::Adapter,
device:wgpu::Device, device:wgpu::Device,
queue:wgpu::Queue, queue:wgpu::Queue,
} }
impl SetupContextPartial4{ impl<'a> SetupContextPartial4<'a>{
fn configure_surface(self,size:&winit::dpi::PhysicalSize<u32>)->SetupContext{ fn configure_surface(self,size:&'a winit::dpi::PhysicalSize<u32>)->SetupContext<'a>{
let mut config=self.surface let mut config=self.surface
.get_default_config(&self.adapter, size.width, size.height) .get_default_config(&self.adapter, size.width, size.height)
.expect("Surface isn't supported by the adapter."); .expect("Surface isn't supported by the adapter.");
@ -182,58 +182,36 @@ impl SetupContextPartial4{
} }
} }
} }
pub struct SetupContext{ pub struct SetupContext<'a>{
pub instance:wgpu::Instance, pub instance:wgpu::Instance,
pub surface:wgpu::Surface, pub surface:wgpu::Surface<'a>,
pub device:wgpu::Device, pub device:wgpu::Device,
pub queue:wgpu::Queue, pub queue:wgpu::Queue,
pub config:wgpu::SurfaceConfiguration, pub config:wgpu::SurfaceConfiguration,
} }
pub fn setup(title:&str)->SetupContextSetup{ pub fn setup_and_start(title:String){
let event_loop=winit::event_loop::EventLoop::new().unwrap(); let event_loop=winit::event_loop::EventLoop::new().unwrap();
let window=create_window(title,&event_loop).unwrap();
println!("Initializing the surface..."); println!("Initializing the surface...");
let partial_1=create_instance(); let partial_1=create_instance();
let window=create_window(title.as_str(),&event_loop).unwrap();
let partial_2=partial_1.create_surface(&window).unwrap(); let partial_2=partial_1.create_surface(&window).unwrap();
let partial_3=partial_2.pick_adapter(); let partial_3=partial_2.pick_adapter();
let partial_4=partial_3.request_device(); let partial_4=partial_3.request_device();
SetupContextSetup{ let size=window.inner_size();
window,
event_loop,
partial_context:partial_4,
}
}
pub struct SetupContextSetup{ let setup_context=partial_4.configure_surface(&size);
window:winit::window::Window,
event_loop:winit::event_loop::EventLoop<()>,
partial_context:SetupContextPartial4,
}
impl SetupContextSetup{
fn into_split(self)->(winit::window::Window,winit::event_loop::EventLoop<()>,SetupContext){
let size=self.window.inner_size();
//Steal values and drop self
(
self.window,
self.event_loop,
self.partial_context.configure_surface(&size),
)
}
pub fn start(self){
let (window,event_loop,setup_context)=self.into_split();
//dedicated thread to ping request redraw back and resize the window doesn't seem logical //dedicated thread to ping request redraw back and resize the window doesn't seem logical
let window=crate::window::WindowContextSetup::new(&setup_context,window); let window=crate::window::WindowContextSetup::new(&setup_context,&window);
//the thread that spawns the physics thread //the thread that spawns the physics thread
let window_thread=window.into_worker(setup_context); let window_thread=window.into_worker(setup_context);
@ -241,7 +219,6 @@ impl SetupContextSetup{
let root_time=std::time::Instant::now(); let root_time=std::time::Instant::now();
run_event_loop(event_loop,window_thread,root_time).unwrap(); run_event_loop(event_loop,window_thread,root_time).unwrap();
} }
}
fn run_event_loop( fn run_event_loop(
event_loop:winit::event_loop::EventLoop<()>, event_loop:winit::event_loop::EventLoop<()>,

View File

@ -15,7 +15,7 @@ struct WindowContext<'a>{
mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>> mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>>
screen_size:glam::UVec2, screen_size:glam::UVec2,
user_settings:crate::settings::UserSettings, user_settings:crate::settings::UserSettings,
window:winit::window::Window, window:&'a winit::window::Window,
physics_thread:crate::compat_worker::QNWorker<'a, TimedInstruction<crate::physics_worker::Instruction>>, physics_thread:crate::compat_worker::QNWorker<'a, TimedInstruction<crate::physics_worker::Instruction>>,
} }
@ -158,15 +158,15 @@ impl WindowContext<'_>{
} }
} }
pub struct WindowContextSetup{ pub struct WindowContextSetup<'a>{
user_settings:crate::settings::UserSettings, user_settings:crate::settings::UserSettings,
window:winit::window::Window, window:&'a winit::window::Window,
physics:crate::physics::PhysicsState, physics:crate::physics::PhysicsState,
graphics:crate::graphics::GraphicsState, graphics:crate::graphics::GraphicsState,
} }
impl WindowContextSetup{ impl<'a> WindowContextSetup<'a>{
pub fn new(context:&crate::setup::SetupContext,window:winit::window::Window)->Self{ pub fn new(context:&crate::setup::SetupContext,window:&'a winit::window::Window)->Self{
//wee //wee
let user_settings=crate::settings::read_user_settings(); let user_settings=crate::settings::read_user_settings();
@ -194,7 +194,7 @@ impl WindowContextSetup{
} }
} }
fn into_context<'a>(self,setup_context:crate::setup::SetupContext)->WindowContext<'a>{ fn into_context(self,setup_context:crate::setup::SetupContext<'a>)->WindowContext<'a>{
let screen_size=glam::uvec2(setup_context.config.width,setup_context.config.height); let screen_size=glam::uvec2(setup_context.config.width,setup_context.config.height);
let graphics_thread=crate::graphics_worker::new(self.graphics,setup_context.config,setup_context.surface,setup_context.device,setup_context.queue); let graphics_thread=crate::graphics_worker::new(self.graphics,setup_context.config,setup_context.surface,setup_context.device,setup_context.queue);
WindowContext{ WindowContext{
@ -208,7 +208,7 @@ impl WindowContextSetup{
} }
} }
pub fn into_worker<'a>(self,setup_context:crate::setup::SetupContext)->crate::compat_worker::QNWorker<'a,TimedInstruction<WindowInstruction>>{ pub fn into_worker(self,setup_context:crate::setup::SetupContext<'a>)->crate::compat_worker::QNWorker<'a,TimedInstruction<WindowInstruction>>{
let mut window_context=self.into_context(setup_context); let mut window_context=self.into_context(setup_context);
crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<WindowInstruction>|{ crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<WindowInstruction>|{
match ins.instruction{ match ins.instruction{