Skip to content

Commit

Permalink
attempted some stuff on the jewel store thing
Browse files Browse the repository at this point in the history
  • Loading branch information
meadowsys committed Nov 12, 2024
1 parent 7e51a01 commit 70d9a88
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 79 deletions.
146 changes: 118 additions & 28 deletions src/vh/jewel.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
extern crate hashbrown;

use crate::prelude_std::*;
use crate::num::*;
use crate::rc::{ RcStr, Counter };
use crate::rc::{ RcStr, Counter, AtomicCounter };
use hashbrown::HashSet;

pub mod store;
struct JewelStore<C: Counter = AtomicCounter> {
modifiers: HashSet<Modifier<C>>,
jewels: Vec<Jewel<C>>
}

struct Modifier<N: Name = String> {
name: N,
ty: ModifierType,
value: ModifierValue
struct Jewel<C: Counter = AtomicCounter> {
level: u16,
size: i16,
modifiers: JewelModifiers<C>
}

pub trait Name {
fn as_str(&self) -> &str;
enum JewelModifiers<C: Counter = AtomicCounter> {
Chipped([ModifierInstance<C>; 1]),
Flawed([ModifierInstance<C>; 2]),
Flawless([ModifierInstance<C>; 3]),
Perfect([ModifierInstance<C>; 4])
}

macro_rules! impl_name_via_deref {
{ [$($generics:tt)*] $($stuff:tt)+ } => {
impl<$($generics)*> Name for $($stuff)+ {
#[inline]
fn as_str(&self) -> &str { self }
}
}
struct ModifierInstance<C: Counter = AtomicCounter> {
modifier: Modifier<C>,
value: ModifierValue
}

impl_name_via_deref! { [] String }
impl_name_via_deref! { [] &str }
impl_name_via_deref! { [] Box<str> }
impl_name_via_deref! { [] Rc<str> }
impl_name_via_deref! { [C: Counter, M] RcStr<C, M> }
struct Modifier<C: Counter = AtomicCounter> {
inner: RcStr<C, ModifierMeta<C>>
}

struct ModifierMeta<C: Counter = AtomicCounter> {
display_name: RcStr<C>,
modifier_type: ModifierType
}

/// Type of modifier (flag or with numeric value, and associated
/// metadata if applicable)
Expand All @@ -51,27 +59,109 @@ enum ModifierType {
}

/// The value of a modifier, including whether or not the modifier is legendary
pub struct ModifierValue {
struct ModifierValue {
/// The highest bit stores if the modifier is legendary, and the rest store
/// the modifier's value (if applicable)
raw: i32
}

impl JewelStore {
#[inline]
fn new() -> Self {
Self::with_counter()
}

#[inline]
fn with_counter<C: Counter>() -> JewelStore<C> {
JewelStore {
modifiers: HashSet::new(),
jewels: Vec::new()
}
}
}

impl<C: Counter> JewelStore<C> {
/// Register a modifier by its identifier, return [`Ok`] if added and [`Err`]
/// if the modifier already exists
#[inline]
fn add_modifier(&mut self, id: &str, display_name: &str, modifier_type: ModifierType) -> Result<(), ()> {
if self.modifiers.get(id).is_none() {
let modifier = Modifier::new(id, display_name, modifier_type);

// SAFETY: just checked `id` is not in set
unsafe {
self.modifiers.insert_unique_unchecked(modifier);
}

Ok(())
} else {
Err(())
}
}
}

impl<C: Counter> Modifier<C> {
/// Create new modifier
///
/// This will always allocate, as it has no knowledge of existing modifier
/// instances. Clone an existing modifier instance if you want to reuse
/// the allocation.
#[inline]
fn new(id: &str, display_name: &str, modifier_type: ModifierType) -> Self {
Self {
inner: RcStr::with_metadata(id, ModifierMeta {
display_name: RcStr::new(display_name),
modifier_type
})
}
}
}

impl<C: Counter> Borrow<str> for Modifier<C> {
#[inline]
fn borrow(&self) -> &str {
&self.inner
}
}

impl<C: Counter> Clone for Modifier<C> {
#[inline]
fn clone(&self) -> Self {
Self { inner: self.inner.clone() }
}
}

impl<C: Counter, C2: Counter> PartialEq<Modifier<C2>> for Modifier<C> {
#[inline]
fn eq(&self, other: &Modifier<C2>) -> bool {
*self.inner == *other.inner
}
}

impl<C: Counter> Eq for Modifier<C> {}

impl<C: Counter> Hash for Modifier<C> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&*self.inner, state)
}
}

impl ModifierValue {
/// Maximum storable modifier value
pub const MAX: i32 = i32::MAX >> 1;
const MAX: i32 = i32::MAX >> 1;

/// Minimum storable modifier value (negative)
pub const MIN: i32 = i32::MIN >> 1;
const MIN: i32 = i32::MIN >> 1;

#[inline]
pub fn new(value: i32, is_legendary: bool) -> Self {
fn new(value: i32, is_legendary: bool) -> Self {
Self::new_checked(value, is_legendary)
.expect("modifier value out of bounds")
}

#[inline]
pub fn new_checked(value: i32, is_legendary: bool) -> Option<Self> {
fn new_checked(value: i32, is_legendary: bool) -> Option<Self> {
(Self::MIN..=Self::MAX).contains(&value).then(|| {
// SAFETY: we just checked we're within the allowed range
unsafe { Self::new_unchecked(value, is_legendary) }
Expand All @@ -82,19 +172,19 @@ impl ModifierValue {
///
/// `value` must be within the range `MIN..=MAX`
#[inline]
pub unsafe fn new_unchecked(value: i32, is_legendary: bool) -> Self {
unsafe fn new_unchecked(value: i32, is_legendary: bool) -> Self {
Self { raw: value | (is_legendary.into_i32() << 31) }
}

#[inline]
pub fn value(&self) -> i32 {
fn value(&self) -> i32 {
// first shift left one to push out the legendary bit, then
// (arithmetic) shift right one to bring back the bit with correct sign
(self.raw << 1) >> 1
}

#[inline]
pub fn is_legendary(&self) -> bool {
fn is_legendary(&self) -> bool {
self.raw >> 31 == 1
}
}
51 changes: 0 additions & 51 deletions src/vh/jewel/store.rs

This file was deleted.

0 comments on commit 70d9a88

Please sign in to comment.