Skip to content

Instantly share code, notes, and snippets.

@Thermatix
Last active July 30, 2021 21:56
Show Gist options
  • Save Thermatix/f545831da0c6202d1cb79e992dcd8fab to your computer and use it in GitHub Desktop.
Save Thermatix/f545831da0c6202d1cb79e992dcd8fab to your computer and use it in GitHub Desktop.
ruby interface DSL
//! This module defines the interface for describing entities in the ruby DSL
//! example:
//! ```ruby
//! entity_group 'basics' do # add new group to entity groups
//! kind :items # set default type
//! # set initial components that can be overridden later
//! components :pos, :loc, glyh: '$'
//!
//! entity 'sword' do # add entity to entity groyp
//! component :renderable do # add new component to entity
//! glyph 'i' # set glyph attribute, overiding default
//! bgColour Colours::White # set bgcolour attribute
//! fgColour Colours::Black # set fgColour attribute
//! end
//! end
//! end
//! ```
use std::collections::HashMap;
#[macro_use]
use super::*;
pub struct Component<'c> {
name: &'c str,
values: HashMap<&'c str, Value>,
}
impl<'c> Component<'c> {
pub fn new(name: &'c str) -> Component<'c> {
Self {
name,
values: HashMap::new(),
}
}
}
pub struct Entity<'e> {
name: &'e str,
kind: &'e str,
components: Vec<Component<'e>>,
}
impl<'e> Entity<'e> {
pub fn new(name: &'e str, kind: &'e str) -> Entity<'e> {
Self {
name,
kind,
components: Vec::new(),
}
}
}
pub struct EntityGroup<'eg> {
name: &'eg str,
kind: &'eg str,
entities: Vec<Entity<'eg>>,
}
impl<'eg> EntityGroup<'eg> {
pub fn new(name: &'eg str) -> EntityGroup<'eg> {
Self {
name,
kind: "",
entities: Vec::new(),
}
}
}
type EntityGroups<'egs> = Vec<EntityGroup<'egs>>;
add_to_ruby!(EntityGroups {
mrusty_class!(Component, "Component", {
def!("initialize", |mruby, slf: Value, c_name: (&str)| {
Component::new(c_name)
});
});
mrusty_class!(Entity, "Entity", {
def!("initialize", |mruby, slf: Value, e_name: (&str), e_kind: (&str)| {
Entity::new(e_name, e_kind)
});
});
mrusty_class!(EntityGroup, "EntityGroup", {
def!("initialize", |mruby, slf: Value, eg_name: (&str)| {
EntityGroup::new(eg_name)
});
def!("kind", |mruby, slf: Value, kind: (&str)| {
slf.set_value("kind", kind);
slf
});
def!("entity", |mruby, slf: Value, e_name: (&str); &block| {
let entity = mruby.run(format!("entity.new {}", e_name)).unwrap();
entity.call("instance_exec", &block);
slf.set_value("kind", kind);
slf
});
});
Component::require(mruby.clone());
Entity::require(mruby.clone());
EntityGroup::require(mruby.clone());
mruby.def_method(mruby.get_class("Object"), "entity_group", mrfn!(|mruby, slf: Value, eg_name: (&str); &block| {
let entity_group = mruby.run(format!("EntityGroup.new {}", eg_name)).unwrap();
entity_group.call("instance_exec", &block);
container.push(entity_group);
}));
});
use mrusty::*;
macro_rules! add_to_ruby {
($container_type:ident $function_body:block) => {
use crate::sys::State;
pub fn add_interface<'c>(mruby: &mut Mruby, state: &mut State) -> $container_type<'c> {
let container: $container_type = $container_type::new();
$function_body
container
}
}
}
pub mod entity;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment