Skip to content

Objects — 其他类型

零散的值类型,以及一份全类型索引。

类型别名

rust
pub type PositionI32 = (i32, i32, i32);
pub type PositionF64 = (f64, f64, f64);
pub type Actor = Entity;
pub type Result<T> = std::result::Result<T, Error>;

坐标就是元组,没有包装成结构体——省掉一层 .x .y .z,解构也方便:

rust
let (x, y, z) = actor.pos()?;

Error

rust
pub struct Error(pub String);

一个字符串。可以从 String&str 直接转,实现了 std::error::Error

Err 通常表示「没找着」,不是「出错了」

player.xxx() 返回 Err 几乎总是因为玩家下线了;actor.xxx() 是因为实体没了;block.xxx() 是因为区块没加载。

所以下面这种写法是正常的,不是在吞错误:

rust
if let Ok(hp) = actor.health() {
    // 实体还在
}

ModContext

生命周期钩子拿到的入口对象。没有自己的状态,复制很便宜。

API返回可用性
ctx.logger()Logger两边
ctx.packets()Packets两边
ctx.server()Serverserver 特性
ctx.client()Clientclient 特性

LeviMod

rust
pub trait LeviMod: Sized + 'static {
    fn on_load(ctx: &ModContext) -> Result<Self>;
    fn on_enable(&mut self, ctx: &ModContext) -> Result<()> { Ok(()) }
    fn on_disable(&mut self, ctx: &ModContext) -> Result<()> { Ok(()) }
    fn on_unload(&mut self, ctx: &ModContext) -> Result<()> { Ok(()) }
}

on_load 外都有默认空实现。

所有钩子在服务器线程运行,模组实例也只被服务器线程碰,所以可以放心持有 !Send 的东西,比如 Listener

配合 register_mod!(MyMod) 宏使用,一个模组写一次。

RAII 句柄一览

四种回调句柄,行为完全一致——drop 就注销,.forget() 就活到模组卸载:

类型来自注销什么
Listenersubscribe_event事件订阅
Subscriptionbus::subscribe总线订阅
Registrationservice::register服务注册
PacketHookpackets().intercept包拦截器

统一成一套习惯,比每个地方各有各的巧妙设计有用。

忘了接返回值 = 立刻失效

rust
ctx.server().subscribe_event(...)?;      // ❌ 当场 drop,订阅没了
ctx.server().subscribe_event(...)?.forget();   // ✅

编译器会给 unused_must_use 警告。

money::on_before / on_after 返回的 guard 也是同样的用法,但语义特殊,见 Money

枚举速查

枚举取值在哪
EventPriorityHighest=0 High=1 Normal=2 Low=3 Lowest=4Event
LogLevelFatal=0 Error=1 Warn=2 Info=3 Debug=4 Trace=5Log
GameModeSurvival=0 Creative=1 Adventure=2 Spectator=6Player
MessageTypeRaw=0 … TextObjectAnnouncement=11Player
TitleKindClear=0 Reset=1 Title=2 Subtitle=3 Actionbar=4 Times=5Player
AbilityBuild=0 … VerticalFlySpeed=19Player
CommandPermissionAny=0 GameDirectors=1 Admin=2 Host=3 Owner=4Command
ParamTypeInt Bool Float String … FilePath(21 种)Command
SoftEnumOpSet=0 Add=1 Remove=2Command
WeatherClear=0 Rain=1 Thunder=2Server
GamingStatusDefault Starting Running StoppingServer
DisplaySlotSidebar List BelowNameScoreboard
FormValueInt Float Text ChoiceGui
FormResponseCancelled Button Custom ModalGui
NbtValueByte … LongArray(12 种)Nbt
NbtBinaryFormatDisk=0 Network=1Nbt
DirectionInbound Outbound BothPacket
VerdictForward DropPacket
ConnectionStateOpened ClosedPacket
CallErrorNotFound Provider Refused UnknownService
GeneratorTypeOverworld=1 Flat=2 Nether=3 TheEnd=4 Void=5Dimensions
DimensionRuleSpawnMonster=0 … EntityCrossPlot=12Dimensions
KeyActionUp=0 Down=1Client

值类型速查

结构体字段
PlayerInfoname xuid uuid dimension pos
PlayerIdentityname xuid uuid
EntityIdid type_name
CommandResultsuccess output
CommandOriginname origin_type dimension position
Objectivename display_name
TitleTimesfade_in stay fade_out
PlayerPosx y z dim
BlockInfoname snbt
EntityInfokind snbt
Cellblock entities
ScanLayery cells
Scanmin max layers
Boundsmin max
VillageInfouuid center bounds poi_count
StructureInfokind bounds
LocalTimeyear month day hour minute second ms
Vetoablerefused delivered
ServiceInfoname owner
MoneyEventkind from to amount
PlotLayoutplot_size road_width border_width floor_y floor_block fill_block road_block border_block biome
PlotMergex z mask