奖杯系统(25 种生物奖杯)
基本信息
奖杯方块 OpenBlocks:trophy 是一个单个方块 + 25 个 meta 的组合:meta 决定奖杯的生物种类,每种生物有独立的缩放、垂直偏移与可选行为。
| 属性 | 值 | 位置 |
|---|---|---|
| 注册名 | OpenBlocks:trophy |
OpenBlocks.java:295 |
| 方块类 | openblocks.common.block.BlockTrophy |
— |
| TileEntity | openblocks.common.tileentity.TileEntityTrophy |
OpenBlocks.java:295 |
| ItemBlock | openblocks.common.item.ItemTrophyBlock |
OpenBlocks.java:295 |
| 枚举 | openblocks.common.TrophyHandler.Trophy |
TrophyHandler.java:95-235 |
| 行为接口 | openblocks.trophy.ITrophyBehavior |
trophy/ITrophyBehavior.java:7 |
| 行为实现 | 10 个 | trophy/ 目录(11 个文件 = 10 实现 + 1 接口) |
「25 种」经两种方式核对:
Trophy枚举体(TrophyHandler.java:97-146)中形如^ [A-Z]\w*\s*[({,]的常量声明行计数 = 25;同一区间的另一种宽松正则计数 = 25。一致。
功能
25 种奖杯
Trophy 枚举(TrophyHandler.java:97-146),括注为构造参数(scale、verticalOffset、behavior):
| # | 常量 | 行 | 参数 | 特殊行为 |
|---|---|---|---|---|
| 0 | Wolf |
:97 |
无 | — |
| 1 | Chicken |
:98 |
ItemDropBehavior(10000, egg, "mob.chicken.plop") |
激活时掉鸡蛋并播 mob.chicken.plop |
| 2 | Cow |
:99 |
ItemDropBehavior(20000, leather) |
激活时掉皮革 |
| 3 | Creeper |
:100 |
CreeperBehavior |
苦力怕行为 |
| 4 | Skeleton |
:101 |
SkeletonBehavior |
骷髅行为 |
| 5 | PigZombie |
:102 |
ItemDropBehavior(20000, gold_nugget) |
激活时掉金粒 |
| 6 | Bat |
:103 |
1.0, -0.3 |
缩放 1.0,垂直偏移 −0.3 |
| 7 | Zombie |
:104 |
无 | — |
| 8 | Witch |
:105 |
0.35, WitchBehavior |
女巫行为 |
| 9 | Villager |
:106 |
无 | — |
| 10 | Ozelot |
:107-120 |
无 + 覆写 | 驯服(setTamed(true));类型不符时 Log.warn("Invalid cat entity class: %s")(:114-117) |
| 11 | Sheep |
:121 |
ItemDropBehavior(20000, wool) |
激活时掉羊毛 |
| 12 | Blaze |
:122 |
BlazeBehavior |
烈焰人行为 |
| 13 | Silverfish |
:123 |
无 | — |
| 14 | Spider |
:124 |
无 | — |
| 15 | CaveSpider |
:125 |
CaveSpiderBehavior |
洞穴蜘蛛行为 |
| 16 | Slime |
:126-132 |
0.6 + 覆写 |
setSlimeSize(entity, 1) 反射调用(:130) |
| 17 | Ghast |
:133 |
0.1, 0.3 |
缩放 0.1,垂直偏移 0.3 |
| 18 | Enderman |
:134 |
0.3, EndermanBehavior |
末影人行为 |
| 19 | LavaSlime |
:135-141 |
0.6 + 覆写 |
同 Slime,setSlimeSize(entity, 1)(:139) |
| 20 | Squid |
:142 |
0.3, 0.5, SquidBehavior |
鱿鱼行为 |
| 21 | MushroomCow |
:143 |
MooshroomBehavior |
哞菇行为 |
| 22 | VillagerGolem |
:144 |
0.3 |
缩放 0.3 |
| 23 | SnowMan |
:145 |
SnowmanBehavior |
雪傀儡行为 |
| 24 | Pig |
:146 |
ItemDropBehavior(20000, porkchop) |
激活时掉猪排 |
行为接口
ITrophyBehavior 只有 2 个方法(trophy/ITrophyBehavior.java:12、:14):
| 方法 | 触发时机 |
|---|---|
executeActivateBehavior(TileEntityTrophy, EntityPlayer) |
玩家右键奖杯方块;返回值是某种内部计数(TrophyHandler.java:210-213) |
executeTickBehavior(TileEntityTrophy) |
每刻(TrophyHandler.java:215-217) |
behavior 为 null 时两个方法都直接返回(:211-212、:216)——25 种里只有 14 种带行为(TrophyHandler.java:97-146 中含 Behavior( 的行数)。Ozelot、Slime、LavaSlime 三个带 {} 覆写的是 createEntity() 而非行为。
10 个行为实现
BlazeBehavior、CaveSpiderBehavior、CreeperBehavior、EndermanBehavior、ItemDropBehavior、MooshroomBehavior、SkeletonBehavior、SnowmanBehavior、SquidBehavior、WitchBehavior(trophy/ 目录)。
其中 ItemDropBehavior 被 4 种奖杯复用(Chicken / Cow / PigZombie / Sheep / Pig 中的 5 种),构造参数是 (probability, ItemStack) 或 (probability, ItemStack, sound)。
实体缓存
每种奖杯只创建一个「假实体」并缓存(ENTITY_CACHE,TrophyHandler.java:50、:70-83):
try {
entity = trophy.createEntity();
} catch (Throwable t) {
Log.severe(t, "Failed to create dummy entity for trophy %s", trophy);
}
createEntity() 用 EntityList.createEntityByName(toString(), null)(:219-221)——按枚举名查实体 ID,所以 PigZombie / VillagerGolem 这类与原版实体 ID 名不完全一致的枚举名会返回 null。这是不吞异常的 catch(记 Log.severe),但缓存仍会把 null 存进去,后续 getEntityFromCache 会走 entity == null 分支重试(:71-79)——即每次访问都会重试创建。
setSlimeSize 也用反射(ReflectionHelper.call 试 func_70799_a 与 setSlimeSize 两名),失败时 Log.warn(e, "Can't update slime size")(:85-93)。
掉落概率:可配置公式
TrophyHandler 有一个可热改的表达式求值器(dropChangeCalculator,:54-55),表达式来自 Config.trophyDropChanceFormula,在 ConfigurationChange.Post 时重读(:61-68)。
公式的三个全局符号(:244-247):
| 符号 | 值 |
|---|---|
looting |
event.lootingLevel |
specialDrop |
event.specialDropValue |
chance |
Config.trophyDropChance |
默认公式(Config.trophyDropChanceFormula,Config.java:145):
let([bias=rand()/4, selection=rand()], (looting + bias) * chance - selection)
trophyDropChance 的默认值是 0.001,且它的配置注释自陈为遗留值:"Legacy value. For actual configuration, see 'trophyDropChanceFormula'"(Config.java:137)。
Supplier.get() 的回退实现(:252-256):
final double bias = fallbackDropChance.nextDouble() / 4;
final double selection = fallbackDropChance.nextDouble();
return (event.lootingLevel + bias) * Config.trophyDropChance - selection;
即结果 > 0 时掉落(:259)。掉落物是 new EntityItem(...),delayBeforeCanPickup = 10(10 刻拾取延迟,:264-270)。
触发条件:event.recentlyHit && canDrop(entity)(:240)。
辅助映射
静态初始化块(:223-230)用 t.name() 建 ImmutableMap<String, Trophy> TYPES(:232),并导出 Trophy[] VALUES = values()(:234)。getItemStack() 把枚举值写进方块 meta(ItemTrophyBlock.putMetadata,:189-191)。
playSound(:193-208)把缓存实体瞬移到目标点,synchronized (e) 内播放 playLivingSound() 后把 worldObj 置回 null。
数值
| 数值名 | 来源 | 值 |
|---|---|---|
| 奖杯种类 | Trophy 枚举 |
25(TrophyHandler.java:97-146) |
| 带行为的奖杯数 | 枚举体中含 Behavior( 的行 |
14(见上表) |
| 行为实现类数 | trophy/ 目录 |
10(11 文件 − 1 接口) |
| 默认缩放 | scale 字段初值 |
0.4(TrophyHandler.java:148) |
| 默认垂直偏移 | verticalOffset 初值 |
0.0(TrophyHandler.java:149) |
| 掉落公式回退偏置 | fallbackDropChance.nextDouble() / 4 |
0 ~ 0.25(:253) |
| 掉落物拾取延迟 | delayBeforeCanPickup |
10 刻(:270) |
| 缩放取值范围 | 逐项统计 | 0.1(Ghast,:133)~ 1.0(Bat,:103) |
| 垂直偏移取值 | 逐项统计 | −0.3(Bat,:103)~ 0.5(Squid,:142) |
交互
| 触发 | 行为 |
|---|---|
| 玩家右键奖杯方块 | 调 executeActivateBehavior(TrophyHandler.java:210-213) |
| 奖杯每刻 | 调 executeTickBehavior(:215-217) |
| 玩家击杀生物 | LivingDropsEvent 触发概率公式,命中则掉对应奖杯(:237-270) |
| 放置方块 / 首次访问 | 创建并缓存假实体用于渲染(:70-83) |
| 声音播放 | 移动缓存实体到目标点后 playLivingSound()(:193-208) |
合成配方
奖杯方块没有合成配方,也不在任何 Config.registerCraftingRecipes 的 recipeList.add 中。唯一来源是 TrophyHandler.onLivingDrops(TrophyHandler.java:238)的击杀掉落,或创造模式/指令。
相关条目
- 方块 / 设备类方块 - 奖杯方块在其索引表中
- 配置项全表 -
trophy分类(2 项:trophyDropChance、trophyDropChanceFormula) - 实体 / 实体(10 个) - 奖杯用的假实体不是注册的实体