This commit is contained in:
2026-01-27 01:05:33 +00:00
parent f3d258cbc9
commit bb80172fe1
3 changed files with 146 additions and 48 deletions

7
Cargo.lock generated
View File

@@ -309,6 +309,7 @@ dependencies = [
"bevy",
"include_dir",
"mlua",
"nameof",
]
[[package]]
@@ -2933,6 +2934,12 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "nameof"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae5794a00611c89e072a2d8bd5164c410a96181f1f7f40676c94293d44af1401"
[[package]]
name = "ndk"
version = "0.8.0"

View File

@@ -7,6 +7,7 @@ edition = "2024"
bevy = { version = "0.16", features = ["file_watcher"] }
include_dir = "0.7.4"
mlua = { version = "0.11.5", features = ["luau","luau-jit","luau-vector4","serde","send"] }
nameof = "1.3.0"
[profile.dev.package."*"]
opt-level = 3

View File

@@ -1,76 +1,166 @@
use mlua::UserData;
use mlua::Lua;
use bevy::prelude::*;
use mlua::UserDataFields;
use mlua::UserDataMethods;
use nameof::name_of_type;
use std::ops::Deref;
use std::ops::DerefMut;
use include_dir::{include_dir, Dir};
static DATA_DIR: Dir<'_> = include_dir!("data");
/*
In lieu of the old Roblox instances.
Instances, at least for the sake of bevy's design,
are helper components that also implement a lua userdata wrapper.
I'm sure storing the Entity in the component is bad practice,
but I can't find a cleaner way of integrating with Bevy's ECS like this.
*/
trait Instance: UserData {
struct BevyContext<'a> {
commands: Commands<'a, 'a>
}
impl<'a> BevyContext<'a> {
fn from_raw(commands: Commands<'a,'a>) -> Self {
BevyContext { commands: commands }
}
/*fn get_instance<T>(&self, entity: Entity) -> &T {
self.commands.entity(entity).
}*/
}
struct Script {
name: String
}
impl Instance for Script {
// Id for this object to the server
struct Netlink {
}
struct Context {
name: String,
lua: Lua
}
impl Instance for Context {
}
struct Part {
name: String
}
impl Instance for Part {
}
struct Folder {
name: String
}
impl Instance for Folder {
trait Class {
// Class name for filtering
fn class_name() -> String { name_of_type!(Self).into() }
// Create a default object
fn new_entity<'a>(context: &BevyContext) -> (EntityCommands<'a>, Self);
// fn clone(&self) -> Self;
fn add_fields<T, F: UserDataFields<T>>(_fields: &mut F) {}
fn add_methods<T, F: UserDataMethods<T>>(_methods: &mut F) {}
}
#[derive(Component)]
struct Instance<S: Class> {
name: String,
class: S,
entity: Entity,
netlink: Netlink
}
impl<S: Class> UserData for Instance<S> {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
S::add_fields::<Self,F>(fields);
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
S::add_methods::<Self,M>(methods);
}
}
impl<S: Class> Instance<S> {
fn new(context: &BevyContext) -> Self {
let (entity,sub) = S::new_entity(context);
Instance {
name: S::class_name(),
class: sub,
entity: entity.id(),
netlink: Netlink {},
}
}
}
struct Constructor;
impl UserData for Constructor {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("part", |lua, this, ()| {
let part = IPart::new()
});
}
}
#[derive(Resource)]
struct ScriptContext {
lua: Lua
}
impl Class for ScriptContext {
fn new_entity(context: &BevyContext) -> (EntityCommands<'_>,Self) {
( context.commands.spawn_empty(), ScriptContext::new() )
}
}
impl ScriptContext {
fn new() -> Self {
let lua = Lua::new();
lua.sandbox(true);
let globals = lua.globals();
globals.set("new",Constructor);
ScriptContext { lua: lua }
}
}
struct Script {
context: Entity
}
impl Class for Script {
fn new_entity(context: &BevyContext) -> (Entity, Self) {
( context.)
}
}
// Attachment
struct Node;
impl Class for Node {}
struct Part {
}
impl Class for Part {
fn new_entity(context: &BevyContext) -> Self {
commands.spawn()
}
}
impl UserData for Part {}
struct Located<S: Class> {
class: S
}
impl<S: Class> UserData for Located<S> {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
S::add_fields(fields);
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
S::add_methods(methods);
}
}
impl<S: Class> Class for Located<S> {
fn new_entity(context: &BevyContext) -> Self {
let (entity,sub) = S::new_entity(context);
Located { class: S::new_entity(context), }
}
}
type IAttachment = Instance<Located<Node>>;
type IModel = Instance<Located<Node>>;
type IPart = Instance<Located<Part>>;
type IContext = Instance<ScriptContext>;
type IScript = Instance<Script>;
type IFolder = Instance<Node>;
#[derive(Component)]
enum AnyInstance {
Context(Context),
Script(Script),
Part(Part)
Attachment(IAttachment),
Context(IContext),
Folder(IFolder),
Script(IScript),
Model(IModel),
Part(IPart)
}
fn script_executor() {
}
fn collision_detector() {
}
pub struct DuckPlugin;
impl Plugin for DuckPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update,(script_executor,collision_detector));
app.add_systems(Update,(script_executor));
app.insert_resource(ScriptContext::new_entity())
}
}