diff options
author | Senmori <thesenmori@gmail.com> | 2018-08-12 18:39:51 +1000 |
---|---|---|
committer | md_5 <git@md-5.net> | 2018-08-12 18:40:03 +1000 |
commit | c0df4b82d380bea4fd66cc887a1476468e2301c4 (patch) | |
tree | 0fa0d8db07d29c0f1c53bb9a70568eb42e9a9c7d /src | |
parent | 15da7067067a0786d221f2ad3cd060acd4dd3431 (diff) | |
download | craftbukkit-c0df4b82d380bea4fd66cc887a1476468e2301c4.tar craftbukkit-c0df4b82d380bea4fd66cc887a1476468e2301c4.tar.gz craftbukkit-c0df4b82d380bea4fd66cc887a1476468e2301c4.tar.lz craftbukkit-c0df4b82d380bea4fd66cc887a1476468e2301c4.tar.xz craftbukkit-c0df4b82d380bea4fd66cc887a1476468e2301c4.zip |
SPIGOT-1936: LootTable API
Diffstat (limited to 'src')
10 files changed, 284 insertions, 7 deletions
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java new file mode 100644 index 00000000..0740c565 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/CraftLootTable.java @@ -0,0 +1,109 @@ +package org.bukkit.craftbukkit; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; +import net.minecraft.server.BlockPosition; +import net.minecraft.server.DamageSource; +import net.minecraft.server.Entity; +import net.minecraft.server.EntityHuman; +import net.minecraft.server.IInventory; +import net.minecraft.server.LootTable; +import net.minecraft.server.LootTableInfo; +import net.minecraft.server.WorldServer; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.LootContext; + +public class CraftLootTable implements org.bukkit.loot.LootTable { + + private final LootTable handle; + private final NamespacedKey key; + + public CraftLootTable(NamespacedKey key, LootTable handle) { + this.handle = handle; + this.key = key; + } + + public LootTable getHandle() { + return handle; + } + + @Override + public Collection<ItemStack> populateLoot(Random random, LootContext context) { + LootTableInfo nmsContext = convertContext(context); + List<net.minecraft.server.ItemStack> nmsItems = handle.a(random, nmsContext); // PAIL rename populateLoot + Collection<ItemStack> bukkit = new ArrayList<>(nmsItems.size()); + + for (net.minecraft.server.ItemStack item : nmsItems) { + if (item.isEmpty()) { + continue; + } + bukkit.add(CraftItemStack.asBukkitCopy(item)); + } + + return bukkit; + } + + @Override + public void fillInventory(Inventory inventory, Random random, LootContext context) { + LootTableInfo nmsContext = convertContext(context); + CraftInventory craftInventory = (CraftInventory) inventory; + IInventory handle = craftInventory.getInventory(); + + // TODO: When events are added, call event here w/ custom reason? + getHandle().a(handle, random, nmsContext); // PAIL rename fillInventory + } + + @Override + public NamespacedKey getKey() { + return key; + } + + private LootTableInfo convertContext(LootContext context) { + Location loc = context.getLocation(); + WorldServer handle = ((CraftWorld) loc.getWorld()).getHandle(); + + LootTableInfo.a builder = new LootTableInfo.a(handle); // PAIL rename Builder + builder.a(context.getLuck()); // PAIL rename withLuck, luck + + if (context.getLootedEntity() != null) { + Entity nmsLootedEntity = ((CraftEntity) context.getLootedEntity()).getHandle(); + builder.a(nmsLootedEntity); // PAIL Rename withLootedEntity, lootedEntity + builder.a(DamageSource.GENERIC); // PAIL rename withDamageSource, damageSource + builder.a(new BlockPosition(nmsLootedEntity)); // PAIL rename withPosition, position + } + + if (context.getKiller() != null) { + EntityHuman nmsKiller = ((CraftHumanEntity) context.getKiller()).getHandle(); + builder.a(nmsKiller); // PAIL rename withKiller, killer + // If there is a player killer, damage source should reflect that in case loot tables use that information + builder.a(DamageSource.playerAttack(nmsKiller)); // PAIL rename withDamageSource, damageSource + } + + return builder.a(); // PAIL rename build + } + + @Override + public String toString() { + return getKey().toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof org.bukkit.loot.LootTable)) { + return false; + } + + org.bukkit.loot.LootTable table = (org.bukkit.loot.LootTable) obj; + return table.getKey().equals(this.getKey()); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index abc08ed3..9bb0ceb2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -95,6 +95,7 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.loot.LootTable; import org.bukkit.permissions.Permissible; import org.bukkit.permissions.Permission; import org.bukkit.plugin.Plugin; @@ -1765,6 +1766,13 @@ public final class CraftServer implements Server { } } + public LootTable getLootTable(NamespacedKey key) { + Validate.notNull(key, "NamespacedKey cannot be null"); + + LootTableRegistry registry = getServer().aP(); // PAIL getLootTableRegistry + return new CraftLootTable(key, registry.a(CraftNamespacedKey.toMinecraft(key))); // PAIL rename getLootTable + } + @Deprecated @Override public UnsafeValues getUnsafe() { diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java index d7677192..34bcc49c 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java @@ -1,12 +1,17 @@ package org.bukkit.craftbukkit.block; +import net.minecraft.server.MinecraftKey; import net.minecraft.server.TileEntityLootable; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Nameable; import org.bukkit.block.Block; import org.bukkit.craftbukkit.util.CraftChatMessage; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.loot.LootTable; +import org.bukkit.loot.Lootable; -public abstract class CraftLootable<T extends TileEntityLootable> extends CraftContainer<T> implements Nameable { +public abstract class CraftLootable<T extends TileEntityLootable> extends CraftContainer<T> implements Nameable, Lootable { public CraftLootable(Block block, Class<T> tileEntityClass) { super(block, tileEntityClass); @@ -34,5 +39,38 @@ public abstract class CraftLootable<T extends TileEntityLootable> extends CraftC if (!this.getSnapshot().hasCustomName()) { lootable.setCustomName(null); } + if (this.getSnapshot().Q_() == null) { + lootable.a((MinecraftKey) null, 0L); // PAIL rename setLootTable + } + } + + @Override + public LootTable getLootTable() { + if (getSnapshot().Q_() == null) { + return null; + } + + MinecraftKey key = getSnapshot().Q_(); + return Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(key)); + } + + @Override + public void setLootTable(LootTable table) { + setLootTable(table, getSeed()); + } + + @Override + public long getSeed() { + return getSnapshotNBT().getLong("LootTableSeed"); // returns OL if an error occurred + } + + @Override + public void setSeed(long seed) { + setLootTable(getLootTable(), seed); + } + + private void setLootTable(LootTable table, long seed) { + MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getSnapshot().a(key, seed); // PAIL setLootTable } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java index 69435c45..1b5b266c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java @@ -9,7 +9,7 @@ import org.bukkit.entity.minecart.StorageMinecart; import org.bukkit.inventory.Inventory; @SuppressWarnings("deprecation") -public class CraftMinecartChest extends CraftMinecart implements StorageMinecart { +public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { private final CraftInventory inventory; public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java new file mode 100644 index 00000000..8ce97374 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java @@ -0,0 +1,54 @@ +package org.bukkit.craftbukkit.entity; + +import net.minecraft.server.EntityMinecartAbstract; +import net.minecraft.server.EntityMinecartContainer; +import net.minecraft.server.MinecraftKey; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.loot.LootTable; +import org.bukkit.loot.Lootable; + +public abstract class CraftMinecartContainer extends CraftMinecart implements Lootable { + + public CraftMinecartContainer(CraftServer server, EntityMinecartAbstract entity) { + super(server, entity); + } + + @Override + public EntityMinecartContainer getHandle() { + return (EntityMinecartContainer) entity; + } + + @Override + public void setLootTable(LootTable table) { + setLootTable(table, getSeed()); + } + + @Override + public LootTable getLootTable() { + MinecraftKey nmsTable = getHandle().Q_(); // PAIL getLootTable + if (nmsTable == null) { + return null; // return empty loot table? + } + + NamespacedKey key = CraftNamespacedKey.fromMinecraft(nmsTable); + return Bukkit.getLootTable(key); + } + + @Override + public void setSeed(long seed) { + setLootTable(getLootTable(), seed); + } + + @Override + public long getSeed() { + return getHandle().d; // PAIL rename lootTableSeed + } + + private void setLootTable(LootTable table, long seed) { + MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + getHandle().a(newKey, seed); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java index e9963e21..f29365c9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java @@ -8,10 +8,10 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.inventory.Inventory; -final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart { +public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { private final CraftInventory inventory; - CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { + public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { super(server, entity); inventory = new CraftInventory(entity); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java index 43178db8..eb643cff 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -1,9 +1,13 @@ package org.bukkit.craftbukkit.entity; import net.minecraft.server.EntityInsentient; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Mob; +import org.bukkit.loot.LootTable; public abstract class CraftMob extends CraftLivingEntity implements Mob { public CraftMob(CraftServer server, EntityInsentient entity) { @@ -36,4 +40,29 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { public String toString() { return "CraftMob"; } + + @Override + public void setLootTable(LootTable table) { + getHandle().bI = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); // PAIL rename lootTableKey + } + + @Override + public LootTable getLootTable() { + if (getHandle().bI == null) { + getHandle().bI = getHandle().getLootTable(); // Restore to entity default + } + + NamespacedKey key = CraftNamespacedKey.fromMinecraft(getHandle().bI); // PAIL rename lootTableKey + return Bukkit.getLootTable(key); + } + + @Override + public void setSeed(long seed) { + getHandle().bJ = seed; // PAIL rename lootTableSeed + } + + @Override + public long getSeed() { + return getHandle().bJ; // PAIL rename lootTableSeed + } } diff --git a/src/test/java/org/bukkit/LootTablesTest.java b/src/test/java/org/bukkit/LootTablesTest.java new file mode 100644 index 00000000..8d2cbb44 --- /dev/null +++ b/src/test/java/org/bukkit/LootTablesTest.java @@ -0,0 +1,22 @@ +package org.bukkit; + +import org.bukkit.loot.LootTable; +import org.bukkit.loot.LootTables; +import org.bukkit.support.AbstractTestingBase; +import org.junit.Assert; +import org.junit.Test; + +public class LootTablesTest extends AbstractTestingBase { + + @Test + public void testLootTablesEnumExists() { + LootTables[] tables = LootTables.values(); + + for (LootTables table : tables) { + LootTable lootTable = Bukkit.getLootTable(table.getKey()); + + Assert.assertNotNull("Unknown LootTable " + table.getKey(), lootTable); + Assert.assertEquals(lootTable.getKey(), table.getKey()); + } + } +} diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java index b6bc6641..53cbb525 100644 --- a/src/test/java/org/bukkit/support/AbstractTestingBase.java +++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; import net.minecraft.server.DispenserRegistry; import net.minecraft.server.EnumResourcePackType; +import net.minecraft.server.LootTableRegistry; import net.minecraft.server.ResourceManager; import net.minecraft.server.ResourcePackVanilla; import net.minecraft.server.TagRegistry; @@ -24,12 +25,16 @@ public abstract class AbstractTestingBase { // Materials that only exist in block form (or are legacy) public static final List<Material> INVALIDATED_MATERIALS; + public static final LootTableRegistry LOOT_TABLE_REGISTRY; + public static final TagRegistry TAG_REGISTRY; + static { DispenserRegistry.c(); // Set up resource manager ResourceManager resourceManager = new ResourceManager(EnumResourcePackType.SERVER_DATA); - // add tags for unit tests - resourceManager.a(new TagRegistry()); + // add tags and loot tables for unit tests + resourceManager.a(TAG_REGISTRY = new TagRegistry()); + resourceManager.a(LOOT_TABLE_REGISTRY = new LootTableRegistry()); // Register vanilla pack resourceManager.a(Collections.singletonList(new ResourcePackVanilla("minecraft"))); @@ -43,6 +48,6 @@ public abstract class AbstractTestingBase { } } INVALIDATED_MATERIALS = builder.build(); - Assert.assertTrue("Expected 543 invalidated materials (got " + INVALIDATED_MATERIALS.size() + ")", INVALIDATED_MATERIALS.size() == 543); + Assert.assertEquals("Expected 543 invalidated materials (got " + INVALIDATED_MATERIALS.size() + ")", 543, INVALIDATED_MATERIALS.size()); } } diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java index a6e7651a..02a31f09 100644 --- a/src/test/java/org/bukkit/support/DummyServer.java +++ b/src/test/java/org/bukkit/support/DummyServer.java @@ -8,10 +8,13 @@ import java.util.logging.Logger; import org.bukkit.Bukkit;
import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
import org.bukkit.Server;
+import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.Versioning;
public class DummyServer implements InvocationHandler {
@@ -79,6 +82,15 @@ public class DummyServer implements InvocationHandler { }
}
);
+ methods.put(Server.class.getMethod("getLootTable", NamespacedKey.class),
+ new MethodHandler() {
+ @Override
+ public Object handle(DummyServer server, Object[] args) {
+ NamespacedKey key = (NamespacedKey) args[0];
+ return new CraftLootTable(key, AbstractTestingBase.LOOT_TABLE_REGISTRY.a(CraftNamespacedKey.toMinecraft(key)));
+ }
+ }
+ );
Bukkit.setServer(Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(new DummyServer()));
} catch (Throwable t) {
throw new Error(t);
|