1 个不稳定版本
0.1.0 | 2024 年 7 月 24 日 |
---|
#1091 在 游戏开发
123 每月下载量
23KB
416 行
🏷️ Moonshine Tag
为 Bevy 设计的廉价、快速、大部分唯一的标识符。
概述
Tag
代表一个廉价、通用、稍微唯一的标识符,可以用于将“事物”相互关联或用于动态标记实体。
use bevy::prelude::*;
use moonshine_tag::{prelude::*, self as tag};
tags! { APPLE, ORANGE, JUICY, CRUNCHY, POISONED }
let mut world = World::new();
// Spawn some fruits!
let a = world.spawn([APPLE, CRUNCHY].into_tags()).id();
let b = world.spawn([ORANGE, JUICY].into_tags()).id();
let c = world.spawn([APPLE, CRUNCHY, POISONED].into_tags()).id();
// Only crunchy, edible apples, please! :)
let filter: TagFilter = (APPLE & CRUNCHY) & !POISONED;
assert!(filter.allows(world.tags(a)));
assert!(!filter.allows(world.tags(b)));
assert!(!filter.allows(world.tags(c)));
功能
- 标签易于创建、复制、比较,并且“足够唯一”。它仅仅是一个
u64
。 - 支持标签和标签过滤器的序列化
- 能够定义复杂的标签过滤表达式
- 简单的实现,没有样板代码和过程宏 🧘
用法
标签
您可以从任何任意字符串定义标签
use moonshine_tag::prelude::*;
tags! { A0 }; // Convenient macro
const A1: Tag = Tag::new("A"); // Manual constant
let a2 = Tag::new("A"); // Runtime
assert_eq!(A0, A1);
assert_eq!(A0, a2);
具有相同名称的两个标签被认为是相等的。
Tags
是用于管理标签集合的专用集合
use moonshine_tag::prelude::*;
tags! { A, B, C }
let a: Tags = A.into_tags();
let ab = [A, B].into_tags();
let c = C.into_tags();
let ac = a.union(c);
标签过滤器
TagFilter
用于测试给定的 Tags
集合是否匹配某个模式
use moonshine_tag::prelude::*;
tags! { A, B, C }
let a = A.into_tags();
let c = C.into_tags();
let a_or_b: TagFilter = A | B;
assert!(a_or_b.allows(a));
assert!(!a_or_b.allows(c));
标签过滤器可以组合在一起以创建复杂的表达式
use moonshine_tag::prelude::*;
tags! { A, B, C, D }
let ab = [A, B].into_tags();
let c = C.into_tags();
let cd = [C, D].into_tags();
let filter = ([A, B] | C) & D;
assert!(!filter.allows(ab));
assert!(!filter.allows(c));
assert!(filter.allows(cd));
限制和指南
在内部,标签只是它们字符串表示的 FNV-1a (为什么?) 哈希。这使得它们非常廉价地使用,但这意味着它们 不能保证是唯一的。
该库的假设是,在大多数游戏应用领域,这是一个小而可能的问题。
在大多数应用程序中,同一子系统内两个不同标签之间的冲突可能性很低,非致命,并且容易纠正(只需重命名其中一个标签即可!)。
但是,您 不应 使用标签进行任何加密目的,或作为全局唯一标识符。
相反,最好将它们用于方便的动态模式匹配或标记系统中的“事物”,特别是实体。
依赖关系
~11MB
~194K SLoC