Fake Player
基本信息
| 属性 | 值 |
|---|---|
| 类 | FakePlayerLogic(tmechworks/lib/player/FakePlayerLogic.java,22 行) |
| 父类 | net.minecraftforge.common.util.FakePlayer |
| 使用者 | Drawbridge / Long Drawbridge / Advanced Drawbridge |
| GameProfile 名 | Player.Drawbridge |
| UUID | null(new GameProfile(null, "Player.Drawbridge")) |
| 惰性创建 | 是(initFakePlayer()) |
用途
Drawbridge 用它作为放置方块时 onBlockPlaced 看到的「玩家」,使受保护方块(ForgeProtection)、统计与事件系统认为方块是被玩家放置而非凭空出现。
实现
DrawbridgeLogic(blocks/logic/DrawbridgeLogic.java):
private FakePlayerLogic fakePlayer = null; // 字段,序列化时不写入
private void initFakePlayer() {
fakePlayer = new FakePlayerLogic(new GameProfile(null, "Player.Drawbridge"), this);
}
fakePlayer 的创建时机是惰性的(每次 updateEntity 放置前调 initFakePlayer()),而非在 validate() / onChunkLoad 中。源码注释明确说明原因:
Because of some weird shit, creating the FakePlayer in validate() causes the TileEntity to be created twice.
setFakePlayerRotation() 在放置前把假玩家的 yaw / pitch 对齐 Drawbridge 当前的 direction。
数值
| 数值 | 值 |
|---|---|
| 类行数 | 22 |
| GameProfile 名 | Player.Drawbridge |
| GameProfile UUID | null |
| 字段 | logicPos(ChunkCoordinates,构造时快照 TE 的 xyz) |
getPlayerCoordinates() |
返回构造时快照的 logicPos(非实时) |
| 序列化 | 不写入 NBT(无 writeToNBT / readFromNBT 覆写) |
| 创建时机 | 惰性,initFakePlayer() |
| 生命周期 | 区块卸载 / TE 失效后被 GC |
交互
| 触发 | 行为 |
|---|---|
| Drawbridge 放置方块 | 调 initFakePlayer() 确保存在 → setFakePlayerRotation() → placeBlockAt(..., fakePlayer, ...) |
| 区块卸载 | invalidate() 置 fakePlayer = null(源码在 updateEntity 的 isInvalid() 检查中) |
| 重载区块 | 从 NBT 恢复,fakePlayer 仍为 null,下次放置时惰性重建 |
源码缺陷
- UUID 为
null(new GameProfile(null, "Player.Drawbridge")):FakePlayer继承自EntityPlayer,其getGameProfile().getId()在 Forge 1.7.10 中可能被用于权限与统计查询。FakePlayerFactory官方实现会UUID.randomUUID()补齐,此处只给了名字。当前靠惰性创建 +invalidate()置空规避了主要问题,但若两个不同位置的 Drawbridge 在同一 tick 各自重建,会得到两个 UUID 为 null 的同名 profile,某些按 UUID 索引的统计/权限表可能冲突。 logicPos是构造时快照(FakePlayerLogic.java:16):new ChunkCoordinates(te.xCoord, te.yCoord, te.zCoord)只在构造时读一次。若 TE 被移动(FakePlayer理论上支持setPosition),getPlayerCoordinates()返回的仍是旧坐标。源码无setPosition覆写,故当前 TE 不移动则无害。- 未覆写
getPlayerCoordinates()的实时语义:其他代码若依赖该方法获取当前位置会读到陈旧值。 - 无
NBT序列化:设计正确(假玩家本就不该持久化),但若将来需要FakePlayer的权限设置(Forge 的fakePlayer.addPermission)会无处存储。 - 无权限授予:未调用
fakePlayer.addPermission(...)任何节点,因此**ForgeProtection保护的方块仍会阻止 Drawbridge 放置**(ForgeProtection.canPlayerEdit查权限节点)。这实际上是一道「保护」而非缺陷,但源码无注释说明,玩家容易困惑「为什么我的 Drawbridge 放不下被保护的方块」。 GameProfile每次重建都新建对象:区块反复加载会持续分配GameProfile(含内部PropertyMap),无复用。
相关条目
- Drawbridge - 唯一使用者
- Advanced Drawbridge - 同样使用
- Long Drawbridge - 同样使用(同一
DrawbridgeLogic) - Drawbridge 放置规则 - 假玩家实际绕过
validMetadata的原因