Skip to content

Commit ee96569

Browse files
committed
Better Stats API
1 parent a5f209c commit ee96569

File tree

30 files changed

+1535
-110
lines changed

30 files changed

+1535
-110
lines changed

paper-api/src/generated/java/io/papermc/paper/registry/keys/CustomStatisticKeys.java

Lines changed: 561 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package io.papermc.paper.registry.keys;
2+
3+
import static net.kyori.adventure.key.Key.key;
4+
5+
import io.papermc.paper.generated.GeneratedFrom;
6+
import io.papermc.paper.registry.RegistryKey;
7+
import io.papermc.paper.registry.TypedKey;
8+
import io.papermc.paper.statistic.StatisticType;
9+
import net.kyori.adventure.key.Key;
10+
import org.jetbrains.annotations.ApiStatus;
11+
import org.jspecify.annotations.NullMarked;
12+
13+
/**
14+
* Vanilla keys for {@link RegistryKey#STAT_TYPE}.
15+
*
16+
* @apiNote The fields provided here are a direct representation of
17+
* what is available from the vanilla game source. They may be
18+
* changed (including removals) on any Minecraft version
19+
* bump, so cross-version compatibility is not provided on the
20+
* same level as it is on most of the other API.
21+
*/
22+
@SuppressWarnings({
23+
"unused",
24+
"SpellCheckingInspection"
25+
})
26+
@GeneratedFrom("1.21.4")
27+
@NullMarked
28+
@ApiStatus.Experimental
29+
public final class StatisticTypeKeys {
30+
/**
31+
* {@code minecraft:broken}
32+
*
33+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
34+
*/
35+
public static final TypedKey<StatisticType<?>> BROKEN = create(key("broken"));
36+
37+
/**
38+
* {@code minecraft:crafted}
39+
*
40+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
41+
*/
42+
public static final TypedKey<StatisticType<?>> CRAFTED = create(key("crafted"));
43+
44+
/**
45+
* {@code minecraft:custom}
46+
*
47+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
48+
*/
49+
public static final TypedKey<StatisticType<?>> CUSTOM = create(key("custom"));
50+
51+
/**
52+
* {@code minecraft:dropped}
53+
*
54+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
55+
*/
56+
public static final TypedKey<StatisticType<?>> DROPPED = create(key("dropped"));
57+
58+
/**
59+
* {@code minecraft:killed}
60+
*
61+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
62+
*/
63+
public static final TypedKey<StatisticType<?>> KILLED = create(key("killed"));
64+
65+
/**
66+
* {@code minecraft:killed_by}
67+
*
68+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
69+
*/
70+
public static final TypedKey<StatisticType<?>> KILLED_BY = create(key("killed_by"));
71+
72+
/**
73+
* {@code minecraft:mined}
74+
*
75+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
76+
*/
77+
public static final TypedKey<StatisticType<?>> MINED = create(key("mined"));
78+
79+
/**
80+
* {@code minecraft:picked_up}
81+
*
82+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
83+
*/
84+
public static final TypedKey<StatisticType<?>> PICKED_UP = create(key("picked_up"));
85+
86+
/**
87+
* {@code minecraft:used}
88+
*
89+
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
90+
*/
91+
public static final TypedKey<StatisticType<?>> USED = create(key("used"));
92+
93+
private StatisticTypeKeys() {
94+
}
95+
96+
private static TypedKey<StatisticType<?>> create(final Key key) {
97+
return TypedKey.create(RegistryKey.STAT_TYPE, key);
98+
}
99+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.papermc.paper.event.player;
2+
3+
import io.papermc.paper.statistic.Statistic;
4+
import it.unimi.dsi.fastutil.objects.Object2IntMap;
5+
import org.bukkit.entity.Player;
6+
import org.bukkit.event.Cancellable;
7+
import org.bukkit.event.HandlerList;
8+
import org.bukkit.event.player.PlayerEvent;
9+
import org.jspecify.annotations.NullMarked;
10+
11+
/**
12+
* Called when the player requests their statistics.
13+
*/
14+
@NullMarked
15+
public class PlayerRequestStatisticsEvent extends PlayerEvent implements Cancellable {
16+
17+
private static final HandlerList HANDLER_LIST = new HandlerList();
18+
19+
private final Object2IntMap<Statistic<?>> statisticMap;
20+
private boolean cancelled;
21+
22+
public PlayerRequestStatisticsEvent(final Player who, final Object2IntMap<Statistic<?>> statisticMap) {
23+
super(who);
24+
this.statisticMap = statisticMap;
25+
}
26+
27+
public static HandlerList getHandlerList() {
28+
return HANDLER_LIST;
29+
}
30+
31+
/**
32+
* Gets the statistic map to be sent to the player.
33+
*
34+
* @return the mutable statistic map
35+
*/
36+
public Object2IntMap<Statistic<?>> getStatisticMap() {
37+
return this.statisticMap;
38+
}
39+
40+
@Override
41+
public boolean isCancelled() {
42+
return this.cancelled;
43+
}
44+
45+
@Override
46+
public void setCancelled(final boolean cancel) {
47+
this.cancelled = cancel;
48+
}
49+
50+
@Override
51+
public HandlerList getHandlers() {
52+
return HANDLER_LIST;
53+
}
54+
}

paper-api/src/main/java/io/papermc/paper/registry/RegistryKey.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import io.papermc.paper.datacomponent.DataComponentType;
44
import io.papermc.paper.registry.tag.TagKey;
5+
import io.papermc.paper.statistic.CustomStatistic;
6+
import io.papermc.paper.statistic.StatisticType;
57
import net.kyori.adventure.key.Key;
68
import net.kyori.adventure.key.KeyPattern;
79
import net.kyori.adventure.key.Keyed;
@@ -127,6 +129,16 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
127129
* @see io.papermc.paper.registry.keys.DataComponentTypeKeys
128130
*/
129131
RegistryKey<DataComponentType> DATA_COMPONENT_TYPE = create("data_component_type");
132+
/**
133+
* Built-in registry for custom statistics.
134+
* @see io.papermc.paper.registry.keys.CustomStatisticKeys
135+
*/
136+
RegistryKey<CustomStatistic> CUSTOM_STAT = create("custom_stat");
137+
/**
138+
* Built-in registry for statistic types.
139+
* @see io.papermc.paper.registry.keys.StatisticTypeKeys
140+
*/
141+
RegistryKey<StatisticType<?>> STAT_TYPE = create("stat_type");
130142

131143

132144

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package io.papermc.paper.statistic;
2+
3+
import net.kyori.adventure.translation.Translatable;
4+
import org.bukkit.Keyed;
5+
import org.bukkit.NamespacedKey;
6+
import org.bukkit.Registry;
7+
import org.jetbrains.annotations.ApiStatus;
8+
9+
/**
10+
* Custom statistic types.
11+
*/
12+
@ApiStatus.NonExtendable
13+
public interface CustomStatistic extends Keyed, Translatable {
14+
15+
CustomStatistic LEAVE_GAME = get("leave_game");
16+
CustomStatistic PLAY_TIME = get("play_time");
17+
CustomStatistic TOTAL_WORLD_TIME = get("total_world_time");
18+
CustomStatistic TIME_SINCE_DEATH = get("time_since_death");
19+
CustomStatistic TIME_SINCE_REST = get("time_since_rest");
20+
CustomStatistic SNEAK_TIME = get("sneak_time");
21+
CustomStatistic WALK_ONE_CM = get("walk_one_cm");
22+
CustomStatistic CROUCH_ONE_CM = get("crouch_one_cm");
23+
CustomStatistic SPRINT_ONE_CM = get("sprint_one_cm");
24+
CustomStatistic WALK_ON_WATER_ONE_CM = get("walk_on_water_one_cm");
25+
CustomStatistic FALL_ONE_CM = get("fall_one_cm");
26+
CustomStatistic CLIMB_ONE_CM = get("climb_one_cm");
27+
CustomStatistic FLY_ONE_CM = get("fly_one_cm");
28+
CustomStatistic WALK_UNDER_WATER_ONE_CM = get("walk_under_water_one_cm");
29+
CustomStatistic MINECART_ONE_CM = get("minecart_one_cm");
30+
CustomStatistic BOAT_ONE_CM = get("boat_one_cm");
31+
CustomStatistic PIG_ONE_CM = get("pig_one_cm");
32+
CustomStatistic HORSE_ONE_CM = get("horse_one_cm");
33+
CustomStatistic AVIATE_ONE_CM = get("aviate_one_cm");
34+
CustomStatistic SWIM_ONE_CM = get("swim_one_cm");
35+
CustomStatistic STRIDER_ONE_CM = get("strider_one_cm");
36+
CustomStatistic JUMP = get("jump");
37+
CustomStatistic DROP = get("drop");
38+
CustomStatistic DAMAGE_DEALT = get("damage_dealt");
39+
CustomStatistic DAMAGE_DEALT_ABSORBED = get("damage_dealt_absorbed");
40+
CustomStatistic DAMAGE_DEALT_RESISTED = get("damage_dealt_resisted");
41+
CustomStatistic DAMAGE_TAKEN = get("damage_taken");
42+
CustomStatistic DAMAGE_BLOCKED_BY_SHIELD = get("damage_blocked_by_shield");
43+
CustomStatistic DAMAGE_ABSORBED = get("damage_absorbed");
44+
CustomStatistic DAMAGE_RESISTED = get("damage_resisted");
45+
CustomStatistic DEATHS = get("deaths");
46+
CustomStatistic MOB_KILLS = get("mob_kills");
47+
CustomStatistic ANIMALS_BRED = get("animals_bred");
48+
CustomStatistic PLAYER_KILLS = get("player_kills");
49+
CustomStatistic FISH_CAUGHT = get("fish_caught");
50+
CustomStatistic TALKED_TO_VILLAGER = get("talked_to_villager");
51+
CustomStatistic TRADED_WITH_VILLAGER = get("traded_with_villager");
52+
CustomStatistic EAT_CAKE_SLICE = get("eat_cake_slice");
53+
CustomStatistic FILL_CAULDRON = get("fill_cauldron");
54+
CustomStatistic USE_CAULDRON = get("use_cauldron");
55+
CustomStatistic CLEAN_ARMOR = get("clean_armor");
56+
CustomStatistic CLEAN_BANNER = get("clean_banner");
57+
CustomStatistic CLEAN_SHULKER_BOX = get("clean_shulker_box");
58+
CustomStatistic INTERACT_WITH_BREWINGSTAND = get("interact_with_brewingstand");
59+
CustomStatistic INTERACT_WITH_BEACON = get("interact_with_beacon");
60+
CustomStatistic INSPECT_DROPPER = get("inspect_dropper");
61+
CustomStatistic INSPECT_HOPPER = get("inspect_hopper");
62+
CustomStatistic INSPECT_DISPENSER = get("inspect_dispenser");
63+
CustomStatistic PLAY_NOTEBLOCK = get("play_noteblock");
64+
CustomStatistic TUNE_NOTEBLOCK = get("tune_noteblock");
65+
CustomStatistic POT_FLOWER = get("pot_flower");
66+
CustomStatistic TRIGGER_TRAPPED_CHEST = get("trigger_trapped_chest");
67+
CustomStatistic OPEN_ENDERCHEST = get("open_enderchest");
68+
CustomStatistic ENCHANT_ITEM = get("enchant_item");
69+
CustomStatistic PLAY_RECORD = get("play_record");
70+
CustomStatistic INTERACT_WITH_FURNACE = get("interact_with_furnace");
71+
CustomStatistic INTERACT_WITH_CRAFTING_TABLE = get("interact_with_crafting_table");
72+
CustomStatistic OPEN_CHEST = get("open_chest");
73+
CustomStatistic SLEEP_IN_BED = get("sleep_in_bed");
74+
CustomStatistic OPEN_SHULKER_BOX = get("open_shulker_box");
75+
CustomStatistic OPEN_BARREL = get("open_barrel");
76+
CustomStatistic INTERACT_WITH_BLAST_FURNACE = get("interact_with_blast_furnace");
77+
CustomStatistic INTERACT_WITH_SMOKER = get("interact_with_smoker");
78+
CustomStatistic INTERACT_WITH_LECTERN = get("interact_with_lectern");
79+
CustomStatistic INTERACT_WITH_CAMPFIRE = get("interact_with_campfire");
80+
CustomStatistic INTERACT_WITH_CARTOGRAPHY_TABLE = get("interact_with_cartography_table");
81+
CustomStatistic INTERACT_WITH_LOOM = get("interact_with_loom");
82+
CustomStatistic INTERACT_WITH_STONECUTTER = get("interact_with_stonecutter");
83+
CustomStatistic BELL_RING = get("bell_ring");
84+
CustomStatistic RAID_TRIGGER = get("raid_trigger");
85+
CustomStatistic RAID_WIN = get("raid_win");
86+
CustomStatistic INTERACT_WITH_ANVIL = get("interact_with_anvil");
87+
CustomStatistic INTERACT_WITH_GRINDSTONE = get("interact_with_grindstone");
88+
CustomStatistic TARGET_HIT = get("target_hit");
89+
CustomStatistic INTERACT_WITH_SMITHING_TABLE = get("interact_with_smithing_table");
90+
91+
/**
92+
* Gets the statistic with the given custom stat.
93+
*
94+
* @return the statistic for the custom stat.
95+
*/
96+
default Statistic<CustomStatistic> stat() {
97+
return StatisticType.CUSTOM.of(this);
98+
}
99+
100+
private static CustomStatistic get(final String key) {
101+
return Registry.CUSTOM_STAT.getOrThrow(NamespacedKey.minecraft(key));
102+
}
103+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.papermc.paper.statistic;
2+
3+
import org.bukkit.scoreboard.Criteria;
4+
import org.jetbrains.annotations.ApiStatus;
5+
6+
/**
7+
* Represents an individual statistic. Obtained via {@link StatisticType#of(Object)}.
8+
* Can be used as a criteria for {@link org.bukkit.scoreboard.Scoreboard#registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
9+
*
10+
* @param <S> stat value type.
11+
*/
12+
@ApiStatus.NonExtendable
13+
public interface Statistic<S> extends Criteria {
14+
15+
/**
16+
* Gets the statistic.
17+
*
18+
* @return the stat
19+
*/
20+
S value();
21+
22+
/**
23+
* Get the stat type.
24+
*
25+
* @return the stat type
26+
*/
27+
StatisticType<S> type();
28+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package io.papermc.paper.statistic;
2+
3+
import io.papermc.paper.registry.RegistryKey;
4+
import net.kyori.adventure.key.Key;
5+
import net.kyori.adventure.key.KeyPattern;
6+
import net.kyori.adventure.translation.Translatable;
7+
import org.bukkit.Keyed;
8+
import org.bukkit.Registry;
9+
import org.bukkit.block.BlockType;
10+
import org.bukkit.entity.EntityType;
11+
import org.bukkit.inventory.ItemType;
12+
import org.jetbrains.annotations.ApiStatus;
13+
14+
@ApiStatus.NonExtendable
15+
public interface StatisticType<S> extends Keyed, Translatable {
16+
17+
StatisticType<BlockType> BLOCK_MINED = get("mined");
18+
StatisticType<ItemType> ITEM_CRAFTED = get("crafted");
19+
StatisticType<ItemType> ITEM_USED = get("used");
20+
StatisticType<ItemType> ITEM_BROKEN = get("broken");
21+
StatisticType<ItemType> ITEM_PICKED_UP = get("picked_up");
22+
StatisticType<ItemType> ITEM_DROPPED = get("dropped");
23+
StatisticType<EntityType> ENTITY_KILLED = get("killed");
24+
StatisticType<EntityType> ENTITY_KILLED_BY = get("killed_by");
25+
StatisticType<CustomStatistic> CUSTOM = get("custom");
26+
27+
@SuppressWarnings("unchecked")
28+
private static <S> StatisticType<S> get(@KeyPattern.Value final String key) {
29+
return (StatisticType<S>) Registry.STAT_TYPE.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
30+
}
31+
32+
/**
33+
* Creates or gets the statistic from this type for the specified value.
34+
*
35+
* @param value what you want the stat of
36+
* @return the statistic for that thing
37+
* @throws IllegalArgumentException if the thing is not valid for this {@link StatisticType}
38+
*/
39+
Statistic<S> of(S value);
40+
41+
/**
42+
* Gets the registry key associated with this stat type.
43+
*
44+
* @return the registry
45+
*/
46+
RegistryKey<S> registryKey();
47+
48+
/**
49+
* {@inheritDoc}
50+
* <p>
51+
* {@link StatisticType#CUSTOM} does <b>NOT</b> have a
52+
* translation key.
53+
* @throws IllegalArgumentException if used with {@link StatisticType#CUSTOM}
54+
* @see CustomStatistic#translationKey()
55+
*/
56+
@Override
57+
String translationKey();
58+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@NullMarked
2+
package io.papermc.paper.statistic;
3+
4+
import org.jspecify.annotations.NullMarked;

0 commit comments

Comments
 (0)