mirror of
https://github.com/songoda/UltimateStacker.git
synced 2024-12-29 03:48:43 +01:00
NBT Support - Async - Block Stacking.
This commit is contained in:
parent
af10fcb026
commit
3e97f839dd
@ -17,8 +17,8 @@ import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.ultimatestacker.commands.*;
|
||||
import com.songoda.ultimatestacker.database.DataManager;
|
||||
import com.songoda.ultimatestacker.database.migrations._1_InitialMigration;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.database.migrations._2_EntityStacks;
|
||||
import com.songoda.ultimatestacker.database.migrations._3_BlockStacks;
|
||||
import com.songoda.ultimatestacker.hook.StackerHook;
|
||||
import com.songoda.ultimatestacker.hook.hooks.JobsHook;
|
||||
import com.songoda.ultimatestacker.listeners.*;
|
||||
@ -27,20 +27,22 @@ import com.songoda.ultimatestacker.listeners.item.ItemLegacyListener;
|
||||
import com.songoda.ultimatestacker.listeners.item.ItemListeners;
|
||||
import com.songoda.ultimatestacker.lootables.LootablesManager;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.Hologramable;
|
||||
import com.songoda.ultimatestacker.stackable.block.BlockStack;
|
||||
import com.songoda.ultimatestacker.stackable.block.BlockStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStackManager;
|
||||
import com.songoda.ultimatestacker.storage.Storage;
|
||||
import com.songoda.ultimatestacker.storage.StorageRow;
|
||||
import com.songoda.ultimatestacker.storage.types.StorageYaml;
|
||||
import com.songoda.ultimatestacker.tasks.StackingTask;
|
||||
import com.songoda.ultimatestacker.utils.EntityUtils;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -65,6 +67,7 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
private final List<StackerHook> stackerHooks = new ArrayList<>();
|
||||
private EntityStackManager entityStackManager;
|
||||
private SpawnerStackManager spawnerStackManager;
|
||||
private BlockStackManager blockStackManager;
|
||||
private LootablesManager lootablesManager;
|
||||
private CommandManager commandManager;
|
||||
private StackingTask stackingTask;
|
||||
@ -73,8 +76,6 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
private DataMigrationManager dataMigrationManager;
|
||||
private DataManager dataManager;
|
||||
|
||||
private EntityUtils entityUtils;
|
||||
|
||||
public static UltimateStacker getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
@ -118,8 +119,6 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
new CommandConvert(guiManager)
|
||||
);
|
||||
|
||||
this.entityUtils = new EntityUtils();
|
||||
|
||||
this.lootablesManager = new LootablesManager();
|
||||
this.lootablesManager.createDefaultLootables();
|
||||
this.getLootablesManager().getLootManager().loadLootables();
|
||||
@ -153,8 +152,8 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
spawnerFile.saveChanges();
|
||||
|
||||
this.spawnerStackManager = new SpawnerStackManager();
|
||||
this.entityStackManager = new EntityStackManager();
|
||||
this.stackingTask = new StackingTask(this);
|
||||
this.entityStackManager = new EntityStackManager(this);
|
||||
this.blockStackManager = new BlockStackManager();
|
||||
|
||||
guiManager.init();
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
@ -185,33 +184,6 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
}
|
||||
HologramManager.load(this);
|
||||
|
||||
// Legacy Data
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
File folder = getDataFolder();
|
||||
File dataFile = new File(folder, "data.yml");
|
||||
|
||||
if (dataFile.exists()) {
|
||||
Storage storage = new StorageYaml(this);
|
||||
if (storage.containsGroup("spawners")) {
|
||||
for (StorageRow row : storage.getRowsByGroup("spawners")) {
|
||||
try {
|
||||
Location location = Methods.unserializeLocation(row.getKey());
|
||||
|
||||
SpawnerStack stack = new SpawnerStack(
|
||||
location,
|
||||
row.get("amount").asInt());
|
||||
|
||||
getDataManager().createSpawner(stack);
|
||||
} catch (Exception e) {
|
||||
console.sendMessage("Failed to load spawner.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
dataFile.delete();
|
||||
}
|
||||
}, 10);
|
||||
|
||||
// Database stuff, go!
|
||||
try {
|
||||
if (Settings.MYSQL_ENABLED.getBoolean()) {
|
||||
@ -235,17 +207,72 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
|
||||
this.dataManager = new DataManager(this.databaseConnector, this);
|
||||
this.dataMigrationManager = new DataMigrationManager(this.databaseConnector, this.dataManager,
|
||||
new _1_InitialMigration());
|
||||
new _1_InitialMigration(),
|
||||
new _2_EntityStacks(),
|
||||
new _3_BlockStacks());
|
||||
this.dataMigrationManager.runMigrations();
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
final boolean useHolo = Settings.SPAWNER_HOLOGRAMS.getBoolean();
|
||||
this.dataManager.getSpawners((spawners) -> {
|
||||
this.spawnerStackManager.addSpawners(spawners);
|
||||
if (useHolo)
|
||||
loadHolograms();
|
||||
});
|
||||
}, 20L);
|
||||
@Override
|
||||
public void onDataLoad() {
|
||||
// Legacy Data
|
||||
File folder = getDataFolder();
|
||||
File dataFile = new File(folder, "data.yml");
|
||||
|
||||
if (dataFile.exists()) {
|
||||
Storage storage = new StorageYaml(this);
|
||||
if (storage.containsGroup("spawners")) {
|
||||
for (StorageRow row : storage.getRowsByGroup("spawners")) {
|
||||
try {
|
||||
Location location = Methods.unserializeLocation(row.getKey());
|
||||
|
||||
SpawnerStack stack = new SpawnerStack(
|
||||
location,
|
||||
row.get("amount").asInt());
|
||||
|
||||
getDataManager().createSpawner(stack);
|
||||
} catch (Exception e) {
|
||||
console.sendMessage("Failed to load spawner.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
dataFile.delete();
|
||||
}
|
||||
|
||||
// Load current data.
|
||||
final boolean useSpawnerHolo = Settings.SPAWNER_HOLOGRAMS.getBoolean();
|
||||
this.dataManager.getSpawners((spawners) -> {
|
||||
this.spawnerStackManager.addSpawners(spawners);
|
||||
if (useSpawnerHolo) {
|
||||
if (spawners.isEmpty()) return;
|
||||
|
||||
for (SpawnerStack spawner : spawners.values()) {
|
||||
if (spawner.getLocation().getWorld() != null) {
|
||||
updateHologram(spawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.dataManager.getEntities((entities) -> {
|
||||
entityStackManager.addStacks(entities.values());
|
||||
entityStackManager.tryAndLoadColdEntities();
|
||||
this.stackingTask = new StackingTask(this);
|
||||
getServer().getPluginManager().registerEvents(new ChunkListeners(this), this);
|
||||
});
|
||||
final boolean useBlockHolo = Settings.SPAWNER_HOLOGRAMS.getBoolean();
|
||||
this.dataManager.getBlocks((blocks) -> {
|
||||
this.blockStackManager.addBlocks(blocks);
|
||||
if (useBlockHolo) {
|
||||
if (blocks.isEmpty()) return;
|
||||
|
||||
for (BlockStack stack : blocks.values()) {
|
||||
if (stack.getLocation().getWorld() != null) {
|
||||
updateHologram(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addExp(Player player, EntityStack stack) {
|
||||
@ -269,8 +296,6 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
this.setLocale(getConfig().getString("System.Language Mode"), true);
|
||||
this.locale.reloadMessages();
|
||||
|
||||
this.entityUtils = new EntityUtils();
|
||||
|
||||
this.stackingTask.cancel();
|
||||
this.stackingTask = new StackingTask(this);
|
||||
|
||||
@ -281,7 +306,8 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
}
|
||||
|
||||
public boolean spawnersEnabled() {
|
||||
return !this.getServer().getPluginManager().isPluginEnabled("EpicSpawners") && Settings.SPAWNERS_ENABLED.getBoolean();
|
||||
return !this.getServer().getPluginManager().isPluginEnabled("EpicSpawners")
|
||||
&& Settings.SPAWNERS_ENABLED.getBoolean();
|
||||
}
|
||||
|
||||
public CommandManager getCommandManager() {
|
||||
@ -316,10 +342,6 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
return spawnerFile;
|
||||
}
|
||||
|
||||
public EntityUtils getEntityUtils() {
|
||||
return entityUtils;
|
||||
}
|
||||
|
||||
public DatabaseConnector getDatabaseConnector() {
|
||||
return databaseConnector;
|
||||
}
|
||||
@ -332,45 +354,20 @@ public class UltimateStacker extends SongodaPlugin {
|
||||
return guiManager;
|
||||
}
|
||||
|
||||
void loadHolograms() {
|
||||
Collection<SpawnerStack> spawners = getSpawnerStackManager().getStacks();
|
||||
if (spawners.isEmpty()) return;
|
||||
|
||||
for (SpawnerStack spawner : spawners) {
|
||||
if (spawner.getLocation().getWorld() != null) {
|
||||
updateHologram(spawner);
|
||||
}
|
||||
}
|
||||
public BlockStackManager getBlockStackManager() {
|
||||
return blockStackManager;
|
||||
}
|
||||
|
||||
public void clearHologram(SpawnerStack stack) {
|
||||
HologramManager.removeHologram(stack.getLocation());
|
||||
}
|
||||
|
||||
public void updateHologram(SpawnerStack stack) {
|
||||
public void updateHologram(Hologramable stack) {
|
||||
// are holograms enabled?
|
||||
if (!Settings.SPAWNER_HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return;
|
||||
Block block = stack.getLocation().getBlock();
|
||||
if (block.getType() != CompatibleMaterial.SPAWNER.getBlockMaterial()) return;
|
||||
// grab the spawner block
|
||||
CreatureSpawner creatureSpawner = (CreatureSpawner) block.getState();
|
||||
String name = Methods.compileSpawnerName(creatureSpawner.getSpawnedType(), stack.getAmount());
|
||||
if (!stack.areHologramsEnabled() && !HologramManager.getManager().isEnabled()) return;
|
||||
// create the hologram
|
||||
HologramManager.updateHologram(stack.getLocation(), name);
|
||||
HologramManager.updateHologram(stack.getLocation(), stack.getHologramName());
|
||||
}
|
||||
|
||||
public void removeHologram(Block block) {
|
||||
HologramManager.removeHologram(block.getLocation());
|
||||
}
|
||||
|
||||
public void updateHologram(Block block) {
|
||||
// verify that this is a spawner
|
||||
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()) return;
|
||||
// are holograms enabled?
|
||||
if (!Settings.SPAWNER_HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return;
|
||||
// update this hologram in a tick
|
||||
SpawnerStack spawner = getSpawnerStackManager().getSpawner(block);
|
||||
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, () -> updateHologram(spawner), 10L);
|
||||
public void removeHologram(Hologramable stack) {
|
||||
HologramManager.removeHologram(stack.getLocation());
|
||||
}
|
||||
|
||||
//////// Convenient API //////////
|
||||
|
@ -2,19 +2,11 @@ package com.songoda.ultimatestacker.commands;
|
||||
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.lootables.gui.GuiEditor;
|
||||
import com.songoda.lootables.gui.GuiLootableEditor;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandLootables extends AbstractCommand {
|
||||
|
||||
|
@ -3,13 +3,14 @@ package com.songoda.ultimatestacker.commands;
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -42,9 +43,9 @@ public class CommandRemoveAll extends AbstractCommand {
|
||||
EntityStackManager stackManager = instance.getEntityStackManager();
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Entity entityO : world.getEntities()) {
|
||||
if (entityO instanceof Player) continue;
|
||||
if (entityO instanceof Player || !(entityO instanceof LivingEntity)) continue;
|
||||
|
||||
if (entityO.getType() != EntityType.DROPPED_ITEM && (stackManager.isStacked(entityO) || all) && type.equalsIgnoreCase("entities")) {
|
||||
if (entityO.getType() != EntityType.DROPPED_ITEM && (stackManager.isStackedAndLoaded((LivingEntity)entityO) || all) && type.equalsIgnoreCase("entities")) {
|
||||
entityO.remove();
|
||||
amountRemoved++;
|
||||
} else if (entityO.getType() == EntityType.DROPPED_ITEM && type.equalsIgnoreCase("items")) {
|
||||
|
@ -2,13 +2,10 @@ package com.songoda.ultimatestacker.commands;
|
||||
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.songoda.ultimatestacker.convert;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import uk.antiperson.stackmob.StackMob;
|
||||
|
||||
@ -38,11 +38,10 @@ public class StackMobConvert implements Convert {
|
||||
public void convertEntities() {
|
||||
EntityStackManager entityStackManager = plugin.getEntityStackManager();
|
||||
for (Map.Entry<UUID, Integer> entry : stackMob.getStorageManager().getAmountCache().entrySet()) {
|
||||
if (!entityStackManager.isStacked(entry.getKey())) {
|
||||
entityStackManager.addStack(entry.getKey(), entry.getValue());
|
||||
if (!entityStackManager.isStackedAndLoaded(entry.getKey())) {
|
||||
entityStackManager.addLegacyColdStack(entry.getKey(), entry.getValue());
|
||||
continue;
|
||||
}
|
||||
entityStackManager.getStack(entry.getKey()).setAmount(entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,21 +3,27 @@ package com.songoda.ultimatestacker.convert;
|
||||
import com.bgsoftware.wildstacker.WildStackerPlugin;
|
||||
import com.bgsoftware.wildstacker.api.WildStackerAPI;
|
||||
import com.bgsoftware.wildstacker.api.objects.StackedSpawner;
|
||||
import com.songoda.core.database.DatabaseConnector;
|
||||
import com.songoda.core.database.SQLiteConnector;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WildStackerConvert implements Convert {
|
||||
|
||||
private WildStackerPlugin wildStacker;
|
||||
private final UltimateStacker plugin;
|
||||
|
||||
public WildStackerConvert() {
|
||||
this.plugin = UltimateStacker.getInstance();
|
||||
this.wildStacker = (WildStackerPlugin) Bukkit.getPluginManager().getPlugin("WildStacker");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -38,18 +44,21 @@ public class WildStackerConvert implements Convert {
|
||||
@Override
|
||||
public void convertEntities() {
|
||||
EntityStackManager entityStackManager = plugin.getEntityStackManager();
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
if (!(entity instanceof LivingEntity)) continue;
|
||||
if (!entityStackManager.isStacked(entity)) {
|
||||
entityStackManager
|
||||
.addStack(entity, WildStackerAPI.getEntityAmount((LivingEntity)entity));
|
||||
continue;
|
||||
|
||||
DatabaseConnector connector = new SQLiteConnector(this.wildStacker);
|
||||
connector.connect(connection -> {
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery("SELECT uuid, stackAmount FROM entities");
|
||||
while (result.next()) {
|
||||
UUID uuid = UUID.fromString(result.getString("uuid"));
|
||||
int amount = result.getInt("stackAmount");
|
||||
if (!entityStackManager.isEntityInColdStorage(uuid))
|
||||
entityStackManager.addLegacyColdStack(uuid, amount);
|
||||
}
|
||||
entityStackManager
|
||||
.getStack(entity).setAmount(WildStackerAPI.getEntityAmount((LivingEntity)entity));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,24 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.database.DataManagerAbstract;
|
||||
import com.songoda.core.database.DatabaseConnector;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import com.songoda.ultimatestacker.stackable.block.BlockStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.ColdEntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.StackedEntity;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DataManager extends DataManagerAbstract {
|
||||
|
||||
public DataManager(DatabaseConnector databaseConnector, Plugin plugin) {
|
||||
@ -49,7 +53,7 @@ public class DataManager extends DataManagerAbstract {
|
||||
|
||||
|
||||
public void createSpawner(SpawnerStack spawnerStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
this.queueAsync(() -> this.databaseConnector.connect(connection -> {
|
||||
|
||||
String createSpawner = "INSERT INTO " + this.getTablePrefix() + "spawners (amount, world, x, y, z) VALUES (?, ?, ?, ?, ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSpawner)) {
|
||||
@ -61,8 +65,137 @@ public class DataManager extends DataManagerAbstract {
|
||||
statement.setInt(5, spawnerStack.getZ());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
int spawnerId = this.lastInsertedId(connection);
|
||||
int spawnerId = this.lastInsertedId(connection, "spawners");
|
||||
this.sync(() -> spawnerStack.setId(spawnerId));
|
||||
}), "create");
|
||||
}
|
||||
|
||||
public void updateBlock(BlockStack blockStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
if (blockStack.getAmount() == 0) return;
|
||||
String updateBlock = "UPDATE " + this.getTablePrefix() + "blocks SET amount = ? WHERE id = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(updateBlock)) {
|
||||
statement.setInt(1, blockStack.getAmount());
|
||||
statement.setInt(2, blockStack.getId());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public void createBlock(BlockStack blockStack) {
|
||||
this.queueAsync(() -> this.databaseConnector.connect(connection -> {
|
||||
|
||||
String createSpawner = "INSERT INTO " + this.getTablePrefix() + "blocks (amount, material, world, x, y, z) VALUES (?, ?, ?, ?, ?, ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSpawner)) {
|
||||
statement.setInt(1, blockStack.getAmount());
|
||||
statement.setString(2, blockStack.getMaterial().name());
|
||||
|
||||
statement.setString(3, blockStack.getWorld().getName());
|
||||
statement.setInt(4, blockStack.getX());
|
||||
statement.setInt(5, blockStack.getY());
|
||||
statement.setInt(6, blockStack.getZ());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
int blockId = this.lastInsertedId(connection, "blocks");
|
||||
this.sync(() -> blockStack.setId(blockId));
|
||||
}), "create");
|
||||
}
|
||||
|
||||
|
||||
public void createHostEntity(ColdEntityStack stack) {
|
||||
this.queueAsync(() -> this.databaseConnector.connect(connection -> {
|
||||
if (stack.getHostUniqueId() == null) return;
|
||||
String createSerializedEntity = "INSERT INTO " + this.getTablePrefix() + "host_entities (uuid, create_duplicates) VALUES (?, ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSerializedEntity)) {
|
||||
statement.setString(1, stack.getHostUniqueId().toString());
|
||||
statement.setInt(2, stack.getCreateDuplicates());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
int stackId = this.lastInsertedId(connection, "host_entities");
|
||||
this.sync(() -> stack.setId(stackId));
|
||||
}), "create");
|
||||
}
|
||||
|
||||
public void createStackedEntity(EntityStack hostStack, StackedEntity stackedEntity) {
|
||||
this.queueAsync(() -> this.databaseConnector.connect(connection -> {
|
||||
if (hostStack.getHostUniqueId() == null) return;
|
||||
String createSerializedEntity = "INSERT INTO " + this.getTablePrefix() + "stacked_entities (uuid, host, serialized_entity) VALUES (?, ?, ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSerializedEntity)) {
|
||||
statement.setString(1, stackedEntity.getUniqueId().toString());
|
||||
statement.setInt(2, hostStack.getId());
|
||||
statement.setBytes(3, stackedEntity.getSerializedEntity());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}), "create");
|
||||
}
|
||||
|
||||
public void createStackedEntities(ColdEntityStack hostStack, List<StackedEntity> stackedEntities) {
|
||||
this.queueAsync(() -> this.databaseConnector.connect(connection -> {
|
||||
if (hostStack.getHostUniqueId() == null) return;
|
||||
String createSerializedEntity = "INSERT INTO " + this.getTablePrefix() + "stacked_entities (uuid, host, serialized_entity) VALUES (?, ?, ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSerializedEntity)) {
|
||||
for (StackedEntity entity : stackedEntities) {
|
||||
statement.setString(1, entity.getUniqueId().toString());
|
||||
statement.setInt(2, hostStack.getId());
|
||||
statement.setBytes(3, entity.getSerializedEntity());
|
||||
statement.addBatch();
|
||||
}
|
||||
statement.executeBatch();
|
||||
}
|
||||
}), "create");
|
||||
}
|
||||
|
||||
public void updateHost(ColdEntityStack hostStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
if (hostStack.getHostUniqueId() == null) return;
|
||||
String updateHost = "UPDATE " + this.getTablePrefix() + "host_entities SET uuid = ?, create_duplicates = ? WHERE id = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(updateHost)) {
|
||||
statement.setString(1, hostStack.getHostUniqueId().toString());
|
||||
statement.setInt(2, hostStack.getCreateDuplicates());
|
||||
statement.setInt(3, hostStack.getId());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteHost(ColdEntityStack stack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String deleteHost = "DELETE FROM " + this.getTablePrefix() + "host_entities WHERE id = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteHost)) {
|
||||
statement.setInt(1, stack.getId());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
|
||||
String deleteStackedEntities = "DELETE FROM " + this.getTablePrefix() + "stacked_entities WHERE host = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteStackedEntities)) {
|
||||
statement.setInt(1, stack.getId());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteStackedEntity(UUID uuid) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String deleteStackedEntity = "DELETE FROM " + this.getTablePrefix() + "stacked_entities WHERE uuid = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteStackedEntity)) {
|
||||
statement.setString(1, uuid.toString());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteStackedEntities(List<StackedEntity> entities) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String deleteStackedEntities = "DELETE FROM " + this.getTablePrefix() + "stacked_entities WHERE uuid = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteStackedEntities)) {
|
||||
for (StackedEntity entity : entities) {
|
||||
if (entity == null) continue;
|
||||
statement.setString(1, entity.getUniqueId().toString());
|
||||
statement.addBatch();
|
||||
}
|
||||
statement.executeBatch();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@ -76,6 +209,59 @@ public class DataManager extends DataManagerAbstract {
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteBlock(BlockStack blockStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String deleteBlock = "DELETE FROM " + this.getTablePrefix() + "blocks WHERE id = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteBlock)) {
|
||||
statement.setInt(1, blockStack.getId());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void getEntities(Consumer<Map<Integer, ColdEntityStack>> callback) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
|
||||
Map<Integer, ColdEntityStack> entities = new HashMap<>();
|
||||
|
||||
String selectEntities = "SELECT * FROM " + this.getTablePrefix() + "host_entities";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery(selectEntities);
|
||||
while (result.next()) {
|
||||
int hostId = result.getInt("id");
|
||||
|
||||
UUID host = UUID.fromString(result.getString("uuid"));
|
||||
|
||||
int createDuplicates = result.getInt("create_duplicates");
|
||||
|
||||
ColdEntityStack stack = new ColdEntityStack(host, hostId);
|
||||
stack.createDuplicates(createDuplicates);
|
||||
entities.put(hostId, stack);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String selectStackedEntities = "SELECT * FROM " + this.getTablePrefix() + "stacked_entities";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery(selectStackedEntities);
|
||||
while (result.next()) {
|
||||
UUID uuid = UUID.fromString(result.getString("uuid"));
|
||||
int hostId = result.getInt("host");
|
||||
byte[] serializedEntity = result.getBytes("serialized_entity");
|
||||
|
||||
ColdEntityStack stack = entities.get(hostId);
|
||||
if (stack == null) continue;
|
||||
stack.addEntityToStackSilently(new StackedEntity(uuid, serializedEntity));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.sync(() -> callback.accept(entities));
|
||||
}));
|
||||
}
|
||||
|
||||
public void getSpawners(Consumer<Map<Location, SpawnerStack>> callback) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String selectSpawners = "SELECT * FROM " + this.getTablePrefix() + "spawners";
|
||||
@ -87,7 +273,7 @@ public class DataManager extends DataManagerAbstract {
|
||||
while (result.next()) {
|
||||
World world = Bukkit.getWorld(result.getString("world"));
|
||||
|
||||
if(world == null)
|
||||
if (world == null)
|
||||
continue;
|
||||
|
||||
int spawnerId = result.getInt("id");
|
||||
@ -110,4 +296,41 @@ public class DataManager extends DataManagerAbstract {
|
||||
this.sync(() -> callback.accept(spawners));
|
||||
}));
|
||||
}
|
||||
|
||||
public void getBlocks(Consumer<Map<Location, BlockStack>> callback) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String selectBlocks = "SELECT * FROM " + this.getTablePrefix() + "blocks";
|
||||
|
||||
Map<Location, BlockStack> blocks = new HashMap<>();
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery(selectBlocks);
|
||||
while (result.next()) {
|
||||
World world = Bukkit.getWorld(result.getString("world"));
|
||||
|
||||
if (world == null)
|
||||
continue;
|
||||
|
||||
int blockId = result.getInt("id");
|
||||
|
||||
CompatibleMaterial material = CompatibleMaterial.getMaterial(result.getString("material"));
|
||||
|
||||
int amount = result.getInt("amount");
|
||||
|
||||
int x = result.getInt("x");
|
||||
int y = result.getInt("y");
|
||||
int z = result.getInt("z");
|
||||
Location location = new Location(world, x, y, z);
|
||||
|
||||
BlockStack blockStack = new BlockStack(material, location, amount);
|
||||
blockStack.setId(blockId);
|
||||
blocks.put(location, blockStack);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.sync(() -> callback.accept(blocks));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.songoda.ultimatestacker.database.migrations;
|
||||
|
||||
import com.songoda.core.database.DataMigration;
|
||||
import com.songoda.core.database.MySQLConnector;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class _2_EntityStacks extends DataMigration {
|
||||
|
||||
public _2_EntityStacks() {
|
||||
super(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(Connection connection, String tablePrefix) throws SQLException {
|
||||
String autoIncrement = UltimateStacker.getInstance().getDatabaseConnector() instanceof MySQLConnector ? " AUTO_INCREMENT" : "";
|
||||
|
||||
// Create host entities table
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE " + tablePrefix + "host_entities (" +
|
||||
"id INTEGER PRIMARY KEY" + autoIncrement + ", " +
|
||||
"uuid VARCHAR(36) NOT NULL," +
|
||||
"create_duplicates INTEGER NOT NULL DEFAULT 0" +
|
||||
")");
|
||||
}
|
||||
|
||||
// Create stacked entities table
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE " + tablePrefix + "stacked_entities (" +
|
||||
"uuid VARCHAR(36) PRIMARY KEY NOT NULL," +
|
||||
"host INTEGER NOT NULL," +
|
||||
"serialized_entity VARBINARY NOT NULL" +
|
||||
")");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.songoda.ultimatestacker.database.migrations;
|
||||
|
||||
import com.songoda.core.database.DataMigration;
|
||||
import com.songoda.core.database.MySQLConnector;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class _3_BlockStacks extends DataMigration {
|
||||
|
||||
public _3_BlockStacks() {
|
||||
super(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(Connection connection, String tablePrefix) throws SQLException {
|
||||
String autoIncrement = UltimateStacker.getInstance().getDatabaseConnector() instanceof MySQLConnector ? " AUTO_INCREMENT" : "";
|
||||
|
||||
// Create blocks table
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE " + tablePrefix + "blocks (" +
|
||||
"id INTEGER PRIMARY KEY" + autoIncrement + ", " +
|
||||
"amount INTEGER NOT NULL," +
|
||||
"material STRING NOT NULL," +
|
||||
"world TEXT NOT NULL, " +
|
||||
"x DOUBLE NOT NULL, " +
|
||||
"y DOUBLE NOT NULL, " +
|
||||
"z DOUBLE NOT NULL " +
|
||||
")");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,274 +0,0 @@
|
||||
package com.songoda.ultimatestacker.entity;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.utils.EntityUtils;
|
||||
import com.songoda.lootables.loot.Drop;
|
||||
import com.songoda.lootables.loot.DropUtils;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.MetadataStoreBase;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
public class EntityStack {
|
||||
|
||||
private UUID entity;
|
||||
private int amount;
|
||||
|
||||
private final Deque<Double> health = new ConcurrentLinkedDeque<>();
|
||||
final Object healthLock = new Object();
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
|
||||
public EntityStack(LivingEntity entity, int amount) {
|
||||
this(entity.getUniqueId(), amount);
|
||||
this.addHealth(entity.getHealth());
|
||||
}
|
||||
|
||||
public EntityStack(UUID uuid, int amount) {
|
||||
this.entity = uuid;
|
||||
this.setAmount(amount);
|
||||
}
|
||||
|
||||
public void updateStack() {
|
||||
if (!Settings.ENTITY_HOLOGRAMS.getBoolean()) return;
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateStacker.getInstance(), () -> {
|
||||
Entity entit = getEntityByUniqueId(this.entity);
|
||||
if (entit == null ||
|
||||
!UltimateStacker.getInstance().getEntityStackManager().isStacked(entity)) return;
|
||||
|
||||
entit.setCustomNameVisible(!Settings.HOLOGRAMS_ON_LOOK_ENTITY.getBoolean());
|
||||
entit.setCustomName(Methods.compileEntityName(entit, amount));
|
||||
}, entity == null ? 1L : 0L);
|
||||
|
||||
}
|
||||
|
||||
public LivingEntity getEntity() {
|
||||
LivingEntity entity = getEntityByUniqueId(this.entity);
|
||||
if (entity == null) {
|
||||
UltimateStacker.getInstance().getEntityStackManager().removeStack(this.entity);
|
||||
return null;
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected void setEntity(Entity entity) {
|
||||
this.entity = entity.getUniqueId();
|
||||
}
|
||||
|
||||
public void addAmount(int amount) {
|
||||
this.amount = this.amount + amount;
|
||||
updateStack();
|
||||
}
|
||||
|
||||
public UUID getEntityUniqueId() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(int amount) {
|
||||
if (amount == 1) {
|
||||
Entity entity = getEntityByUniqueId(this.entity);
|
||||
if (entity == null) return;
|
||||
|
||||
UltimateStacker.getInstance().getEntityStackManager().removeStack(this.entity);
|
||||
entity.setCustomName(null);
|
||||
entity.setCustomNameVisible(false);
|
||||
return;
|
||||
}
|
||||
this.amount = amount;
|
||||
if (amount != 0)
|
||||
updateStack();
|
||||
}
|
||||
|
||||
private LivingEntity getEntityByUniqueId(UUID uniqueId) {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12))
|
||||
return (LivingEntity) Bukkit.getEntity(uniqueId);
|
||||
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
if (entity.getUniqueId().equals(uniqueId))
|
||||
return (LivingEntity) entity;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleWholeStackDeath(LivingEntity killed, List<Drop> drops, boolean custom, int droppedExp, EntityDeathEvent event) {
|
||||
UltimateStacker.getInstance().getEntityStackManager().removeStack(event.getEntity());
|
||||
|
||||
Location killedLocation = killed.getLocation();
|
||||
List<Drop> preStackedDrops = new ArrayList<>();
|
||||
for (int i = 1; i < amount; i++) {
|
||||
if (i == 1) {
|
||||
drops.removeIf(it -> it.getItemStack() != null
|
||||
&& it.getItemStack().isSimilar(killed.getEquipment().getItemInHand()));
|
||||
for (ItemStack item : killed.getEquipment().getArmorContents()) {
|
||||
drops.removeIf(it -> it.getItemStack() != null && it.getItemStack().isSimilar(item));
|
||||
}
|
||||
}
|
||||
if (custom)
|
||||
drops = plugin.getLootablesManager().getDrops(killed);
|
||||
preStackedDrops.addAll(drops);
|
||||
}
|
||||
if (!preStackedDrops.isEmpty())
|
||||
DropUtils.processStackedDrop(killed, preStackedDrops, event);
|
||||
|
||||
if (droppedExp > 0)
|
||||
killedLocation.getWorld().spawn(killedLocation, ExperienceOrb.class).setExperience(droppedExp * amount);
|
||||
|
||||
if (killed.getKiller() == null) return;
|
||||
UltimateStacker.getInstance().addExp(killed.getKiller(), this);
|
||||
}
|
||||
|
||||
private void handleSingleStackDeath(LivingEntity killed, List<Drop> drops, EntityDeathEvent event) {
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
|
||||
LivingEntity newEntity = plugin.getEntityUtils().newEntity(killed);
|
||||
|
||||
updateHealth(newEntity);
|
||||
|
||||
newEntity.getEquipment().clear();
|
||||
|
||||
if (killed.getType().name().equals("PIG_ZOMBIE"))
|
||||
newEntity.getEquipment().setItemInHand(CompatibleMaterial.GOLDEN_SWORD.getItem());
|
||||
|
||||
|
||||
|
||||
if (Settings.CARRY_OVER_METADATA_ON_DEATH.getBoolean()) {
|
||||
for (Map.Entry<String, MetadataValue> entry : getMetadata(killed).entrySet())
|
||||
newEntity.setMetadata(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
if (!EntityUtils.isAware(killed))
|
||||
EntityUtils.setUnaware(newEntity);
|
||||
|
||||
DropUtils.processStackedDrop(killed, drops, event);
|
||||
|
||||
EntityStack entityStack = stackManager.updateStack(killed, newEntity);
|
||||
|
||||
entityStack.addAmount(-1);
|
||||
|
||||
if (entityStack.getAmount() <= 1) {
|
||||
stackManager.removeStack(newEntity);
|
||||
newEntity.setCustomNameVisible(false);
|
||||
newEntity.setCustomName(null);
|
||||
}
|
||||
}
|
||||
|
||||
static final int metaCarryOverMin = Settings.META_CARRY_OVER_MIN.getInt() * 20;
|
||||
|
||||
public Map<String, MetadataValue> getMetadata(LivingEntity subject) {
|
||||
Map<String, MetadataValue> v = new HashMap<>();
|
||||
if (subject.getTicksLived() >= metaCarryOverMin) return v;
|
||||
|
||||
Map<String, Map<Plugin, MetadataValue>> metadataMap = null;
|
||||
try {
|
||||
Object entityMetadata = methodGetEntityMetadata.invoke(Bukkit.getServer());
|
||||
metadataMap = (Map) fieldMetadataMap.get(entityMetadata);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (metadataMap == null) return v;
|
||||
|
||||
for (Map.Entry<String, Map<Plugin, MetadataValue>> entry : metadataMap.entrySet()) {
|
||||
if (!entry.getKey().startsWith(subject.getUniqueId().toString())) continue;
|
||||
String key = entry.getKey().split(":")[1];
|
||||
for (MetadataValue value : entry.getValue().values())
|
||||
v.put(key, value);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static Method methodGetEntityMetadata;
|
||||
private static Field fieldMetadataMap;
|
||||
|
||||
static {
|
||||
try {
|
||||
String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23);
|
||||
Class<?> clazzCraftServer = Class.forName("org.bukkit.craftbukkit." + ver + ".CraftServer");
|
||||
methodGetEntityMetadata = clazzCraftServer.getDeclaredMethod("getEntityMetadata");
|
||||
fieldMetadataMap = MetadataStoreBase.class.getDeclaredField("metadataMap");
|
||||
} catch (NoSuchFieldException | ClassNotFoundException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
fieldMetadataMap.setAccessible(true);
|
||||
}
|
||||
|
||||
public void onDeath(LivingEntity killed, List<Drop> drops, boolean custom, int droppedExp, EntityDeathEvent event) {
|
||||
killed.setCustomName(null);
|
||||
killed.setCustomNameVisible(false);
|
||||
|
||||
boolean killWholeStack = Settings.KILL_WHOLE_STACK_ON_DEATH.getBoolean()
|
||||
|| plugin.getMobFile().getBoolean("Mobs." + killed.getType().name() + ".Kill Whole Stack");
|
||||
|
||||
if (killWholeStack && getAmount() != 1) {
|
||||
handleWholeStackDeath(killed, drops, custom, droppedExp, event);
|
||||
} else if (getAmount() != 1) {
|
||||
List<String> reasons = Settings.INSTANT_KILL.getStringList();
|
||||
EntityDamageEvent lastDamageCause = killed.getLastDamageCause();
|
||||
|
||||
if (lastDamageCause != null) {
|
||||
EntityDamageEvent.DamageCause cause = lastDamageCause.getCause();
|
||||
for (String s : reasons) {
|
||||
if (!cause.name().equalsIgnoreCase(s)) continue;
|
||||
handleWholeStackDeath(killed, drops, custom, Settings.NO_EXP_INSTANT_KILL.getBoolean() ? 0 : droppedExp, event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
handleSingleStackDeath(killed, drops, event);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateHealth(LivingEntity entity) {
|
||||
if (entity == null) return;
|
||||
synchronized (healthLock) {
|
||||
entity.setHealth(Settings.STACK_ENTITY_HEALTH.getBoolean()
|
||||
&& !health.isEmpty()
|
||||
? (health.getFirst() > entity.getMaxHealth() ? entity.getMaxHealth() : health.removeFirst())
|
||||
: entity.getMaxHealth());
|
||||
}
|
||||
}
|
||||
|
||||
public void addHealth(double health) {
|
||||
synchronized (healthLock) {
|
||||
this.health.addLast(health);
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeHealth(EntityStack stack) {
|
||||
synchronized (healthLock) {
|
||||
this.health.addAll(stack.health);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityStack:{"
|
||||
+ "Entity:\"" + entity.toString() + "\","
|
||||
+ "Amount:\"" + amount + "\","
|
||||
+ "}";
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
package com.songoda.ultimatestacker.entity;
|
||||
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntityStackManager {
|
||||
|
||||
// These are all stacked mobs loaded into memory.
|
||||
private static final Map<UUID, EntityStack> stacks = new HashMap<>();
|
||||
|
||||
public EntityStack addStack(EntityStack stack) {
|
||||
stacks.put(stack.getEntityUniqueId(), stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack addStack(Entity entity, int amount) {
|
||||
return addStack(entity.getUniqueId(), amount);
|
||||
}
|
||||
|
||||
public EntityStack addStack(UUID uuid, int amount) {
|
||||
EntityStack stack = new EntityStack(uuid, amount);
|
||||
stacks.put(uuid, stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack addSerializedStack(Entity entity, String customName) {
|
||||
if (customName != null && customName.contains(String.valueOf(ChatColor.COLOR_CHAR))) {
|
||||
String name = customName.replace(String.valueOf(ChatColor.COLOR_CHAR), "")
|
||||
.replace(";", "");
|
||||
if (!name.contains(":")) return null;
|
||||
String split = name.split(":")[0];
|
||||
int amount = Methods.isInt(split) ? Integer.parseInt(split) : 0;
|
||||
return addStack(entity, amount);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public EntityStack addSerializedStack(Entity entity) {
|
||||
return addSerializedStack(entity, entity.getCustomName());
|
||||
}
|
||||
|
||||
public EntityStack getStack(Entity entity) {
|
||||
EntityStack stack = getStack(entity.getUniqueId());
|
||||
if (stack == null) stack = addSerializedStack(entity);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack getStack(UUID uuid) {
|
||||
return stacks.get(uuid);
|
||||
}
|
||||
|
||||
public boolean isStacked(Entity entity) {
|
||||
if (entity == null) return false;
|
||||
boolean isStacked = isStacked(entity.getUniqueId());
|
||||
if (!isStacked && addSerializedStack(entity) != null) {
|
||||
return true;
|
||||
}
|
||||
return isStacked(entity.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean isStacked(UUID uuid) {
|
||||
return stacks.containsKey(uuid);
|
||||
}
|
||||
|
||||
public EntityStack removeStack(UUID entity) {
|
||||
return stacks.remove(entity);
|
||||
}
|
||||
|
||||
public EntityStack removeStack(Entity entity) {
|
||||
return stacks.remove(entity.getUniqueId());
|
||||
}
|
||||
|
||||
public Map<UUID, EntityStack> getStacks() {
|
||||
return Collections.unmodifiableMap(stacks);
|
||||
}
|
||||
|
||||
public EntityStack updateStack(Entity oldEntity, Entity newEntity) {
|
||||
EntityStack stack = stacks.remove(oldEntity.getUniqueId());
|
||||
if (stack == null) return null;
|
||||
stack.setEntity(newEntity);
|
||||
stacks.put(newEntity.getUniqueId(), stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.gui;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.convert.Convert;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -53,6 +54,7 @@ public class GUIConvertWhat extends Gui {
|
||||
void run(Player player) {
|
||||
if (entities) {
|
||||
convertFrom.convertEntities();
|
||||
UltimateStacker.getInstance().getEntityStackManager().tryAndLoadColdEntities();
|
||||
}
|
||||
if (spawners) {
|
||||
convertFrom.convertSpawners();
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.songoda.ultimatestacker.hook;
|
||||
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface StackerHook {
|
||||
|
@ -4,7 +4,7 @@ import com.gamingmesh.jobs.Jobs;
|
||||
import com.gamingmesh.jobs.actions.EntityActionInfo;
|
||||
import com.gamingmesh.jobs.container.ActionType;
|
||||
import com.gamingmesh.jobs.container.JobsPlayer;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.hook.StackerHook;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -22,7 +22,7 @@ public class JobsHook implements StackerHook {
|
||||
return;
|
||||
|
||||
for (int i = 1; i < entityStack.getAmount(); i++) {
|
||||
Entity entity = entityStack.getEntity();
|
||||
Entity entity = entityStack.getHostEntity();
|
||||
EntityActionInfo eInfo = new EntityActionInfo(entity, ActionType.KILL);
|
||||
Jobs.action(jPlayer, eInfo, entity);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.songoda.ultimatestacker.listeners;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleHand;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.nms.NmsManager;
|
||||
import com.songoda.core.nms.nbt.NBTItem;
|
||||
@ -7,11 +8,13 @@ import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.events.SpawnerBreakEvent;
|
||||
import com.songoda.ultimatestacker.events.SpawnerPlaceEvent;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.stackable.block.BlockStack;
|
||||
import com.songoda.ultimatestacker.stackable.block.BlockStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import java.util.ArrayList;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
@ -28,8 +31,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockListeners implements Listener {
|
||||
|
||||
@ -40,18 +42,79 @@ public class BlockListeners implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onSpawnerInteract(PlayerInteractEvent event) {
|
||||
public void onBlockInteract(PlayerInteractEvent event) {
|
||||
Block block = event.getClickedBlock();
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = event.getPlayer().getInventory().getItemInHand();
|
||||
|
||||
if (block == null
|
||||
|| block.getType() != CompatibleMaterial.SPAWNER.getMaterial()
|
||||
if (block == null) return;
|
||||
|
||||
if (Settings.STACK_BLOCKS.getBoolean()) {
|
||||
CompatibleHand hand = CompatibleHand.getHand(event);
|
||||
ItemStack inHand = hand.getItem(player);
|
||||
BlockStackManager blockStackManager = plugin.getBlockStackManager();
|
||||
|
||||
boolean isStacked = blockStackManager.isBlock(block.getLocation());
|
||||
|
||||
CompatibleMaterial blockType = CompatibleMaterial.getMaterial(block);
|
||||
|
||||
if (isStacked || Settings.STACKABLE_BLOCKS.getStringList().contains(blockType.name())) {
|
||||
BlockStack stack = blockStackManager.getBlock(block, blockType);
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
if (!isStacked) plugin.getDataManager().createBlock(stack);
|
||||
if (stack.getMaterial() == CompatibleMaterial.getMaterial(inHand)) {
|
||||
int amountToAdd = player.isSneaking() || Settings.ALWAYS_ADD_ALL.getBoolean() ? inHand.getAmount() : 1;
|
||||
if (!isStacked) amountToAdd ++;
|
||||
stack.add(amountToAdd);
|
||||
event.setCancelled(true);
|
||||
if (player.getGameMode() != GameMode.CREATIVE)
|
||||
hand.takeItem(player, amountToAdd);
|
||||
plugin.updateHologram(stack);
|
||||
}
|
||||
plugin.getDataManager().updateBlock(stack);
|
||||
} else if (event.getAction() == Action.LEFT_CLICK_BLOCK && stack.getAmount() != 0) {
|
||||
event.setCancelled(true);
|
||||
int amountToRemove = player.isSneaking()
|
||||
? Math.min(Settings.MAX_REMOVEABLE.getInt(), stack.getAmount()) - 1 : 1;
|
||||
|
||||
ItemStack removed = stack.getMaterial().getItem();
|
||||
removed.setAmount(amountToRemove);
|
||||
stack.take(amountToRemove);
|
||||
int maxStack = removed.getMaxStackSize();
|
||||
|
||||
while (amountToRemove > 0) {
|
||||
int subtract = Math.min(amountToRemove, maxStack);
|
||||
amountToRemove -= subtract;
|
||||
ItemStack newItem = removed.clone();
|
||||
newItem.setAmount(subtract);
|
||||
if (Settings.ADD_TO_INVENTORY.getBoolean()) {
|
||||
Map<Integer, ItemStack> result = player.getInventory().addItem(newItem);
|
||||
if (result.get(0) != null) {
|
||||
amountToRemove += result.get(0).getAmount();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
block.getWorld().dropItemNaturally(block.getLocation().clone().add(.5, 1, .5), newItem);
|
||||
}
|
||||
}
|
||||
stack.add(amountToRemove);
|
||||
if (stack.getAmount() < 2)
|
||||
stack.destroy();
|
||||
else {
|
||||
plugin.updateHologram(stack);
|
||||
plugin.getDataManager().updateBlock(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()
|
||||
|| item.getType() != CompatibleMaterial.SPAWNER.getMaterial()
|
||||
|| event.getAction() == Action.LEFT_CLICK_BLOCK) return;
|
||||
|
||||
List<String> disabledWorlds = Settings.DISABLED_WORLDS.getStringList();
|
||||
if (disabledWorlds.stream().anyMatch(worldStr -> event.getPlayer().getWorld().getName().equalsIgnoreCase(worldStr))) return;
|
||||
if (disabledWorlds.stream().anyMatch(worldStr -> event.getPlayer().getWorld().getName().equalsIgnoreCase(worldStr)))
|
||||
return;
|
||||
|
||||
if (!plugin.spawnersEnabled()) return;
|
||||
|
||||
@ -101,42 +164,36 @@ public class BlockListeners implements Listener {
|
||||
Methods.takeItem(player, itemAmount);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.updateHologram(block);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onSpawnerPlace(BlockPlaceEvent event) {
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
Block block = event.getBlock();
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()
|
||||
|| !(block.getState() instanceof CreatureSpawner) // Needed for a DataPack
|
||||
|| !plugin.spawnersEnabled())
|
||||
return;
|
||||
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()
|
||||
|| !(block.getState() instanceof CreatureSpawner) // Needed for a DataPack
|
||||
|| !plugin.spawnersEnabled())
|
||||
return;
|
||||
|
||||
CreatureSpawner cs = (CreatureSpawner) block.getState();
|
||||
CreatureSpawner cs2 = (CreatureSpawner) ((BlockStateMeta) event.getItemInHand().getItemMeta()).getBlockState();
|
||||
int amount = getSpawnerAmount(event.getItemInHand());
|
||||
CreatureSpawner cs = (CreatureSpawner) block.getState();
|
||||
CreatureSpawner cs2 = (CreatureSpawner) ((BlockStateMeta) event.getItemInHand().getItemMeta()).getBlockState();
|
||||
int amount = getSpawnerAmount(event.getItemInHand());
|
||||
|
||||
SpawnerPlaceEvent placeEvent = new SpawnerPlaceEvent(player, block, cs2.getSpawnedType(), amount);
|
||||
Bukkit.getPluginManager().callEvent(placeEvent);
|
||||
if (placeEvent.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnerStack stack = plugin.getSpawnerStackManager().addSpawner(new SpawnerStack(block.getLocation(), amount));
|
||||
plugin.getDataManager().createSpawner(stack);
|
||||
|
||||
cs.setSpawnedType(cs2.getSpawnedType());
|
||||
cs.update();
|
||||
|
||||
plugin.updateHologram(stack);
|
||||
SpawnerPlaceEvent placeEvent = new SpawnerPlaceEvent(player, block, cs2.getSpawnedType(), amount);
|
||||
Bukkit.getPluginManager().callEvent(placeEvent);
|
||||
if (placeEvent.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.updateHologram(block);
|
||||
SpawnerStack stack = plugin.getSpawnerStackManager().addSpawner(new SpawnerStack(block.getLocation(), amount));
|
||||
plugin.getDataManager().createSpawner(stack);
|
||||
|
||||
cs.setSpawnedType(cs2.getSpawnedType());
|
||||
cs.update();
|
||||
|
||||
plugin.updateHologram(stack);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
@ -175,7 +232,7 @@ public class BlockListeners implements Listener {
|
||||
|
||||
if (remove) {
|
||||
event.setCancelled(false);
|
||||
plugin.clearHologram(stack);
|
||||
plugin.removeHologram(stack);
|
||||
SpawnerStack spawnerStack = plugin.getSpawnerStackManager().removeSpawner(block.getLocation());
|
||||
plugin.getDataManager().deleteSpawner(spawnerStack);
|
||||
} else {
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.songoda.ultimatestacker.listeners;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
|
||||
public class ChunkListeners implements Listener {
|
||||
|
||||
private final EntityStackManager entityStackManager;
|
||||
|
||||
public ChunkListeners(UltimateStacker plugin) {
|
||||
this.entityStackManager = plugin.getEntityStackManager();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
Chunk chunk = event.getChunk();
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (!(entity instanceof LivingEntity)) continue;
|
||||
if (entityStackManager.isEntityInColdStorage((LivingEntity) entity)) {
|
||||
entityStackManager.loadStack((LivingEntity) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkUnload(ChunkUnloadEvent event) {
|
||||
Chunk chunk = event.getChunk();
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (!(entity instanceof LivingEntity)) continue;
|
||||
if (entityStackManager.isStackedAndLoaded((LivingEntity) entity)) {
|
||||
entityStackManager.unloadStack((LivingEntity) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.listeners;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import me.minebuilders.clearlag.events.EntityRemoveEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
@ -17,7 +18,7 @@ public class ClearLagListeners implements Listener {
|
||||
@EventHandler
|
||||
public void onClearLaggTask(EntityRemoveEvent event) {
|
||||
for (Entity entity : event.getWorld().getEntities()) {
|
||||
if (instance.getEntityStackManager().isStacked(entity)) {
|
||||
if (entity instanceof LivingEntity && instance.getEntityStackManager().isStackedAndLoaded((LivingEntity)entity)) {
|
||||
instance.getEntityStackManager().removeStack(entity);
|
||||
event.addEntity(entity);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.lootables.loot.Drop;
|
||||
import com.songoda.lootables.loot.DropUtils;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.Material;
|
||||
@ -57,7 +57,7 @@ public class DeathListeners implements Listener {
|
||||
&& !event.getEntity().getWorld().getGameRuleValue(GameRule.DO_MOB_LOOT))
|
||||
drops.clear();
|
||||
|
||||
if (instance.getEntityStackManager().isStacked(event.getEntity()))
|
||||
if (instance.getEntityStackManager().isStackedAndLoaded(event.getEntity()))
|
||||
instance.getEntityStackManager().getStack(event.getEntity())
|
||||
.onDeath(event.getEntity(), drops, custom, event.getDroppedExp(), event);
|
||||
else
|
||||
@ -115,8 +115,11 @@ public class DeathListeners implements Listener {
|
||||
public void onEntityHit(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Player) || ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12))
|
||||
return;
|
||||
if (!instance.getEntityStackManager().isStacked(event.getEntity())) return;
|
||||
EntityStack stack = instance.getEntityStackManager().getStack(event.getEntity());
|
||||
|
||||
if (!(event.getEntity() instanceof LivingEntity)) return;
|
||||
LivingEntity entity = (LivingEntity) event.getEntity();
|
||||
if (!instance.getEntityStackManager().isStackedAndLoaded(entity)) return;
|
||||
EntityStack stack = instance.getEntityStackManager().getStack(entity);
|
||||
|
||||
if (Settings.KILL_WHOLE_STACK_ON_DEATH.getBoolean() && Settings.REALISTIC_DAMAGE.getBoolean()) {
|
||||
Player player = (Player) event.getDamager();
|
||||
|
@ -2,10 +2,10 @@ package com.songoda.ultimatestacker.listeners;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -17,12 +17,11 @@ import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityTransformEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -38,15 +37,15 @@ public class EntityListeners implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onSpawn(CreatureSpawnEvent event) {
|
||||
LivingEntity entity = event.getEntity();
|
||||
entity.setMetadata("US_REASON", new FixedMetadataValue(plugin, event.getSpawnReason().name()));
|
||||
|
||||
if (event.getSpawnReason().name().equals("DROWNED")
|
||||
|| event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.LIGHTNING) {
|
||||
String name = event.getEntity().getCustomName();
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
() -> plugin.getEntityStackManager().addSerializedStack(entity, name), 1L);
|
||||
public void onSpawn(EntityTransformEvent event) {
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
if (stackManager.isStackedAndLoaded(event.getEntity().getUniqueId())
|
||||
&& event.getEntity() instanceof LivingEntity
|
||||
&& event.getTransformedEntity() instanceof LivingEntity) {
|
||||
EntityStack stack = stackManager.updateStack((LivingEntity) event.getEntity(),
|
||||
(LivingEntity) event.getTransformedEntity());
|
||||
stack.releaseHost();
|
||||
stack.updateStack();
|
||||
}
|
||||
|
||||
}
|
||||
@ -63,11 +62,15 @@ public class EntityListeners implements Listener {
|
||||
|
||||
if (entities.isEmpty()) return;
|
||||
|
||||
Entity entity = entities.get(0);
|
||||
Entity nonLivingEntity = entities.get(0);
|
||||
|
||||
if (!(nonLivingEntity instanceof LivingEntity)) return;
|
||||
|
||||
LivingEntity entity = (LivingEntity) nonLivingEntity;
|
||||
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
|
||||
if (!stackManager.isStacked(entity)) return;
|
||||
if (!stackManager.isStackedAndLoaded(entity)) return;
|
||||
|
||||
EntityStack stack = stackManager.getStack(entity);
|
||||
|
||||
@ -83,7 +86,9 @@ public class EntityListeners implements Listener {
|
||||
public void onHurt(EntityDamageByEntityEvent event) {
|
||||
if (!Settings.STACK_ENTITIES.getBoolean() || !(event.getDamager() instanceof Player)) return;
|
||||
|
||||
if (plugin.getEntityStackManager().isStacked(event.getEntity())
|
||||
Entity entity = event.getEntity();
|
||||
|
||||
if (entity instanceof LivingEntity && plugin.getEntityStackManager().isStackedAndLoaded((LivingEntity) entity)
|
||||
&& Settings.DISABLE_KNOCKBACK.getBoolean()
|
||||
&& ((Player) event.getDamager()).getItemInHand().getEnchantmentLevel(Enchantment.KNOCKBACK) == 0) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
|
||||
@ -127,7 +132,7 @@ public class EntityListeners implements Listener {
|
||||
|
||||
SpawnerStack spawnerStack = plugin.getSpawnerStackManager().removeSpawner(spawnLocation);
|
||||
plugin.getDataManager().deleteSpawner(spawnerStack);
|
||||
plugin.removeHologram(block);
|
||||
plugin.removeHologram(spawnerStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package com.songoda.ultimatestacker.listeners;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.Split;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Split;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@ -38,7 +38,7 @@ public class InteractListeners implements Listener {
|
||||
|
||||
ItemStack item = player.getInventory().getItemInHand();
|
||||
|
||||
if (!plugin.getEntityStackManager().isStacked(entity)) return;
|
||||
if (!plugin.getEntityStackManager().isStackedAndLoaded(entity)) return;
|
||||
|
||||
if (item.getType() != Material.NAME_TAG && !correctFood(item, entity)) return;
|
||||
|
||||
@ -56,7 +56,7 @@ public class InteractListeners implements Listener {
|
||||
else if (entity instanceof Ageable && !((Ageable) entity).isAdult())
|
||||
return;
|
||||
|
||||
plugin.getEntityUtils().splitFromStack(entity);
|
||||
stack.releaseHost();
|
||||
|
||||
if (item.getType() == Material.NAME_TAG) {
|
||||
entity.setCustomName(item.getItemMeta().getDisplayName());
|
||||
|
@ -3,9 +3,9 @@ package com.songoda.ultimatestacker.listeners;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.entity.Split;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Split;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
@ -28,13 +28,13 @@ public class ShearListeners implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onShear(PlayerShearEntityEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
LivingEntity entity = (LivingEntity)event.getEntity();
|
||||
|
||||
if (entity.getType() != EntityType.SHEEP
|
||||
&& entity.getType() != EntityType.MUSHROOM_COW
|
||||
&& entity.getType() != EntityType.SNOWMAN) return;
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
if (!stackManager.isStacked(entity)) return;
|
||||
if (!stackManager.isStackedAndLoaded(entity)) return;
|
||||
|
||||
if (event.getEntity().getType() == EntityType.SHEEP
|
||||
&& Settings.SPLIT_CHECKS.getStringList().stream().noneMatch(line -> Split.valueOf(line) == Split.SHEEP_SHEAR)
|
||||
@ -45,9 +45,10 @@ public class ShearListeners implements Listener {
|
||||
return;
|
||||
|
||||
|
||||
EntityStack stack = stackManager.getStack(entity);
|
||||
|
||||
if (Settings.SHEAR_IN_ONE_CLICK.getBoolean()) {
|
||||
World world = entity.getLocation().getWorld();
|
||||
EntityStack stack = stackManager.getStack(entity);
|
||||
int amount = stack.getAmount() - 1;
|
||||
ItemStack item = getDrop(entity);
|
||||
if (item == null)
|
||||
@ -76,7 +77,7 @@ public class ShearListeners implements Listener {
|
||||
world.dropItemNaturally(entity.getLocation(), clone);
|
||||
}
|
||||
} else
|
||||
plugin.getEntityUtils().splitFromStack((LivingEntity) entity);
|
||||
stack.releaseHost();
|
||||
}
|
||||
|
||||
private ItemStack getDrop(Entity entity) {
|
||||
|
@ -1,8 +1,9 @@
|
||||
package com.songoda.ultimatestacker.listeners;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.entity.Split;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Split;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -23,11 +24,13 @@ public class SheepDyeListeners implements Listener {
|
||||
LivingEntity entity = event.getEntity();
|
||||
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
if (!stackManager.isStacked(entity)) return;
|
||||
if (!stackManager.isStackedAndLoaded(entity)) return;
|
||||
|
||||
if (Settings.SPLIT_CHECKS.getStringList().stream().noneMatch(line -> Split.valueOf(line) == Split.SHEEP_DYE))
|
||||
return;
|
||||
|
||||
plugin.getEntityUtils().splitFromStack(entity);
|
||||
EntityStack stack = stackManager.getStack(entity);
|
||||
if (stack == null) return;
|
||||
stack.releaseHost();
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ package com.songoda.ultimatestacker.listeners;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.nms.NmsManager;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStackManager;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import com.songoda.ultimatestacker.utils.Reflection;
|
||||
import org.bukkit.GameMode;
|
||||
@ -44,7 +44,9 @@ public class SpawnerListeners implements Listener {
|
||||
|
||||
spawnerStack.initialize();
|
||||
|
||||
EntityStack stack = plugin.getEntityStackManager().addStack(event.getEntity().getUniqueId(), spawnerStack.calculateSpawnCount());
|
||||
EntityStack stack = plugin.getEntityStackManager().addStack((LivingEntity)event.getEntity());
|
||||
stack.createDuplicates(spawnerStack.calculateSpawnCount());
|
||||
stack.updateStack();
|
||||
|
||||
plugin.getStackingTask().attemptSplit(stack, (LivingEntity) event.getEntity());
|
||||
}
|
||||
|
@ -1,18 +1,13 @@
|
||||
package com.songoda.ultimatestacker.listeners;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import org.bukkit.entity.Entity;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityTameEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class TameListeners implements Listener {
|
||||
|
||||
@ -24,27 +19,15 @@ public class TameListeners implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onTame(EntityTameEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
LivingEntity entity = event.getEntity();
|
||||
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
if (!stackManager.isStacked(entity)) return;
|
||||
|
||||
Tameable tameable = (Tameable) entity;
|
||||
if (!stackManager.isStackedAndLoaded(entity)) return;
|
||||
|
||||
EntityStack stack = plugin.getEntityStackManager().getStack(entity);
|
||||
|
||||
if (stack.getAmount() <= 1) return;
|
||||
|
||||
LivingEntity newEntity = plugin.getEntityUtils().newEntity((LivingEntity) tameable);
|
||||
|
||||
EntityStack second = plugin.getEntityStackManager().addStack(new EntityStack(newEntity, stack.getAmount() - 1));
|
||||
stack.setAmount(1);
|
||||
second.setAmount(stack.getAmount() - 1);
|
||||
plugin.getEntityStackManager().removeStack(entity);
|
||||
entity.setVelocity(getRandomVector());
|
||||
}
|
||||
|
||||
private Vector getRandomVector() {
|
||||
return new Vector(ThreadLocalRandom.current().nextDouble(-1, 1.01), 0, ThreadLocalRandom.current().nextDouble(-1, 1.01)).normalize().multiply(0.5);
|
||||
stack.releaseHost();
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,9 @@ package com.songoda.ultimatestacker.settings;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.configuration.ConfigSetting;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.Check;
|
||||
import com.songoda.ultimatestacker.entity.Split;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Check;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Split;
|
||||
import jdk.nashorn.internal.ir.LiteralNode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -48,7 +49,7 @@ public class Settings {
|
||||
"Should all qualifying entities in each chunk be stacked?",
|
||||
"This will override the stacking radius.");
|
||||
|
||||
public static final ConfigSetting ENTITY_HOLOGRAMS = new ConfigSetting(config, "Entities.Holograms Enabled", true,
|
||||
public static final ConfigSetting ENTITY_NAMETAGS = new ConfigSetting(config, "Entities.Holograms Enabled", true,
|
||||
"Should holograms be displayed above stacked entities?");
|
||||
|
||||
public static final ConfigSetting HOLOGRAMS_ON_LOOK_ENTITY = new ConfigSetting(config, "Entities.Only Show Holograms On Look", false,
|
||||
@ -110,18 +111,6 @@ public class Settings {
|
||||
"\"NAME_TAG\", \"MUSHROOM_SHEAR\", \"SHEEP_SHEAR\", \"SNOWMAN_DERP\",",
|
||||
"\"SHEEP_DYE\", \"ENTITY_BREED\".");
|
||||
|
||||
|
||||
public static final ConfigSetting KEEP_FIRE = new ConfigSetting(config, "Entities.Keep Fire", true,
|
||||
"Should fire ticks persist to the next entity when an entity dies?");
|
||||
|
||||
public static final ConfigSetting KEEP_POTION = new ConfigSetting(config, "Entities.Keep Potion Effects", true,
|
||||
"Should potion effects persist to the next entity when an entity dies?");
|
||||
|
||||
public static final ConfigSetting CARRY_OVER_LOWEST_HEALTH = new ConfigSetting(config, "Entities.Carry Over Lowest Health", false,
|
||||
"Should the lowest health be carried over when stacked?",
|
||||
"This should not be used in collaboration with 'Stack Entity Health'.",
|
||||
"If it is used this setting will be overrode.");
|
||||
|
||||
public static final ConfigSetting ONLY_STACK_FROM_SPAWNERS = new ConfigSetting(config, "Entities.Only Stack From Spawners", false,
|
||||
"Should entities only be stacked if they originate from a spawner?",
|
||||
"It should be noted that the identifier that tells the plugin",
|
||||
@ -141,17 +130,6 @@ public class Settings {
|
||||
"\"SHOULDER_ENTITY\", \"DROWNED\", \"SHEARED\", \"EXPLOSION\",",
|
||||
"\"CUSTOM\", \"DEFAULT\".");
|
||||
|
||||
public static final ConfigSetting CARRY_OVER_METADATA_ON_DEATH = new ConfigSetting(config, "Entities.Carry Over Metadata On Death", true,
|
||||
"With this enabled any metadata assigned from supported plugins such",
|
||||
"as EpicSpawners and mcMMO will be preserved when the entity is killed.");
|
||||
|
||||
public static final ConfigSetting META_CARRY_OVER_MIN = new ConfigSetting(config, "Entities.Meta Carry Over Min", 10,
|
||||
"The amount of time in seconds an entity needs to have lived",
|
||||
"for in order for their metadata to be carried over to their next",
|
||||
"stack on death. Setting this value to zero may improve compatibility",
|
||||
"with other plugins but this will be at the cost of performance if you",
|
||||
"have a lot of grinders on your server.");
|
||||
|
||||
public static final ConfigSetting WEAPONS_ARENT_EQUIPMENT = new ConfigSetting(config, "Entities.Weapons Arent Equipment", false,
|
||||
"This allows entities holding weapons to stack. Enchanted weapons are excluded.",
|
||||
"If you would like to disable the stacked entity check you can do that by removing",
|
||||
@ -161,12 +139,6 @@ public class Settings {
|
||||
"Should entities only be stacked if they are touching the ground",
|
||||
"or swimming? This does not effect flying entities.");
|
||||
|
||||
public static final ConfigSetting STACK_ENTITY_HEALTH = new ConfigSetting(config, "Entities.Stack Entity Health", true,
|
||||
"Should entity health be stacked? When enabled Entity stacks will",
|
||||
"remember the health of all entities inside of the stack. This",
|
||||
"works the best with 'Only Stack On Surface enabled' as entities",
|
||||
"falling out of grinders may stack before hitting the ground.");
|
||||
|
||||
public static final ConfigSetting ONLY_STACK_FLYING_DOWN = new ConfigSetting(config, "Entities.Only Stack Flying Down", true,
|
||||
"Should entities that fly only stack with entities that are lower on the",
|
||||
"Y axis. This is important for grinders so that flying entities don't continuously",
|
||||
@ -255,6 +227,31 @@ public class Settings {
|
||||
"The text displayed above a stacked spawner where {TYPE} refers to",
|
||||
"The entities type and {AMT} is the amount currently stacked.");
|
||||
|
||||
public static final ConfigSetting STACK_BLOCKS = new ConfigSetting(config, "Blocks.Enabled", true,
|
||||
"Should blocks be stacked?");
|
||||
|
||||
public static final ConfigSetting BLOCK_HOLOGRAMS = new ConfigSetting(config, "Blocks.Holograms Enabled", true,
|
||||
"Should holograms be displayed above stacked blocks?");
|
||||
|
||||
public static final ConfigSetting STACKABLE_BLOCKS = new ConfigSetting(config, "Blocks.Stackable Blocks", Collections.singletonList("DIAMOND_BLOCK"),
|
||||
"What blocks should be stackable?");
|
||||
|
||||
public static final ConfigSetting ALWAYS_ADD_ALL = new ConfigSetting(config, "Blocks.Always Add All", false,
|
||||
"Should the whole stack the player is holding always",
|
||||
"be added to the stack regardless of if they are sneaking or not?");
|
||||
|
||||
public static final ConfigSetting MAX_REMOVEABLE = new ConfigSetting(config, "Blocks.Max Removeable", 64,
|
||||
"What should be the max amount that can be removed with",
|
||||
"a single click? Keep in mind high numbers could cause lag.");
|
||||
|
||||
public static final ConfigSetting ADD_TO_INVENTORY = new ConfigSetting(config, "Blocks.Add To Inventory", false,
|
||||
"Should blocks be added directly to the inventory when removed?");
|
||||
|
||||
public static final ConfigSetting NAME_FORMAT_BLOCK = new ConfigSetting(config, "Blocks.Name Format", "&6{AMT}x &f{TYPE}",
|
||||
"The text displayed above a stacked block where {TYPE} refers to",
|
||||
"The entities type and {AMT} is the amount currently stacked.");
|
||||
|
||||
|
||||
public static final ConfigSetting LANGUGE_MODE = new ConfigSetting(config, "System.Language Mode", "en_US",
|
||||
"The enabled language file.",
|
||||
"More language files (if available) can be found in the plugins data folder.");
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.songoda.ultimatestacker.stackable;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public interface Hologramable {
|
||||
|
||||
Location getLocation();
|
||||
|
||||
String getHologramName();
|
||||
|
||||
boolean areHologramsEnabled();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.songoda.ultimatestacker.stackable;
|
||||
|
||||
|
||||
public interface Stackable {
|
||||
|
||||
int getAmount();
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package com.songoda.ultimatestacker.stackable.block;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.stackable.Hologramable;
|
||||
import com.songoda.ultimatestacker.stackable.Stackable;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class BlockStack implements Stackable, Hologramable {
|
||||
|
||||
// The id that identifies this stack in the database.
|
||||
private int id;
|
||||
|
||||
private int amount = 0;
|
||||
private final CompatibleMaterial material;
|
||||
private final Location location;
|
||||
|
||||
public BlockStack(CompatibleMaterial material, Location location) {
|
||||
this.material = material;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public BlockStack(CompatibleMaterial material, Location location, int amount) {
|
||||
this.amount = amount;
|
||||
this.material = material;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void add(int amount) {
|
||||
this.amount = this.amount + amount;
|
||||
}
|
||||
|
||||
public void take(int amount) {
|
||||
this.amount = this.amount - amount;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return location.getBlockX();
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return location.getBlockY();
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return location.getBlockZ();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return location.getWorld();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
amount = 0;
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
plugin.getBlockStackManager().removeBlock(location);
|
||||
plugin.removeHologram(this);
|
||||
plugin.getDataManager().deleteBlock(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public CompatibleMaterial getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHologramName() {
|
||||
String nameFormat = Settings.NAME_FORMAT_BLOCK.getString();
|
||||
String displayName = Methods.formatText(material.name().toLowerCase().replace("_", " "), true);
|
||||
|
||||
nameFormat = nameFormat.replace("{TYPE}", displayName);
|
||||
nameFormat = nameFormat.replace("{AMT}", Integer.toString(amount));
|
||||
|
||||
return Methods.formatText(nameFormat).trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areHologramsEnabled() {
|
||||
return Settings.BLOCK_HOLOGRAMS.getBoolean();
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlockStack{" +
|
||||
"id=" + id +
|
||||
", amount=" + amount +
|
||||
", material=" + material +
|
||||
", location=" + location +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.songoda.ultimatestacker.stackable.block;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.ultimatestacker.stackable.spawner.SpawnerStack;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockStackManager {
|
||||
|
||||
private final Map<Location, BlockStack> registeredBlocks = new HashMap<>();
|
||||
|
||||
public void addBlocks(Map<Location, BlockStack> blocks) {
|
||||
this.registeredBlocks.putAll(blocks);
|
||||
}
|
||||
|
||||
public BlockStack addBlock(BlockStack blockStack) {
|
||||
this.registeredBlocks.put(roundLocation(blockStack.getLocation()), blockStack);
|
||||
return blockStack;
|
||||
}
|
||||
|
||||
public BlockStack removeBlock(Location location) {
|
||||
return registeredBlocks.remove(roundLocation(location));
|
||||
}
|
||||
|
||||
public BlockStack getBlock(Location location, CompatibleMaterial material) {
|
||||
return this.registeredBlocks.computeIfAbsent(location, b -> new BlockStack(material, location));
|
||||
}
|
||||
|
||||
public BlockStack getBlock(Block block, CompatibleMaterial material) {
|
||||
return this.getBlock(block.getLocation(), material);
|
||||
}
|
||||
|
||||
public boolean isBlock(Location location) {
|
||||
return this.registeredBlocks.get(location) != null;
|
||||
}
|
||||
|
||||
public Collection<BlockStack> getStacks() {
|
||||
return Collections.unmodifiableCollection(this.registeredBlocks.values());
|
||||
}
|
||||
|
||||
private Location roundLocation(Location location) {
|
||||
location = location.clone();
|
||||
location.setX(location.getBlockX());
|
||||
location.setY(location.getBlockY());
|
||||
location.setZ(location.getBlockZ());
|
||||
return location;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.songoda.ultimatestacker.entity;
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -15,31 +15,31 @@ public enum Check {
|
||||
ANIMAL_OWNER(true),
|
||||
SKELETON_TYPE(true),
|
||||
ZOMBIE_BABY(true),
|
||||
HAS_EQUIPMENT(true),
|
||||
HAS_EQUIPMENT(false),
|
||||
SLIME_SIZE(true),
|
||||
PIG_SADDLE(true),
|
||||
SHEEP_SHEARED(true),
|
||||
SHEEP_COLOR(true),
|
||||
SHEEP_COLOR(false),
|
||||
SNOWMAN_DERPED(true),
|
||||
WOLF_COLLAR_COLOR(true),
|
||||
OCELOT_TYPE(true),
|
||||
HORSE_COLOR(true),
|
||||
OCELOT_TYPE(false),
|
||||
HORSE_COLOR(false),
|
||||
HORSE_STYLE(true),
|
||||
HORSE_CARRYING_CHEST(true),
|
||||
HORSE_HAS_ARMOR(true),
|
||||
HORSE_HAS_SADDLE(true),
|
||||
HORSE_JUMP(true),
|
||||
RABBIT_TYPE(true),
|
||||
RABBIT_TYPE(false),
|
||||
VILLAGER_PROFESSION(true),
|
||||
LLAMA_COLOR(true),
|
||||
LLAMA_COLOR(false),
|
||||
LLAMA_STRENGTH(true),
|
||||
PARROT_TYPE(true),
|
||||
PARROT_TYPE(false),
|
||||
PUFFERFISH_STATE(true),
|
||||
TROPICALFISH_PATTERN(true),
|
||||
TROPICALFISH_BODY_COLOR(true),
|
||||
TROPICALFISH_PATTERN_COLOR(true),
|
||||
PHANTOM_SIZE(true),
|
||||
CAT_TYPE(true);
|
||||
CAT_TYPE(false);
|
||||
|
||||
private final boolean isEnabledByDefault;
|
||||
private final static Map<String, Check> checks = new HashMap();
|
@ -0,0 +1,137 @@
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
import com.songoda.core.nms.NmsManager;
|
||||
import com.songoda.core.nms.nbt.NBTEntity;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.stackable.Stackable;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ColdEntityStack implements Stackable {
|
||||
|
||||
protected static final UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
|
||||
// The id to identify this stack in the database.
|
||||
private int id;
|
||||
|
||||
// The unique id of the stacks host.
|
||||
protected UUID hostUniqueId;
|
||||
|
||||
// These are the entities below the host.
|
||||
protected final Deque<StackedEntity> stackedEntities = new ConcurrentLinkedDeque<>();
|
||||
|
||||
// The amount of duplicates of the host to create when loaded.
|
||||
protected int createDuplicates = 0;
|
||||
|
||||
public ColdEntityStack(UUID hostUniqueId, int id) {
|
||||
this.hostUniqueId = hostUniqueId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ColdEntityStack(UUID hostUniqueId) {
|
||||
this.hostUniqueId = hostUniqueId;
|
||||
}
|
||||
|
||||
public StackedEntity addEntityToStackSilently(Entity entity) {
|
||||
return addEntityToStackSilently(getStackedEntity(entity));
|
||||
}
|
||||
|
||||
public List<StackedEntity> addRawEntitiesToStackSilently(List<LivingEntity> unstackedEntities) {
|
||||
List<StackedEntity> stackedEntities = unstackedEntities.stream()
|
||||
.map(this::getStackedEntity).collect(Collectors.toList());
|
||||
addEntitiesToStackSilently(stackedEntities);
|
||||
return stackedEntities;
|
||||
}
|
||||
|
||||
public void addEntitiesToStackSilently(List<StackedEntity> stackedEntities) {
|
||||
stackedEntities.removeIf(Objects::isNull);
|
||||
this.stackedEntities.addAll(stackedEntities);
|
||||
}
|
||||
|
||||
public StackedEntity addEntityToStackSilently(StackedEntity stackedEntity) {
|
||||
if (stackedEntity == null) return null;
|
||||
stackedEntities.push(stackedEntity);
|
||||
return stackedEntity;
|
||||
}
|
||||
|
||||
public void moveEntitiesFromStack(EntityStack stack, int amount) {
|
||||
List<StackedEntity> stackedEntities = stack.takeEntities(amount);
|
||||
this.stackedEntities.addAll(stackedEntities);
|
||||
plugin.getDataManager().createStackedEntities(this, stackedEntities);
|
||||
}
|
||||
|
||||
public List<StackedEntity> takeEntities(int amount) {
|
||||
List<StackedEntity> entities = new LinkedList<>();
|
||||
for (int i = 0; i < amount; i ++) {
|
||||
StackedEntity entity = stackedEntities.pollFirst();
|
||||
if (entity != null)
|
||||
entities.add(entity);
|
||||
}
|
||||
plugin.getDataManager().deleteStackedEntities(entities);
|
||||
return entities;
|
||||
}
|
||||
|
||||
public List<StackedEntity> takeAllEntities() {
|
||||
List<StackedEntity> entities = new LinkedList<>(stackedEntities);
|
||||
stackedEntities.clear();
|
||||
return entities;
|
||||
}
|
||||
|
||||
public LivingEntity takeOneAndSpawnEntity(Location location) {
|
||||
NBTEntity nbtEntity = NmsManager.getNbt().newEntity();
|
||||
nbtEntity.deSerialize(stackedEntities.getFirst().getSerializedEntity());
|
||||
LivingEntity newEntity = (LivingEntity)nbtEntity.spawn(location);
|
||||
stackedEntities.removeFirst();
|
||||
plugin.getDataManager().deleteStackedEntity(newEntity.getUniqueId());
|
||||
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount() {
|
||||
return stackedEntities.size() + 1;
|
||||
}
|
||||
|
||||
public void createDuplicates(int duplicates) {
|
||||
this.createDuplicates = duplicates;
|
||||
}
|
||||
|
||||
public int getCreateDuplicates() {
|
||||
return createDuplicates;
|
||||
}
|
||||
|
||||
protected StackedEntity getStackedEntity(Entity entity) {
|
||||
return getStackedEntity(entity, false);
|
||||
}
|
||||
|
||||
protected StackedEntity getStackedEntity(Entity entity, boolean newUUID) {
|
||||
UUID uuid = entity.getUniqueId();
|
||||
NBTEntity nbtEntity = NmsManager.getNbt().of(entity);
|
||||
if (newUUID) {
|
||||
uuid = UUID.randomUUID();
|
||||
nbtEntity.set("UUID", uuid);
|
||||
}
|
||||
return new StackedEntity(uuid, nbtEntity.serialize("Attributes"));
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UUID getHostUniqueId() {
|
||||
return hostUniqueId;
|
||||
}
|
||||
|
||||
public void setHostUniqueId(UUID hostUniqueId) {
|
||||
this.hostUniqueId = hostUniqueId;
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
import com.songoda.lootables.loot.Drop;
|
||||
import com.songoda.lootables.loot.DropUtils;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class EntityStack extends ColdEntityStack {
|
||||
|
||||
// This is the host entity which is not stored in serialized nbt.
|
||||
private LivingEntity hostEntity;
|
||||
|
||||
public EntityStack(LivingEntity hostEntity) {
|
||||
super(hostEntity.getUniqueId());
|
||||
this.hostEntity = hostEntity;
|
||||
}
|
||||
|
||||
public EntityStack(LivingEntity hostEntity, ColdEntityStack coldEntityStack) {
|
||||
this(hostEntity);
|
||||
this.setId(coldEntityStack.getId());
|
||||
this.stackedEntities.addAll(coldEntityStack.stackedEntities);
|
||||
}
|
||||
|
||||
public StackedEntity addEntityToStack(Entity entity) {
|
||||
StackedEntity stackedEntity = addEntityToStackSilently(entity);
|
||||
updateStack();
|
||||
return stackedEntity;
|
||||
}
|
||||
|
||||
public void updateStack() {
|
||||
if (createDuplicates != 0) {
|
||||
List<StackedEntity> stackedEntities = new ArrayList<>();
|
||||
for (int i = 0; i < createDuplicates; i++)
|
||||
stackedEntities.add(addEntityToStackSilently(getStackedEntity(hostEntity, true)));
|
||||
plugin.getDataManager().createStackedEntities(this, stackedEntities);
|
||||
|
||||
createDuplicates = 0;
|
||||
}
|
||||
if (!Settings.ENTITY_NAMETAGS.getBoolean()) return;
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateStacker.getInstance(), () -> {
|
||||
if (hostEntity == null) return;
|
||||
|
||||
hostEntity.setCustomNameVisible(!Settings.HOLOGRAMS_ON_LOOK_ENTITY.getBoolean());
|
||||
hostEntity.setCustomName(Methods.compileEntityName(hostEntity, getAmount()));
|
||||
}, hostEntity == null ? 1L : 0L);
|
||||
|
||||
}
|
||||
|
||||
public LivingEntity getHostEntity() {
|
||||
if (hostEntity == null) {
|
||||
plugin.getEntityStackManager().removeStack(this.hostUniqueId);
|
||||
return null;
|
||||
}
|
||||
return hostEntity;
|
||||
}
|
||||
|
||||
public StackedEntity getHostAsStackedEntity() {
|
||||
return getStackedEntity(hostEntity);
|
||||
}
|
||||
|
||||
protected void setHostEntity(LivingEntity hostEntity) {
|
||||
this.hostEntity = hostEntity;
|
||||
this.hostUniqueId = hostEntity.getUniqueId();
|
||||
}
|
||||
|
||||
private void handleWholeStackDeath(LivingEntity killed, List<Drop> drops, boolean custom, int droppedExp, EntityDeathEvent event) {
|
||||
plugin.getEntityStackManager().removeStack(event.getEntity());
|
||||
plugin.getDataManager().deleteHost(this);
|
||||
|
||||
|
||||
Location killedLocation = killed.getLocation();
|
||||
List<Drop> preStackedDrops = new ArrayList<>();
|
||||
for (int i = 1; i < getAmount(); i++) {
|
||||
if (i == 1) {
|
||||
drops.removeIf(it -> it.getItemStack() != null
|
||||
&& it.getItemStack().isSimilar(killed.getEquipment().getItemInHand()));
|
||||
for (ItemStack item : killed.getEquipment().getArmorContents()) {
|
||||
drops.removeIf(it -> it.getItemStack() != null && it.getItemStack().isSimilar(item));
|
||||
}
|
||||
}
|
||||
if (custom)
|
||||
drops = plugin.getLootablesManager().getDrops(killed);
|
||||
preStackedDrops.addAll(drops);
|
||||
}
|
||||
if (!preStackedDrops.isEmpty())
|
||||
DropUtils.processStackedDrop(killed, preStackedDrops, event);
|
||||
|
||||
if (droppedExp > 0)
|
||||
killedLocation.getWorld().spawn(killedLocation, ExperienceOrb.class).setExperience(droppedExp * getAmount());
|
||||
|
||||
if (killed.getKiller() == null) return;
|
||||
UltimateStacker.getInstance().addExp(killed.getKiller(), this);
|
||||
}
|
||||
|
||||
private void handleSingleStackDeath(LivingEntity killed, List<Drop> drops, EntityDeathEvent event) {
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
|
||||
killed.remove();
|
||||
LivingEntity newEntity = takeOneAndSpawnEntity(killed.getLocation());
|
||||
|
||||
//if (!EntityUtils.isAware(killed))
|
||||
// EntityUtils.setUnaware(newEntity);
|
||||
|
||||
DropUtils.processStackedDrop(killed, drops, event);
|
||||
|
||||
newEntity.setVelocity(killed.getVelocity());
|
||||
stackManager.updateStack(killed, newEntity);
|
||||
|
||||
updateStack();
|
||||
|
||||
if (stackedEntities.isEmpty())
|
||||
destroy();
|
||||
}
|
||||
|
||||
public void onDeath(LivingEntity killed, List<Drop> drops, boolean custom, int droppedExp, EntityDeathEvent event) {
|
||||
killed.setCustomName(null);
|
||||
killed.setCustomNameVisible(false);
|
||||
|
||||
boolean killWholeStack = Settings.KILL_WHOLE_STACK_ON_DEATH.getBoolean()
|
||||
|| plugin.getMobFile().getBoolean("Mobs." + killed.getType().name() + ".Kill Whole Stack");
|
||||
|
||||
if (killWholeStack && getAmount() != 1) {
|
||||
handleWholeStackDeath(killed, drops, custom, droppedExp, event);
|
||||
} else if (getAmount() != 1) {
|
||||
List<String> reasons = Settings.INSTANT_KILL.getStringList();
|
||||
EntityDamageEvent lastDamageCause = killed.getLastDamageCause();
|
||||
|
||||
if (lastDamageCause != null) {
|
||||
EntityDamageEvent.DamageCause cause = lastDamageCause.getCause();
|
||||
for (String s : reasons) {
|
||||
if (!cause.name().equalsIgnoreCase(s)) continue;
|
||||
handleWholeStackDeath(killed, drops, custom, Settings.NO_EXP_INSTANT_KILL.getBoolean() ? 0 : droppedExp, event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
handleSingleStackDeath(killed, drops, event);
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseHost() {
|
||||
LivingEntity oldHost = hostEntity;
|
||||
LivingEntity entity = takeOneAndSpawnEntity(hostEntity.getLocation());
|
||||
if (!stackedEntities.isEmpty()) {
|
||||
destroy(false);
|
||||
plugin.getEntityStackManager().updateStack(oldHost, entity);
|
||||
entity.setVelocity(new Vector(ThreadLocalRandom.current().nextDouble(-1, 1.01),
|
||||
0, ThreadLocalRandom.current().nextDouble(-1, 1.01)).normalize().multiply(0.5));
|
||||
} else {
|
||||
destroy();
|
||||
}
|
||||
updateStack();
|
||||
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroy(true);
|
||||
}
|
||||
|
||||
public void destroy(boolean full) {
|
||||
if (full)
|
||||
plugin.getEntityStackManager().removeStack(this.hostUniqueId);
|
||||
if (hostEntity != null) {
|
||||
hostEntity.setCustomNameVisible(false);
|
||||
hostEntity.setCustomName(null);
|
||||
}
|
||||
hostEntity = null;
|
||||
hostUniqueId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityStack{" +
|
||||
"hostEntity=" + hostEntity +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class EntityStackManager {
|
||||
|
||||
// These are all stacked mobs loaded into memory.
|
||||
private static final Map<UUID, EntityStack> stacks = new HashMap<>();
|
||||
|
||||
// This will only be used for stacks that have not yet been loaded into the game.
|
||||
private static final Map<UUID, ColdEntityStack> coldStacks = new HashMap<>();
|
||||
|
||||
private final UltimateStacker plugin;
|
||||
|
||||
public EntityStackManager(UltimateStacker plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public EntityStack addStack(EntityStack stack) {
|
||||
stacks.put(stack.getHostEntity().getUniqueId(), stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack addStack(LivingEntity entity) {
|
||||
if (entity == null) return null;
|
||||
EntityStack stack = new EntityStack(entity);
|
||||
plugin.getDataManager().createHostEntity(stack);
|
||||
stacks.put(entity.getUniqueId(), stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack addStack(LivingEntity entity, int amount) {
|
||||
if (entity == null) return null;
|
||||
EntityStack stack = new EntityStack(entity);
|
||||
plugin.getDataManager().createHostEntity(stack);
|
||||
stacks.put(entity.getUniqueId(), stack);
|
||||
stack.createDuplicates(amount - 1);
|
||||
plugin.getDataManager().updateHost(stack);
|
||||
stack.updateStack();
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public EntityStack addSerializedStack(LivingEntity entity, String customName) {
|
||||
if (customName != null && customName.contains(String.valueOf(ChatColor.COLOR_CHAR))) {
|
||||
String name = customName.replace(String.valueOf(ChatColor.COLOR_CHAR), "")
|
||||
.replace(";", "");
|
||||
if (!name.contains(":")) return null;
|
||||
String split = name.split(":")[0];
|
||||
int amount = Methods.isInt(split) ? Integer.parseInt(split) : 0;
|
||||
return addStack(entity, amount);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public EntityStack addSerializedStack(LivingEntity entity) {
|
||||
return addSerializedStack(entity, entity.getCustomName());
|
||||
}
|
||||
|
||||
public EntityStack getStack(LivingEntity entity) {
|
||||
EntityStack stack = getStack(entity.getUniqueId());
|
||||
if (stack == null) stack = addSerializedStack(entity);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public EntityStack getStack(UUID uuid) {
|
||||
return stacks.get(uuid);
|
||||
}
|
||||
|
||||
public EntityStack removeStack(Entity entity) {
|
||||
return removeStack(entity.getUniqueId());
|
||||
}
|
||||
|
||||
public EntityStack removeStack(UUID uuid) {
|
||||
EntityStack stack = stacks.remove(uuid);
|
||||
if (stack != null) {
|
||||
plugin.getDataManager().deleteHost(stack);
|
||||
stack.destroy();
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
public Map<UUID, EntityStack> getStacks() {
|
||||
return Collections.unmodifiableMap(stacks);
|
||||
}
|
||||
|
||||
public EntityStack updateStack(LivingEntity oldEntity, LivingEntity newEntity) {
|
||||
EntityStack stack = stacks.remove(oldEntity.getUniqueId());
|
||||
if (stack == null) return null;
|
||||
stack.setHostEntity(newEntity);
|
||||
stacks.put(newEntity.getUniqueId(), stack);
|
||||
plugin.getDataManager().updateHost(stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isStacked(UUID entity) {
|
||||
return isStackedAndLoaded(entity);
|
||||
}
|
||||
|
||||
public boolean isStackedAndLoaded(LivingEntity entity) {
|
||||
return stacks.containsKey(entity.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean isStackedAndLoaded(UUID entity) {
|
||||
return stacks.containsKey(entity);
|
||||
}
|
||||
|
||||
public boolean isEntityInColdStorage(UUID entity) {
|
||||
return coldStacks.containsKey(entity);
|
||||
}
|
||||
|
||||
public boolean isEntityInColdStorage(LivingEntity entity) {
|
||||
return isEntityInColdStorage(entity.getUniqueId());
|
||||
}
|
||||
|
||||
public void loadStack(LivingEntity entity) {
|
||||
ColdEntityStack coldStack = coldStacks.get(entity.getUniqueId());
|
||||
if (coldStack == null) return;
|
||||
EntityStack stack = new EntityStack(entity, coldStack);
|
||||
stack.updateStack();
|
||||
stacks.put(entity.getUniqueId(), stack);
|
||||
}
|
||||
|
||||
public void unloadStack(LivingEntity entity) {
|
||||
EntityStack stack = stacks.get(entity.getUniqueId());
|
||||
if (stack == null) return;
|
||||
ColdEntityStack coldStack = new EntityStack(entity, stack);
|
||||
stack.destroy();
|
||||
coldStacks.put(entity.getUniqueId(), coldStack);
|
||||
}
|
||||
|
||||
public void addStacks(Collection<ColdEntityStack> entities) {
|
||||
for (ColdEntityStack stack : entities)
|
||||
coldStacks.put(stack.hostUniqueId, stack);
|
||||
}
|
||||
|
||||
public ColdEntityStack addLegacyColdStack(UUID entity, int amount) {
|
||||
ColdEntityStack stack = new ColdEntityStack(entity);
|
||||
plugin.getDataManager().createHostEntity(stack);
|
||||
stack.createDuplicates(amount - 1);
|
||||
plugin.getDataManager().updateHost(stack);
|
||||
coldStacks.put(entity, stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public void tryAndLoadColdEntities() {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (entity instanceof LivingEntity)
|
||||
loadStack((LivingEntity)entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.songoda.ultimatestacker.entity;
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
public enum Split {
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.songoda.ultimatestacker.stackable.entity;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StackedEntity {
|
||||
|
||||
private final UUID uniqueId;
|
||||
private final byte[] serializedEntity;
|
||||
|
||||
public StackedEntity(UUID uniqueId, byte[] serializedEntity) {
|
||||
this.uniqueId = uniqueId;
|
||||
this.serializedEntity = serializedEntity;
|
||||
}
|
||||
|
||||
public UUID getUniqueId() {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
public byte[] getSerializedEntity() {
|
||||
return serializedEntity;
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package com.songoda.ultimatestacker.spawner;
|
||||
package com.songoda.ultimatestacker.stackable.spawner;
|
||||
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.stackable.Hologramable;
|
||||
import com.songoda.ultimatestacker.stackable.Stackable;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import com.songoda.ultimatestacker.utils.Reflection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -11,7 +14,7 @@ import org.bukkit.block.CreatureSpawner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class SpawnerStack {
|
||||
public class SpawnerStack implements Stackable, Hologramable {
|
||||
|
||||
private int id;
|
||||
private boolean initialized = false;
|
||||
@ -19,23 +22,24 @@ public class SpawnerStack {
|
||||
private final Location location;
|
||||
private int amount;
|
||||
|
||||
private static final UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
|
||||
public SpawnerStack(Location location, int amount) {
|
||||
this.location = location;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(int amount) {
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
this.amount = amount;
|
||||
plugin.getDataManager().updateSpawner(this);
|
||||
}
|
||||
|
||||
public void updateAmount() {
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (!(location.getBlock().getState() instanceof CreatureSpawner)) return;
|
||||
int count = Settings.STACK_ENTITIES.getBoolean()
|
||||
@ -73,6 +77,17 @@ public class SpawnerStack {
|
||||
return location.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHologramName() {
|
||||
CreatureSpawner creatureSpawner = (CreatureSpawner) location.getBlock().getState();
|
||||
return Methods.compileSpawnerName(creatureSpawner.getSpawnedType(), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areHologramsEnabled() {
|
||||
return Settings.SPAWNER_HOLOGRAMS.getBoolean();
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return location.getBlockX();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.songoda.ultimatestacker.spawner;
|
||||
package com.songoda.ultimatestacker.stackable.spawner;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import org.bukkit.Location;
|
@ -2,8 +2,7 @@ package com.songoda.ultimatestacker.storage;
|
||||
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Storage {
|
||||
@ -25,11 +24,6 @@ public abstract class Storage {
|
||||
public abstract void prepareSaveItem(String group, StorageItem... items);
|
||||
|
||||
public void updateData(UltimateStacker instance) {
|
||||
|
||||
for (SpawnerStack stack : instance.getSpawnerStackManager().getStacks()) {
|
||||
prepareSaveItem("spawners", new StorageItem("location", Methods.serializeLocation(stack.getLocation())),
|
||||
new StorageItem("amount", stack.getAmount()));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void doSave();
|
||||
|
@ -4,15 +4,19 @@ import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.hooks.WorldGuardHook;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import com.songoda.ultimatestacker.stackable.entity.Check;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.stackable.entity.StackedEntity;
|
||||
import com.songoda.ultimatestacker.utils.CachedChunk;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
@ -23,25 +27,31 @@ public class StackingTask extends BukkitRunnable {
|
||||
|
||||
private final EntityStackManager stackManager;
|
||||
|
||||
ConfigurationSection configurationSection = UltimateStacker.getInstance().getMobFile();
|
||||
|
||||
private final ConfigurationSection configurationSection = UltimateStacker.getInstance().getMobFile();
|
||||
private final List<UUID> processed = new ArrayList<>();
|
||||
|
||||
private final Map<CachedChunk, Entity[]> cachedChunks = new HashMap<>();
|
||||
|
||||
private final HashMap<EntityType, Integer> entityStackSizes = new HashMap();
|
||||
private final int maxEntityStackSize = Settings.MAX_STACK_ENTITIES.getInt();
|
||||
private final int minEntityStackSize = Settings.MIN_STACK_ENTITIES.getInt();
|
||||
private final int maxPerTypeStacksPerChunk = Settings.MAX_PER_TYPE_STACKS_PER_CHUNK.getInt();
|
||||
private final List<String> disabledWorlds = Settings.DISABLED_WORLDS.getStringList();
|
||||
private final boolean onlyStackFromSpawners = Settings.ONLY_STACK_FROM_SPAWNERS.getBoolean();
|
||||
private final List<String> stackReasons = Settings.STACK_REASONS.getStringList();
|
||||
private final boolean onlyStackOnSurface = Settings.ONLY_STACK_ON_SURFACE.getBoolean();
|
||||
private final int maxEntityStackSize = Settings.MAX_STACK_ENTITIES.getInt(),
|
||||
minEntityStackSize = Settings.MIN_STACK_ENTITIES.getInt(),
|
||||
searchRadius = Settings.SEARCH_RADIUS.getInt(),
|
||||
maxPerTypeStacksPerChunk = Settings.MAX_PER_TYPE_STACKS_PER_CHUNK.getInt();
|
||||
private final List<String> disabledWorlds = Settings.DISABLED_WORLDS.getStringList(),
|
||||
stackReasons = Settings.STACK_REASONS.getStringList();
|
||||
private final List<Check> checks = Check.getChecks(Settings.STACK_CHECKS.getStringList());
|
||||
private final boolean stackFlyingDown = Settings.ONLY_STACK_FLYING_DOWN.getBoolean(),
|
||||
stackWholeChunk = Settings.STACK_WHOLE_CHUNK.getBoolean(),
|
||||
weaponsArentEquipment = Settings.WEAPONS_ARENT_EQUIPMENT.getBoolean(),
|
||||
onlyStackFromSpawners = Settings.ONLY_STACK_FROM_SPAWNERS.getBoolean(),
|
||||
onlyStackOnSurface = Settings.ONLY_STACK_ON_SURFACE.getBoolean();
|
||||
|
||||
public StackingTask(UltimateStacker plugin) {
|
||||
this.plugin = plugin;
|
||||
this.stackManager = plugin.getEntityStackManager();
|
||||
|
||||
// Start stacking task.
|
||||
runTaskTimer(plugin, 0, Settings.STACK_SEARCH_TICK_SPEED.getInt());
|
||||
// Start the stacking task.
|
||||
runTaskTimerAsynchronously(plugin, 0, Settings.STACK_SEARCH_TICK_SPEED.getInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,8 +73,9 @@ public class StackingTask extends BukkitRunnable {
|
||||
// Get entity location to pass around as its faster this way.
|
||||
Location location = entity.getLocation();
|
||||
|
||||
// Check to see if entity is stackable.
|
||||
if (!isEntityStackable(entity, location)) continue;
|
||||
// Check to see if entity is not stackable.
|
||||
if (!isEntityStackable(entity))
|
||||
continue;
|
||||
|
||||
// Make sure our entity has not already been processed.
|
||||
// Skip it if it has been.
|
||||
@ -80,14 +91,14 @@ public class StackingTask extends BukkitRunnable {
|
||||
}
|
||||
// Clear caches in preparation for the next run.
|
||||
this.processed.clear();
|
||||
plugin.getEntityUtils().clearChunkCache();
|
||||
this.cachedChunks.clear();
|
||||
}
|
||||
|
||||
public boolean isWorldDisabled(World world) {
|
||||
return disabledWorlds.stream().anyMatch(worldStr -> world.getName().equalsIgnoreCase(worldStr));
|
||||
}
|
||||
|
||||
private boolean isEntityStackable(Entity entity, Location location) {
|
||||
private boolean isEntityStackable(Entity entity) {
|
||||
// Make sure we have the correct entity type and that it is valid.
|
||||
if (!entity.isValid()
|
||||
|| !(entity instanceof LivingEntity)
|
||||
@ -117,7 +128,7 @@ public class StackingTask extends BukkitRunnable {
|
||||
|
||||
// If only stack on surface is enabled make sure the entity is on a surface then entity is stackable.
|
||||
return !onlyStackOnSurface
|
||||
|| Methods.canFly(livingEntity)
|
||||
|| canFly(livingEntity)
|
||||
|| entity.getType().name().equals("SHULKER")
|
||||
|
||||
|| (livingEntity.isOnGround()
|
||||
@ -150,8 +161,11 @@ public class StackingTask extends BukkitRunnable {
|
||||
|
||||
// Get similar entities around our entity and make sure those entities are both compatible and stackable.
|
||||
List<LivingEntity> stackableFriends = new LinkedList<>();
|
||||
for (LivingEntity entity : plugin.getEntityUtils().getSimilarEntitiesAroundEntity(livingEntity, location)) {
|
||||
if (!isEntityStackable(entity, location)) continue;
|
||||
for (LivingEntity entity : getSimilarEntitiesAroundEntity(livingEntity, location)) {
|
||||
// Check to see if entity is not stackable.
|
||||
if (!isEntityStackable(entity))
|
||||
continue;
|
||||
// Add this entity to our stackable friends.
|
||||
stackableFriends.add(entity);
|
||||
}
|
||||
|
||||
@ -173,28 +187,29 @@ public class StackingTask extends BukkitRunnable {
|
||||
// for this entity.
|
||||
if (friendStack != null && (friendStack.getAmount() + amountToStack) <= maxEntityStackSize) {
|
||||
|
||||
// Add one to the found friendStack.
|
||||
friendStack.addAmount(amountToStack);
|
||||
|
||||
// Add our entities health to the friendStacks health.
|
||||
friendStack.addHealth(entity.getHealth());
|
||||
|
||||
// Fix the friendStacks health.
|
||||
if (!isStack)
|
||||
friendStack.addHealth(entity.getHealth());
|
||||
else
|
||||
friendStack.mergeHealth(stack);
|
||||
|
||||
|
||||
fixHealth(entity, livingEntity);
|
||||
if (Settings.STACK_ENTITY_HEALTH.getBoolean())
|
||||
entity.setHealth(entity.getMaxHealth() < livingEntity.getHealth()
|
||||
? entity.getMaxHealth() : livingEntity.getHealth());
|
||||
|
||||
// If we are a stack lets merge our stack with the just found friend stack.
|
||||
if (isStack) {
|
||||
// Get all the stacked entities in our stack and add them to a list.
|
||||
List<StackedEntity> entities = stack.takeAllEntities();
|
||||
// Add the host to this list.
|
||||
entities.add(stack.getHostAsStackedEntity());
|
||||
// Add the collected entities to the new stack.
|
||||
friendStack.addEntitiesToStackSilently(entities);
|
||||
// Update friend stack to display changes.
|
||||
friendStack.updateStack();
|
||||
// Destroy our stack.
|
||||
stack.destroy();
|
||||
// Push changes to the database.
|
||||
plugin.getDataManager().createStackedEntities(friendStack, entities);
|
||||
} else {
|
||||
// If we are not stacked add ourselves to the found friendStack.
|
||||
plugin.getDataManager().createStackedEntity(friendStack, friendStack.addEntityToStack(livingEntity));
|
||||
}
|
||||
|
||||
// Drop lead if applicable then remove our entity and mark it as processed.
|
||||
if (livingEntity.isLeashed())
|
||||
livingEntity.getWorld().dropItemNaturally(livingEntity.getLocation(), CompatibleMaterial.LEAD.getItem());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> livingEntity.getWorld()
|
||||
.dropItemNaturally(livingEntity.getLocation(), CompatibleMaterial.LEAD.getItem()));
|
||||
livingEntity.remove();
|
||||
processed.add(livingEntity.getUniqueId());
|
||||
|
||||
@ -202,27 +217,19 @@ public class StackingTask extends BukkitRunnable {
|
||||
} else if (friendStack == null
|
||||
&& isStack
|
||||
&& (stack.getAmount() + 1) <= maxEntityStackSize
|
||||
&& Methods.canFly(entity)
|
||||
&& canFly(entity)
|
||||
&& Settings.ONLY_STACK_FLYING_DOWN.getBoolean()
|
||||
&& location.getY() > entity.getLocation().getY()) {
|
||||
|
||||
// Create a new stack with the current stacks amount and add one to it.
|
||||
EntityStack newStack = stackManager.addStack(entity, stack.getAmount() + 1);
|
||||
// Make the friend the new stack host.
|
||||
EntityStack newStack = stackManager.updateStack(livingEntity, entity);
|
||||
|
||||
// Fix the entities health.
|
||||
newStack.mergeHealth(stack);
|
||||
newStack.addHealth(livingEntity.getHealth());
|
||||
fixHealth(livingEntity, entity);
|
||||
if (Settings.STACK_ENTITY_HEALTH.getBoolean())
|
||||
entity.setHealth(entity.getHealth());
|
||||
|
||||
// Remove our entities stack from the stack manager.
|
||||
stackManager.removeStack(livingEntity);
|
||||
// Add our entity to that stack
|
||||
plugin.getDataManager().createStackedEntity(newStack, newStack.addEntityToStack(livingEntity));
|
||||
|
||||
// Remove our entity and mark it as processed.
|
||||
livingEntity.remove();
|
||||
processed.add(livingEntity.getUniqueId());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -236,11 +243,11 @@ public class StackingTask extends BukkitRunnable {
|
||||
return;
|
||||
|
||||
// Remove all stacked entities from our stackable friends.
|
||||
stackableFriends.removeIf(stackManager::isStacked);
|
||||
stackableFriends.removeIf(stackManager::isStackedAndLoaded);
|
||||
|
||||
// If the stack cap is met then delete this entity.
|
||||
if (maxPerTypeStacksPerChunk != -1
|
||||
&& (plugin.getEntityUtils().getSimilarStacksInChunk(livingEntity) + 1) > maxPerTypeStacksPerChunk) {
|
||||
&& (getSimilarStacksInChunk(livingEntity) + 1) > maxPerTypeStacksPerChunk) {
|
||||
livingEntity.remove();
|
||||
this.processed.add(livingEntity.getUniqueId());
|
||||
return;
|
||||
@ -253,56 +260,56 @@ public class StackingTask extends BukkitRunnable {
|
||||
|| minEntityStackSize > maxEntityStackSize) return;
|
||||
|
||||
// If a stack was never found create a new one.
|
||||
EntityStack newStack = stackManager.addStack(new EntityStack(livingEntity,
|
||||
Math.min((stackableFriends.size() + 1), maxEntityStackSize)));
|
||||
EntityStack newStack = stackManager.addStack(livingEntity);
|
||||
|
||||
List<LivingEntity> livingEntities = new LinkedList<>();
|
||||
|
||||
// Loop through the unstacked and unprocessed stackable friends while not creating
|
||||
// a stack larger than the maximum.
|
||||
stackableFriends.stream().filter(entity -> !stackManager.isStacked(entity)
|
||||
stackableFriends.stream().filter(entity -> !stackManager.isStackedAndLoaded(entity)
|
||||
&& !this.processed.contains(entity.getUniqueId())).limit(maxEntityStackSize).forEach(entity -> {
|
||||
|
||||
// Make sure we're not naming some poor kids pet.
|
||||
if (entity.getCustomName() != null) {
|
||||
processed.add(livingEntity.getUniqueId());
|
||||
newStack.addAmount(-1);
|
||||
newStack.destroy();
|
||||
return;
|
||||
}
|
||||
// Fix the entities health.
|
||||
fixHealth(livingEntity, entity);
|
||||
newStack.addHealth(entity.getHealth());
|
||||
|
||||
// Drop lead if applicable then remove our entity and mark it as processed.
|
||||
if (entity.isLeashed())
|
||||
entity.getWorld().dropItemNaturally(entity.getLocation(), CompatibleMaterial.LEAD.getItem());
|
||||
livingEntities.add(entity);
|
||||
entity.remove();
|
||||
processed.add(entity.getUniqueId());
|
||||
|
||||
});
|
||||
|
||||
// Update our stacks health.
|
||||
updateHealth(newStack);
|
||||
// Add our new approved entities to the new stack and commit them to the database.
|
||||
plugin.getDataManager().createStackedEntities(newStack,
|
||||
newStack.addRawEntitiesToStackSilently(livingEntities));
|
||||
|
||||
// Update our stack.
|
||||
newStack.updateStack();
|
||||
}
|
||||
|
||||
private void updateHealth(EntityStack stack) {
|
||||
if (Settings.STACK_ENTITY_HEALTH.getBoolean())
|
||||
stack.updateHealth(stack.getEntity());
|
||||
}
|
||||
|
||||
|
||||
public boolean attemptSplit(EntityStack stack, LivingEntity livingEntity) {
|
||||
int stackSize = stack.getAmount();
|
||||
int maxEntityStackAmount = getEntityStackSize(livingEntity);
|
||||
|
||||
if (stackSize <= maxEntityStackAmount) return false;
|
||||
|
||||
for (int i = stackSize; i > 0; i -= maxEntityStackAmount)
|
||||
this.processed.add(plugin.getEntityStackManager()
|
||||
.addStack(plugin.getEntityUtils().newEntity(livingEntity), Math.min(i, maxEntityStackAmount)).getEntityUniqueId());
|
||||
// Destroy the stack.
|
||||
stack.destroy();
|
||||
|
||||
// Remove our entities stack from the stack manager.
|
||||
stackManager.removeStack(livingEntity);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
for (int i = stackSize; i > 0; i -= maxEntityStackAmount) {
|
||||
LivingEntity entity = stack.takeOneAndSpawnEntity(livingEntity.getLocation());
|
||||
EntityStack newStack = plugin.getEntityStackManager().addStack(entity);
|
||||
newStack.moveEntitiesFromStack(stack, Math.min(i, maxEntityStackAmount) - 1);
|
||||
newStack.updateStack();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove our entity and mark it as processed.
|
||||
livingEntity.remove();
|
||||
@ -310,10 +317,329 @@ public class StackingTask extends BukkitRunnable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Set<CachedChunk> getNearbyChunks(Location location, double radius, boolean singleChunk) {
|
||||
World world = location.getWorld();
|
||||
Set<CachedChunk> chunks = new HashSet<>();
|
||||
if (world == null) return chunks;
|
||||
|
||||
private void fixHealth(LivingEntity entity, LivingEntity initialEntity) {
|
||||
if (!Settings.STACK_ENTITY_HEALTH.getBoolean() && Settings.CARRY_OVER_LOWEST_HEALTH.getBoolean() && initialEntity.getHealth() < entity.getHealth())
|
||||
entity.setHealth(initialEntity.getHealth());
|
||||
CachedChunk firstChunk = new CachedChunk(location);
|
||||
chunks.add(firstChunk);
|
||||
|
||||
if (singleChunk) return chunks;
|
||||
|
||||
int minX = (int) Math.floor(((location.getX() - radius) - 2.0D) / 16.0D);
|
||||
int maxX = (int) Math.floor(((location.getX() + radius) + 2.0D) / 16.0D);
|
||||
int minZ = (int) Math.floor(((location.getZ() - radius) - 2.0D) / 16.0D);
|
||||
int maxZ = (int) Math.floor(((location.getZ() + radius) + 2.0D) / 16.0D);
|
||||
|
||||
for (int x = minX; x <= maxX; ++x) {
|
||||
for (int z = minZ; z <= maxZ; ++z) {
|
||||
if (firstChunk.getX() == x && firstChunk.getZ() == z) continue;
|
||||
chunks.add(new CachedChunk(world.getName(), x, z));
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private List<LivingEntity> getNearbyEntities(Location location, double radius, boolean singleChunk) {
|
||||
List<LivingEntity> entities = new ArrayList<>();
|
||||
for (CachedChunk chunk : getNearbyChunks(location, radius, singleChunk)) {
|
||||
if (chunk == null) continue;
|
||||
Entity[] entityArray;
|
||||
if (cachedChunks.containsKey(chunk)) {
|
||||
entityArray = cachedChunks.get(chunk);
|
||||
} else {
|
||||
entityArray = chunk.getEntities();
|
||||
cachedChunks.put(chunk, entityArray);
|
||||
}
|
||||
if (entityArray == null) continue;
|
||||
for (Entity e : entityArray) {
|
||||
if (e == null) continue;
|
||||
if (e.getWorld() != location.getWorld()
|
||||
|| !(e instanceof LivingEntity)
|
||||
|| (!singleChunk && location.distanceSquared(e.getLocation()) >= radius * radius)) continue;
|
||||
entities.add((LivingEntity) e);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public int getSimilarStacksInChunk(LivingEntity entity) {
|
||||
int count = 0;
|
||||
for (LivingEntity e : getNearbyEntities(entity.getLocation(), -1, true)) {
|
||||
if (entity.getType() == e.getType() && plugin.getEntityStackManager().isStackedAndLoaded(e))
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public List<LivingEntity> getSimilarEntitiesAroundEntity(LivingEntity initialEntity, Location location) {
|
||||
// Create a list of all entities around the initial entity of the same type.
|
||||
List<LivingEntity> entityList = new LinkedList<>();
|
||||
|
||||
for (LivingEntity entity : getNearbyEntities(location, searchRadius, stackWholeChunk)) {
|
||||
if (entity.getType() != initialEntity.getType() || entity == initialEntity)
|
||||
continue;
|
||||
entityList.add(entity);
|
||||
}
|
||||
|
||||
if (stackFlyingDown && canFly(initialEntity))
|
||||
entityList.removeIf(entity -> entity.getLocation().getY() > initialEntity.getLocation().getY());
|
||||
|
||||
for (Check check : checks) {
|
||||
if (check == null) continue;
|
||||
switch (check) {
|
||||
case SPAWN_REASON: {
|
||||
if (initialEntity.hasMetadata("US_REASON"))
|
||||
entityList.removeIf(entity -> entity.hasMetadata("US_REASON") && !entity.getMetadata("US_REASON").get(0).asString().equals("US_REASON"));
|
||||
}
|
||||
case AGE: {
|
||||
if (!(initialEntity instanceof Ageable)) break;
|
||||
|
||||
if (((Ageable) initialEntity).isAdult()) {
|
||||
entityList.removeIf(entity -> !((Ageable) entity).isAdult());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Ageable) entity).isAdult());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NERFED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) break;
|
||||
entityList.removeIf(entity -> entity.hasAI() != initialEntity.hasAI());
|
||||
}
|
||||
case IS_TAMED: {
|
||||
if (!(initialEntity instanceof Tameable)) break;
|
||||
if (((Tameable) initialEntity).isTamed()) {
|
||||
entityList.removeIf(entity -> !((Tameable) entity).isTamed());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Tameable) entity).isTamed());
|
||||
}
|
||||
}
|
||||
case ANIMAL_OWNER: {
|
||||
if (!(initialEntity instanceof Tameable)) break;
|
||||
|
||||
Tameable tameable = ((Tameable) initialEntity);
|
||||
entityList.removeIf(entity -> ((Tameable) entity).getOwner() != tameable.getOwner());
|
||||
}
|
||||
case PIG_SADDLE: {
|
||||
if (!(initialEntity instanceof Pig)) break;
|
||||
entityList.removeIf(entity -> ((Pig) entity).hasSaddle());
|
||||
break;
|
||||
}
|
||||
case SKELETON_TYPE: {
|
||||
if (!(initialEntity instanceof Skeleton)) break;
|
||||
|
||||
Skeleton skeleton = (Skeleton) initialEntity;
|
||||
entityList.removeIf(entity -> ((Skeleton) entity).getSkeletonType() != skeleton.getSkeletonType());
|
||||
break;
|
||||
}
|
||||
case SHEEP_COLOR: {
|
||||
if (!(initialEntity instanceof Sheep)) break;
|
||||
|
||||
Sheep sheep = ((Sheep) initialEntity);
|
||||
entityList.removeIf(entity -> ((Sheep) entity).getColor() != sheep.getColor());
|
||||
break;
|
||||
}
|
||||
case SHEEP_SHEARED: {
|
||||
if (!(initialEntity instanceof Sheep)) break;
|
||||
|
||||
Sheep sheep = ((Sheep) initialEntity);
|
||||
if (sheep.isSheared()) {
|
||||
entityList.removeIf(entity -> !((Sheep) entity).isSheared());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Sheep) entity).isSheared());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SNOWMAN_DERPED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)
|
||||
|| !(initialEntity instanceof Snowman)) break;
|
||||
|
||||
Snowman snowman = ((Snowman) initialEntity);
|
||||
if (snowman.isDerp()) {
|
||||
entityList.removeIf(entity -> !((Snowman) entity).isDerp());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Snowman) entity).isDerp());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LLAMA_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(initialEntity instanceof Llama)) break;
|
||||
Llama llama = ((Llama) initialEntity);
|
||||
entityList.removeIf(entity -> ((Llama) entity).getColor() != llama.getColor());
|
||||
break;
|
||||
}
|
||||
case LLAMA_STRENGTH: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(initialEntity instanceof Llama)) break;
|
||||
Llama llama = ((Llama) initialEntity);
|
||||
entityList.removeIf(entity -> ((Llama) entity).getStrength() != llama.getStrength());
|
||||
break;
|
||||
}
|
||||
case VILLAGER_PROFESSION: {
|
||||
if (!(initialEntity instanceof Villager)) break;
|
||||
Villager villager = ((Villager) initialEntity);
|
||||
entityList.removeIf(entity -> ((Villager) entity).getProfession() != villager.getProfession());
|
||||
break;
|
||||
}
|
||||
case SLIME_SIZE: {
|
||||
if (!(initialEntity instanceof Slime)) break;
|
||||
Slime slime = ((Slime) initialEntity);
|
||||
entityList.removeIf(entity -> ((Slime) entity).getSize() != slime.getSize());
|
||||
break;
|
||||
}
|
||||
case HORSE_CARRYING_CHEST: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
|
||||
if (!(initialEntity instanceof ChestedHorse)) break;
|
||||
entityList.removeIf(entity -> ((ChestedHorse) entity).isCarryingChest());
|
||||
} else {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).isCarryingChest());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HORSE_HAS_ARMOR: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).getInventory().getArmor() != null);
|
||||
break;
|
||||
}
|
||||
case HORSE_HAS_SADDLE: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
&& initialEntity instanceof AbstractHorse) {
|
||||
entityList.removeIf(entity -> ((AbstractHorse) entity).getInventory().getSaddle() != null);
|
||||
break;
|
||||
}
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).getInventory().getSaddle() != null);
|
||||
break;
|
||||
}
|
||||
case HORSE_JUMP: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
|
||||
if (!(initialEntity instanceof AbstractHorse)) break;
|
||||
AbstractHorse horse = ((AbstractHorse) initialEntity);
|
||||
entityList.removeIf(entity -> ((AbstractHorse) entity).getJumpStrength() != horse.getJumpStrength());
|
||||
} else {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getJumpStrength() != horse.getJumpStrength());
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HORSE_COLOR: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getColor() != horse.getColor());
|
||||
break;
|
||||
}
|
||||
case HORSE_STYLE: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getStyle() != horse.getStyle());
|
||||
break;
|
||||
}
|
||||
case ZOMBIE_BABY: {
|
||||
if (!(initialEntity instanceof Zombie)) break;
|
||||
Zombie zombie = (Zombie) initialEntity;
|
||||
entityList.removeIf(entity -> ((Zombie) entity).isBaby() != zombie.isBaby());
|
||||
break;
|
||||
}
|
||||
case WOLF_COLLAR_COLOR: {
|
||||
if (!(initialEntity instanceof Wolf)) break;
|
||||
Wolf wolf = (Wolf) initialEntity;
|
||||
entityList.removeIf(entity -> ((Wolf) entity).getCollarColor() != wolf.getCollarColor());
|
||||
break;
|
||||
}
|
||||
case OCELOT_TYPE: {
|
||||
if (!(initialEntity instanceof Ocelot)) break;
|
||||
Ocelot ocelot = (Ocelot) initialEntity;
|
||||
entityList.removeIf(entity -> ((Ocelot) entity).getCatType() != ocelot.getCatType());
|
||||
}
|
||||
case CAT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14)
|
||||
|| !(initialEntity instanceof Cat)) break;
|
||||
Cat cat = (Cat) initialEntity;
|
||||
entityList.removeIf(entity -> ((Cat) entity).getCatType() != cat.getCatType());
|
||||
break;
|
||||
}
|
||||
case HAS_EQUIPMENT: {
|
||||
if (initialEntity.getEquipment() == null) break;
|
||||
boolean imEquipped = isEquipped(initialEntity);
|
||||
if (imEquipped)
|
||||
entityList = new ArrayList<>();
|
||||
else
|
||||
entityList.removeIf(this::isEquipped);
|
||||
break;
|
||||
}
|
||||
case RABBIT_TYPE: {
|
||||
if (!(initialEntity instanceof Rabbit)) break;
|
||||
Rabbit rabbit = (Rabbit) initialEntity;
|
||||
entityList.removeIf(entity -> ((Rabbit) entity).getRabbitType() != rabbit.getRabbitType());
|
||||
break;
|
||||
}
|
||||
case PARROT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12)
|
||||
|| !(initialEntity instanceof Parrot)) break;
|
||||
Parrot parrot = (Parrot) initialEntity;
|
||||
entityList.removeIf(entity -> ((Parrot) entity).getVariant() != parrot.getVariant());
|
||||
break;
|
||||
}
|
||||
case PUFFERFISH_STATE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof PufferFish)) break;
|
||||
PufferFish pufferFish = (PufferFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((PufferFish) entity).getPuffState() != pufferFish.getPuffState());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getPattern() != tropicalFish.getPattern());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getPatternColor() != tropicalFish.getPatternColor());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_BODY_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getBodyColor() != tropicalFish.getBodyColor());
|
||||
break;
|
||||
}
|
||||
case PHANTOM_SIZE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof Phantom)) break;
|
||||
Phantom phantom = (Phantom) initialEntity;
|
||||
entityList.removeIf(entity -> ((Phantom) entity).getSize() != phantom.getSize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialEntity.hasMetadata("breedCooldown")) {
|
||||
entityList.removeIf(entity -> !entity.hasMetadata("breedCooldown"));
|
||||
}
|
||||
|
||||
return entityList;
|
||||
}
|
||||
|
||||
public boolean isEquipped(LivingEntity initialEntity) {
|
||||
if (initialEntity.getEquipment() == null) return false;
|
||||
EntityEquipment equipment = initialEntity.getEquipment();
|
||||
|
||||
return (equipment.getItemInHand().getType() != Material.AIR
|
||||
&& !weaponsArentEquipment && !equipment.getItemInHand().getEnchantments().isEmpty()
|
||||
|| (equipment.getHelmet() != null && equipment.getHelmet().getType() != Material.AIR)
|
||||
|| (equipment.getChestplate() != null && equipment.getChestplate().getType() != Material.AIR)
|
||||
|| (equipment.getLeggings() != null && equipment.getLeggings().getType() != Material.AIR)
|
||||
|| (equipment.getBoots() != null && equipment.getBoots().getType() != Material.AIR));
|
||||
}
|
||||
|
||||
private int getEntityStackSize(LivingEntity initialEntity) {
|
||||
@ -327,4 +653,17 @@ public class StackingTask extends BukkitRunnable {
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public boolean canFly(LivingEntity entity) {
|
||||
switch (entity.getType()) {
|
||||
case GHAST:
|
||||
case BLAZE:
|
||||
case PHANTOM:
|
||||
case BAT:
|
||||
case BEE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,537 +0,0 @@
|
||||
package com.songoda.ultimatestacker.utils;
|
||||
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.entity.Check;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.settings.Settings;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class EntityUtils {
|
||||
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
|
||||
private final List<Check> checks = Check.getChecks(Settings.STACK_CHECKS.getStringList());
|
||||
private final boolean stackFlyingDown = Settings.ONLY_STACK_FLYING_DOWN.getBoolean(),
|
||||
keepFire = Settings.KEEP_FIRE.getBoolean(),
|
||||
keepPotion = Settings.KEEP_POTION.getBoolean(),
|
||||
stackWholeChunk = Settings.STACK_WHOLE_CHUNK.getBoolean(),
|
||||
weaponsArentEquipment = Settings.WEAPONS_ARENT_EQUIPMENT.getBoolean();
|
||||
private final int searchRadius = Settings.SEARCH_RADIUS.getInt();
|
||||
|
||||
private final Map<CachedChunk, Entity[]> cachedChunks = new HashMap<>();
|
||||
|
||||
public void clearChunkCache() {
|
||||
this.cachedChunks.clear();
|
||||
}
|
||||
|
||||
|
||||
private Set<CachedChunk> getNearbyChunks(Location location, double radius, boolean singleChunk) {
|
||||
World world = location.getWorld();
|
||||
Set<CachedChunk> chunks = new HashSet<>();
|
||||
if (world == null) return chunks;
|
||||
|
||||
CachedChunk firstChunk = new CachedChunk(location);
|
||||
chunks.add(firstChunk);
|
||||
|
||||
if (singleChunk) return chunks;
|
||||
|
||||
int minX = (int) Math.floor(((location.getX() - radius) - 2.0D) / 16.0D);
|
||||
int maxX = (int) Math.floor(((location.getX() + radius) + 2.0D) / 16.0D);
|
||||
int minZ = (int) Math.floor(((location.getZ() - radius) - 2.0D) / 16.0D);
|
||||
int maxZ = (int) Math.floor(((location.getZ() + radius) + 2.0D) / 16.0D);
|
||||
|
||||
for (int x = minX; x <= maxX; ++x) {
|
||||
for (int z = minZ; z <= maxZ; ++z) {
|
||||
if (firstChunk.getX() == x && firstChunk.getZ() == z) continue;
|
||||
chunks.add(new CachedChunk(world.getName(), x, z));
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private List<LivingEntity> getNearbyEntities(Location location, double radius, boolean singleChunk) {
|
||||
List<LivingEntity> entities = new ArrayList<>();
|
||||
for (CachedChunk chunk : getNearbyChunks(location, radius, singleChunk)) {
|
||||
Entity[] entityArray;
|
||||
if (cachedChunks.containsKey(chunk)) {
|
||||
entityArray = cachedChunks.get(chunk);
|
||||
} else {
|
||||
entityArray = chunk.getEntities();
|
||||
cachedChunks.put(chunk, entityArray);
|
||||
}
|
||||
for (Entity e : entityArray) {
|
||||
if (e.getWorld() != location.getWorld()
|
||||
|| !(e instanceof LivingEntity)
|
||||
|| (!singleChunk && location.distanceSquared(e.getLocation()) >= radius * radius)) continue;
|
||||
entities.add((LivingEntity) e);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public int getSimilarStacksInChunk(LivingEntity entity) {
|
||||
int count = 0;
|
||||
for (LivingEntity e : getNearbyEntities(entity.getLocation(), -1, true)) {
|
||||
if (entity.getType() == e.getType() && plugin.getEntityStackManager().isStacked(e))
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public LivingEntity newEntity(LivingEntity toClone) {
|
||||
LivingEntity newEntity = (LivingEntity) toClone.getWorld().spawnEntity(toClone.getLocation(), toClone.getType());
|
||||
|
||||
Player player = toClone.getKiller();
|
||||
if (player == null
|
||||
|| !Settings.DISABLE_KNOCKBACK.getBoolean()
|
||||
|| player.getItemInHand().getEnchantmentLevel(Enchantment.KNOCKBACK) != 0) {
|
||||
newEntity.setVelocity(toClone.getVelocity());
|
||||
}
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12))
|
||||
newEntity.setInvulnerable(false);
|
||||
|
||||
for (Check check : checks) {
|
||||
switch (check) {
|
||||
case AGE: {
|
||||
if (!(toClone instanceof Ageable) || ((Ageable) toClone).isAdult()) break;
|
||||
((Ageable) newEntity).setBaby();
|
||||
break;
|
||||
}
|
||||
case NERFED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) break;
|
||||
if (!toClone.hasAI()) newEntity.setAI(false);
|
||||
}
|
||||
case IS_TAMED: {
|
||||
if (!(toClone instanceof Tameable)) break;
|
||||
((Tameable) newEntity).setTamed(((Tameable) toClone).isTamed());
|
||||
}
|
||||
case ANIMAL_OWNER: {
|
||||
if (!(toClone instanceof Tameable)) break;
|
||||
((Tameable) newEntity).setOwner(((Tameable) toClone).getOwner());
|
||||
}
|
||||
case SKELETON_TYPE: {
|
||||
if (!(toClone instanceof Skeleton)
|
||||
|| ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) break;
|
||||
((Skeleton) newEntity).setSkeletonType(((Skeleton) toClone).getSkeletonType());
|
||||
break;
|
||||
}
|
||||
case SHEEP_COLOR: {
|
||||
if (!(toClone instanceof Sheep)) break;
|
||||
((Sheep) newEntity).setColor(((Sheep) toClone).getColor());
|
||||
break;
|
||||
}
|
||||
case SHEEP_SHEARED: {
|
||||
if (!(toClone instanceof Sheep)) break;
|
||||
((Sheep) newEntity).setSheared(((Sheep) toClone).isSheared());
|
||||
break;
|
||||
}
|
||||
case SNOWMAN_DERPED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)
|
||||
|| !(toClone instanceof Snowman)) break;
|
||||
((Snowman) newEntity).setDerp(((Snowman) toClone).isDerp());
|
||||
break;
|
||||
}
|
||||
case LLAMA_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(toClone instanceof Llama)) break;
|
||||
((Llama) newEntity).setColor(((Llama) toClone).getColor());
|
||||
break;
|
||||
}
|
||||
case LLAMA_STRENGTH: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(toClone instanceof Llama)) break;
|
||||
((Llama) newEntity).setStrength(((Llama) toClone).getStrength());
|
||||
break;
|
||||
}
|
||||
case VILLAGER_PROFESSION: {
|
||||
if (!(toClone instanceof Villager)) break;
|
||||
((Villager) newEntity).setProfession(((Villager) toClone).getProfession());
|
||||
break;
|
||||
}
|
||||
case SLIME_SIZE: {
|
||||
if (!(toClone instanceof Slime)) break;
|
||||
((Slime) newEntity).setSize(((Slime) toClone).getSize());
|
||||
break;
|
||||
}
|
||||
case HORSE_JUMP: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(toClone instanceof AbstractHorse)) break;
|
||||
((AbstractHorse) newEntity).setJumpStrength(((AbstractHorse) toClone).getJumpStrength());
|
||||
break;
|
||||
}
|
||||
case HORSE_COLOR: {
|
||||
if (!(toClone instanceof Horse)) break;
|
||||
((Horse) newEntity).setColor(((Horse) toClone).getColor());
|
||||
break;
|
||||
}
|
||||
case HORSE_STYLE: {
|
||||
if (!(toClone instanceof Horse)) break;
|
||||
((Horse) newEntity).setStyle(((Horse) toClone).getStyle());
|
||||
break;
|
||||
}
|
||||
case ZOMBIE_BABY: {
|
||||
if (!(toClone instanceof Zombie)) break;
|
||||
((Zombie) newEntity).setBaby(((Zombie) toClone).isBaby());
|
||||
break;
|
||||
}
|
||||
case WOLF_COLLAR_COLOR: {
|
||||
if (!(toClone instanceof Wolf)) break;
|
||||
((Wolf) newEntity).setCollarColor(((Wolf) toClone).getCollarColor());
|
||||
break;
|
||||
}
|
||||
case OCELOT_TYPE: {
|
||||
if (!(toClone instanceof Ocelot)
|
||||
|| ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14)) break;
|
||||
((Ocelot) newEntity).setCatType(((Ocelot) toClone).getCatType());
|
||||
}
|
||||
case CAT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14)
|
||||
|| !(toClone instanceof Cat)) break;
|
||||
((Cat) newEntity).setCatType(((Cat) toClone).getCatType());
|
||||
break;
|
||||
}
|
||||
case RABBIT_TYPE: {
|
||||
if (!(toClone instanceof Rabbit)) break;
|
||||
((Rabbit) newEntity).setRabbitType(((Rabbit) toClone).getRabbitType());
|
||||
break;
|
||||
}
|
||||
case PARROT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12)
|
||||
|| !(toClone instanceof Parrot)) break;
|
||||
((Parrot) newEntity).setVariant(((Parrot) toClone).getVariant());
|
||||
break;
|
||||
}
|
||||
case PUFFERFISH_STATE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(toClone instanceof PufferFish)) break;
|
||||
((PufferFish) newEntity).setPuffState(((PufferFish) toClone).getPuffState());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(toClone instanceof TropicalFish)) break;
|
||||
((TropicalFish) newEntity).setPattern(((TropicalFish) toClone).getPattern());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(toClone instanceof TropicalFish)) break;
|
||||
((TropicalFish) newEntity).setPatternColor(((TropicalFish) toClone).getPatternColor());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_BODY_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(toClone instanceof TropicalFish)) break;
|
||||
((TropicalFish) newEntity).setBodyColor(((TropicalFish) toClone).getBodyColor());
|
||||
break;
|
||||
}
|
||||
case PHANTOM_SIZE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(toClone instanceof Phantom)) break;
|
||||
((Phantom) newEntity).setSize(((Phantom) toClone).getSize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keepFire)
|
||||
newEntity.setFireTicks(toClone.getFireTicks());
|
||||
if (keepPotion)
|
||||
newEntity.addPotionEffects(toClone.getActivePotionEffects());
|
||||
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
public List<LivingEntity> getSimilarEntitiesAroundEntity(LivingEntity initialEntity, Location location) {
|
||||
// Create a list of all entities around the initial entity of the same type.
|
||||
List<LivingEntity> entityList = new LinkedList<>();
|
||||
for (LivingEntity entity : getNearbyEntities(location, searchRadius, stackWholeChunk)) {
|
||||
if (entity.getType() != initialEntity.getType() || entity == initialEntity)
|
||||
continue;
|
||||
entityList.add(entity);
|
||||
}
|
||||
|
||||
if (stackFlyingDown && Methods.canFly(initialEntity))
|
||||
entityList.removeIf(entity -> entity.getLocation().getY() > initialEntity.getLocation().getY());
|
||||
|
||||
for (Check check : checks) {
|
||||
if (check == null) continue;
|
||||
switch (check) {
|
||||
case SPAWN_REASON: {
|
||||
if (initialEntity.hasMetadata("US_REASON"))
|
||||
entityList.removeIf(entity -> entity.hasMetadata("US_REASON") && !entity.getMetadata("US_REASON").get(0).asString().equals("US_REASON"));
|
||||
}
|
||||
case AGE: {
|
||||
if (!(initialEntity instanceof Ageable)) break;
|
||||
|
||||
if (((Ageable) initialEntity).isAdult()) {
|
||||
entityList.removeIf(entity -> !((Ageable) entity).isAdult());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Ageable) entity).isAdult());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NERFED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) break;
|
||||
entityList.removeIf(entity -> entity.hasAI() != initialEntity.hasAI());
|
||||
}
|
||||
case IS_TAMED: {
|
||||
if (!(initialEntity instanceof Tameable)) break;
|
||||
if (((Tameable) initialEntity).isTamed()) {
|
||||
entityList.removeIf(entity -> !((Tameable) entity).isTamed());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Tameable) entity).isTamed());
|
||||
}
|
||||
}
|
||||
case ANIMAL_OWNER: {
|
||||
if (!(initialEntity instanceof Tameable)) break;
|
||||
|
||||
Tameable tameable = ((Tameable) initialEntity);
|
||||
entityList.removeIf(entity -> ((Tameable) entity).getOwner() != tameable.getOwner());
|
||||
}
|
||||
case PIG_SADDLE: {
|
||||
if (!(initialEntity instanceof Pig)) break;
|
||||
entityList.removeIf(entity -> ((Pig) entity).hasSaddle());
|
||||
break;
|
||||
}
|
||||
case SKELETON_TYPE: {
|
||||
if (!(initialEntity instanceof Skeleton)) break;
|
||||
|
||||
Skeleton skeleton = (Skeleton) initialEntity;
|
||||
entityList.removeIf(entity -> ((Skeleton) entity).getSkeletonType() != skeleton.getSkeletonType());
|
||||
break;
|
||||
}
|
||||
case SHEEP_COLOR: {
|
||||
if (!(initialEntity instanceof Sheep)) break;
|
||||
|
||||
Sheep sheep = ((Sheep) initialEntity);
|
||||
entityList.removeIf(entity -> ((Sheep) entity).getColor() != sheep.getColor());
|
||||
break;
|
||||
}
|
||||
case SHEEP_SHEARED: {
|
||||
if (!(initialEntity instanceof Sheep)) break;
|
||||
|
||||
Sheep sheep = ((Sheep) initialEntity);
|
||||
if (sheep.isSheared()) {
|
||||
entityList.removeIf(entity -> !((Sheep) entity).isSheared());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Sheep) entity).isSheared());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SNOWMAN_DERPED: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)
|
||||
|| !(initialEntity instanceof Snowman)) break;
|
||||
|
||||
Snowman snowman = ((Snowman) initialEntity);
|
||||
if (snowman.isDerp()) {
|
||||
entityList.removeIf(entity -> !((Snowman) entity).isDerp());
|
||||
} else {
|
||||
entityList.removeIf(entity -> ((Snowman) entity).isDerp());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LLAMA_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(initialEntity instanceof Llama)) break;
|
||||
Llama llama = ((Llama) initialEntity);
|
||||
entityList.removeIf(entity -> ((Llama) entity).getColor() != llama.getColor());
|
||||
break;
|
||||
}
|
||||
case LLAMA_STRENGTH: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)
|
||||
|| !(initialEntity instanceof Llama)) break;
|
||||
Llama llama = ((Llama) initialEntity);
|
||||
entityList.removeIf(entity -> ((Llama) entity).getStrength() != llama.getStrength());
|
||||
break;
|
||||
}
|
||||
case VILLAGER_PROFESSION: {
|
||||
if (!(initialEntity instanceof Villager)) break;
|
||||
Villager villager = ((Villager) initialEntity);
|
||||
entityList.removeIf(entity -> ((Villager) entity).getProfession() != villager.getProfession());
|
||||
break;
|
||||
}
|
||||
case SLIME_SIZE: {
|
||||
if (!(initialEntity instanceof Slime)) break;
|
||||
Slime slime = ((Slime) initialEntity);
|
||||
entityList.removeIf(entity -> ((Slime) entity).getSize() != slime.getSize());
|
||||
break;
|
||||
}
|
||||
case HORSE_CARRYING_CHEST: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
|
||||
if (!(initialEntity instanceof ChestedHorse)) break;
|
||||
entityList.removeIf(entity -> ((ChestedHorse) entity).isCarryingChest());
|
||||
} else {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).isCarryingChest());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HORSE_HAS_ARMOR: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).getInventory().getArmor() != null);
|
||||
break;
|
||||
}
|
||||
case HORSE_HAS_SADDLE: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
&& initialEntity instanceof AbstractHorse) {
|
||||
entityList.removeIf(entity -> ((AbstractHorse) entity).getInventory().getSaddle() != null);
|
||||
break;
|
||||
}
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
entityList.removeIf(entity -> ((Horse) entity).getInventory().getSaddle() != null);
|
||||
break;
|
||||
}
|
||||
case HORSE_JUMP: {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
|
||||
if (!(initialEntity instanceof AbstractHorse)) break;
|
||||
AbstractHorse horse = ((AbstractHorse) initialEntity);
|
||||
entityList.removeIf(entity -> ((AbstractHorse) entity).getJumpStrength() != horse.getJumpStrength());
|
||||
} else {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getJumpStrength() != horse.getJumpStrength());
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HORSE_COLOR: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getColor() != horse.getColor());
|
||||
break;
|
||||
}
|
||||
case HORSE_STYLE: {
|
||||
if (!(initialEntity instanceof Horse)) break;
|
||||
Horse horse = ((Horse) initialEntity);
|
||||
entityList.removeIf(entity -> ((Horse) entity).getStyle() != horse.getStyle());
|
||||
break;
|
||||
}
|
||||
case ZOMBIE_BABY: {
|
||||
if (!(initialEntity instanceof Zombie)) break;
|
||||
Zombie zombie = (Zombie) initialEntity;
|
||||
entityList.removeIf(entity -> ((Zombie) entity).isBaby() != zombie.isBaby());
|
||||
break;
|
||||
}
|
||||
case WOLF_COLLAR_COLOR: {
|
||||
if (!(initialEntity instanceof Wolf)) break;
|
||||
Wolf wolf = (Wolf) initialEntity;
|
||||
entityList.removeIf(entity -> ((Wolf) entity).getCollarColor() != wolf.getCollarColor());
|
||||
break;
|
||||
}
|
||||
case OCELOT_TYPE: {
|
||||
if (!(initialEntity instanceof Ocelot)) break;
|
||||
Ocelot ocelot = (Ocelot) initialEntity;
|
||||
entityList.removeIf(entity -> ((Ocelot) entity).getCatType() != ocelot.getCatType());
|
||||
}
|
||||
case CAT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14)
|
||||
|| !(initialEntity instanceof Cat)) break;
|
||||
Cat cat = (Cat) initialEntity;
|
||||
entityList.removeIf(entity -> ((Cat) entity).getCatType() != cat.getCatType());
|
||||
break;
|
||||
}
|
||||
case HAS_EQUIPMENT: {
|
||||
if (initialEntity.getEquipment() == null) break;
|
||||
boolean imEquipped = isEquipped(initialEntity);
|
||||
if (imEquipped)
|
||||
entityList = new ArrayList<>();
|
||||
else
|
||||
entityList.removeIf(this::isEquipped);
|
||||
break;
|
||||
}
|
||||
case RABBIT_TYPE: {
|
||||
if (!(initialEntity instanceof Rabbit)) break;
|
||||
Rabbit rabbit = (Rabbit) initialEntity;
|
||||
entityList.removeIf(entity -> ((Rabbit) entity).getRabbitType() != rabbit.getRabbitType());
|
||||
break;
|
||||
}
|
||||
case PARROT_TYPE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12)
|
||||
|| !(initialEntity instanceof Parrot)) break;
|
||||
Parrot parrot = (Parrot) initialEntity;
|
||||
entityList.removeIf(entity -> ((Parrot) entity).getVariant() != parrot.getVariant());
|
||||
break;
|
||||
}
|
||||
case PUFFERFISH_STATE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof PufferFish)) break;
|
||||
PufferFish pufferFish = (PufferFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((PufferFish) entity).getPuffState() != pufferFish.getPuffState());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getPattern() != tropicalFish.getPattern());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_PATTERN_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getPatternColor() != tropicalFish.getPatternColor());
|
||||
break;
|
||||
}
|
||||
case TROPICALFISH_BODY_COLOR: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof TropicalFish)) break;
|
||||
TropicalFish tropicalFish = (TropicalFish) initialEntity;
|
||||
entityList.removeIf(entity -> ((TropicalFish) entity).getBodyColor() != tropicalFish.getBodyColor());
|
||||
break;
|
||||
}
|
||||
case PHANTOM_SIZE: {
|
||||
if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
|| !(initialEntity instanceof Phantom)) break;
|
||||
Phantom phantom = (Phantom) initialEntity;
|
||||
entityList.removeIf(entity -> ((Phantom) entity).getSize() != phantom.getSize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialEntity.hasMetadata("breedCooldown")) {
|
||||
entityList.removeIf(entity -> !entity.hasMetadata("breedCooldown"));
|
||||
}
|
||||
|
||||
return entityList;
|
||||
}
|
||||
|
||||
public boolean isEquipped(LivingEntity initialEntity) {
|
||||
if (initialEntity.getEquipment() == null) return false;
|
||||
EntityEquipment equipment = initialEntity.getEquipment();
|
||||
|
||||
return (equipment.getItemInHand().getType() != Material.AIR
|
||||
&& !weaponsArentEquipment && !equipment.getItemInHand().getEnchantments().isEmpty()
|
||||
|| (equipment.getHelmet() != null && equipment.getHelmet().getType() != Material.AIR)
|
||||
|| (equipment.getChestplate() != null && equipment.getChestplate().getType() != Material.AIR)
|
||||
|| (equipment.getLeggings() != null && equipment.getLeggings().getType() != Material.AIR)
|
||||
|| (equipment.getBoots() != null && equipment.getBoots().getType() != Material.AIR));
|
||||
}
|
||||
|
||||
public void splitFromStack(LivingEntity entity) {
|
||||
UltimateStacker instance = plugin;
|
||||
EntityStack stack = instance.getEntityStackManager().getStack(entity);
|
||||
|
||||
if (stack.getAmount() <= 1) return;
|
||||
|
||||
LivingEntity newEntity = newEntity(entity);
|
||||
|
||||
int newAmount = stack.getAmount() - 1;
|
||||
if (newAmount != 1)
|
||||
instance.getEntityStackManager().addStack(new EntityStack(newEntity, newAmount));
|
||||
stack.setAmount(1);
|
||||
instance.getEntityStackManager().removeStack(entity);
|
||||
entity.setVelocity(Methods.getRandomVector());
|
||||
}
|
||||
}
|
@ -106,23 +106,6 @@ public class Methods {
|
||||
return info + Methods.formatText(nameFormat).trim();
|
||||
}
|
||||
|
||||
public static boolean canFly(LivingEntity entity) {
|
||||
switch (entity.getType()) {
|
||||
case GHAST:
|
||||
case BLAZE:
|
||||
case PHANTOM:
|
||||
case BAT:
|
||||
case BEE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Vector getRandomVector() {
|
||||
return new Vector(ThreadLocalRandom.current().nextDouble(-1, 1.01), 0, ThreadLocalRandom.current().nextDouble(-1, 1.01)).normalize().multiply(0.5);
|
||||
}
|
||||
|
||||
public static String compileSpawnerName(EntityType entityType, int amount) {
|
||||
String nameFormat = UltimateStacker.getInstance().getConfig().getString("Spawners.Name Format");
|
||||
String displayName = Methods.formatText(UltimateStacker.getInstance().getSpawnerFile().getString("Spawners." + entityType.name() + ".Display Name"));
|
||||
@ -130,8 +113,7 @@ public class Methods {
|
||||
nameFormat = nameFormat.replace("{TYPE}", displayName);
|
||||
nameFormat = nameFormat.replace("{AMT}", Integer.toString(amount));
|
||||
|
||||
String info = TextUtils.convertToInvisibleString(insertSemicolon(String.valueOf(amount)) + ":");
|
||||
return info + Methods.formatText(nameFormat).trim();
|
||||
return Methods.formatText(nameFormat).trim();
|
||||
}
|
||||
|
||||
public static String compileEntityName(Entity entity, int amount) {
|
||||
@ -141,9 +123,7 @@ public class Methods {
|
||||
nameFormat = nameFormat.replace("{TYPE}", displayName);
|
||||
nameFormat = nameFormat.replace("{AMT}", Integer.toString(amount));
|
||||
|
||||
String info = TextUtils.convertToInvisibleString(insertSemicolon(String.valueOf(amount)) + ":");
|
||||
|
||||
return info + Methods.formatText(nameFormat).trim();
|
||||
return Methods.formatText(nameFormat).trim();
|
||||
}
|
||||
|
||||
public static void takeItem(Player player, int amount) {
|
||||
@ -182,37 +162,6 @@ public class Methods {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the location of the block specified.
|
||||
*
|
||||
* @param b The block whose location is to be saved.
|
||||
* @return The serialized data.
|
||||
*/
|
||||
public static String serializeLocation(Block b) {
|
||||
if (b == null)
|
||||
return "";
|
||||
return serializeLocation(b.getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the location specified.
|
||||
*
|
||||
* @param location The location that is to be saved.
|
||||
* @return The serialized data.
|
||||
*/
|
||||
public static String serializeLocation(Location location) {
|
||||
if (location == null || location.getWorld() == null)
|
||||
return "";
|
||||
String w = location.getWorld().getName();
|
||||
double x = location.getX();
|
||||
double y = location.getY();
|
||||
double z = location.getZ();
|
||||
String str = w + ":" + x + ":" + y + ":" + z;
|
||||
str = str.replace(".0", "").replace(".", "/");
|
||||
return str;
|
||||
}
|
||||
|
||||
private static Map<String, Location> serializeCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user