物品的创建

如果你想制作一个自定义的物品,你需要经过若干步骤方能搞定。让我们从最基础的开始,然后制作一把附魔的钻石剑。

创建一个 ItemStack 对象需要 ItemStack 的构造器;这构造器可通过 ItemStack#builder() 方法获得。这个构造器能让我们设定这个物品的类型及耐久。接下来,我们要制作一个带有自定义的名字的无限耐久附魔钻石剑。如果你想要一把普通的钻石剑,没有任何其他奇奇怪怪的数据,只需如此:

import org.spongepowered.api.item.ItemTypes;
import org.spongepowered.api.item.inventory.ItemStack;

public ItemStack generateSword() {
    ItemStack superMegaAwesomeSword = ItemStack.builder()
        .itemType(ItemTypes.DIAMOND_SWORD).build();
    return superMegaAwesomeSword;
}

现在一把崭新的钻石剑就出来了。但这是把普通的钻石剑。如果我们想要加点有趣的属性呢?比如,改个名字?或者加个附魔?附魔可以借助 EnchantmentData 完成。下面我们将为钻石剑加附魔。你需要确保你在 return superMegaAwesomeSword; 之前把这些附魔全部搞定。

import java.util.List;
import java.util.stream.Collectors;

import org.spongepowered.api.Sponge;
import org.spongepowered.api.data.manipulator.mutable.item.EnchantmentData;
import org.spongepowered.api.data.meta.ItemEnchantment
import org.spongepowered.api.item.Enchantment;

EnchantmentData enchantmentData = superMegaAwesomeSword
    .getOrCreate(EnchantmentData.class).get();
final List<Enchantment> enchantments = Sponge.getRegistry()
    .getAllOf(Enchantment.class).stream().collect(Collectors.toList());

for (Enchantment enchantment : enchantments) {
    enchantmentData.set(enchantmentData.enchantments()
        .add(new ItemEnchantment(enchantment, 1000)));
}
superMegaAwesomeSword.offer(enchantmentData);

现在我们想给这 OP 钻石剑起个看起来很厉害的名字。我们可以直接为 ItemStack 提供一个名字的键值,这样我们就能直接把这个 ItemStack 对象的名字改成 SUPER MEGA AWESOME Diamond Sword (译注:大概就是“狂拽酷炫叼炸天的钻石剑”的意思):

import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.text.format.TextColors;

superMegaAwesomeSword.offer(Keys.DISPLAY_NAME, Text.of(
    TextColors.BLUE, "SUPER ",
    TextColors.GOLD, "MEGA ",
    TextColors.DARK_AQUA, "AWESOME ",
    TextColors.AQUA, "Diamond Sword"));

最后,如果想要让你的剑永不磨损,你可以用另外一个键:

superMegaAwesomeSword.offer(Keys.UNBREAKABLE, true);

完工!现在这把永不损坏的剑不仅有各种附魔,还有一个华丽的名字,拿去给服务器里的小伙伴们玩去吧。

生成物品

当然我们可以直接把这把剑扔进玩家的背包中,但如果我们想让这把剑以掉落物的形式出现呢?是时候让“实体生成”登场了。有鉴于在游戏中,ItemStack 表现出来的外观还是 Item,我们是可以用生成普通 Entity 的方式来搞定这个事情的。此时,EntityType 将会是 EntityTypes#ITEM,同时我们还需要指定 Entity 代表了我们的 ItemStack 实例。这个过程可以通过使用 Keys#REPRESENTED_ITEM 完成。下面是例子:

import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.EntityTypes;
import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.event.cause.entity.spawn.EntitySpawnCause;
import org.spongepowered.api.event.cause.entity.spawn.SpawnTypes;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.Extent;

import java.util.Optional;

public void spawnItem(ItemStack superMegaAwesomeSword, Location<World> spawnLocation) {
    Extent extent = spawnLocation.getExtent();
    Optional<Entity> optional = extent
        .createEntity(EntityTypes.ITEM, spawnLocation.getPosition());
    if (optional.isPresent()) {
        Entity item = optional.get();
        item.offer(Keys.REPRESENTED_ITEM, superMegaAwesomeSword.createSnapshot());
        extent.spawnEntity(item, Cause.source(EntitySpawnCause.builder()
            .entity(item).type(SpawnTypes.PLUGIN).build()).build());
    }
}

用方块创建 ItemStack

正常情况下,若需要方块对应的 ItemStack,可以用 ItemStack.Builder#itemType(ItemType) 方法来获得方块对应的物品,但如果我们需要根据 BlockState 来创建 ItemStack 实例呢?只需要使用 ItemStack.Builder#fromBlockState(BlockState) 即可。下面是例子:

import org.spongepowered.api.block.BlockState;

public ItemStack createStack(BlockState state) {
    return ItemStack.builder().fromBlockState(state).build();
}