Доступ к блокам
Основная информация
Чаще всего блоки идентифицируют и получают к ним доступ через их Location. Локация указывает координаты в пределах Extent. Чаще всего именно World будет использован как Extent
.
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;
}
Предупреждение
Внимание: данный пример не проверяет мир на существование. 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()
так как существует только один вариант BlockType для каждого блока, однако в основном мы рекомендуем использовать именно equals()
.
Манипуляторы данными блока
Данные о блоке содержатся в DataManipulator подобно остальным частям API. Это является контейнером которые хранит в себе информацию о блоке, такую как направление блока, тип блока (камень или гранит) и так далее. Проверить эти значения очень просто, например для проверки направления блока необходимо использовать 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;
}
First, we need to know which DataManipulator
sub-interface we need. Those that are applicable to blocks are found
in the org.spongepowered.api.data.manipulator.mutable and
org.spongepowered.api.data.manipulator.mutable.block packages. Then, we can just pass that class to the
get(DataManipulator)
method of Location
which will return an Optional
. We then have to check if our
DataManipulator
actually exists for our block by checking ifPresent()
. If it exists, then we can use it.
Подробнее о``DataManipulator`` можно прочитать в data documentation.
Совет
If a block will never stop supporting a particular DataManipulator
, such as DirectionalData
with stairs,
then there is no need to check for isPresent()
. Just remove the optional around the DataManipulator
and
fetch the non-optional data by adding .get()
to the end of the statement. Note, that this will cause a
NullPointerException
if a block ever stops supporting a particular DataManipulator
.
Состояния блока
A BlockState contains a BlockType, any DataManipulator
s and properties that are applied to
the block, and any BlockTraits for a block. It stores all immutable value’s for a particular block. One
use of this is getting an ImmutableDataManipulator, as shown below:
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.data.manipulator.immutable.ImmutableWetData;
public void 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();
}
More information on mutable and immutable DataManipulator
s can be found in the data documentation.
Свойства блока
Блоки могут содержать определенные свойства. Свойство представляет собой заданное значение, которое определяет логику игры в этом конкретном блоке. Например, блоки могут содержать предопределенные значения сопротивления взрывам, которые могут использоваться для определения того, с чем вы работаете, без фактической проверки типа блока; он может быть один 10: один. Например, если мы хотели получить сопротивление взрывам блока и проверяем, больше оно или равно одному, это будет сделано так:
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 = DoubleProperty.greaterThanOrEqual(1);
return one.matches(resistance);
}
return false;
}
This will get the blast resistance of our block and compare it to a new DoubleProperty, as
BlastResistanceProperty inherits from DoubleProperty
. The method will then return if the blast
resistance of our block is greater than one, the value in placed matches()
. If we wanted to see if it was less than
two, we would replace it with lessThan()
.
If we were comparing two pre-existing properties, it will take the Operator
of our first value, the one we are
creating a double property for. If the Operator
is DELEGATE
, which is the none operator, then it will take the
Operator
of the second value, the one in matches()
. Comparison will return false if both are DELEGATE
.
An example of comparing two PoweredPropertys, a BooleanProperty, can be seen below:
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 = BooleanProperty.of(property1);
BooleanProperty booleanProperty2 = BooleanProperty.of(true);
if(booleanProperty2.matches(property1)) {
return booleanProperty.matches(property2);
}
}
return false;
}
Второй «if»-контроль проверяет, является ли одно из свойств истинным. Если оно истинно, и оба равны, то оба значения должны быть истинными. Таким образом устраняется необходимость проверки второго значения. Теперь мы знаем, что оба блока приведены в действие.
Список возможных свойств для блоков можно найти в пакете org.spongepowered.api.data.property.block.
Черты блока
A block trait is a certain value on the current state of a block. A block may or may not contain block traits depending
on the type of block. For example, a bed has a BooleanTrait called
BED_OCCUPIED
. As a boolean can only have two values, true and false, the BED_OCCUPIED
trait can only be true or
false. Checking this value is simple, just call the BlockState#getTraitValue(BlockTrait) method. An example
of this with a bed is shown below:
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;
}
Предупреждение
If possible, it is recommended to use DataManipulator
s in place of BlockTrait
s where possible as they are
only to be meant as a fallback for modded compatibility.