Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix spawner delay feature #3239

Merged
merged 12 commits into from
Aug 5, 2020
27 changes: 21 additions & 6 deletions Essentials/src/com/earth2me/essentials/Essentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@
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;
Expand Down Expand Up @@ -107,7 +109,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
private transient EssentialsTimer timer;
private final transient Set<String> 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;
Expand Down Expand Up @@ -244,8 +247,15 @@ public void onEnable() {
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)) {
Expand Down Expand Up @@ -945,8 +955,13 @@ public Iterable<User> getOnlineUsers() {
}

@Override
public SpawnerProvider getSpawnerProvider() {
return spawnerProvider;
public SpawnerItemProvider getSpawnerItemProvider() {
return spawnerItemProvider;
}

@Override
public SpawnerBlockProvider getSpawnerBlockProvider() {
return spawnerBlockProvider;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void onBlockPlace(final BlockPlaceEvent event) {
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);
Expand Down
7 changes: 5 additions & 2 deletions Essentials/src/com/earth2me/essentials/IEssentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
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;
Expand Down Expand Up @@ -103,7 +104,9 @@ public interface IEssentials extends Plugin {

Iterable<User> getOnlineUsers();

SpawnerProvider getSpawnerProvider();
SpawnerItemProvider getSpawnerItemProvider();

SpawnerBlockProvider getSpawnerBlockProvider();

ServerStateProvider getServerStateProvider();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
Expand Down Expand Up @@ -59,6 +60,13 @@ protected void run(final Server server, final User user, final String commandLab
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) {
Expand Down
4 changes: 2 additions & 2 deletions Essentials/src/com/earth2me/essentials/items/FlatItemDb.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public ItemStack get(String id, boolean useResolvers) throws Exception {
// 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;
Expand Down Expand Up @@ -203,7 +203,7 @@ private ItemData lookup(ItemStack item) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public ItemStack get(final String id, final boolean useResolvers) throws Excepti
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.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}