summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSenmori <thesenmori@gmail.com>2018-08-12 18:23:28 +1000
committermd_5 <git@md-5.net>2018-08-12 18:32:40 +1000
commitf0f3398172aa20a2ea1f29bf69799c4a920f24e3 (patch)
treed64bbf361b9c99eb41554c21382ec9e61d8ec04c
parentc23d391fcdf19a054ebf5ac886a5679c2bf0ad49 (diff)
downloadbukkit-f0f3398172aa20a2ea1f29bf69799c4a920f24e3.tar
bukkit-f0f3398172aa20a2ea1f29bf69799c4a920f24e3.tar.gz
bukkit-f0f3398172aa20a2ea1f29bf69799c4a920f24e3.tar.lz
bukkit-f0f3398172aa20a2ea1f29bf69799c4a920f24e3.tar.xz
bukkit-f0f3398172aa20a2ea1f29bf69799c4a920f24e3.zip
SPIGOT-1936: LootTable API
-rw-r--r--src/main/java/org/bukkit/Bukkit.java11
-rw-r--r--src/main/java/org/bukkit/Server.java9
-rw-r--r--src/main/java/org/bukkit/block/Chest.java3
-rw-r--r--src/main/java/org/bukkit/block/Dispenser.java3
-rw-r--r--src/main/java/org/bukkit/block/Dropper.java3
-rw-r--r--src/main/java/org/bukkit/block/Hopper.java3
-rw-r--r--src/main/java/org/bukkit/block/ShulkerBox.java3
-rw-r--r--src/main/java/org/bukkit/entity/Mob.java4
-rw-r--r--src/main/java/org/bukkit/entity/minecart/HopperMinecart.java3
-rw-r--r--src/main/java/org/bukkit/entity/minecart/StorageMinecart.java3
-rw-r--r--src/main/java/org/bukkit/loot/LootContext.java168
-rw-r--r--src/main/java/org/bukkit/loot/LootTable.java37
-rw-r--r--src/main/java/org/bukkit/loot/LootTables.java128
-rw-r--r--src/main/java/org/bukkit/loot/Lootable.java51
14 files changed, 421 insertions, 8 deletions
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index bdd5a753..5bea055b 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -33,6 +33,7 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Merchant;
import org.bukkit.inventory.Recipe;
+import org.bukkit.loot.LootTable;
import org.bukkit.map.MapView;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.PluginManager;
@@ -1254,6 +1255,16 @@ public final class Bukkit {
}
/**
+ * Gets the specified {@link LootTable}.
+ *
+ * @param key the name of the LootTable
+ * @return the LootTable, or null if no LootTable is found with that name
+ */
+ public static LootTable getLootTable(NamespacedKey key) {
+ return server.getLootTable(key);
+ }
+
+ /**
* @see UnsafeValues
* @return the unsafe values instance
*/
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 4daee3b0..c3535e90 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -33,6 +33,7 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Merchant;
import org.bukkit.inventory.Recipe;
+import org.bukkit.loot.LootTable;
import org.bukkit.map.MapView;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.PluginManager;
@@ -1037,6 +1038,14 @@ public interface Server extends PluginMessageRecipient {
<T extends Keyed> Tag<T> getTag(String registry, NamespacedKey tag, Class<T> clazz);
/**
+ * Gets the specified {@link LootTable}.
+ *
+ * @param key the name of the LootTable
+ * @return the LootTable, or null if no LootTable is found with that name
+ */
+ LootTable getLootTable(NamespacedKey key);
+
+ /**
* @see UnsafeValues
* @return the unsafe values instance
*/
diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java
index 97dc7813..815d79a5 100644
--- a/src/main/java/org/bukkit/block/Chest.java
+++ b/src/main/java/org/bukkit/block/Chest.java
@@ -2,11 +2,12 @@ package org.bukkit.block;
import org.bukkit.Nameable;
import org.bukkit.inventory.Inventory;
+import org.bukkit.loot.Lootable;
/**
* Represents a captured state of a chest.
*/
-public interface Chest extends Container, Nameable {
+public interface Chest extends Container, Nameable, Lootable {
/**
* Gets the inventory of the chest block represented by this block state.
diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java
index 108332df..2741625d 100644
--- a/src/main/java/org/bukkit/block/Dispenser.java
+++ b/src/main/java/org/bukkit/block/Dispenser.java
@@ -1,12 +1,13 @@
package org.bukkit.block;
import org.bukkit.Nameable;
+import org.bukkit.loot.Lootable;
import org.bukkit.projectiles.BlockProjectileSource;
/**
* Represents a captured state of a dispenser.
*/
-public interface Dispenser extends Container, Nameable {
+public interface Dispenser extends Container, Nameable, Lootable {
/**
* Gets the BlockProjectileSource object for the dispenser.
diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java
index ba091374..2e8c3f71 100644
--- a/src/main/java/org/bukkit/block/Dropper.java
+++ b/src/main/java/org/bukkit/block/Dropper.java
@@ -1,11 +1,12 @@
package org.bukkit.block;
import org.bukkit.Nameable;
+import org.bukkit.loot.Lootable;
/**
* Represents a captured state of a dropper.
*/
-public interface Dropper extends Container, Nameable {
+public interface Dropper extends Container, Nameable, Lootable {
/**
* Tries to drop a randomly selected item from the dropper's inventory,
diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java
index bc3aeef2..73fce5f3 100644
--- a/src/main/java/org/bukkit/block/Hopper.java
+++ b/src/main/java/org/bukkit/block/Hopper.java
@@ -1,8 +1,9 @@
package org.bukkit.block;
import org.bukkit.Nameable;
+import org.bukkit.loot.Lootable;
/**
* Represents a captured state of a hopper.
*/
-public interface Hopper extends Container, Nameable { }
+public interface Hopper extends Container, Nameable, Lootable { }
diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java
index 4c1740e7..8e061e4a 100644
--- a/src/main/java/org/bukkit/block/ShulkerBox.java
+++ b/src/main/java/org/bukkit/block/ShulkerBox.java
@@ -2,11 +2,12 @@ package org.bukkit.block;
import org.bukkit.DyeColor;
import org.bukkit.Nameable;
+import org.bukkit.loot.Lootable;
/**
* Represents a captured state of a ShulkerBox.
*/
-public interface ShulkerBox extends Container, Nameable {
+public interface ShulkerBox extends Container, Nameable, Lootable {
/**
* Get the {@link DyeColor} corresponding to this ShulkerBox
diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java
index 15dee0ee..d029d34e 100644
--- a/src/main/java/org/bukkit/entity/Mob.java
+++ b/src/main/java/org/bukkit/entity/Mob.java
@@ -1,9 +1,11 @@
package org.bukkit.entity;
+import org.bukkit.loot.Lootable;
+
/**
* Represents a Mob. Mobs are living entities with simple AI.
*/
-public interface Mob extends LivingEntity {
+public interface Mob extends LivingEntity, Lootable {
/**
* Instructs this Mob to set the specified LivingEntity as its target.
diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
index 03304319..8ced5403 100644
--- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
+++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java
@@ -2,11 +2,12 @@ package org.bukkit.entity.minecart;
import org.bukkit.entity.Minecart;
import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.loot.Lootable;
/**
* Represents a Minecart with a Hopper inside it
*/
-public interface HopperMinecart extends Minecart, InventoryHolder {
+public interface HopperMinecart extends Minecart, InventoryHolder, Lootable {
/**
* Checks whether or not this Minecart will pick up
diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
index 4f04ab40..9ea403e6 100644
--- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
+++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java
@@ -2,11 +2,12 @@ package org.bukkit.entity.minecart;
import org.bukkit.entity.Minecart;
import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.loot.Lootable;
/**
* Represents a minecart with a chest. These types of {@link Minecart
* minecarts} have their own inventory that can be accessed using methods
* from the {@link InventoryHolder} interface.
*/
-public interface StorageMinecart extends Minecart, InventoryHolder {
+public interface StorageMinecart extends Minecart, InventoryHolder, Lootable {
}
diff --git a/src/main/java/org/bukkit/loot/LootContext.java b/src/main/java/org/bukkit/loot/LootContext.java
new file mode 100644
index 00000000..a2c83e58
--- /dev/null
+++ b/src/main/java/org/bukkit/loot/LootContext.java
@@ -0,0 +1,168 @@
+package org.bukkit.loot;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.HumanEntity;
+
+/**
+ * Represents additional information a {@link LootTable} can use to modify it's
+ * generated loot.
+ */
+public final class LootContext {
+
+ public static final int DEFAULT_LOOT_MODIFIER = -1;
+
+ private final Location location;
+ private final float luck;
+ private final int lootingModifier;
+ private final Entity lootedEntity;
+ private final HumanEntity killer;
+
+ private LootContext(Location location, float luck, int lootingModifier, Entity lootedEntity, HumanEntity killer) {
+ Validate.notNull(location, "LootContext location cannot be null");
+ Validate.notNull(location.getWorld(), "LootContext World cannot be null");
+ this.location = location;
+ this.luck = luck;
+ this.lootingModifier = lootingModifier;
+ this.lootedEntity = lootedEntity;
+ this.killer = killer;
+ }
+
+ /**
+ * The {@link Location} to store where the loot will be generated.
+ *
+ * @return the Location of where the loot will be generated
+ */
+ public Location getLocation() {
+ return location;
+ }
+
+ /**
+ * Represents the {@link org.bukkit.potion.PotionEffectType#LUCK} that an
+ * entity can have. The higher the value the better chance of receiving more
+ * loot.
+ *
+ * @return luck
+ */
+ public float getLuck() {
+ return luck;
+ }
+
+ /**
+ * Represents the
+ * {@link org.bukkit.enchantments.Enchantment#LOOT_BONUS_MOBS} the
+ * {@link #getKiller()} entity has on their equipped item.
+ *
+ * This value is only set via
+ * {@link LootContext.Builder#lootingModifier(int)}. If not set, the
+ * {@link #getKiller()} entity's looting level will be used instead.
+ *
+ * @return the looting level
+ */
+ public int getLootingModifier() {
+ return lootingModifier;
+ }
+
+ /**
+ * Get the {@link Entity} that was killed. Can be null.
+ *
+ * @return the looted entity or null
+ */
+ public Entity getLootedEntity() {
+ return lootedEntity;
+ }
+
+ /**
+ * Get the {@link HumanEntity} who killed the {@link #getLootedEntity()}.
+ * Can be null.
+ *
+ * @return the killer entity, or null.
+ */
+ public HumanEntity getKiller() {
+ return killer;
+ }
+
+ /**
+ * Utility class to make building {@link LootContext} easier. The only
+ * required argument is {@link Location} with a valid (non-null)
+ * {@link org.bukkit.World}.
+ */
+ public static class Builder {
+
+ private final Location location;
+ private float luck;
+ private int lootingModifier = LootContext.DEFAULT_LOOT_MODIFIER;
+ private Entity lootedEntity;
+ private HumanEntity killer;
+
+ /**
+ * Creates a new LootContext.Builder instance to facilitate easy
+ * creation of {@link LootContext}s.
+ *
+ * @param location the location the LootContext should use
+ */
+ public Builder(Location location) {
+ this.location = location;
+ }
+
+ /**
+ * Set how much luck to have when generating loot.
+ *
+ * @param luck the luck level
+ * @return the Builder
+ */
+ public Builder luck(float luck) {
+ this.luck = luck;
+ return this;
+ }
+
+ /**
+ * Set the {@link org.bukkit.enchantments.Enchantment#LOOT_BONUS_MOBS}
+ * level equivalent to use when generating loot. Values less than or
+ * equal to 0 will force the {@link LootTable} to only return a single
+ * {@link org.bukkit.inventory.ItemStack} per pool.
+ *
+ * @param modifier the looting level modifier
+ * @return the Builder
+ */
+ public Builder lootingModifier(int modifier) {
+ this.lootingModifier = modifier;
+ return this;
+ }
+
+ /**
+ * The entity that was killed.
+ *
+ * @param lootedEntity the looted entity
+ * @return the Builder
+ */
+ public Builder lootedEntity(Entity lootedEntity) {
+ this.lootedEntity = lootedEntity;
+ return this;
+ }
+
+ /**
+ * Set the {@link org.bukkit.entity.HumanEntity} that killed
+ * {@link #getLootedEntity()}. This entity will be used to get the
+ * looting level if {@link #lootingModifier(int)} is not set.
+ *
+ * @param killer the killer entity
+ * @return the Builder
+ */
+ public Builder killer(HumanEntity killer) {
+ this.killer = killer;
+ return this;
+ }
+
+ /**
+ * Create a new {@link LootContext} instance using the supplied
+ * parameters.
+ *
+ * @return a new {@link LootContext} instance
+ */
+ public LootContext build() {
+ return new LootContext(location, luck, lootingModifier, lootedEntity, killer);
+ }
+ }
+}
diff --git a/src/main/java/org/bukkit/loot/LootTable.java b/src/main/java/org/bukkit/loot/LootTable.java
new file mode 100644
index 00000000..30b16200
--- /dev/null
+++ b/src/main/java/org/bukkit/loot/LootTable.java
@@ -0,0 +1,37 @@
+package org.bukkit.loot;
+
+import org.bukkit.Keyed;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Collection;
+import java.util.Random;
+
+/**
+ * LootTables are technical files that represent what items should be in
+ * naturally generated containers, what items should be dropped when killing a
+ * mob, or what items can be fished.
+ *
+ * See the <a href="https://minecraft.gamepedia.com/Loot_table">
+ * Minecraft Wiki</a> for more information.
+ */
+public interface LootTable extends Keyed {
+
+ /**
+ * Returns a mutable list of loot generated by this LootTable.
+ *
+ * @param random the random instance to use to generate loot
+ * @param context context within to populate loot
+ * @return a list of ItemStacks
+ */
+ Collection<ItemStack> populateLoot(Random random, LootContext context);
+
+ /**
+ * Attempt to fill an inventory with this LootTable's loot.
+ *
+ * @param inventory the inventory to fill
+ * @param random the random instance to use to generate loot
+ * @param context context within to populate loot
+ */
+ void fillInventory(Inventory inventory, Random random, LootContext context);
+}
diff --git a/src/main/java/org/bukkit/loot/LootTables.java b/src/main/java/org/bukkit/loot/LootTables.java
new file mode 100644
index 00000000..613a198e
--- /dev/null
+++ b/src/main/java/org/bukkit/loot/LootTables.java
@@ -0,0 +1,128 @@
+package org.bukkit.loot;
+
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+
+/**
+ * This enum holds a list of all known {@link LootTable}s offered by Mojang.
+ * This list is not guaranteed to be accurate in future versions.
+ *
+ * See the
+ * <a href="https://minecraft.gamepedia.com/Loot_table#List_of_loot_tables">
+ * Minecraft Wiki</a> for more information on loot tables.
+ */
+public enum LootTables implements Keyed {
+
+ EMPTY("empty"),
+ // Chests/Dispensers - treasure chests
+ ABANDONED_MINESHAFT("chests/abandoned_mineshaft"),
+ BURIED_TREASURE("chests/buried_treasure"),
+ DESERT_PYRAMID("chests/desert_pyramid"),
+ END_CITY_TREASURE("chests/end_city_treasure"),
+ IGLOO_CHEST("chests/igloo_chest"),
+ JUNGLE_TEMPLE("chests/jungle_temple"),
+ JUNGLE_TEMPLE_DISPENSER("chests/jungle_temple_dispenser"),
+ NETHER_BRIDGE("chests/nether_bridge"),
+ SHIPWRECK_MAP("chests/shipwreck_map"),
+ SHIPWRECK_SUPPLY("chests/shipwreck_supply"),
+ SHIPWRECK_TREASURE("chests/shipwreck_treasure"),
+ SIMPLE_DUNGEON("chests/simple_dungeon"),
+ SPAWN_BONUS_CHEST("chests/spawn_bonus_chest"),
+ STRONGHOLD_CORRIDOR("chests/stronghold_corridor"),
+ STRONGHOLD_CROSSING("chests/stronghold_crossing"),
+ STRONGHOLD_LIBRARY("chests/stronghold_library"),
+ UNDERWATER_RUIN_BIG("chests/underwater_ruin_big"),
+ UNDERWATER_RUIN_SMALL("chests/underwater_ruin_small"),
+ VILLAGE_BLACKSMITH("chests/village_blacksmith"),
+ WOODLAND_MANSION("chests/woodland_mansion"),
+ // Entities
+ BAT("entities/bat"),
+ BLAZE("entities/blaze"),
+ CAVE_SPIDER("entities/cave_spider"),
+ CHICKEN("entities/chicken"),
+ COD("entities/cod"),
+ COW("entities/cow"),
+ CREEPER("entities/creeper"),
+ DOLPHIN("entities/dolphin"),
+ DONKEY("entities/donkey"),
+ DROWNED("entities/drowned"),
+ ELDER_GUARDIAN("entities/elder_guardian"),
+ ENDERMAN("entities/enderman"),
+ ENDERMITE("entities/endermite"),
+ ENDER_DRAGON("entities/ender_dragon"),
+ EVOKER("entities/evoker"),
+ GHAST("entities/ghast"),
+ GIANT("entities/giant"),
+ GUARDIAN("entities/guardian"),
+ HORSE("entities/horse"),
+ HUSK("entities/husk"),
+ IRON_GOLEM("entities/iron_golem"),
+ LLAMA("entities/llama"),
+ MAGMA_CUBE("entities/magma_cube"),
+ MULE("entities/mule"),
+ MUSHROOM_COW("entities/mushroom_cow"),
+ OCELOT("entities/ocelot"),
+ PARROT("entities/parrot"),
+ PHANTOM("entities/phantom"),
+ PIG("entities/pig"),
+ POLAR_BEAR("entities/polar_bear"),
+ PUFFERFISH("entities/pufferfish"),
+ RABBIT("entities/rabbit"),
+ SALMON("entities/salmon"),
+ // Sheep entry here, moved below for organizational purposes
+ SHULKER("entities/shulker"),
+ SILVERFISH("entities/silverfish"),
+ SKELETON("entities/skeleton"),
+ SKELETON_HORSE("entities/skeleton_horse"),
+ SLIME("entities/slime"),
+ SNOW_GOLEM("entities/snow_golem"),
+ SPIDER("entities/spider"),
+ SQUID("entities/squid"),
+ STRAY("entities/stray"),
+ TROPICAL_FISH("entities/tropical_fish"),
+ TURTLE("entities/turtle"),
+ VEX("entities/vex"),
+ VILLAGER("entities/villager"),
+ VINDICATOR("entities/vindicator"),
+ WITCH("entities/witch"),
+ WITHER_SKELETON("entities/wither_skeleton"),
+ WOLF("entities/wolf"),
+ ZOMBIE("entities/zombie"),
+ ZOMBIE_HORSE("entities/zombie_horse"),
+ ZOMBIE_PIGMAN("entities/zombie_pigman"),
+ ZOMBIE_VILLAGER("entities/zombie_villager"),
+ // Gameplay
+ FISHING("gameplay/fishing"),
+ FISHING_FISH("gameplay/fishing/fish"),
+ FISHING_JUNK("gameplay/fishing/junk"),
+ FISHING_TREASURE("gameplay/fishing/treasure"),
+ // Sheep
+ SHEEP("entities/sheep"),
+ SHEEP_BLACK("entities/sheep/black"),
+ SHEEP_BLUE("entities/sheep/blue"),
+ SHEEP_BROWN("entities/sheep/brown"),
+ SHEEP_CYAN("entities/sheep/cyan"),
+ SHEEP_GRAY("entities/sheep/gray"),
+ SHEEP_GREEN("entities/sheep/green"),
+ SHEEP_LIGHT_BLUE("entities/sheep/light_blue"),
+ SHEEP_LIME("entities/sheep/lime"),
+ SHEEP_MAGENTA("entities/sheep/magenta"),
+ SHEEP_ORANGE("entities/sheep/orange"),
+ SHEEP_PINK("entities/sheep/pink"),
+ SHEEP_PURPLE("entities/sheep/purple"),
+ SHEEP_RED("entities/sheep/red"),
+ SHEEP_WHITE("entities/sheep/white"),
+ SHEEP_YELLOW("entities/sheep/yellow"),
+ ;
+
+ private final String location;
+
+ private LootTables(String location) {
+ this.location = location;
+ }
+
+ @Override
+ public NamespacedKey getKey() {
+ return NamespacedKey.minecraft(location);
+ }
+}
diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java
new file mode 100644
index 00000000..f4b3d021
--- /dev/null
+++ b/src/main/java/org/bukkit/loot/Lootable.java
@@ -0,0 +1,51 @@
+package org.bukkit.loot;
+
+/**
+ * Represents a {@link org.bukkit.block.Container} or a
+ * {@link org.bukkit.entity.Mob} that can have a loot table.
+ * <br>
+ * Container loot will only generate upon opening, and only when the container
+ * is <i>first</i> opened.
+ * <br>
+ * Entities will only generate loot upon death.
+ */
+public interface Lootable {
+
+ /**
+ * Set the loot table for a container or entity.
+ * <br>
+ * To remove a loot table use null. Do not use {@link LootTables#EMPTY} to
+ * clear a LootTable.
+ *
+ * @param table the Loot Table this {@link org.bukkit.block.Container} or
+ * {@link org.bukkit.entity.Mob} will have.
+ */
+ void setLootTable(LootTable table);
+
+ /**
+ * Gets the Loot Table attached to this block or entity.
+ * <br>
+ *
+ * If an block/entity does not have a loot table, this will return null, NOT
+ * an empty loot table.
+ *
+ * @return the Loot Table attached to this block or entity.
+ */
+ LootTable getLootTable();
+
+ /**
+ * Set the seed used when this Loot Table generates loot.
+ *
+ * @param seed the seed to used to generate loot. Default is 0.
+ */
+ void setSeed(long seed);
+
+ /**
+ * Get the Loot Table's seed.
+ * <br>
+ * The seed is used when generating loot.
+ *
+ * @return the seed
+ */
+ long getSeed();
+}