Bukkit(原版同理)的玩家/实体带颜色发光机制简谈

众所周知,在 Bukkit 的代表实体的 org.bukkit.entity.Entity 对象中有 setGlowing(boolean flag) 这么一个方法,根据 Javadoc 中的描述:

  • setGlowing

    void setGlowing(boolean flag)

    Sets whether the entity has a team colored (default: white) glow. nb: this refers to the 'Glowing' entity property, not whether a glowing potion effect is applied

    • Parameters:

    flag - if the entity is glowing

我们可以很容易的得知,这个方法是通过设置实体的 Glowing 属性,来实现让实体发光的效果。

但是我们发现,这样设置的实体发光,其发光颜色是白色的,但并没有在类似的位置找到设置实体发光颜色的方法。因此,该如何让一个实体发出其他颜色的光呢。

其实这就要借助 Minecraft 的记分板(ScoreBoard)功能了。众所周知,ScoreBoard 可以将玩家划分成不同的队伍,然后为队伍设置不同的颜色,此时,当玩家发光时,发光颜色就会变为队伍颜色。所以,我们需要为实体设置计分板队伍。

在过去的版本中,Bukkit 仅支持 OfflinePlayer 作为 Team 对象的成员,但现在,Bukkit 将成员的类型设置成了 String 而不是 OfflinePlayer,这就允许非玩家对象被加入 Team中。

那么,我们应该传入什么样的 String 来代表一个实体呢?很容易联想到就是实体的 UUID 了。

因此,键入以下代码:

Entity entity = ...
Scoreboard sb = Bukkit.getScoreboardManager().getMainScoreboard();
Team team = sb.registerNewTeam("Team_Name");
team.setColor(ChatColor.RED)
team.addEntry(entity.getUniqueId().toString())

此时,当为 entity 设置 setGlowing(true) 后,就会看到实体产生红色的光芒了。

使用这种方式设置的实体发光,支持诸如动物(Animal),怪物(Monster),掉落物(Item)等等一众的自然实体,除了...玩家。

这是一个令人疑惑的设计:当我们查看 Bukkit 已经弃用的 addPlayer 方法(而不是 addEntry )时,我们看到实现是这样的:

public void addPlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException {
        Validate.notNull(player, "OfflinePlayer cannot be null");
        this.addEntry(player.getName());
    }

这也就意味着,对于记分板而言,需要用玩家的游戏 ID 来表示这个玩家,而非这个玩家的 UUID,这是需要注意的一点。

同时,还需要注意的一些事情是:对于 ScoreboardManager,Bukkit 还提供了一个 getNewScoreboard() 方法用来产生一个新的子记分板,用以区分主记分板,但 使用这个计分板创建的队伍并不能(通过setColor方法)改变实体颜色。另外,由于 getMainScoreboard() 返回的记分板对象代表的是游戏世界的主记分板,因此,这些计分板数据 不仅可以被 /scoreboard 指令操控,所有修改还将随着世界一齐被保存,因此,当创建 Team 时,请务必检查上一次是否已经创建过一个同名的 Team,避免引发异常。