Skip to content

Commit cbe03ad

Browse files
committed
BlockProperty API
1 parent ad74b67 commit cbe03ad

31 files changed

+1432
-16
lines changed

paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.papermc.paper;
22

3+
import io.papermc.paper.block.property.EnumBlockProperty;
34
import net.kyori.adventure.util.Services;
45
import org.bukkit.damage.DamageEffect;
56
import org.jetbrains.annotations.ApiStatus;
@@ -35,5 +36,15 @@ class Holder {
3536
* @return the damage effect.
3637
*/
3738
DamageEffect getDamageEffect(String key);
39+
40+
/**
41+
* Gets the string representation for this bukkit enum.
42+
*
43+
* @param enumProperty the enum data property
44+
* @param bukkitEnum the enum to get the string representation of
45+
* @param <B> the bukkit enum type
46+
* @return the string representation of the supplied enum
47+
*/
48+
<B extends Enum<B>> String getPropertyEnumName(EnumBlockProperty<B> enumProperty, B bukkitEnum);
3849
}
3950

paper-api/src/main/java/io/papermc/paper/block/fluid/FluidData.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.papermc.paper.block.fluid;
22

3+
import io.papermc.paper.block.property.BlockPropertyHolder;
34
import org.bukkit.Fluid;
45
import org.bukkit.Location;
56
import org.bukkit.util.Vector;
@@ -11,7 +12,7 @@
1112
* This type is not linked to a specific location and hence mostly resembles a {@link org.bukkit.block.data.BlockData}.
1213
*/
1314
@NullMarked
14-
public interface FluidData extends Cloneable {
15+
public interface FluidData extends Cloneable, BlockPropertyHolder {
1516

1617
/**
1718
* Gets the fluid type of this fluid data.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.papermc.paper.block.property;
2+
3+
import com.google.common.collect.BiMap;
4+
import com.google.common.collect.ImmutableBiMap;
5+
import java.util.function.IntFunction;
6+
import org.jetbrains.annotations.ApiStatus;
7+
8+
@ApiStatus.Internal
9+
sealed interface AsIntegerProperty<T extends Comparable<T>> extends BlockProperty<T> permits NoteBlockProperty, RotationBlockProperty {
10+
11+
static <T extends Comparable<T>> BiMap<Integer, T> createCache(final int max, final IntFunction<? extends T> function) {
12+
final ImmutableBiMap.Builder<Integer, T> builder = ImmutableBiMap.builder();
13+
for (int i = 0; i <= max; i++) {
14+
builder.put(i, function.apply(i));
15+
}
16+
return builder.buildOrThrow();
17+
}
18+
19+
BiMap<Integer, T> cache();
20+
21+
default int toIntValue(final T value) {
22+
if (!this.cache().inverse().containsKey(value)) {
23+
throw ExceptionCreator.INSTANCE.create(value, ExceptionCreator.Type.VALUE, this);
24+
}
25+
return this.cache().inverse().get(value);
26+
}
27+
28+
default T fromIntValue(final int value) {
29+
if (!this.cache().containsKey(value)) {
30+
throw ExceptionCreator.INSTANCE.create(value, ExceptionCreator.Type.VALUE, this);
31+
}
32+
return this.cache().get(value);
33+
}
34+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package io.papermc.paper.block.property;
2+
3+
import com.google.common.collect.HashMultimap;
4+
import com.google.common.collect.Multimap;
5+
import java.util.Arrays;
6+
import java.util.Set;
7+
import java.util.function.Predicate;
8+
import java.util.stream.Collectors;
9+
import org.bukkit.Axis;
10+
import org.bukkit.Instrument;
11+
import org.bukkit.Note;
12+
import org.bukkit.block.BlockFace;
13+
import org.bukkit.block.data.Bisected;
14+
import org.bukkit.block.data.FaceAttachable;
15+
import org.bukkit.block.data.Rail;
16+
import org.bukkit.block.data.type.Bamboo;
17+
import org.bukkit.block.data.type.Bed;
18+
import org.bukkit.block.data.type.Bell;
19+
import org.bukkit.block.data.type.BigDripleaf;
20+
import org.bukkit.block.data.type.Chest;
21+
import org.bukkit.block.data.type.Comparator;
22+
import org.bukkit.block.data.type.CreakingHeart;
23+
import org.bukkit.block.data.type.Door;
24+
import org.bukkit.block.data.type.Jigsaw;
25+
import org.bukkit.block.data.type.PointedDripstone;
26+
import org.bukkit.block.data.type.RedstoneWire;
27+
import org.bukkit.block.data.type.SculkSensor;
28+
import org.bukkit.block.data.type.Slab;
29+
import org.bukkit.block.data.type.Stairs;
30+
import org.bukkit.block.data.type.StructureBlock;
31+
import org.bukkit.block.data.type.TechnicalPiston;
32+
import org.bukkit.block.data.type.TrialSpawner;
33+
import org.bukkit.block.data.type.Vault;
34+
import org.bukkit.block.data.type.Wall;
35+
36+
/**
37+
* All block properties applicable to {@link BlockPropertyHolder}s.
38+
*/
39+
public final class BlockProperties {
40+
41+
static final Multimap<String, BlockProperty<?>> PROPERTIES = HashMultimap.create();
42+
43+
public static final BooleanBlockProperty ATTACHED = bool("attached");
44+
public static final BooleanBlockProperty BOTTOM = bool("bottom");
45+
public static final BooleanBlockProperty CONDITIONAL = bool("conditional");
46+
public static final BooleanBlockProperty CRACKED = bool("cracked");
47+
public static final BooleanBlockProperty DISARMED = bool("disarmed");
48+
public static final BooleanBlockProperty DRAG = bool("drag");
49+
public static final BooleanBlockProperty ENABLED = bool("enabled");
50+
public static final BooleanBlockProperty EXTENDED = bool("extended");
51+
public static final BooleanBlockProperty EYE = bool("eye");
52+
public static final BooleanBlockProperty FALLING = bool("falling");
53+
public static final BooleanBlockProperty HANGING = bool("hanging");
54+
public static final BooleanBlockProperty HAS_BOTTLE_0 = bool("has_bottle_0");
55+
public static final BooleanBlockProperty HAS_BOTTLE_1 = bool("has_bottle_1");
56+
public static final BooleanBlockProperty HAS_BOTTLE_2 = bool("has_bottle_2");
57+
public static final BooleanBlockProperty HAS_RECORD = bool("has_record");
58+
public static final BooleanBlockProperty HAS_BOOK = bool("has_book");
59+
public static final BooleanBlockProperty INVERTED = bool("inverted");
60+
public static final BooleanBlockProperty IN_WALL = bool("in_wall");
61+
public static final BooleanBlockProperty LIT = bool("lit");
62+
public static final BooleanBlockProperty LOCKED = bool("locked");
63+
public static final BooleanBlockProperty OCCUPIED = bool("occupied");
64+
public static final BooleanBlockProperty OPEN = bool("open");
65+
public static final BooleanBlockProperty PERSISTENT = bool("persistent");
66+
public static final BooleanBlockProperty POWERED = bool("powered");
67+
public static final BooleanBlockProperty SHORT = bool("short");
68+
public static final BooleanBlockProperty SIGNAL_FIRE = bool("signal_fire");
69+
public static final BooleanBlockProperty SNOWY = bool("snowy");
70+
public static final BooleanBlockProperty TRIGGERED = bool("triggered");
71+
public static final BooleanBlockProperty UNSTABLE = bool("unstable");
72+
public static final BooleanBlockProperty WATERLOGGED = bool("waterlogged");
73+
public static final BooleanBlockProperty BERRIES = bool("berries");
74+
public static final BooleanBlockProperty BLOOM = bool("bloom");
75+
public static final BooleanBlockProperty SHRIEKING = bool("shrieking");
76+
public static final BooleanBlockProperty CAN_SUMMON = bool("can_summon");
77+
public static final BooleanBlockProperty UP = bool("up");
78+
public static final BooleanBlockProperty DOWN = bool("down");
79+
public static final BooleanBlockProperty NORTH = bool("north");
80+
public static final BooleanBlockProperty EAST = bool("east");
81+
public static final BooleanBlockProperty SOUTH = bool("south");
82+
public static final BooleanBlockProperty WEST = bool("west");
83+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = bool("slot_0_occupied");
84+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = bool("slot_1_occupied");
85+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = bool("slot_2_occupied");
86+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = bool("slot_3_occupied");
87+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = bool("slot_4_occupied");
88+
public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = bool("slot_5_occupied");
89+
public static final BooleanBlockProperty CRAFTING = bool("crafting");
90+
public static final BooleanBlockProperty OMINOUS = bool("ominous");
91+
public static final BooleanBlockProperty TIP = bool("tip");
92+
public static final BooleanBlockProperty ACTIVE = bool("active");
93+
public static final BooleanBlockProperty NATURAL = bool("natural");
94+
95+
public static final IntegerBlockProperty AGE_1 = integer("age", 0, 1);
96+
public static final IntegerBlockProperty AGE_2 = integer("age", 0, 2);
97+
public static final IntegerBlockProperty AGE_3 = integer("age", 0, 3);
98+
public static final IntegerBlockProperty AGE_4 = integer("age", 0, 4);
99+
public static final IntegerBlockProperty AGE_5 = integer("age", 0, 5);
100+
public static final IntegerBlockProperty AGE_7 = integer("age", 0, 7);
101+
public static final IntegerBlockProperty AGE_15 = integer("age", 0, 15);
102+
public static final IntegerBlockProperty AGE_25 = integer("age", 0, 25);
103+
public static final IntegerBlockProperty BITES = integer("bites", 0, 6);
104+
public static final IntegerBlockProperty CANDLES = integer("candles", 1, 4);
105+
public static final IntegerBlockProperty DELAY = integer("delay", 1, 4);
106+
public static final IntegerBlockProperty DISTANCE = integer("distance", 1, 7);
107+
public static final IntegerBlockProperty DUSTED = integer("dusted", 0, 3);
108+
public static final IntegerBlockProperty EGGS = integer("eggs", 1, 4);
109+
public static final IntegerBlockProperty FLOWER_AMOUNT = integer("flower_amount", 1, 4);
110+
public static final IntegerBlockProperty HATCH = integer("hatch", 0, 2);
111+
public static final IntegerBlockProperty LAYERS = integer("layers", 1, 8);
112+
public static final IntegerBlockProperty LEVEL_CAULDRON = integer("level", 1, 3);
113+
public static final IntegerBlockProperty LEVEL_COMPOSTER = integer("level", 0, 8);
114+
public static final IntegerBlockProperty LEVEL_FLOWING = integer("level", 1, 8);
115+
public static final IntegerBlockProperty LEVEL_HONEY = integer("honey_level", 0, 5);
116+
public static final IntegerBlockProperty LEVEL = integer("level", 0, 15);
117+
public static final IntegerBlockProperty MOISTURE = integer("moisture", 0, 7);
118+
public static final BlockProperty<Note> NOTE = register(new NoteBlockProperty("note")); // is stored as int, but represented as object
119+
public static final IntegerBlockProperty PICKLES = integer("pickles", 1, 4);
120+
public static final IntegerBlockProperty POWER = integer("power", 0, 15);
121+
public static final IntegerBlockProperty STAGE = integer("stage", 0, 1);
122+
public static final IntegerBlockProperty STABILITY_DISTANCE = integer("distance", 0, 7);
123+
public static final IntegerBlockProperty RESPAWN_ANCHOR_CHARGES = integer("charges", 0, 4);
124+
125+
public static final EnumBlockProperty<BlockFace> ROTATION_16 = register(new RotationBlockProperty("rotation")); // is stored as int, but represented as enum
126+
public static final EnumBlockProperty<Axis> HORIZONTAL_AXIS = enumeration("axis", Axis.class, Axis.X, Axis.Z);
127+
public static final EnumBlockProperty<Axis> AXIS = enumeration("axis", Axis.class);
128+
public static final EnumBlockProperty<BlockFace> FACING = enumeration("facing", BlockFace.class, BlockFace::isCartesian);
129+
public static final EnumBlockProperty<BlockFace> FACING_HOPPER = enumeration("facing", BlockFace.class, ((Predicate<BlockFace>) BlockFace::isCartesian).and(face -> face != BlockFace.UP));
130+
public static final EnumBlockProperty<BlockFace> HORIZONTAL_FACING = enumeration("facing", BlockFace.class, BlockFace::isCardinal);
131+
public static final EnumBlockProperty<Jigsaw.Orientation> ORIENTATION = enumeration("orientation", Jigsaw.Orientation.class);
132+
public static final EnumBlockProperty<FaceAttachable.AttachedFace> ATTACH_FACE = enumeration("face", FaceAttachable.AttachedFace.class);
133+
public static final EnumBlockProperty<Bell.Attachment> BELL_ATTACHMENT = enumeration("attachment", Bell.Attachment.class);
134+
public static final EnumBlockProperty<Wall.Height> EAST_WALL = enumeration("east", Wall.Height.class);
135+
public static final EnumBlockProperty<Wall.Height> NORTH_WALL = enumeration("north", Wall.Height.class);
136+
public static final EnumBlockProperty<Wall.Height> SOUTH_WALL = enumeration("south", Wall.Height.class);
137+
public static final EnumBlockProperty<Wall.Height> WEST_WALL = enumeration("west", Wall.Height.class);
138+
public static final EnumBlockProperty<RedstoneWire.Connection> EAST_REDSTONE = enumeration("east", RedstoneWire.Connection.class);
139+
public static final EnumBlockProperty<RedstoneWire.Connection> NORTH_REDSTONE = enumeration("north", RedstoneWire.Connection.class);
140+
public static final EnumBlockProperty<RedstoneWire.Connection> SOUTH_REDSTONE = enumeration("south", RedstoneWire.Connection.class);
141+
public static final EnumBlockProperty<RedstoneWire.Connection> WEST_REDSTONE = enumeration("west", RedstoneWire.Connection.class);
142+
public static final EnumBlockProperty<Bisected.Half> DOUBLE_BLOCK_HALF = enumeration("half", Bisected.Half.class);
143+
public static final EnumBlockProperty<Bisected.Half> HALF = enumeration("half", Bisected.Half.class);
144+
public static final EnumBlockProperty<Rail.Shape> RAIL_SHAPE = enumeration("shape", Rail.Shape.class);
145+
public static final EnumBlockProperty<Rail.Shape> RAIL_SHAPE_STRAIGHT = enumeration("shape", Rail.Shape.class, Rail.Shape::isStraight);
146+
public static final EnumBlockProperty<Bed.Part> BED_PART = enumeration("part", Bed.Part.class);
147+
public static final EnumBlockProperty<Chest.Type> CHEST_TYPE = enumeration("type", Chest.Type.class);
148+
public static final EnumBlockProperty<Comparator.Mode> MODE_COMPARATOR = enumeration("mode", Comparator.Mode.class);
149+
public static final EnumBlockProperty<Door.Hinge> DOOR_HINGE = enumeration("hinge", Door.Hinge.class);
150+
public static final EnumBlockProperty<Instrument> NOTEBLOCK_INSTRUMENT = enumeration("instrument", Instrument.class);
151+
public static final EnumBlockProperty<TechnicalPiston.Type> PISTON_TYPE = enumeration("type", TechnicalPiston.Type.class);
152+
public static final EnumBlockProperty<Slab.Type> SLAB_TYPE = enumeration("type", Slab.Type.class);
153+
public static final EnumBlockProperty<Stairs.Shape> STAIRS_SHAPE = enumeration("shape", Stairs.Shape.class);
154+
public static final EnumBlockProperty<StructureBlock.Mode> STRUCTUREBLOCK_MODE = enumeration("mode", StructureBlock.Mode.class);
155+
public static final EnumBlockProperty<Bamboo.Leaves> BAMBOO_LEAVES = enumeration("leaves", Bamboo.Leaves.class);
156+
public static final EnumBlockProperty<BigDripleaf.Tilt> TILT = enumeration("tilt", BigDripleaf.Tilt.class);
157+
public static final EnumBlockProperty<BlockFace> VERTICAL_DIRECTION = enumeration("vertical_direction", BlockFace.class, face -> Math.abs(face.getModY()) > 0);
158+
public static final EnumBlockProperty<PointedDripstone.Thickness> DRIPSTONE_THICKNESS = enumeration("thickness", PointedDripstone.Thickness.class);
159+
public static final EnumBlockProperty<SculkSensor.Phase> SCULK_SENSOR_PHASE = enumeration("sculk_sensor_phase", SculkSensor.Phase.class);
160+
public static final EnumBlockProperty<TrialSpawner.State> TRIAL_SPAWNER_STATE = enumeration("trial_spawner_state", TrialSpawner.State.class);
161+
public static final EnumBlockProperty<Vault.State> VAULT_STATE = enumeration("vault_state", Vault.State.class);
162+
163+
private BlockProperties() {
164+
}
165+
166+
//<editor-fold defaultstate="collapsed" desc="static factory methods">
167+
private static IntegerBlockProperty integer(final String name, final int min, final int max) {
168+
return register(new IntegerBlockPropertyImpl(name, min, max));
169+
}
170+
171+
private static BooleanBlockProperty bool(final String name) {
172+
return register(new BooleanBlockPropertyImpl(name));
173+
}
174+
175+
private static <E extends Enum<E>> EnumBlockProperty<E> enumeration(final String name, final Class<E> enumClass) {
176+
return register(new EnumBlockPropertyImpl<>(name, enumClass, Set.of(enumClass.getEnumConstants())));
177+
}
178+
179+
@SuppressWarnings("SameParameterValue")
180+
@SafeVarargs
181+
private static <E extends Enum<E>> EnumBlockProperty<E> enumeration(final String name, final Class<E> enumClass, final E... values) {
182+
return register(new EnumBlockPropertyImpl<>(name, enumClass, Set.of(values)));
183+
}
184+
185+
private static <E extends Enum<E>> EnumBlockProperty<E> enumeration(final String name, final Class<E> enumClass, final Predicate<E> test) {
186+
return register(new EnumBlockPropertyImpl<>(name, enumClass, Arrays.stream(enumClass.getEnumConstants()).filter(test).collect(Collectors.toSet())));
187+
}
188+
189+
private static <V extends Comparable<V>, P extends BlockProperty<V>> P register(final P property) {
190+
PROPERTIES.put(property.name(), property);
191+
return property;
192+
}
193+
//</editor-fold>
194+
}

0 commit comments

Comments
 (0)