Hey, so I didn’t really make a big scene about this initially, I think I got 2 comments… but I’ve been doing a huge amount of work on Mimic over the past months.
Its first incarnation was more of a Swiss army knife for the IC, wrapping most of the ic-cdk functions and auto-generating code via a build.rs script. I wanted a framework that would allow us to do most of the heavy lifting for canisters. It became too slow, unwieldy, and made too many assumptions about how developers develop.
I’ve stripped it down to be a data modelling, query language with a focus on types and validation. It does have a re-exported ic crate but it’s optional. I’ve thrown in a few helper functions that help our specific use case.
Error mapping has been a huge pain, especially things like call:: because RejectionCode doesn’t derive anything useful. The latest update means that there’s one single error enum, like the Diesel framework.
This is the only open source thing Im ever going to do, because it’s an absolutely indispensible tool that I need to create Dragginz.
Anyway please check it out, I’d like nothing more than people to deep dive and provide feedback. I want to emphasise that …
THE DOCUMENTATION IS OUT OF DATE AND AWFUL
but a few code snippets here can help understand what im trying to create
use api::prelude::*;
use design::{
config::{
api::manifest::component::{CharacterCreator, WorldBuilder},
game::Rarity,
},
db::config::registry::Feature as RegistryFeature,
};
use game::Error;
use mimic::{prelude::*, types::SortDirection};
// mimic
mimic_start!("../../../mimic.toml");
mimic_memory_manager!(MEMORY_MANAGER);
mimic_stores!(MEMORY_MANAGER, CONFIG_STORE, 10);
#[init]
fn init() {
mimic_init();
}
//
// ENDPOINTS
//
// rarities
// for testing
#[query(guard = "guard_query")]
pub fn rarities() -> Result<Vec<Rarity>, Error> {
perf!();
let rarities =
mimic::query::load::<Rarity>().debug().all().execute(&CONFIG_STORE)?.entities().collect();
Ok(rarities)
}
// rarities_query
// for testing
#[query(guard = "guard_query")]
pub fn rarities_query(
filter: String,
order: Vec<(String, SortDirection)>,
offset: u32,
limit: Option<u32>,
) -> Result<Vec<Rarity>, Error> {
perf!();
let rarities = mimic::query::load::<Rarity>()
.debug()
.all()
.offset(offset)
.filter_all(&filter)
.order(order)
.limit_option(limit)
.execute(&CONFIG_STORE)?
.entities()
.collect();
Ok(rarities)
}
///
/// Rarity
///
/// affects the chance of an item dropping or an event occurring
///
/// order : frontend logic to see which order they come in, common lowest
/// and rarest highest
///
#[entity(
sk(entity = "Rarity", field = "id"),
fields(
field(name = "id", value(item(is = "Ulid"), default = "Ulid::generate")),
field(name = "name", value(item(is = "game::text::Name"))),
field(name = "description", value(item(is = "game::text::Description"))),
field(name = "level", value(item(is = "U8"))),
field(name = "color", value(item(is = "types::color::RgbHex"))),
field(name = "key", value(item(is = "game::client::Key"))),
order(field = "level", direction = "asc"),
),
traits(remove(EntityFixture))
)]
pub struct Rarity {}
impl EntityFixture for Rarity {
fn fixtures() -> FixtureList {
use RarityId as Id;
let data = [
(Id::Common, "Common", "ffffff", "common"),
(Id::Uncommon, "Uncommon", "1eff00", "uncommon"),
(Id::Rare, "Rare", "0070dd", "rare"),
(Id::Epic, "Epic", "a335ee", "epic"),
(Id::Legendary, "Legendary", "ff8000", "legendary"),
(Id::Mythical, "Mythical", "e6cc80", "mythical"),
(Id::Inconceivable, "Inconceivable", "ef0a6a", "inconceivable"),
];
let mut fixtures = FixtureList::new();
for (id, name, color, key) in data {
fixtures.push(Self {
id: id.into(),
name: name.into(),
color: color.into(),
key: key.into(),
..Default::default()
});
}
fixtures
}
}
///
/// RarityId
///
#[entity_id(
key = "Common",
key = "Uncommon",
key = "Rare",
key = "Epic",
key = "Legendary",
key = "Mythical",
key = "Inconceivable"
)]
pub struct RarityId {}
I’ll keep working on it, updating the forums. Help will be absolutely insanely appreciated.
Adam