diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index 47be9587a..379c034ba 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -40,11 +40,13 @@ import net.ess3.api.ISettings; import net.ess3.api.*; import net.ess3.nms.refl.providers.ReflServerStateProvider; import net.ess3.nms.refl.providers.ReflSpawnEggProvider; +import net.ess3.nms.refl.providers.ReflSpawnerBlockProvider; import net.ess3.provider.PotionMetaProvider; import net.ess3.provider.ProviderListener; import net.ess3.provider.ServerStateProvider; import net.ess3.provider.SpawnEggProvider; -import net.ess3.provider.SpawnerProvider; +import net.ess3.provider.SpawnerBlockProvider; +import net.ess3.provider.SpawnerItemProvider; import net.ess3.provider.providers.*; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -107,7 +109,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { private transient EssentialsTimer timer; private final transient Set vanishedPlayers = new LinkedHashSet<>(); private transient Method oldGetOnlinePlayers; - private transient SpawnerProvider spawnerProvider; + private transient SpawnerItemProvider spawnerItemProvider; + private transient SpawnerBlockProvider spawnerBlockProvider; private transient SpawnEggProvider spawnEggProvider; private transient PotionMetaProvider potionMetaProvider; private transient ServerStateProvider serverStateProvider; @@ -244,8 +247,15 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { confList.add(jails); execTimer.mark("Init(Jails)"); - //Spawner provider only uses one but it's here for legacy... - spawnerProvider = new BlockMetaSpawnerProvider(); + //Spawner item provider only uses one but it's here for legacy... + spawnerItemProvider = new BlockMetaSpawnerItemProvider(); + + //Spawner block providers + if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_12_0_R01)) { + spawnerBlockProvider = new ReflSpawnerBlockProvider(); + } else { + spawnerBlockProvider = new BukkitSpawnerBlockProvider(); + } //Spawn Egg Providers if (VersionUtil.getServerBukkitVersion().isLowerThanOrEqualTo(VersionUtil.v1_8_8_R01)) { @@ -945,8 +955,13 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { } @Override - public SpawnerProvider getSpawnerProvider() { - return spawnerProvider; + public SpawnerItemProvider getSpawnerItemProvider() { + return spawnerItemProvider; + } + + @Override + public SpawnerBlockProvider getSpawnerBlockProvider() { + return spawnerBlockProvider; } @Override diff --git a/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java b/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java index 6d2c1024b..7d2c8ef38 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java @@ -37,7 +37,7 @@ public class EssentialsBlockListener implements Listener { final BlockState blockState = event.getBlockPlaced().getState(); if (blockState instanceof CreatureSpawner) { final CreatureSpawner spawner = (CreatureSpawner) blockState; - final EntityType type = ess.getSpawnerProvider().getEntityType(event.getItemInHand()); + final EntityType type = ess.getSpawnerItemProvider().getEntityType(event.getItemInHand()); if (type != null && Mob.fromBukkitType(type) != null) { if (ess.getUser(event.getPlayer()).isAuthorized("essentials.spawnerconvert." + Mob.fromBukkitType(type).name().toLowerCase(Locale.ENGLISH))) { spawner.setSpawnedType(type); diff --git a/Essentials/src/com/earth2me/essentials/IEssentials.java b/Essentials/src/com/earth2me/essentials/IEssentials.java index 3f4d8a6bc..4646f638d 100644 --- a/Essentials/src/com/earth2me/essentials/IEssentials.java +++ b/Essentials/src/com/earth2me/essentials/IEssentials.java @@ -6,7 +6,8 @@ import com.earth2me.essentials.api.IWarps; import com.earth2me.essentials.perm.PermissionsHandler; import com.earth2me.essentials.register.payment.Methods; import net.ess3.provider.ServerStateProvider; -import net.ess3.provider.SpawnerProvider; +import net.ess3.provider.SpawnerBlockProvider; +import net.ess3.provider.SpawnerItemProvider; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -103,7 +104,9 @@ public interface IEssentials extends Plugin { Iterable getOnlineUsers(); - SpawnerProvider getSpawnerProvider(); + SpawnerItemProvider getSpawnerItemProvider(); + + SpawnerBlockProvider getSpawnerBlockProvider(); ServerStateProvider getServerStateProvider(); } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java b/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java index ee079d678..a7590eeb9 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java @@ -7,6 +7,7 @@ import com.earth2me.essentials.utils.EnumUtil; import com.earth2me.essentials.utils.LocationUtil; import com.earth2me.essentials.utils.NumberUtil; import com.earth2me.essentials.utils.StringUtil; +import net.ess3.provider.SpawnerBlockProvider; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Server; @@ -59,6 +60,13 @@ public class Commandspawner extends EssentialsCommand { try { CreatureSpawner spawner = (CreatureSpawner) target.getBlock().getState(); spawner.setSpawnedType(mob.getType()); + if (delay > 0) { + SpawnerBlockProvider spawnerBlockProvider = ess.getSpawnerBlockProvider(); + spawnerBlockProvider.setMinSpawnDelay(spawner, 1); + spawnerBlockProvider.setMaxSpawnDelay(spawner, Integer.MAX_VALUE); + spawnerBlockProvider.setMinSpawnDelay(spawner, delay); + spawnerBlockProvider.setMaxSpawnDelay(spawner, delay); + } spawner.setDelay(delay); spawner.update(); } catch (Throwable ex) { diff --git a/Essentials/src/com/earth2me/essentials/items/FlatItemDb.java b/Essentials/src/com/earth2me/essentials/items/FlatItemDb.java index 202052956..e33c476c9 100644 --- a/Essentials/src/com/earth2me/essentials/items/FlatItemDb.java +++ b/Essentials/src/com/earth2me/essentials/items/FlatItemDb.java @@ -145,7 +145,7 @@ public class FlatItemDb extends AbstractItemDb { // setItemMeta to prevent a race condition EntityType entity = data.getEntity(); if (entity != null && material.toString().contains("SPAWNER")) { - ess.getSpawnerProvider().setEntityType(stack, entity); + ess.getSpawnerItemProvider().setEntityType(stack, entity); } return stack; @@ -203,7 +203,7 @@ public class FlatItemDb extends AbstractItemDb { PotionData potion = ((PotionMeta) item.getItemMeta()).getBasePotionData(); return new ItemData(type, potion); } else if (type.toString().contains("SPAWNER")) { - EntityType entity = ess.getSpawnerProvider().getEntityType(item); + EntityType entity = ess.getSpawnerItemProvider().getEntityType(item); return new ItemData(type, entity); } else { return new ItemData(type); diff --git a/Essentials/src/com/earth2me/essentials/items/LegacyItemDb.java b/Essentials/src/com/earth2me/essentials/items/LegacyItemDb.java index ea9a47107..a7d3457f3 100644 --- a/Essentials/src/com/earth2me/essentials/items/LegacyItemDb.java +++ b/Essentials/src/com/earth2me/essentials/items/LegacyItemDb.java @@ -185,7 +185,7 @@ public class LegacyItemDb extends AbstractItemDb { if (mat == MOB_SPAWNER) { if (metaData == 0) metaData = EntityType.PIG.getTypeId(); try { - retval = ess.getSpawnerProvider().setEntityType(retval, EntityType.fromId(metaData)); + retval = ess.getSpawnerItemProvider().setEntityType(retval, EntityType.fromId(metaData)); } catch (IllegalArgumentException e) { throw new Exception("Can't spawn entity ID " + metaData + " from mob spawners."); } diff --git a/providers/BaseProviders/src/net/ess3/provider/SpawnerBlockProvider.java b/providers/BaseProviders/src/net/ess3/provider/SpawnerBlockProvider.java new file mode 100644 index 000000000..98f2f8b26 --- /dev/null +++ b/providers/BaseProviders/src/net/ess3/provider/SpawnerBlockProvider.java @@ -0,0 +1,9 @@ +package net.ess3.provider; + +import org.bukkit.block.CreatureSpawner; + +public interface SpawnerBlockProvider extends Provider { + void setMaxSpawnDelay(CreatureSpawner spawner, int delay); + + void setMinSpawnDelay(CreatureSpawner spawner, int delay); +} diff --git a/providers/BaseProviders/src/net/ess3/provider/SpawnerProvider.java b/providers/BaseProviders/src/net/ess3/provider/SpawnerItemProvider.java similarity index 96% rename from providers/BaseProviders/src/net/ess3/provider/SpawnerProvider.java rename to providers/BaseProviders/src/net/ess3/provider/SpawnerItemProvider.java index 4d479c810..d377ee8bd 100644 --- a/providers/BaseProviders/src/net/ess3/provider/SpawnerProvider.java +++ b/providers/BaseProviders/src/net/ess3/provider/SpawnerItemProvider.java @@ -9,7 +9,7 @@ import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; -public interface SpawnerProvider extends Provider { +public interface SpawnerItemProvider extends Provider { ItemStack setEntityType(ItemStack is, EntityType type) throws IllegalArgumentException; EntityType getEntityType(ItemStack is) throws IllegalArgumentException; diff --git a/providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerProvider.java b/providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerItemProvider.java similarity index 89% rename from providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerProvider.java rename to providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerItemProvider.java index ac5c1bd28..cc67da3b2 100644 --- a/providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerProvider.java +++ b/providers/BaseProviders/src/net/ess3/provider/providers/BlockMetaSpawnerItemProvider.java @@ -1,13 +1,13 @@ package net.ess3.provider.providers; -import net.ess3.provider.SpawnerProvider; +import net.ess3.provider.SpawnerItemProvider; import org.bukkit.block.BlockState; import org.bukkit.block.CreatureSpawner; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BlockStateMeta; -public class BlockMetaSpawnerProvider implements SpawnerProvider { +public class BlockMetaSpawnerItemProvider implements SpawnerItemProvider { @Override public ItemStack setEntityType(ItemStack is, EntityType type) throws IllegalArgumentException { BlockStateMeta bsm = (BlockStateMeta) is.getItemMeta(); diff --git a/providers/BaseProviders/src/net/ess3/provider/providers/BukkitSpawnerBlockProvider.java b/providers/BaseProviders/src/net/ess3/provider/providers/BukkitSpawnerBlockProvider.java new file mode 100644 index 000000000..eac24e970 --- /dev/null +++ b/providers/BaseProviders/src/net/ess3/provider/providers/BukkitSpawnerBlockProvider.java @@ -0,0 +1,21 @@ +package net.ess3.provider.providers; + +import net.ess3.provider.SpawnerBlockProvider; +import org.bukkit.block.CreatureSpawner; + +public class BukkitSpawnerBlockProvider implements SpawnerBlockProvider { + @Override + public void setMaxSpawnDelay(CreatureSpawner spawner, int delay) { + spawner.setMaxSpawnDelay(delay); + } + + @Override + public void setMinSpawnDelay(CreatureSpawner spawner, int delay) { + spawner.setMinSpawnDelay(delay); + } + + @Override + public String getDescription() { + return "Bukkit 1.12+ provider"; + } +} diff --git a/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflSpawnerBlockProvider.java b/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflSpawnerBlockProvider.java new file mode 100644 index 000000000..554cc9908 --- /dev/null +++ b/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflSpawnerBlockProvider.java @@ -0,0 +1,55 @@ +package net.ess3.nms.refl.providers; + +import net.ess3.nms.refl.ReflUtil; +import net.ess3.provider.SpawnerBlockProvider; +import org.bukkit.block.CreatureSpawner; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ReflSpawnerBlockProvider implements SpawnerBlockProvider { + @Override + public void setMaxSpawnDelay(CreatureSpawner spawner, int delay) { + Class mobSpawnerAbstract = ReflUtil.getNMSClass("MobSpawnerAbstract"); + Field maxSpawnDelay = ReflUtil.getFieldCached(mobSpawnerAbstract, "maxSpawnDelay"); + if (maxSpawnDelay != null) { + try { + maxSpawnDelay.setInt(getNMSSpawner(spawner), delay); + } catch (IllegalAccessException ignored) { + } + } + } + + @Override + public void setMinSpawnDelay(CreatureSpawner spawner, int delay) { + Class mobSpawnerAbstract = ReflUtil.getNMSClass("MobSpawnerAbstract"); + Field minSpawnDelay = ReflUtil.getFieldCached(mobSpawnerAbstract, "minSpawnDelay"); + if (minSpawnDelay != null) { + try { + minSpawnDelay.setInt(getNMSSpawner(spawner), delay); + } catch (IllegalAccessException ignored) { + } + } + } + + @Override + public String getDescription() { + return "Reflection based provider"; + } + + private Object getNMSSpawner(CreatureSpawner spawner) { + try { + Class craftWorld = ReflUtil.getOBCClass("CraftWorld"); + Class tileEntityMobSpawner = ReflUtil.getNMSClass("TileEntityMobSpawner"); + Method getSpawner = ReflUtil.getMethodCached(tileEntityMobSpawner, "getSpawner"); + Method getTileEntityAt = ReflUtil.getMethodCached(craftWorld, "getTileEntityAt", int.class, int.class, int.class); + if (getSpawner != null && getTileEntityAt != null) { + Object craftTileEntity = getTileEntityAt.invoke(spawner.getWorld(), spawner.getX(), spawner.getY(), spawner.getZ()); + return getSpawner.invoke(craftTileEntity); + } + } catch (IllegalAccessException | InvocationTargetException ignored) { + } + return null; + } +}