Skip to content

Commit bc9b207

Browse files
committed
keep working on docs and fixing bugs
1 parent 1cac0aa commit bc9b207

File tree

26 files changed

+1875
-117
lines changed

26 files changed

+1875
-117
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ clap = { version = "4.1", features = ["derive"] }
7979
rand = "0.8.5"
8080
bevy_console = "0.13"
8181
rhai-rand = "0.1"
82+
ansi-parser = "0.9"
8283

8384
[workspace]
8485
members = [

assets/scripts/game_of_life.lua

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,63 @@
1-
math.randomseed(os.time())
2-
3-
function init()
4-
local LifeState = world.get_type_by_name("LifeState")
5-
local life_state = world.get_component(entity,LifeState)
6-
local cells = life_state.cells
7-
8-
-- set some cells alive
9-
for _=1,10000 do
10-
local index = math.random(#cells)
11-
cells[index] = 255
12-
end
1+
-- print("The game_of_life.lua script just got loaded")
2+
-- print("Hello from Lua! I am initiating the game of life simulation state to a random state now")
3+
4+
-- math.randomseed(os.time())
5+
-- _LifeState = world.get_type_by_name("LifeState")
6+
_Settings = world.get_type_by_name("Settings")
7+
8+
-- function fetch_life_state()
9+
-- -- find the entity with life state
10+
-- local life_state = nil
11+
-- for i,result in pairs(world.query({_LifeState}):build()) do
12+
-- life_state = result:components()[1]
13+
-- break
14+
-- end
15+
-- return life_state
16+
-- end
17+
18+
function on_init()
19+
-- print("On init was called")
20+
-- local life_state = fetch_life_state()
21+
-- local cells = life_state.cells
22+
23+
-- -- set some cells alive
24+
-- for _=1,10000 do
25+
-- local index = math.random(#cells)
26+
-- cells[index] = 255
27+
-- end
1328
end
1429

1530
function on_update()
16-
local LifeState = world.get_type_by_name("LifeState")
17-
local Settings = world.get_type_by_name("Settings")
18-
19-
local life_state = world.get_component(entity,LifeState)
20-
-- note currently this is a copy of the cells, as of now the macro does not automatically support Vec<T> proxies by reference
21-
local cells = life_state.cells
22-
23-
-- note that here we do not make use of LuaProxyable and just go off pure reflection
24-
local settings = world.get_resource(Settings)
25-
local dimensions = settings.physical_grid_dimensions
26-
27-
28-
-- primitives are passed by value to lua, keep a hold of old state but turn 255's into 1's
29-
local prev_state = {}
30-
for k,v in pairs(cells) do
31-
prev_state[k] = (not(v == 0)) and 1 or 0
32-
end
33-
34-
for i=1,(dimensions[1] * dimensions[2]) do
35-
local north = prev_state[i - dimensions[1]] or 1
36-
local south = prev_state[i + dimensions[1]] or 1
37-
local east = prev_state[i + 1] or 1
38-
local west = prev_state[i - 1] or 1
39-
local northeast = prev_state[i - dimensions[1] + 1] or 1
40-
local southeast = prev_state[i + dimensions[1] + 1] or 1
41-
local northwest = prev_state[i - dimensions[1] - 1] or 1
42-
local southwest = prev_state[i + dimensions[1] - 1] or 1
43-
44-
local neighbours = north + south + east + west
45-
+ northeast + southeast + northwest + southwest
31+
-- local cells = fetch_life_state().cells
32+
local settings = world.get_resource(_Settings)
33+
-- local dimensions = settings.physical_grid_dimensions
34+
-- local dimension_x = dimensions._1
35+
-- local dimension_y = dimensions._2
36+
37+
-- -- primitives are passed by value to lua, keep a hold of old state but turn 255's into 1's
38+
-- local prev_state = {}
39+
-- for k,v in pairs(cells) do
40+
-- prev_state[k] = (not(v == 0)) and 1 or 0
41+
-- end
42+
-- for i=1,(dimension_x * dimension_y) do
43+
-- local north = prev_state[i - dimension_x] or 1
44+
-- local south = prev_state[i + dimension_x] or 1
45+
-- local east = prev_state[i + 1] or 1
46+
-- local west = prev_state[i - 1] or 1
47+
-- local northeast = prev_state[i - dimension_x + 1] or 1
48+
-- local southeast = prev_state[i + dimension_x + 1] or 1
49+
-- local northwest = prev_state[i - dimension_x - 1] or 1
50+
-- local southwest = prev_state[i + dimension_x - 1] or 1
51+
52+
-- local neighbours = north + south + east + west
53+
-- + northeast + southeast + northwest + southwest
4654

47-
-- was dead and got 3 neighbours now
48-
if prev_state[i] == 0 and neighbours == 3 then
49-
cells[i] = 255
50-
-- was alive and should die now
51-
elseif prev_state[i] == 1 and ((neighbours < 2) or (neighbours > 3)) then
52-
cells[i] = 0
53-
end
54-
end
55-
56-
-- propagate the updates
57-
life_state.cells = cells
55+
-- -- was dead and got 3 neighbours now
56+
-- if prev_state[i] == 0 and neighbours == 3 then
57+
-- cells[i] = 255
58+
-- -- was alive and should die now
59+
-- elseif prev_state[i] == 1 and ((neighbours < 2) or (neighbours > 3)) then
60+
-- cells[i] = 0
61+
-- end
62+
-- end
5863
end

crates/bevy_mod_scripting_core/src/bindings/allocator.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ use bevy::reflect::{PartialReflect, Reflect};
33
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
44
use std::any::{Any, TypeId};
55
use std::cell::UnsafeCell;
6+
use std::cmp::Ordering;
67
use std::collections::HashMap;
78
use std::fmt::{Display, Formatter};
9+
use std::hash::Hasher;
810
use std::io::Read;
911
use std::sync::Arc;
1012

11-
#[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
13+
#[derive(Clone, Debug)]
1214
pub struct ReflectAllocationId(pub(crate) Arc<usize>);
1315
impl ReflectAllocationId {
1416
pub fn id(&self) -> usize {
@@ -25,6 +27,32 @@ impl ReflectAllocationId {
2527
}
2628
}
2729

30+
impl std::hash::Hash for ReflectAllocationId {
31+
fn hash<H: Hasher>(&self, state: &mut H) {
32+
self.id().hash(state);
33+
}
34+
}
35+
36+
impl PartialEq for ReflectAllocationId {
37+
fn eq(&self, other: &Self) -> bool {
38+
self.id() == other.id()
39+
}
40+
}
41+
42+
impl Eq for ReflectAllocationId {}
43+
44+
impl PartialOrd for ReflectAllocationId {
45+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
46+
Some(self.id().cmp(&other.id()))
47+
}
48+
}
49+
50+
impl Ord for ReflectAllocationId {
51+
fn cmp(&self, other: &Self) -> Ordering {
52+
self.id().cmp(&other.id())
53+
}
54+
}
55+
2856
/// Pointer which owns the value it points to, and will deallocate it when dropped
2957
#[derive(Debug)]
3058
pub struct OwningPtr<T: ?Sized> {
@@ -193,7 +221,15 @@ impl ReflectAllocator {
193221
/// Runs a garbage collection pass on the allocations, removing any allocations which have no more strong references
194222
/// Needs to be run periodically to prevent memory leaks
195223
pub fn clean_garbage_allocations(&mut self) {
196-
self.allocations.retain(|k, _| Arc::strong_count(&k.0) > 1);
224+
bevy::log::debug!("Cleaning garbage allocations");
225+
226+
self.allocations.retain(|k, _| {
227+
let retain = Arc::strong_count(&k.0) > 1;
228+
if !retain {
229+
bevy::log::debug!("Deallocating allocation {:?}", k);
230+
}
231+
retain
232+
});
197233
}
198234
}
199235

crates/bevy_mod_scripting_core/src/bindings/function/from.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,10 @@ impl<T: FromReflect> FromScript for Val<T> {
182182
T::from_reflect(r).ok_or_else(|| {
183183
InteropError::failed_from_reflect(
184184
Some(TypeId::of::<T>()),
185-
format!("from reflect failed to produce output when converting to Val<T> from: {r:?}")
186-
.to_owned(),
185+
format!(
186+
"Expected '{}' but receievd: {r:?}",
187+
std::any::type_name::<T>()
188+
),
187189
)
188190
})
189191
},

crates/bevy_mod_scripting_core/src/bindings/function/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,19 @@ impl CallScriptFunction for DynamicScriptFunction {
4646
) -> Result<ScriptValue, InteropError> {
4747
let args = args.into_iter().collect::<Vec<_>>();
4848
let world_callback_access = WorldCallbackAccess::from_guard(world.clone());
49+
bevy::log::debug!(
50+
"Calling function {} with args {:?}",
51+
self.name(),
52+
args.display_with_world(world.clone())
53+
);
4954
// should we be inlining call errors into the return value?
5055
let return_val = self.call(context, world_callback_access, args);
5156
match return_val {
52-
ScriptValue::Error(e) => Err(InteropError::function_interop_error(self.name(), e)),
57+
ScriptValue::Error(e) => Err(InteropError::function_interop_error(
58+
self.name(),
59+
context.self_type,
60+
e,
61+
)),
5362
v => Ok(v),
5463
}
5564
}
@@ -67,7 +76,11 @@ impl CallScriptFunction for DynamicScriptFunctionMut {
6776
// should we be inlining call errors into the return value?
6877
let return_val = self.call(context, world_callback_access, args);
6978
match return_val {
70-
ScriptValue::Error(e) => Err(InteropError::function_interop_error(self.name(), e)),
79+
ScriptValue::Error(e) => Err(InteropError::function_interop_error(
80+
self.name(),
81+
context.self_type,
82+
e,
83+
)),
7184
v => Ok(v),
7285
}
7386
}

crates/bevy_mod_scripting_core/src/bindings/function/script_function.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use bevy::{
1616
},
1717
};
1818
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
19-
use std::borrow::Cow;
2019
use std::collections::HashMap;
2120
use std::hash::Hash;
2221
use std::ops::{Deref, DerefMut};
2322
use std::sync::Arc;
23+
use std::{any::TypeId, borrow::Cow};
2424

2525
#[diagnostic::on_unimplemented(
2626
message = "Only functions with all arguments impplementing FromScript and return values supporting IntoScript are supported. Registering functions also requires they implement GetInnerTypeDependencies",
@@ -96,8 +96,8 @@ macro_rules! register_tuple_dependencies {
9696
};
9797
}
9898

99-
no_type_dependencies!(ReflectReference, InteropError);
100-
self_type_dependency_only!(WorldCallbackAccess, CallerContext);
99+
no_type_dependencies!(InteropError);
100+
self_type_dependency_only!(WorldCallbackAccess, CallerContext, ReflectReference);
101101

102102
recursive_type_dependencies!(
103103
(Val<T> where T: GetTypeRegistration),
@@ -118,8 +118,10 @@ pub trait GetFunctionTypeDependencies<Marker> {
118118
/// The caller context when calling a script function.
119119
/// Functions can choose to react to caller preferences such as converting 1-indexed numbers to 0-indexed numbers
120120
#[derive(Clone, Copy, Debug, Reflect)]
121+
#[reflect(opaque)]
121122
pub struct CallerContext {
122123
pub convert_to_0_indexed: bool,
124+
pub self_type: Option<TypeId>,
123125
}
124126

125127
/// The Script Function equivalent for dynamic functions. Currently unused

crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl ReflectReferencePrinter {
7676
let base_kind = match base.base_id {
7777
ReflectBase::Component(e, _) => format!("Component on entity {}", e),
7878
ReflectBase::Resource(_) => "Resource".to_owned(),
79-
ReflectBase::Owned(_) => "Allocation".to_owned(),
79+
ReflectBase::Owned(ref id) => format!("Allocation({})", id),
8080
};
8181

8282
out.push_str(&format!("{}({})", base_kind, type_path));
@@ -328,7 +328,7 @@ macro_rules! impl_dummy_display (
328328
($t:ty) => {
329329
impl std::fmt::Display for $t {
330330
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
331-
write!(f, "Displaying {} without world access: {:#?}", stringify!($t), self)?;
331+
write!(f, "<use display_with_world instead: {:#?}>", stringify!($t))?;
332332
Ok(())
333333
}
334334
}
@@ -403,7 +403,7 @@ impl DisplayWithWorld for ScriptValue {
403403
ScriptValue::Integer(i) => i.to_string(),
404404
ScriptValue::Float(f) => f.to_string(),
405405
ScriptValue::String(cow) => cow.to_string(),
406-
ScriptValue::Error(script_error) => script_error.to_string(),
406+
ScriptValue::Error(script_error) => script_error.display_with_world(world),
407407
ScriptValue::List(vec) => {
408408
let mut string = String::new();
409409
ReflectReferencePrinter::pretty_print_key_values(
@@ -417,3 +417,31 @@ impl DisplayWithWorld for ScriptValue {
417417
}
418418
}
419419
}
420+
421+
impl<T: DisplayWithWorld> DisplayWithWorld for Vec<T> {
422+
fn display_with_world(&self, world: WorldGuard) -> String {
423+
let mut string = String::new();
424+
BracketType::Square.surrounded(&mut string, |string| {
425+
for (i, v) in self.iter().enumerate() {
426+
string.push_str(&v.display_with_world(world.clone()));
427+
if i != self.len() - 1 {
428+
string.push_str(", ");
429+
}
430+
}
431+
});
432+
string
433+
}
434+
435+
fn display_value_with_world(&self, world: WorldGuard) -> String {
436+
let mut string = String::new();
437+
BracketType::Square.surrounded(&mut string, |string| {
438+
for (i, v) in self.iter().enumerate() {
439+
string.push_str(&v.display_value_with_world(world.clone()));
440+
if i != self.len() - 1 {
441+
string.push_str(", ");
442+
}
443+
}
444+
});
445+
string
446+
}
447+
}

crates/bevy_mod_scripting_core/src/bindings/query.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,33 @@ impl<'w> WorldAccessGuard<'w> {
132132
// which entities match the query
133133
// so we might be being slightly overkill
134134
for c in &query.components {
135-
dynamic_query.ref_id(c.component_id().unwrap());
135+
dynamic_query.ref_id(c.component_id().ok_or_else(|| {
136+
InteropError::unsupported_operation(
137+
Some(c.type_id()),
138+
None,
139+
"query for component on non-component type".to_owned(),
140+
)
141+
})?);
136142
}
137143

138144
for w in query.with {
139-
dynamic_query.with_id(w.component_id.unwrap());
145+
dynamic_query.with_id(w.component_id.ok_or_else(|| {
146+
InteropError::unsupported_operation(
147+
Some(w.type_id()),
148+
None,
149+
"query for entity with component which is non-component type".to_owned(),
150+
)
151+
})?);
140152
}
141153

142154
for without_id in query.without {
143-
dynamic_query.without_id(without_id.component_id.unwrap());
155+
dynamic_query.without_id(without_id.component_id.ok_or_else(|| {
156+
InteropError::unsupported_operation(
157+
Some(without_id.type_id()),
158+
None,
159+
"query for entity without component which is non-component type".to_owned(),
160+
)
161+
})?);
144162
}
145163

146164
let mut built_query = dynamic_query.build();

crates/bevy_mod_scripting_core/src/bindings/reference.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ impl ReflectReference {
218218
///
219219
/// # Panics
220220
/// - if the value is aliased and the access is not allowed
221+
#[track_caller]
221222
pub fn with_reflect<O, F: FnOnce(&dyn PartialReflect) -> O>(
222223
&self,
223224
world: WorldGuard,
@@ -238,6 +239,7 @@ impl ReflectReference {
238239
///
239240
/// # Panics
240241
/// - if the value is aliased and the access is not allowed
242+
#[track_caller]
241243
pub fn with_reflect_mut<O, F: FnOnce(&mut dyn PartialReflect) -> O>(
242244
&self,
243245
world: WorldGuard,

0 commit comments

Comments
 (0)