mirror of
https://github.com/EssentialsX/Essentials.git
synced 2024-12-09 02:20:33 +08:00
Fix spawner delay feature (#3239)
Closes #1332 The spawner delay feature has been broken in Essentials for as long as anyone can remember. The reasons for this are mentioned in the issue above. This PR fixes this by changing the command to utilize new API for setting the minimum and maximum spawn delay on spawners. This API was added in 1.12.2, so all supported versions before that (1.8.8 thru 1.12.1) require NMS to function properly. I'm aware that Essentials avoids NMS for maintainability reasons, however that should not be of much concern here since all versions 1.12.2 and later are going to be using the Bukkit API. Hence, no NMS updates will be necessary. Also let me know if you want the NMS code refactored somewhere else. I saw the net.ess3.nms packages, but I wasn't sure where this would fit into the organisation of that. Tested on: 1.8.8, 1.9.4, 1.10.2, 1.11.2 (NMS) 1.12.2, 1.15.2 (Bukkit API)
This commit is contained in:
parent
68d0aa9688
commit
14c6c2a055
@ -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<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;
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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<User> getOnlineUsers();
|
||||
|
||||
SpawnerProvider getSpawnerProvider();
|
||||
SpawnerItemProvider getSpawnerItemProvider();
|
||||
|
||||
SpawnerBlockProvider getSpawnerBlockProvider();
|
||||
|
||||
ServerStateProvider getServerStateProvider();
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
@ -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();
|
@ -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";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user