mirror of
https://github.com/craftaro/EpicSpawners.git
synced 2025-01-08 11:37:51 +08:00
Removed all reflection.
This commit is contained in:
parent
a6bad531f2
commit
8e4a6c8b1b
@ -5,6 +5,7 @@ import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.nms.NmsManager;
|
||||
import com.songoda.core.nms.nbt.NBTItem;
|
||||
import com.songoda.core.utils.EntityUtils;
|
||||
import com.songoda.epicspawners.EpicSpawners;
|
||||
import com.songoda.epicspawners.particles.ParticleDensity;
|
||||
import com.songoda.epicspawners.particles.ParticleEffect;
|
||||
@ -179,39 +180,9 @@ public class SpawnerManager {
|
||||
.build();
|
||||
|
||||
List<EntityType> entities = new ArrayList<>(Collections.singletonList(type));
|
||||
List<CompatibleMaterial> spawnBlocks = new ArrayList<>(Collections.singletonList(CompatibleMaterial.AIR));
|
||||
List<CompatibleMaterial> spawnBlocks;
|
||||
|
||||
switch (typeString.toUpperCase()) {
|
||||
case "PIG":
|
||||
case "SHEEP":
|
||||
case "CHICKEN":
|
||||
case "COW":
|
||||
case "RABBIT":
|
||||
case "LLAMA":
|
||||
case "HORSE":
|
||||
case "CAT":
|
||||
spawnBlocks = new ArrayList<>(Collections.singletonList(CompatibleMaterial.GRASS_BLOCK));
|
||||
break;
|
||||
case "MUSHROOM_COW":
|
||||
spawnBlocks = new ArrayList<>(Collections.singletonList(CompatibleMaterial.MYCELIUM));
|
||||
break;
|
||||
case "SQUID":
|
||||
case "ELDER_GUARDIAN":
|
||||
case "COD":
|
||||
case "SALMON":
|
||||
case "PUFFERFISH":
|
||||
case "TROPICAL_FISH":
|
||||
spawnBlocks = new ArrayList<>(Collections.singletonList(CompatibleMaterial.WATER));
|
||||
break;
|
||||
case "OCELOT":
|
||||
spawnBlocks = new ArrayList<>(Arrays.asList(CompatibleMaterial.GRASS_BLOCK,
|
||||
CompatibleMaterial.JUNGLE_LEAVES, CompatibleMaterial.ACACIA_LEAVES,
|
||||
CompatibleMaterial.BIRCH_LEAVES, CompatibleMaterial.DARK_OAK_LEAVES,
|
||||
CompatibleMaterial.OAK_LEAVES, CompatibleMaterial.SPRUCE_LEAVES));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
spawnBlocks = EntityUtils.getSpawnBlocks(type);
|
||||
|
||||
SpawnerTierBuilder tierBuilder = new SpawnerTierBuilder(spawnerData)
|
||||
.setEntities(entities)
|
||||
@ -329,7 +300,7 @@ public class SpawnerManager {
|
||||
if (currentSection2.contains("Conditions")) {
|
||||
String biomeString = currentSection2.getString("Conditions.Biomes");
|
||||
Set<Biome> biomes;
|
||||
if (biomeString.toLowerCase().equals("all"))
|
||||
if (biomeString.toUpperCase().equals("ALL"))
|
||||
biomes = EnumSet.allOf(Biome.class);
|
||||
else {
|
||||
biomes = new HashSet<>();
|
||||
|
@ -2,7 +2,6 @@ package com.songoda.epicspawners.spawners.spawner;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.nms.NmsManager;
|
||||
import com.songoda.core.nms.nbt.NBTItem;
|
||||
@ -16,8 +15,7 @@ import com.songoda.epicspawners.spawners.condition.SpawnCondition;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOption;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionBlock;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionCommand;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionEntity_1_12;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionEntity_1_13;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionEntity;
|
||||
import com.songoda.epicspawners.spawners.spawner.option.SpawnOptionItem;
|
||||
import com.songoda.epicspawners.utils.CostType;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
@ -81,11 +79,7 @@ public class SpawnerTier {
|
||||
|
||||
public void reloadSpawnMethods() {
|
||||
spawnOptions.clear();
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
||||
if (!entities.isEmpty()) spawnOptions.add(new SpawnOptionEntity_1_13(entities));
|
||||
} else {
|
||||
if (!entities.isEmpty()) spawnOptions.add(new SpawnOptionEntity_1_12(entities));
|
||||
}
|
||||
if (!entities.isEmpty()) spawnOptions.add(new SpawnOptionEntity(entities));
|
||||
if (!blocks.isEmpty()) spawnOptions.add(new SpawnOptionBlock(blocks));
|
||||
if (!items.isEmpty()) spawnOptions.add(new SpawnOptionItem(items));
|
||||
if (!commands.isEmpty()) spawnOptions.add(new SpawnOptionCommand(commands));
|
||||
|
@ -0,0 +1,127 @@
|
||||
package com.songoda.epicspawners.spawners.spawner.option;
|
||||
|
||||
import com.songoda.core.math.MathUtils;
|
||||
import com.songoda.core.utils.EntityUtils;
|
||||
import com.songoda.epicspawners.EpicSpawners;
|
||||
import com.songoda.epicspawners.api.events.SpawnerSpawnEvent;
|
||||
import com.songoda.epicspawners.boost.types.Boosted;
|
||||
import com.songoda.epicspawners.particles.ParticleType;
|
||||
import com.songoda.epicspawners.settings.Settings;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnCondition;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnConditionNearbyEntities;
|
||||
import com.songoda.epicspawners.spawners.spawner.PlacedSpawner;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerStack;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerTier;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class SpawnOptionEntity implements SpawnOption {
|
||||
|
||||
private final EntityType[] types;
|
||||
|
||||
private final EpicSpawners plugin = EpicSpawners.getInstance();
|
||||
|
||||
private static final boolean mcmmo = Bukkit.getPluginManager().isPluginEnabled("mcMMO");
|
||||
|
||||
public SpawnOptionEntity(EntityType... types) {
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
public SpawnOptionEntity(Collection<EntityType> entities) {
|
||||
this(entities.toArray(new EntityType[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn(SpawnerTier data, SpawnerStack stack, PlacedSpawner spawner) {
|
||||
Location location = spawner.getLocation();
|
||||
location.add(.5, .5, .5);
|
||||
if (location.getWorld() == null) return;
|
||||
|
||||
String[] randomLowHigh = Settings.RANDOM_LOW_HIGH.getString().split(":");
|
||||
|
||||
// Get the amount of entities to spawn per spawner in the stack.
|
||||
int spawnCount = 0;
|
||||
for (int i = 0; i < stack.getStackSize(); i++) {
|
||||
int randomAmt = ThreadLocalRandom.current().nextInt(Integer.parseInt(randomLowHigh[0]), Integer.parseInt(randomLowHigh[1]));
|
||||
|
||||
String equation = Settings.SPAWNER_SPAWN_EQUATION.getString();
|
||||
equation = equation.replace("{RAND}", Integer.toString(randomAmt));
|
||||
equation = equation.replace("{STACK_SIZE}", Integer.toString(stack.getStackSize()));
|
||||
|
||||
spawnCount += MathUtils.eval(equation,
|
||||
"EpicSpawners (Mobs Spawned Per Single Spawn) Equation");
|
||||
}
|
||||
|
||||
// Get the max entities allowed around a spawner.
|
||||
int maxEntitiesAllowed = 0;
|
||||
for (SpawnCondition spawnCondition : data.getConditions()) {
|
||||
if (spawnCondition instanceof SpawnConditionNearbyEntities)
|
||||
maxEntitiesAllowed = ((SpawnConditionNearbyEntities) spawnCondition).getMax();
|
||||
}
|
||||
|
||||
// Should we skip the max entity amount on first spawn?
|
||||
if (spawner.getSpawnCount() == 0 && Settings.IGNORE_MAX_ON_FIRST_SPAWN.getBoolean())
|
||||
maxEntitiesAllowed = Integer.MAX_VALUE;
|
||||
|
||||
// Get the amount of entities around the spawner.
|
||||
int size = SpawnConditionNearbyEntities.getEntitiesAroundSpawner(location, true);
|
||||
|
||||
// Calculate the amount of entities to spawn.
|
||||
spawnCount = Math.min(maxEntitiesAllowed - size, spawnCount) + spawner.getBoosts().stream().mapToInt(Boosted::getAmountBoosted).sum();
|
||||
|
||||
ParticleType particleType = data.getEntitySpawnParticle();
|
||||
|
||||
int amountSpawned = spawner.spawn(spawnCount,
|
||||
particleType != ParticleType.NONE ? null : particleType.getEffect(),
|
||||
new HashSet<>(Arrays.asList(data.getSpawnBlocks())), entity -> {
|
||||
SpawnerSpawnEvent event = new SpawnerSpawnEvent(entity, spawner);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
entity.remove();
|
||||
return false;
|
||||
}
|
||||
if (data.isSpawnOnFire()) entity.setFireTicks(160);
|
||||
|
||||
entity.setMetadata("ESData", new FixedMetadataValue(plugin, data.getSpawnerData().getIdentifyingName()));
|
||||
entity.setMetadata("ESTier", new FixedMetadataValue(plugin, data.getIdentifyingName()));
|
||||
|
||||
if (mcmmo)
|
||||
entity.setMetadata("mcMMO: Spawned Entity", new FixedMetadataValue(plugin, true));
|
||||
|
||||
if (Settings.NO_AI.getBoolean())
|
||||
EntityUtils.setUnaware(entity);
|
||||
|
||||
plugin.getSpawnManager().addUnnaturalSpawn(entity.getUniqueId());
|
||||
return true;
|
||||
}, types);
|
||||
|
||||
spawner.setSpawnCount(spawner.getSpawnCount() + amountSpawned);
|
||||
EpicSpawners.getInstance().getDataManager().updateSpawner(spawner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnOptionType getType() {
|
||||
return SpawnOptionType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * (types != null ? Arrays.hashCode(types) : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == this) return true;
|
||||
if (!(object instanceof SpawnOptionEntity)) return false;
|
||||
|
||||
SpawnOptionEntity other = (SpawnOptionEntity) object;
|
||||
return Arrays.equals(types, other.types);
|
||||
}
|
||||
}
|
@ -1,387 +0,0 @@
|
||||
package com.songoda.epicspawners.spawners.spawner.option;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.CompatibleParticleHandler;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.utils.EntityUtils;
|
||||
import com.songoda.epicspawners.EpicSpawners;
|
||||
import com.songoda.epicspawners.api.events.SpawnerSpawnEvent;
|
||||
import com.songoda.epicspawners.boost.types.Boosted;
|
||||
import com.songoda.epicspawners.particles.ParticleType;
|
||||
import com.songoda.epicspawners.settings.Settings;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnCondition;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnConditionNearbyEntities;
|
||||
import com.songoda.epicspawners.spawners.spawner.PlacedSpawner;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerStack;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerTier;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class SpawnOptionEntity_1_12 implements SpawnOption {
|
||||
|
||||
private final EntityType[] types;
|
||||
|
||||
private final ScriptEngine engine;
|
||||
|
||||
private final EpicSpawners plugin = EpicSpawners.getInstance();
|
||||
|
||||
private boolean useUltimateStacker;
|
||||
|
||||
private boolean mcmmo;
|
||||
|
||||
private final Map<String, Integer> cache = new HashMap<>();
|
||||
private Class<?> clazzMobSpawnerData,
|
||||
clazzCraftWorld,
|
||||
clazzWorld,
|
||||
clazzEntity,
|
||||
clazzEntityInsentient,
|
||||
clazzBlockPosition;
|
||||
private Method methodAddEntity,
|
||||
methodCreateEntityByName,
|
||||
methodSetPositionRotation,
|
||||
methodB,
|
||||
methodSetString,
|
||||
methodGetHandle,
|
||||
methodEntityInsentientPrepare,
|
||||
methodChunkRegionLoaderA,
|
||||
methodEntityGetBukkitEntity,
|
||||
methodCraftEntityTeleport,
|
||||
methodEntityInsentientCanSpawn,
|
||||
methodChunkRegionLoaderA2,
|
||||
methodGetDamageScaler;
|
||||
private Field fieldWorldRandom;
|
||||
|
||||
public SpawnOptionEntity_1_12(EntityType... types) {
|
||||
this.types = types;
|
||||
this.engine = new ScriptEngineManager(null).getEngineByName("JavaScript");
|
||||
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("UltimateStacker")) {
|
||||
this.useUltimateStacker = ((Plugin) com.songoda.ultimatestacker.UltimateStacker.getInstance()).getConfig().getBoolean("Entities.Enabled");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public SpawnOptionEntity_1_12(Collection<EntityType> entities) {
|
||||
this(entities.toArray(new EntityType[0]));
|
||||
}
|
||||
|
||||
private void init() {
|
||||
try {
|
||||
String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23);
|
||||
|
||||
Class<?> clazzChunkRegionLoader = Class.forName("net.minecraft.server." + ver + ".ChunkRegionLoader");
|
||||
Class<?> clazzCraftEntity = Class.forName("org.bukkit.craftbukkit." + ver + ".entity.CraftEntity");
|
||||
Class<?> clazzSpawnReason = Class.forName("org.bukkit.event.entity.CreatureSpawnEvent$SpawnReason");
|
||||
Class<?> clazzGroupDataEntity = Class.forName("net.minecraft.server." + ver + ".GroupDataEntity");
|
||||
Class<?> clazzDifficultyDamageScaler = Class.forName("net.minecraft.server." + ver + ".DifficultyDamageScaler");
|
||||
|
||||
clazzWorld = Class.forName("net.minecraft.server." + ver + ".World");
|
||||
clazzEntity = Class.forName("net.minecraft.server." + ver + ".Entity");
|
||||
clazzCraftWorld = Class.forName("org.bukkit.craftbukkit." + ver + ".CraftWorld");
|
||||
clazzEntityInsentient = Class.forName("net.minecraft.server." + ver + ".EntityInsentient");
|
||||
clazzBlockPosition = Class.forName("net.minecraft.server." + ver + ".BlockPosition");
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||
clazzMobSpawnerData = Class.forName("net.minecraft.server." + ver + ".MobSpawnerData");
|
||||
Class<?> clazzNBTTagCompound = Class.forName("net.minecraft.server." + ver + ".NBTTagCompound");
|
||||
|
||||
methodB = clazzMobSpawnerData.getDeclaredMethod("b");
|
||||
methodSetString = clazzNBTTagCompound.getDeclaredMethod("setString", String.class, String.class);
|
||||
|
||||
methodGetDamageScaler = clazzWorld.getDeclaredMethod("D", clazzBlockPosition);
|
||||
|
||||
methodChunkRegionLoaderA = clazzChunkRegionLoader.getDeclaredMethod("a", clazzNBTTagCompound, clazzWorld, double.class, double.class, double.class, boolean.class);
|
||||
methodChunkRegionLoaderA2 = clazzChunkRegionLoader.getDeclaredMethod("a", clazzEntity, clazzWorld, clazzSpawnReason);
|
||||
} else {
|
||||
Class<?> clazzEntityTypes = Class.forName("net.minecraft.server." + ver + ".EntityTypes");
|
||||
methodCreateEntityByName = clazzEntityTypes.getDeclaredMethod("createEntityByName", String.class, clazzWorld);
|
||||
methodSetPositionRotation = clazzEntity.getDeclaredMethod("setPositionRotation", double.class, double.class, double.class, float.class, float.class);
|
||||
methodAddEntity = clazzWorld.getDeclaredMethod("addEntity", clazzEntity, clazzSpawnReason);
|
||||
methodGetDamageScaler = clazzWorld.getDeclaredMethod("E", clazzBlockPosition);
|
||||
}
|
||||
|
||||
methodGetHandle = clazzCraftWorld.getDeclaredMethod("getHandle");
|
||||
|
||||
methodEntityGetBukkitEntity = clazzEntity.getDeclaredMethod("getBukkitEntity");
|
||||
methodCraftEntityTeleport = clazzCraftEntity.getDeclaredMethod("teleport", Location.class);
|
||||
methodEntityInsentientCanSpawn = clazzEntityInsentient.getDeclaredMethod("canSpawn");
|
||||
methodEntityInsentientPrepare = clazzEntityInsentient.getDeclaredMethod("prepare", clazzDifficultyDamageScaler, clazzGroupDataEntity);
|
||||
|
||||
fieldWorldRandom = clazzWorld.getDeclaredField("random");
|
||||
fieldWorldRandom.setAccessible(true);
|
||||
} catch (NoSuchFieldException | NoSuchMethodException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.mcmmo = Bukkit.getPluginManager().isPluginEnabled("mcMMO");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn(SpawnerTier data, SpawnerStack stack, PlacedSpawner spawner) {
|
||||
Location location = spawner.getLocation();
|
||||
location.add(.5, .5, .5);
|
||||
if (location.getWorld() == null) return;
|
||||
|
||||
String[] randomLowHigh = Settings.RANDOM_LOW_HIGH.getString().split(":");
|
||||
|
||||
// Get the amount of entities to spawn per spawner in the stack.
|
||||
int spawnCount = 0;
|
||||
for (int i = 0; i < stack.getStackSize(); i++) {
|
||||
int randomAmt = ThreadLocalRandom.current().nextInt(Integer.parseInt(randomLowHigh[0]), Integer.parseInt(randomLowHigh[1]));
|
||||
|
||||
String equation = Settings.SPAWNER_SPAWN_EQUATION.getString();
|
||||
equation = equation.replace("{RAND}", Integer.toString(randomAmt));
|
||||
equation = equation.replace("{STACK_SIZE}", Integer.toString(stack.getStackSize()));
|
||||
try {
|
||||
if (!cache.containsKey(equation)) {
|
||||
spawnCount += (int) Math.round(Double.parseDouble(engine.eval(equation).toString()));
|
||||
cache.put(equation, spawnCount);
|
||||
} else {
|
||||
spawnCount += cache.get(equation);
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
System.out.println("Your spawner equation is broken, fix it.");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the max entities allowed around a spawner.
|
||||
int maxEntitiesAllowed = 0;
|
||||
for (SpawnCondition spawnCondition : data.getConditions()) {
|
||||
if (spawnCondition instanceof SpawnConditionNearbyEntities)
|
||||
maxEntitiesAllowed = ((SpawnConditionNearbyEntities) spawnCondition).getMax();
|
||||
}
|
||||
|
||||
// Should we skip the max entity amount on first spawn?
|
||||
if (spawner.getSpawnCount() == 0 && Settings.IGNORE_MAX_ON_FIRST_SPAWN.getBoolean())
|
||||
maxEntitiesAllowed = Integer.MAX_VALUE;
|
||||
|
||||
// Get the amount of entities around the spawner.
|
||||
int size = SpawnConditionNearbyEntities.getEntitiesAroundSpawner(location, true);
|
||||
|
||||
// Calculate the amount of entities to spawn.
|
||||
spawnCount = Math.min(maxEntitiesAllowed - size, spawnCount) + spawner.getBoosts().stream().mapToInt(Boosted::getAmountBoosted).sum();
|
||||
|
||||
// Check to make sure we're not spawning a stack smaller than the minimum stack size.
|
||||
boolean useUltimateStacker = this.useUltimateStacker && com.songoda.ultimatestacker.settings
|
||||
.Settings.DISABLED_WORLDS.getStringList().stream()
|
||||
.noneMatch(worldStr -> location.getWorld().getName().equalsIgnoreCase(worldStr))
|
||||
&& spawnCount >= com.songoda.ultimatestacker.settings.Settings.MIN_STACK_ENTITIES.getInt();
|
||||
|
||||
int spawnCountUsed = useUltimateStacker ? 1 : spawnCount;
|
||||
|
||||
while (spawnCountUsed-- > 0) {
|
||||
EntityType type = types[ThreadLocalRandom.current().nextInt(types.length)];
|
||||
Entity entity = spawnEntity(type, spawner, data);
|
||||
if (entity != null) {
|
||||
// If we're using UltimateStacker and this entity is indeed stackable then spawn a single stack with the desired stack size.
|
||||
if (useUltimateStacker && com.songoda.ultimatestacker.UltimateStacker.getInstance().getMobFile().getBoolean("Mobs." + entity.getType().name() + ".Enabled"))
|
||||
com.songoda.ultimatestacker.UltimateStacker.getInstance().getEntityStackManager().addStack((LivingEntity) entity, spawnCount);
|
||||
spawner.setSpawnCount(spawner.getSpawnCount() + (useUltimateStacker ? spawnCount : 1));
|
||||
EpicSpawners.getInstance().getDataManager().updateSpawner(spawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Entity spawnEntity(EntityType type, PlacedSpawner spawner, SpawnerTier tier) {
|
||||
try {
|
||||
Object objMobSpawnerData = null;
|
||||
Object objNBTTagCompound;
|
||||
|
||||
String typeTranslationUpper = TypeTranslations.getUpperFromType(type);
|
||||
String typeTranslationLower = TypeTranslations.getLowerFromType(type);
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||
objMobSpawnerData = clazzMobSpawnerData.newInstance();
|
||||
objNBTTagCompound = methodB.invoke(objMobSpawnerData);
|
||||
|
||||
methodSetString.invoke(objNBTTagCompound, "id", ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11) ? "minecraft:" + typeTranslationLower : typeTranslationUpper);
|
||||
}
|
||||
|
||||
int spawnRange = 4;
|
||||
for (int i = 0; i < 25; i++) {
|
||||
Object objCraftWorld = clazzCraftWorld.cast(spawner.getWorld());
|
||||
objCraftWorld = methodGetHandle.invoke(objCraftWorld);
|
||||
Object objWorld = clazzWorld.cast(objCraftWorld);
|
||||
|
||||
Random random = (Random) fieldWorldRandom.get(objWorld);
|
||||
double x = (double) spawner.getX() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D;
|
||||
double y = spawner.getY() + random.nextInt(3) - 1;
|
||||
double z = (double) spawner.getZ() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D;
|
||||
|
||||
Object objEntity;
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||
objNBTTagCompound = methodB.invoke(objMobSpawnerData);
|
||||
objEntity = methodChunkRegionLoaderA.invoke(null, objNBTTagCompound, objWorld, x, y, z, false);
|
||||
} else {
|
||||
objEntity = methodCreateEntityByName.invoke(null, typeTranslationUpper, objWorld);
|
||||
methodSetPositionRotation.invoke(objEntity, x, y, z, 360.0F, 0.0F);
|
||||
}
|
||||
Object objEntityInsentient = null;
|
||||
if (clazzEntityInsentient.isInstance(objEntity))
|
||||
objEntityInsentient = clazzEntityInsentient.cast(objEntity);
|
||||
|
||||
Location spot = new Location(spawner.getWorld(), x, y, z);
|
||||
if (!canSpawn(objEntityInsentient, tier, spot))
|
||||
continue;
|
||||
|
||||
Object objBlockPosition = clazzBlockPosition.getConstructor(clazzEntity).newInstance(objEntity);
|
||||
Object objDamageScaler = methodGetDamageScaler.invoke(objWorld, objBlockPosition);
|
||||
|
||||
methodEntityInsentientPrepare.invoke(objEntity, objDamageScaler, null);
|
||||
|
||||
ParticleType particleType = tier.getEntitySpawnParticle();
|
||||
|
||||
if (particleType != ParticleType.NONE) {
|
||||
float xx = (float) (0 + (Math.random() * 1));
|
||||
float yy = (float) (0 + (Math.random() * 2));
|
||||
float zz = (float) (0 + (Math.random() * 1));
|
||||
CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(particleType.getEffect()),
|
||||
spot, 5, xx, yy, zz, 0);
|
||||
}
|
||||
|
||||
Entity craftEntity = (Entity) methodEntityGetBukkitEntity.invoke(objEntity);
|
||||
|
||||
SpawnerSpawnEvent event = new SpawnerSpawnEvent(craftEntity, spawner);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
craftEntity.remove();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||
methodChunkRegionLoaderA2.invoke(null, objEntity, objWorld, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
||||
} else {
|
||||
methodAddEntity.invoke(objWorld, objEntity, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
||||
}
|
||||
|
||||
if (tier.isSpawnOnFire()) craftEntity.setFireTicks(160);
|
||||
|
||||
craftEntity.setMetadata("ESData", new FixedMetadataValue(plugin, tier.getSpawnerData().getIdentifyingName()));
|
||||
craftEntity.setMetadata("ESTier", new FixedMetadataValue(plugin, tier.getIdentifyingName()));
|
||||
|
||||
if (mcmmo)
|
||||
craftEntity.setMetadata("mcMMO: Spawned Entity", new FixedMetadataValue(plugin, true));
|
||||
|
||||
if (Settings.NO_AI.getBoolean())
|
||||
EntityUtils.setUnaware(objEntity);
|
||||
|
||||
Object objBukkitEntity = methodEntityGetBukkitEntity.invoke(objEntity);
|
||||
spot.setYaw(random.nextFloat() * 360.0F);
|
||||
methodCraftEntityTeleport.invoke(objBukkitEntity, spot);
|
||||
|
||||
plugin.getSpawnManager().addUnnaturalSpawn(craftEntity.getUniqueId());
|
||||
return craftEntity;
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean canSpawn(Object objEntityInsentient, SpawnerTier data, Location location) {
|
||||
try {
|
||||
if (!(boolean) methodEntityInsentientCanSpawn.invoke(objEntityInsentient))
|
||||
return false;
|
||||
|
||||
CompatibleMaterial[] spawnBlocks = data.getSpawnBlocks();
|
||||
|
||||
CompatibleMaterial spawnedIn = CompatibleMaterial.getMaterial(location.getBlock());
|
||||
CompatibleMaterial spawnedOn = CompatibleMaterial.getMaterial(location.getBlock().getRelative(BlockFace.DOWN));
|
||||
|
||||
if (!spawnedIn.isAir()
|
||||
&& !spawnedIn.isWater()
|
||||
&& !spawnedIn.name().contains("PRESSURE")
|
||||
&& !spawnedIn.name().contains("SLAB")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CompatibleMaterial material : spawnBlocks) {
|
||||
if (material == null) continue;
|
||||
|
||||
if (spawnedOn.equals(material) || material.isAir())
|
||||
return true;
|
||||
}
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum TypeTranslations {
|
||||
VINDICATOR("vindication_illager", "VindicationIllager"),
|
||||
SNOWMAN("snowman", "SnowMan"),
|
||||
PIG_ZOMBIE("zombie_pigman", "PigZombie"),
|
||||
EVOKER("evocation_illager", "EvocationIllager"),
|
||||
ILLUSIONER("illusion_illager", "IllusionIllager"),
|
||||
IRON_GOLEM("villager_golem", "VillagerGolem"),
|
||||
MUSHROOM_COW("mooshroom", "MushroomCow"),
|
||||
MAGMA_CUBE("magma_cube", "LavaSlime");
|
||||
|
||||
private final String lower;
|
||||
private final String upper;
|
||||
|
||||
TypeTranslations(String lower, String upper) {
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
}
|
||||
|
||||
public static String getLowerFromType(EntityType type) {
|
||||
try {
|
||||
TypeTranslations typeTranslation = valueOf(type.name());
|
||||
return typeTranslation.lower;
|
||||
} catch (Exception e) {
|
||||
return type.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUpperFromType(EntityType type) {
|
||||
try {
|
||||
TypeTranslations typeTranslation = valueOf(type.name());
|
||||
return typeTranslation.upper;
|
||||
} catch (Exception e) {
|
||||
return WordUtils.capitalize(type.name().toLowerCase()).replace(" ", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnOptionType getType() {
|
||||
return SpawnOptionType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * (types != null ? Arrays.hashCode(types) : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == this) return true;
|
||||
if (!(object instanceof SpawnOptionEntity_1_12)) return false;
|
||||
|
||||
SpawnOptionEntity_1_12 other = (SpawnOptionEntity_1_12) object;
|
||||
return Arrays.equals(types, other.types);
|
||||
}
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
package com.songoda.epicspawners.spawners.spawner.option;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.utils.EntityUtils;
|
||||
import com.songoda.epicspawners.EpicSpawners;
|
||||
import com.songoda.epicspawners.api.events.SpawnerSpawnEvent;
|
||||
import com.songoda.epicspawners.boost.types.Boosted;
|
||||
import com.songoda.epicspawners.particles.ParticleType;
|
||||
import com.songoda.epicspawners.settings.Settings;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnCondition;
|
||||
import com.songoda.epicspawners.spawners.condition.SpawnConditionNearbyEntities;
|
||||
import com.songoda.epicspawners.spawners.spawner.PlacedSpawner;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerStack;
|
||||
import com.songoda.epicspawners.spawners.spawner.SpawnerTier;
|
||||
import com.songoda.epicspawners.utils.PaperUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class SpawnOptionEntity_1_13 implements SpawnOption {
|
||||
|
||||
private final EntityType[] types;
|
||||
|
||||
private final ScriptEngine engine;
|
||||
|
||||
private final EpicSpawners plugin = EpicSpawners.getInstance();
|
||||
|
||||
private boolean useUltimateStacker;
|
||||
|
||||
private Enum<?> SpawnerEnum;
|
||||
|
||||
private boolean mcmmo;
|
||||
|
||||
private final Map<String, Integer> cache = new HashMap<>();
|
||||
private Class<?> clazzMobSpawnerData,
|
||||
clazzWorldServer,
|
||||
clazzWorldAccess,
|
||||
clazzGeneratorAccess,
|
||||
clazzCraftWorld,
|
||||
clazzWorld,
|
||||
clazzEntity,
|
||||
clazzEntityInsentient,
|
||||
clazzBlockPosition,
|
||||
clazzIWorldReader,
|
||||
clazzICollisionAccess;
|
||||
private Method methodGetEntity,
|
||||
methodGetChunkCoordinates,
|
||||
methodSetString,
|
||||
methodSetPosition,
|
||||
methodA,
|
||||
methodAddEntity,
|
||||
methodGetHandle,
|
||||
methodChunkRegionLoaderA,
|
||||
methodEntityGetBukkitEntity,
|
||||
methodCraftEntityTeleport,
|
||||
methodEntityInsentientPrepare,
|
||||
methodChunkRegionLoaderA2,
|
||||
methodGetDamageScaler,
|
||||
methodGetCubes,
|
||||
methodGetBoundingBox;
|
||||
private Field fieldWorldRandom,
|
||||
fieldSpawnReason;
|
||||
|
||||
public SpawnOptionEntity_1_13(EntityType... types) {
|
||||
this.types = types;
|
||||
this.engine = new ScriptEngineManager(null).getEngineByName("JavaScript");
|
||||
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("UltimateStacker")) {
|
||||
this.useUltimateStacker = ((Plugin) com.songoda.ultimatestacker.UltimateStacker.getInstance()).getConfig().getBoolean("Entities.Enabled");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public SpawnOptionEntity_1_13(Collection<EntityType> entities) {
|
||||
this(entities.toArray(new EntityType[0]));
|
||||
}
|
||||
|
||||
private void init() {
|
||||
try {
|
||||
String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23);
|
||||
|
||||
Class<?> clazzNBTTagCompound = Class.forName("net.minecraft.server." + ver + ".NBTTagCompound"),
|
||||
clazzChunkRegionLoader = Class.forName("net.minecraft.server." + ver + ".ChunkRegionLoader"),
|
||||
clazzCraftEntity = Class.forName("org.bukkit.craftbukkit." + ver + ".entity.CraftEntity"),
|
||||
clazzGroupDataEntity = Class.forName("net.minecraft.server." + ver + ".GroupDataEntity"),
|
||||
clazzDifficultyDamageScaler = Class.forName("net.minecraft.server." + ver + ".DifficultyDamageScaler"),
|
||||
clazzAxisAlignedBB = Class.forName("net.minecraft.server." + ver + ".AxisAlignedBB"),
|
||||
clazzEntityTypes = Class.forName("net.minecraft.server." + ver + ".EntityTypes");
|
||||
|
||||
clazzMobSpawnerData = Class.forName("net.minecraft.server." + ver + ".MobSpawnerData");
|
||||
clazzCraftWorld = Class.forName("org.bukkit.craftbukkit." + ver + ".CraftWorld");
|
||||
clazzWorld = Class.forName("net.minecraft.server." + ver + ".World");
|
||||
clazzEntity = Class.forName("net.minecraft.server." + ver + ".Entity");
|
||||
clazzEntityInsentient = Class.forName("net.minecraft.server." + ver + ".EntityInsentient");
|
||||
clazzBlockPosition = Class.forName("net.minecraft.server." + ver + ".BlockPosition");
|
||||
clazzIWorldReader = Class.forName("net.minecraft.server." + ver + ".IWorldReader");
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16))
|
||||
methodGetChunkCoordinates = clazzEntity.getMethod("getChunkCoordinates");
|
||||
|
||||
try {
|
||||
clazzICollisionAccess = Class.forName("net.minecraft.server." + ver + ".ICollisionAccess");
|
||||
methodGetCubes = clazzICollisionAccess.getDeclaredMethod("getCubes", clazzEntity, clazzAxisAlignedBB);
|
||||
} catch (ClassNotFoundException e) {
|
||||
clazzIWorldReader = Class.forName("net.minecraft.server." + ver + ".IWorldReader");
|
||||
methodGetCubes = clazzIWorldReader.getDeclaredMethod("getCubes", clazzEntity, clazzAxisAlignedBB);
|
||||
}
|
||||
|
||||
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_16)
|
||||
|| ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16) && ver.equals("v1_16_R1"))
|
||||
clazzGeneratorAccess = Class.forName("net.minecraft.server." + ver + ".GeneratorAccess");
|
||||
else
|
||||
clazzWorldAccess = Class.forName("net.minecraft.server." + ver + ".WorldAccess");
|
||||
|
||||
try {
|
||||
methodGetEntity = clazzMobSpawnerData.getDeclaredMethod("getEntity");
|
||||
} catch (NoSuchMethodException e) {
|
||||
methodGetEntity = clazzMobSpawnerData.getDeclaredMethod("b");
|
||||
}
|
||||
methodSetString = clazzNBTTagCompound.getDeclaredMethod("setString", String.class, String.class);
|
||||
|
||||
methodGetBoundingBox = clazzEntity.getDeclaredMethod("getBoundingBox");
|
||||
methodSetPosition = clazzEntity.getDeclaredMethod("setPosition", double.class, double.class, double.class);
|
||||
methodGetHandle = clazzCraftWorld.getDeclaredMethod("getHandle");
|
||||
try {
|
||||
methodChunkRegionLoaderA = clazzChunkRegionLoader.getDeclaredMethod("a", clazzNBTTagCompound, clazzWorld, double.class, double.class, double.class, boolean.class);
|
||||
methodEntityInsentientPrepare = clazzEntityInsentient.getDeclaredMethod("prepare", clazzDifficultyDamageScaler, clazzGroupDataEntity, clazzNBTTagCompound);
|
||||
methodChunkRegionLoaderA2 = clazzChunkRegionLoader.getDeclaredMethod("a", clazzEntity, clazzGeneratorAccess, Class.forName("org.bukkit.event.entity.CreatureSpawnEvent$SpawnReason"));
|
||||
} catch (NoSuchMethodException e) {
|
||||
methodA = clazzEntityTypes.getDeclaredMethod("a", clazzNBTTagCompound, clazzWorld);
|
||||
|
||||
Class<?> clazzEnumMobSpawn = Class.forName("net.minecraft.server." + ver + ".EnumMobSpawn");
|
||||
for (Object enumValue : clazzEnumMobSpawn.getEnumConstants()) {
|
||||
Enum<?> mobSpawnEnum = (Enum<?>) enumValue;
|
||||
if (mobSpawnEnum.name().equals("SPAWNER")) {
|
||||
this.SpawnerEnum = mobSpawnEnum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clazzWorldServer = Class.forName("net.minecraft.server." + ver + ".WorldServer");
|
||||
|
||||
methodEntityInsentientPrepare = clazzEntityInsentient.getDeclaredMethod("prepare", clazzGeneratorAccess == null ? clazzWorldAccess : clazzGeneratorAccess, clazzDifficultyDamageScaler, clazzEnumMobSpawn, clazzGroupDataEntity, clazzNBTTagCompound);
|
||||
methodAddEntity = clazzWorldServer.getDeclaredMethod("addEntity", clazzEntity, Class.forName("org.bukkit.event.entity.CreatureSpawnEvent$SpawnReason"));
|
||||
}
|
||||
|
||||
methodEntityGetBukkitEntity = clazzEntity.getDeclaredMethod("getBukkitEntity");
|
||||
methodCraftEntityTeleport = clazzCraftEntity.getDeclaredMethod("teleport", Location.class);
|
||||
methodGetDamageScaler = clazzWorld.getDeclaredMethod("getDamageScaler", clazzBlockPosition);
|
||||
|
||||
fieldWorldRandom = clazzWorld.getDeclaredField("random");
|
||||
fieldWorldRandom.setAccessible(true);
|
||||
|
||||
if (PaperUtils.isPaper()) {
|
||||
fieldSpawnReason = clazzEntity.getDeclaredField("spawnReason");
|
||||
}
|
||||
} catch (NoSuchFieldException | NoSuchMethodException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.mcmmo = Bukkit.getPluginManager().isPluginEnabled("mcMMO");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn(SpawnerTier data, SpawnerStack stack, PlacedSpawner spawner) {
|
||||
Location location = spawner.getLocation();
|
||||
location.add(.5, .5, .5);
|
||||
if (location.getWorld() == null) return;
|
||||
|
||||
String[] randomLowHigh = Settings.RANDOM_LOW_HIGH.getString().split(":");
|
||||
|
||||
// Get the amount of entities to spawn per spawner in the stack.
|
||||
int spawnCount = 0;
|
||||
for (int i = 0; i < stack.getStackSize(); i++) {
|
||||
int randomAmt = ThreadLocalRandom.current().nextInt(Integer.parseInt(randomLowHigh[0]), Integer.parseInt(randomLowHigh[1]));
|
||||
|
||||
String equation = Settings.SPAWNER_SPAWN_EQUATION.getString();
|
||||
equation = equation.replace("{RAND}", Integer.toString(randomAmt));
|
||||
equation = equation.replace("{STACK_SIZE}", Integer.toString(stack.getStackSize()));
|
||||
try {
|
||||
if (!cache.containsKey(equation)) {
|
||||
spawnCount += (int) Math.round(Double.parseDouble(engine.eval(equation).toString()));
|
||||
cache.put(equation, spawnCount);
|
||||
} else {
|
||||
spawnCount += cache.get(equation);
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
System.out.println("Your spawner equation is broken, fix it.");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the max entities allowed around a spawner.
|
||||
int maxEntitiesAllowed = 0;
|
||||
for (SpawnCondition spawnCondition : data.getConditions()) {
|
||||
if (spawnCondition instanceof SpawnConditionNearbyEntities)
|
||||
maxEntitiesAllowed = ((SpawnConditionNearbyEntities) spawnCondition).getMax();
|
||||
}
|
||||
|
||||
// Should we skip the max entity amount on first spawn?
|
||||
if (spawner.getSpawnCount() == 0 && Settings.IGNORE_MAX_ON_FIRST_SPAWN.getBoolean())
|
||||
maxEntitiesAllowed = Integer.MAX_VALUE;
|
||||
|
||||
// Get the amount of entities around the spawner.
|
||||
int size = SpawnConditionNearbyEntities.getEntitiesAroundSpawner(location, true);
|
||||
|
||||
// Calculate the amount of entities to spawn.
|
||||
spawnCount = Math.min(maxEntitiesAllowed - size, spawnCount) + spawner.getBoosts().stream().mapToInt(Boosted::getAmountBoosted).sum();
|
||||
|
||||
// Check to make sure we're not spawning a stack smaller than the minimum stack size.
|
||||
boolean useUltimateStacker = this.useUltimateStacker && com.songoda.ultimatestacker.settings
|
||||
.Settings.DISABLED_WORLDS.getStringList().stream()
|
||||
.noneMatch(worldStr -> location.getWorld().getName().equalsIgnoreCase(worldStr))
|
||||
&& spawnCount >= com.songoda.ultimatestacker.settings.Settings.MIN_STACK_ENTITIES.getInt();
|
||||
|
||||
int spawnCountUsed = useUltimateStacker ? 1 : spawnCount;
|
||||
|
||||
while (spawnCountUsed-- > 0) {
|
||||
EntityType type = types[ThreadLocalRandom.current().nextInt(types.length)];
|
||||
Entity entity = spawnEntity(type, spawner, data);
|
||||
if (entity != null) {
|
||||
// If we're using UltimateStacker and this entity is indeed stackable then spawn a single stack with the desired stack size.
|
||||
if (useUltimateStacker && com.songoda.ultimatestacker.UltimateStacker.getInstance().getMobFile().getBoolean("Mobs." + entity.getType().name() + ".Enabled"))
|
||||
com.songoda.ultimatestacker.UltimateStacker.getInstance().getEntityStackManager().addStack((LivingEntity) entity, spawnCount);
|
||||
spawner.setSpawnCount(spawner.getSpawnCount() + (useUltimateStacker ? spawnCount : 1));
|
||||
EpicSpawners.getInstance().getDataManager().updateSpawner(spawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Entity spawnEntity(EntityType type, PlacedSpawner spawner, SpawnerTier tier) {
|
||||
try {
|
||||
Object objMobSpawnerData = clazzMobSpawnerData.newInstance();
|
||||
Object objNTBTagCompound = methodGetEntity.invoke(objMobSpawnerData);
|
||||
|
||||
String name = type.name().toLowerCase().replace("pig_zombie", "zombie_pigman").replace("snowman", "snow_golem").replace("mushroom_cow", "mooshroom");
|
||||
methodSetString.invoke(objNTBTagCompound, "id", "minecraft:" + name);
|
||||
|
||||
short spawnRange = 4;
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Object objNBTTagCompound = methodGetEntity.invoke(objMobSpawnerData);
|
||||
Object objCraftWorld = clazzCraftWorld.cast(spawner.getWorld());
|
||||
objCraftWorld = methodGetHandle.invoke(objCraftWorld);
|
||||
Object objWorld = clazzWorld.cast(objCraftWorld);
|
||||
|
||||
Random random = (Random) fieldWorldRandom.get(objWorld);
|
||||
double x = (double) spawner.getX() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D;
|
||||
double y = spawner.getY() + random.nextInt(3) - 1;
|
||||
double z = (double) spawner.getZ() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D;
|
||||
|
||||
Object objEntity;
|
||||
if (methodChunkRegionLoaderA != null) {
|
||||
objEntity = methodChunkRegionLoaderA.invoke(null, objNBTTagCompound, objWorld, x, y, z, false);
|
||||
} else {
|
||||
Optional optional = (Optional) methodA.invoke(null, objNBTTagCompound, objWorld);
|
||||
|
||||
if (!optional.isPresent()) continue;
|
||||
|
||||
objEntity = optional.get();
|
||||
|
||||
methodSetPosition.invoke(objEntity, x, y, z);
|
||||
}
|
||||
|
||||
Object objBlockPosition;
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16))
|
||||
objBlockPosition = methodGetChunkCoordinates.invoke(objEntity);
|
||||
else
|
||||
objBlockPosition = clazzBlockPosition.getConstructor(clazzEntity).newInstance(objEntity);
|
||||
Object objDamageScaler = methodGetDamageScaler.invoke(objWorld, objBlockPosition);
|
||||
|
||||
Object objEntityInsentient = clazzEntityInsentient.isInstance(objEntity) ? clazzEntityInsentient.cast(objEntity) : null;
|
||||
|
||||
Location spot = new Location(spawner.getWorld(), x, y, z);
|
||||
if (!canSpawn(objWorld, objEntityInsentient, tier, spot))
|
||||
continue;
|
||||
|
||||
if (methodChunkRegionLoaderA != null) {
|
||||
methodEntityInsentientPrepare.invoke(objEntity, objDamageScaler, null, null);
|
||||
} else {
|
||||
methodEntityInsentientPrepare.invoke(objEntity, objWorld, objDamageScaler, SpawnerEnum, null, null);
|
||||
}
|
||||
|
||||
Entity craftEntity = (Entity) methodEntityGetBukkitEntity.invoke(objEntity);
|
||||
|
||||
SpawnerSpawnEvent event = new SpawnerSpawnEvent(craftEntity, spawner);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
craftEntity.remove();
|
||||
return null;
|
||||
}
|
||||
|
||||
ParticleType particleType = tier.getEntitySpawnParticle();
|
||||
|
||||
if (particleType != ParticleType.NONE) {
|
||||
float xx = (float) (0 + (Math.random() * 1));
|
||||
float yy = (float) (0 + (Math.random() * 2));
|
||||
float zz = (float) (0 + (Math.random() * 1));
|
||||
spot.getWorld().spawnParticle(Particle.valueOf(particleType.getEffect()), spot, 5, xx, yy, zz, 0);
|
||||
}
|
||||
|
||||
if (methodChunkRegionLoaderA != null) {
|
||||
methodChunkRegionLoaderA2.invoke(null, objEntity, objWorld, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
||||
} else {
|
||||
methodAddEntity.invoke(clazzWorldServer.cast(objWorld), objEntity, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
||||
}
|
||||
|
||||
if (fieldSpawnReason != null) {
|
||||
fieldSpawnReason.set(objEntity, CreatureSpawnEvent.SpawnReason.SPAWNER);
|
||||
}
|
||||
|
||||
if (tier.isSpawnOnFire()) craftEntity.setFireTicks(160);
|
||||
|
||||
craftEntity.setMetadata("ESData", new FixedMetadataValue(plugin, tier.getSpawnerData().getIdentifyingName()));
|
||||
craftEntity.setMetadata("ESTier", new FixedMetadataValue(plugin, tier.getIdentifyingName()));
|
||||
|
||||
if (mcmmo)
|
||||
craftEntity.setMetadata("mcMMO: Spawned Entity", new FixedMetadataValue(plugin, true));
|
||||
|
||||
if (Settings.NO_AI.getBoolean())
|
||||
EntityUtils.setUnaware(objEntity);
|
||||
|
||||
Object objBukkitEntity = methodEntityGetBukkitEntity.invoke(objEntity);
|
||||
spot.setYaw(random.nextFloat() * 360.0F);
|
||||
methodCraftEntityTeleport.invoke(objBukkitEntity, spot);
|
||||
|
||||
plugin.getSpawnManager().addUnnaturalSpawn(craftEntity.getUniqueId());
|
||||
|
||||
return craftEntity;
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean canSpawn(Object objWorld, Object objEntityInsentient, SpawnerTier data, Location location) {
|
||||
try {
|
||||
Object objIWR = clazzIWorldReader == null ? clazzICollisionAccess.cast(objWorld) : clazzIWorldReader.cast(objWorld);
|
||||
|
||||
if (!(boolean) methodGetCubes.invoke(objIWR, objEntityInsentient, methodGetBoundingBox.invoke(objEntityInsentient)))
|
||||
return false;
|
||||
|
||||
CompatibleMaterial[] spawnBlocks = data.getSpawnBlocks();
|
||||
|
||||
CompatibleMaterial spawnedIn = CompatibleMaterial.getMaterial(location.getBlock());
|
||||
CompatibleMaterial spawnedOn = CompatibleMaterial.getMaterial(location.getBlock().getRelative(BlockFace.DOWN));
|
||||
|
||||
if (!spawnedIn.isAir()
|
||||
&& !spawnedIn.isWater()
|
||||
&& !spawnedIn.name().contains("PRESSURE")
|
||||
&& !spawnedIn.name().contains("SLAB")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CompatibleMaterial material : spawnBlocks) {
|
||||
if (material == null) continue;
|
||||
|
||||
if (spawnedOn.equals(material) || material.isAir())
|
||||
return true;
|
||||
}
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnOptionType getType() {
|
||||
return SpawnOptionType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * (types != null ? Arrays.hashCode(types) : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == this) return true;
|
||||
if (!(object instanceof SpawnOptionEntity_1_13)) return false;
|
||||
|
||||
SpawnOptionEntity_1_13 other = (SpawnOptionEntity_1_13) object;
|
||||
return Arrays.equals(types, other.types);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user