存取方塊
基本資訊
方塊最常由它的 :javadoc:`Location`來識別與訪問。此位置指向特定座標並包含一個:javadoc:`Extent`。在大多數情況下,一個:javadoc:`World`作為父類別。
import org.spongepowered.api.Sponge;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
public Location<World> getBlockAt(String worldName, int posX, int posY, int posZ) {
World world = Sponge.getServer().getWorld(worldName).get();
Location<World> blockLoc = new Location<World>(world, posX, posY, posZ);
return blockLoc;
}
警告
注意以上的範例並未檢查世界是否存在。若名為worldName的世界不存在,``getWorld(worldName).get()``將失敗。
有了這個 ``Location``物件,使用者能獲取更多方塊資訊。以下的代碼藉由檢查方塊類別來判別該方塊是不是任何一種的旗幟。
import org.spongepowered.api.block.BlockType;
import org.spongepowered.api.block.BlockTypes;
public boolean isBanner(Location<World> blockLoc) {
BlockType type = blockLoc.getBlock().getType();
return type.equals(BlockTypes.STANDING_BANNER)
|| type.equals(BlockTypes.WALL_BANNER);
}
小訣竅
==``能用來代替``equals()
,因為每個方塊只有一個:javadoc:BlockType`實體,但一般仍推薦使用 ``equals()`。
方塊資料操作子(Entity Data Manipulators)
和API的其他部分的存储方式类似,一个方块的数据被以 DataManipulator 的方式存储。它是一个存储了方块的各种角度的信息的容器。这样的信息有方块的方向、特殊类型(例如石头和花岗岩)等。获取这样的数据是十分简单的,如果想要获取方块的方向,你只需要使用 DirectionalData。
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.data.manipulator.mutable.block.DirectionalData;
public boolean isFacingNorth(Location<World> blockLoc) {
Optional<DirectionalData> optionalData = blockLoc.get(DirectionalData.class);
if (!optionalData.isPresent()) {
return false;
}
DirectionalData data = optionalData.get();
if (data.get(Keys.DIRECTION).get().equals(Direction.NORTH)) {
return true;
}
return false;
}
首先,我们需要知道我们需要的``DataManipulator``的子接口是什么样子。我们可以在 org.spongepowered.api.data.manipulator.mutable 和 org.spongepowered.api.data.manipulator.mutable.block 两个包下找到适用于方块的部分。然后,我们直接把对应的class传入 Location
类的 get(DataManipulator)
方法从而返回一个 Optional
。然后我们就需要通过 isPresent()
(译者注:原文为 ifPresent()
,怀疑其笔误)方法判断这一 DataManipulator
是否真的存在,如果存在,我们就可以使用它了。
更多和 DataManipulator
有关的东西可以在 数据 API 文档 中找到。
小訣竅
如果一个方块永远支持一种特定的``DataManipulator``,比如台阶支持``DirectionalData``,自然就没有必要检查``isPresent()``。直接通过添加``.get()``在语句的末尾就可以获取被Optional包装的数据。请注意,如果一个方块不支持这种特定的``DataManipulator``,那么这样的操作会产生一个``NullPointerException``。
方塊狀態
一个 BlockState 包含一个 BlockType、所有应用于该方块的 DataManipulator
和属性、以及该方块所拥有的 BlockTrait。它储存了一个特定的方块的所有不可变数据。一种用法是获取一个 ImmutableDataManipulator ,就像下面这样:
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.data.manipulator.immutable.ImmutableWetData;
public boolean isWet(Location blockLoc) {
BlockState sponge = blockLoc.getBlock();
if (!sponge.getType().equals(BlockTypes.SPONGE)) {
return false;
}
Optional<ImmutableWetData> wetness = sponge.get(ImmutableWetData.class);
return wetness.isPresent();
}
更多和可变或不可变的 DataManipulator
有关的东西可以在 数据 API 文档 中找到。
方塊屬性
一个方块可以包含若干种属性。一种属性是一类定义了特定方块的游戏逻辑的值的集合。例如,方块可以包含既定的爆炸抗性值,这一值可以被拿来使用而不需要逐个检查每个方块的种类。比如如果我们想要获取爆炸抗性并检查它是否大于等于一,我们就可以这么做:
import org.spongepowered.api.data.Property;
import org.spongepowered.api.data.property.DoubleProperty;
import org.spongepowered.api.data.property.block.BlastResistanceProperty;
public boolean blastResistanceGreaterThanOne(Location<World> blockLoc) {
Optional<BlastResistanceProperty> optional =
blockLoc.getProperty(BlastResistanceProperty.class);
if(optional.isPresent()) {
BlastResistanceProperty resistance = optional.get();
DoubleProperty one = new DoubleProperty(1, Property.Operator.GEQUAL);
return one.matches(resistance);
}
return false;
}
这就可以得到我们针对的方块的爆炸抗性值并和一个新 DoubleProperty 进行比较,因为 BlastResistanceProperty 是``DoubleProperty``的子类。这一方法就会返回爆炸抗性是否大于等于一,也就是被放置在``matches()``方法里的``DoubleProperty``。如果我们想要知道它是否小于 2,我们就会把 DoubleProperty
的构造器中的属性算符换成 Property.Operator.LESS
。
如果我们在比较两个已经存在的属性,那么先会判断第一个的 Operator
,这里也就是我们设置的 DoubleProperty
的 Operator
。如果它是 DELEGATE
,也就是并不存在,那么它就会获取第二个的 Operator
,也就是 matches()
中的属性的 Operator
。如果两个属性的 Operator
都是 DELEGATE
,那么它将会返回假。下面是比较两个 PoweredProperty 和一个 BooleanProperty 的例子:
import org.spongepowered.api.data.property.BooleanProperty;
import org.spongepowered.api.data.property.block.PoweredProperty;
public boolean areBlocksPowered(Location<World> blockLoc, Location<World> blockLoc2) {
Optional<PoweredProperty> optional = blockLoc.getProperty(PoweredProperty.class);
Optional<PoweredProperty> optional2 = blockLoc2.getProperty(PoweredProperty.class);
if(optional.isPresent() && optional2.isPresent()) {
PoweredProperty property1 = optional2.get();
PoweredProperty property2 = optional2.get();
BooleanProperty booleanProperty = new BooleanProperty(true, Property.Operator.EQUAL);
if(booleanProperty.matches(property1)) {
return property1.matches(property2);
}
}
return false;
}
第二个``if``条件判断其中一个属性是否为真。如果其为真而且两个属性一致,那么两个属性自然都为真。因此,我们不需要检查第二个值就可以知道两个方块都是被充能的。
可能的方块属性列表可以在 org.spongepowered.api.data.property.block 下找到。
方塊狀態值
方塊狀態值是表現方塊目前狀態的一個特定值。一個方塊可能或可能不包含方塊狀態值,取決於方塊類型。例如一張床有一個``BED_OCCUPIED``的布林方塊狀態值( BooleanTrait )。因為布林只能有兩種值,真或假,故``BED_OCCUPIED``只能是真或假。檢查值非常簡單,只要呼叫:javadoc:`BlockState#getTraitValue(BlockTrait)`函式。以下是一段以床作為範例的程式碼:
import org.spongepowered.api.block.trait.BooleanTraits;
public boolean isBedOccupied(Location<World> blockLoc) {
if(blockLoc.getBlock().getType().equals(BlockTypes.BED)) {
return blockLoc.getBlock().getTraitValue(BooleanTraits.BED_OCCUPIED).get();
}
return false;
}
警告
如果有可能,请尽量使用 DataManipulator
以替代 BlockTrait
,因为 BlockTrait
只是在考虑与 Mod 的兼容性时才有意义。