mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-06-25 02:04:44 +02:00
Merge features/v5/internal-updates into api/v5/packages
This commit is contained in:
@ -27,21 +27,23 @@ package com.plotsquared.bukkit;
|
||||
|
||||
import com.plotsquared.bukkit.entity.EntityWrapper;
|
||||
import com.plotsquared.bukkit.entity.ReplicatingEntityWrapper;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.core.generator.AugmentedUtils;
|
||||
import com.plotsquared.core.listener.WEExtent;
|
||||
import com.plotsquared.core.location.Location;
|
||||
import com.plotsquared.core.location.PlotLoc;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.location.PlotLoc;
|
||||
import com.plotsquared.core.util.task.RunnableVal;
|
||||
import com.plotsquared.core.util.ChunkManager;
|
||||
import com.plotsquared.core.util.task.TaskManager;
|
||||
import com.plotsquared.core.queue.GlobalBlockQueue;
|
||||
import com.plotsquared.core.queue.LocalBlockQueue;
|
||||
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
|
||||
import com.plotsquared.core.util.ChunkManager;
|
||||
import com.plotsquared.core.util.RegionUtil;
|
||||
import com.plotsquared.core.util.entity.EntityCategories;
|
||||
import com.plotsquared.core.util.task.RunnableVal;
|
||||
import com.plotsquared.core.util.task.TaskManager;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -54,8 +56,6 @@ import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@ -72,6 +72,12 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MOB;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MONSTER;
|
||||
import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
|
||||
|
||||
public class BukkitChunkManager extends ChunkManager {
|
||||
|
||||
@ -514,135 +520,27 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
}
|
||||
|
||||
private void count(int[] count, Entity entity) {
|
||||
switch (entity.getType()) {
|
||||
case PLAYER:
|
||||
// not valid
|
||||
return;
|
||||
case SMALL_FIREBALL:
|
||||
case FIREBALL:
|
||||
case DROPPED_ITEM:
|
||||
case EGG:
|
||||
case THROWN_EXP_BOTTLE:
|
||||
case SPLASH_POTION:
|
||||
case SNOWBALL:
|
||||
case ENDER_PEARL:
|
||||
case ARROW:
|
||||
case TRIDENT:
|
||||
case SHULKER_BULLET:
|
||||
case SPECTRAL_ARROW:
|
||||
case DRAGON_FIREBALL:
|
||||
case LLAMA_SPIT:
|
||||
// projectile
|
||||
case PRIMED_TNT:
|
||||
case FALLING_BLOCK:
|
||||
// Block entities
|
||||
case ENDER_CRYSTAL:
|
||||
case FISHING_HOOK:
|
||||
case ENDER_SIGNAL:
|
||||
case EXPERIENCE_ORB:
|
||||
case LEASH_HITCH:
|
||||
case FIREWORK:
|
||||
case LIGHTNING:
|
||||
case WITHER_SKULL:
|
||||
case UNKNOWN:
|
||||
case AREA_EFFECT_CLOUD:
|
||||
case EVOKER_FANGS:
|
||||
// non moving / unremovable
|
||||
break;
|
||||
case ITEM_FRAME:
|
||||
case PAINTING:
|
||||
case ARMOR_STAND:
|
||||
count[5]++;
|
||||
break;
|
||||
// misc
|
||||
case MINECART:
|
||||
case MINECART_CHEST:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_FURNACE:
|
||||
case MINECART_HOPPER:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT:
|
||||
case BOAT:
|
||||
count[4]++;
|
||||
break;
|
||||
case POLAR_BEAR:
|
||||
case RABBIT:
|
||||
case SHEEP:
|
||||
case MUSHROOM_COW:
|
||||
case OCELOT:
|
||||
case PIG:
|
||||
case HORSE:
|
||||
case SQUID:
|
||||
case VILLAGER:
|
||||
case IRON_GOLEM:
|
||||
case WOLF:
|
||||
case CHICKEN:
|
||||
case COW:
|
||||
case SNOWMAN:
|
||||
case BAT:
|
||||
case DONKEY:
|
||||
case LLAMA:
|
||||
case SKELETON_HORSE:
|
||||
case ZOMBIE_HORSE:
|
||||
case MULE:
|
||||
case DOLPHIN:
|
||||
case TURTLE:
|
||||
case COD:
|
||||
case PARROT:
|
||||
case SALMON:
|
||||
case PUFFERFISH:
|
||||
case TROPICAL_FISH:
|
||||
case CAT:
|
||||
case FOX:
|
||||
case PANDA:
|
||||
// animal
|
||||
count[3]++;
|
||||
count[1]++;
|
||||
break;
|
||||
case BLAZE:
|
||||
case CAVE_SPIDER:
|
||||
case CREEPER:
|
||||
case ENDERMAN:
|
||||
case ENDERMITE:
|
||||
case ENDER_DRAGON:
|
||||
case GHAST:
|
||||
case GIANT:
|
||||
case GUARDIAN:
|
||||
case MAGMA_CUBE:
|
||||
case PIG_ZOMBIE:
|
||||
case SILVERFISH:
|
||||
case SKELETON:
|
||||
case SLIME:
|
||||
case SPIDER:
|
||||
case WITCH:
|
||||
case WITHER:
|
||||
case ZOMBIE:
|
||||
case SHULKER:
|
||||
case ELDER_GUARDIAN:
|
||||
case STRAY:
|
||||
case HUSK:
|
||||
case EVOKER:
|
||||
case VEX:
|
||||
case WITHER_SKELETON:
|
||||
case ZOMBIE_VILLAGER:
|
||||
case VINDICATOR:
|
||||
// monster
|
||||
count[3]++;
|
||||
count[2]++;
|
||||
break;
|
||||
default:
|
||||
if (entity instanceof Creature) {
|
||||
count[3]++;
|
||||
if (entity instanceof Animals) {
|
||||
count[1]++;
|
||||
} else {
|
||||
count[2]++;
|
||||
}
|
||||
} else {
|
||||
count[4]++;
|
||||
}
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType =
|
||||
BukkitAdapter.adapt(entity.getType());
|
||||
|
||||
if (EntityCategories.PLAYER.contains(entityType)) {
|
||||
return;
|
||||
} else if (EntityCategories.PROJECTILE.contains(entityType) ||
|
||||
EntityCategories.OTHER.contains(entityType) ||
|
||||
EntityCategories.HANGING.contains(entityType)) {
|
||||
count[CAP_MISC]++;
|
||||
} else if (EntityCategories.ANIMAL.contains(entityType) ||
|
||||
EntityCategories.VILLAGER.contains(entityType) ||
|
||||
EntityCategories.TAMEABLE.contains(entityType)) {
|
||||
count[CAP_MOB]++;
|
||||
count[CAP_ANIMAL]++;
|
||||
} else if (EntityCategories.VEHICLE.contains(entityType)) {
|
||||
count[CAP_VEHICLE]++;
|
||||
} else if (EntityCategories.HOSTILE.contains(entityType)) {
|
||||
count[CAP_MOB]++;
|
||||
count[CAP_MONSTER]++;
|
||||
}
|
||||
count[0]++;
|
||||
count[CAP_ENTITY]++;
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,6 @@ import com.plotsquared.bukkit.schematic.BukkitSchematicHandler;
|
||||
import com.plotsquared.bukkit.util.BukkitSetupUtils;
|
||||
import com.plotsquared.bukkit.util.BukkitTaskManager;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.bukkit.util.Metrics;
|
||||
import com.plotsquared.bukkit.util.SetGenCB;
|
||||
import com.plotsquared.bukkit.util.UpdateUtility;
|
||||
import com.plotsquared.bukkit.queue.BukkitLocalQueue;
|
||||
@ -64,6 +63,8 @@ import com.plotsquared.core.generator.IndependentPlotGenerator;
|
||||
import com.plotsquared.core.listener.PlotListener;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.plot.PlotAreaTerrainType;
|
||||
import com.plotsquared.core.plot.PlotAreaType;
|
||||
import com.plotsquared.core.plot.PlotId;
|
||||
import com.plotsquared.core.player.PlotPlayer;
|
||||
import com.plotsquared.core.plot.SetupObject;
|
||||
@ -94,6 +95,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
@ -119,6 +121,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -690,14 +693,28 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
|
||||
return new BukkitSetupUtils();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
// Metrics are controlled via bstats config
|
||||
@Override public void startMetrics() {
|
||||
if (this.metricsStarted) {
|
||||
return;
|
||||
}
|
||||
this.metricsStarted = true;
|
||||
Metrics metrics = new Metrics(this, BSTATS_ID);// bstats
|
||||
metrics.addCustomChart(new Metrics.DrilldownPie("area_types", () -> {
|
||||
final Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||
for (final PlotAreaType plotAreaType : PlotAreaType.values()) {
|
||||
final Map<String, Integer> terrainTypes = new HashMap<>();
|
||||
for (final PlotAreaTerrainType plotAreaTerrainType : PlotAreaTerrainType.values()) {
|
||||
terrainTypes.put(plotAreaTerrainType.name().toLowerCase(), 0);
|
||||
}
|
||||
map.put(plotAreaType.name().toLowerCase(), terrainTypes);
|
||||
}
|
||||
for (final PlotArea plotArea : PlotSquared.get().getPlotAreas()) {
|
||||
final Map<String, Integer> terrainTypeMap = map.get(plotArea.getType().name().toLowerCase());
|
||||
terrainTypeMap.put(plotArea.getTerrain().name().toLowerCase(),
|
||||
terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1);
|
||||
}
|
||||
return map;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override public ChunkManager initChunkManager() {
|
||||
|
@ -256,9 +256,9 @@ import java.util.UUID;
|
||||
MainUtil.sendMessage(player, "&7 - Updating plot objects");
|
||||
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
UUID value = uCMap.get(plot.owner);
|
||||
UUID value = uCMap.get(plot.getOwnerAbs());
|
||||
if (value != null) {
|
||||
plot.owner = value;
|
||||
plot.setOwnerAbs(value);
|
||||
}
|
||||
plot.getTrusted().clear();
|
||||
plot.getMembers().clear();
|
||||
@ -275,9 +275,9 @@ import java.util.UUID;
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, "&cConversion failed! Attempting recovery");
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
UUID value = uCReverse.get(plot.owner);
|
||||
UUID value = uCReverse.get(plot.getOwnerAbs());
|
||||
if (value != null) {
|
||||
plot.owner = value;
|
||||
plot.setOwnerAbs(value);
|
||||
}
|
||||
}
|
||||
DBFunc.createPlotsAndData(new ArrayList<>(PlotSquared.get().getPlots()),
|
||||
|
@ -100,40 +100,39 @@ import com.plotsquared.core.util.MainUtil;
|
||||
import com.plotsquared.core.util.MathMan;
|
||||
import com.plotsquared.core.util.Permissions;
|
||||
import com.plotsquared.core.util.RegExUtil;
|
||||
import com.plotsquared.core.util.entity.EntityCategories;
|
||||
import com.plotsquared.core.util.task.TaskManager;
|
||||
import com.plotsquared.core.util.uuid.UUIDHandler;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.EnderDragon;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Fireball;
|
||||
import org.bukkit.entity.Golem;
|
||||
import org.bukkit.entity.Hanging;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.entity.WaterMob;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
@ -156,12 +155,38 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||
import org.bukkit.event.block.BlockSpreadEvent;
|
||||
import org.bukkit.event.block.EntityBlockFormEvent;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.entity.ExplosionPrimeEvent;
|
||||
import org.bukkit.event.entity.LingeringPotionSplashEvent;
|
||||
import org.bukkit.event.entity.PotionSplashEvent;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
import org.bukkit.event.hanging.HangingPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||
import org.bukkit.event.player.PlayerBucketFillEvent;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerEggThrowEvent;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.vehicle.VehicleCreateEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDestroyEvent;
|
||||
import org.bukkit.event.vehicle.VehicleEntityCollisionEvent;
|
||||
@ -244,147 +269,40 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
.getFlagContainer().getFlagMap().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
switch (entity.getType()) {
|
||||
case PLAYER:
|
||||
return false;
|
||||
case ARROW:
|
||||
case DRAGON_FIREBALL:
|
||||
case DROPPED_ITEM:
|
||||
case EGG:
|
||||
case ENDER_PEARL:
|
||||
case FIREBALL:
|
||||
case LLAMA_SPIT:
|
||||
case SHULKER_BULLET:
|
||||
case SMALL_FIREBALL:
|
||||
case SNOWBALL:
|
||||
case SPECTRAL_ARROW:
|
||||
case SPLASH_POTION:
|
||||
case THROWN_EXP_BOTTLE:
|
||||
// projectile
|
||||
case FALLING_BLOCK:
|
||||
case PRIMED_TNT:
|
||||
// Block entities
|
||||
case AREA_EFFECT_CLOUD:
|
||||
case ENDER_CRYSTAL:
|
||||
case ENDER_SIGNAL:
|
||||
case EVOKER_FANGS:
|
||||
case EXPERIENCE_ORB:
|
||||
case FIREWORK:
|
||||
case FISHING_HOOK:
|
||||
case LEASH_HITCH:
|
||||
case LIGHTNING:
|
||||
case UNKNOWN:
|
||||
case WITHER_SKULL:
|
||||
// non moving / unmovable
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED);
|
||||
case ARMOR_STAND:
|
||||
case ITEM_FRAME:
|
||||
case PAINTING:
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MiscCapFlag.MISC_CAP_UNLIMITED);
|
||||
// misc
|
||||
case BOAT:
|
||||
case MINECART:
|
||||
case MINECART_CHEST:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_FURNACE:
|
||||
case MINECART_HOPPER:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT:
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
VehicleCapFlag.VEHICLE_CAP_UNLIMITED);
|
||||
case BAT:
|
||||
case CHICKEN:
|
||||
case CAT:
|
||||
case COD:
|
||||
case COW:
|
||||
case DOLPHIN:
|
||||
case DONKEY:
|
||||
case FOX:
|
||||
case HORSE:
|
||||
case IRON_GOLEM:
|
||||
case LLAMA:
|
||||
case MULE:
|
||||
case MUSHROOM_COW:
|
||||
case OCELOT:
|
||||
case PANDA:
|
||||
case PARROT:
|
||||
case PIG:
|
||||
case POLAR_BEAR:
|
||||
case PUFFERFISH:
|
||||
case RABBIT:
|
||||
case SALMON:
|
||||
case SHEEP:
|
||||
case SKELETON_HORSE:
|
||||
case SNOWMAN:
|
||||
case SQUID:
|
||||
case TRADER_LLAMA:
|
||||
case TROPICAL_FISH:
|
||||
case TURTLE:
|
||||
case VILLAGER:
|
||||
case WOLF:
|
||||
case ZOMBIE_HORSE:
|
||||
// animal
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, AnimalCapFlag.ANIMAL_CAP_UNLIMITED);
|
||||
case BLAZE:
|
||||
case CAVE_SPIDER:
|
||||
case CREEPER:
|
||||
case DROWNED:
|
||||
case ELDER_GUARDIAN:
|
||||
case ENDERMAN:
|
||||
case ENDERMITE:
|
||||
case ENDER_DRAGON:
|
||||
case EVOKER:
|
||||
case GHAST:
|
||||
case GIANT:
|
||||
case GUARDIAN:
|
||||
case HUSK:
|
||||
case ILLUSIONER:
|
||||
case MAGMA_CUBE:
|
||||
case PIG_ZOMBIE:
|
||||
case SHULKER:
|
||||
case SILVERFISH:
|
||||
case SKELETON:
|
||||
case SLIME:
|
||||
case SPIDER:
|
||||
case STRAY:
|
||||
case VEX:
|
||||
case VINDICATOR:
|
||||
case WITCH:
|
||||
case WITHER:
|
||||
case WITHER_SKELETON:
|
||||
case ZOMBIE:
|
||||
case ZOMBIE_VILLAGER:
|
||||
case PILLAGER:
|
||||
case PHANTOM:
|
||||
case RAVAGER:
|
||||
// monster
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, HostileCapFlag.HOSTILE_CAP_UNLIMITED);
|
||||
default:
|
||||
if (entity instanceof LivingEntity) {
|
||||
if (entity instanceof Animals || entity instanceof WaterMob) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, AnimalCapFlag.ANIMAL_CAP_UNLIMITED);
|
||||
} else if (entity instanceof Monster) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, HostileCapFlag.HOSTILE_CAP_UNLIMITED);
|
||||
} else {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED);
|
||||
}
|
||||
}
|
||||
if (entity instanceof Vehicle) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
VehicleCapFlag.VEHICLE_CAP_UNLIMITED);
|
||||
}
|
||||
if (entity instanceof Hanging) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MiscCapFlag.MISC_CAP_UNLIMITED);
|
||||
}
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED);
|
||||
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(entity.getType());
|
||||
|
||||
if (EntityCategories.PLAYER.contains(entityType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EntityCategories.PROJECTILE.contains(entityType) ||
|
||||
EntityCategories.OTHER.contains(entityType) ||
|
||||
EntityCategories.HANGING.contains(entityType)) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MiscCapFlag.MISC_CAP_UNLIMITED);
|
||||
}
|
||||
|
||||
// Has to go go before vehicle as horses are both
|
||||
// animals and vehicles
|
||||
if (EntityCategories.ANIMAL.contains(entityType) ||
|
||||
EntityCategories.VILLAGER.contains(entityType) ||
|
||||
EntityCategories.TAMEABLE.contains(entityType)) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, AnimalCapFlag.ANIMAL_CAP_UNLIMITED);
|
||||
}
|
||||
|
||||
if (EntityCategories.HOSTILE.contains(entityType)) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
MobCapFlag.MOB_CAP_UNLIMITED, HostileCapFlag.HOSTILE_CAP_UNLIMITED);
|
||||
}
|
||||
|
||||
if (EntityCategories.VEHICLE.contains(entityType)) {
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
|
||||
VehicleCapFlag.VEHICLE_CAP_UNLIMITED);
|
||||
}
|
||||
|
||||
return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED);
|
||||
}
|
||||
|
||||
@EventHandler public void onVehicleEntityCollision(VehicleEntityCollisionEvent e) {
|
||||
@ -414,53 +332,6 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
|
||||
@EventHandler public void onRedstoneEvent(BlockRedstoneEvent event) {
|
||||
Block block = event.getBlock();
|
||||
/* switch (block.getType()) {
|
||||
case OBSERVER:
|
||||
case REDSTONE:
|
||||
case REDSTONE_ORE:
|
||||
case REDSTONE_BLOCK:
|
||||
case REDSTONE_TORCH:
|
||||
case REDSTONE_WALL_TORCH:
|
||||
case REDSTONE_WIRE:
|
||||
case REDSTONE_LAMP:
|
||||
case PISTON_HEAD:
|
||||
case PISTON:
|
||||
case STICKY_PISTON:
|
||||
case MOVING_PISTON:
|
||||
case LEVER:
|
||||
case ACACIA_BUTTON:
|
||||
case BIRCH_BUTTON:
|
||||
case DARK_OAK_BUTTON:
|
||||
case JUNGLE_BUTTON:
|
||||
case OAK_BUTTON:
|
||||
case SPRUCE_BUTTON:
|
||||
case STONE_BUTTON:
|
||||
case STONE_PRESSURE_PLATE:
|
||||
case ACACIA_PRESSURE_PLATE:
|
||||
case BIRCH_PRESSURE_PLATE:
|
||||
case DARK_OAK_PRESSURE_PLATE:
|
||||
case HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||
case JUNGLE_PRESSURE_PLATE:
|
||||
case LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
case OAK_PRESSURE_PLATE:
|
||||
case SPRUCE_PRESSURE_PLATE:
|
||||
case SPRUCE_DOOR:
|
||||
case BIRCH_DOOR:
|
||||
case JUNGLE_DOOR:
|
||||
case ACACIA_DOOR:
|
||||
case DARK_OAK_DOOR:
|
||||
case IRON_DOOR:
|
||||
case OAK_DOOR:
|
||||
case IRON_TRAPDOOR:
|
||||
case SPRUCE_FENCE_GATE:
|
||||
case BIRCH_FENCE_GATE:
|
||||
case JUNGLE_FENCE_GATE:
|
||||
case ACACIA_FENCE_GATE:
|
||||
case DARK_OAK_FENCE_GATE:
|
||||
case OAK_FENCE_GATE:
|
||||
case POWERED_RAIL:
|
||||
return;
|
||||
default:*/
|
||||
Location location = BukkitUtil.getLocation(block.getLocation());
|
||||
PlotArea area = location.getPlotArea();
|
||||
if (area == null) {
|
||||
@ -510,7 +381,6 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
}
|
||||
event.setNewCurrent(0);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
@ -908,27 +778,20 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
}
|
||||
}
|
||||
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
|
||||
switch (vehicle.getType()) {
|
||||
case BOAT:
|
||||
case ENDER_CRYSTAL:
|
||||
case MINECART:
|
||||
case MINECART_CHEST:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_FURNACE:
|
||||
case MINECART_HOPPER:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT: {
|
||||
List<MetadataValue> meta = vehicle.getMetadata("plot");
|
||||
Plot toPlot = BukkitUtil.getLocation(to).getPlot();
|
||||
if (!meta.isEmpty()) {
|
||||
Plot origin = (Plot) meta.get(0).value();
|
||||
if (!origin.getBasePlot(false).equals(toPlot)) {
|
||||
vehicle.remove();
|
||||
}
|
||||
} else if (toPlot != null) {
|
||||
vehicle.setMetadata("plot",
|
||||
new FixedMetadataValue((Plugin) PlotSquared.get().IMP, toPlot));
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(vehicle.getType());
|
||||
// Horses etc are vehicles, but they're also animals
|
||||
// so this filters out all living entities
|
||||
if (EntityCategories.VEHICLE.contains(entityType) && !EntityCategories.ANIMAL.contains(entityType)) {
|
||||
List<MetadataValue> meta = vehicle.getMetadata("plot");
|
||||
Plot toPlot = BukkitUtil.getLocation(to).getPlot();
|
||||
if (!meta.isEmpty()) {
|
||||
Plot origin = (Plot) meta.get(0).value();
|
||||
if (origin != null && !origin.getBasePlot(false).equals(toPlot)) {
|
||||
vehicle.remove();
|
||||
}
|
||||
} else if (toPlot != null) {
|
||||
vehicle.setMetadata("plot",
|
||||
new FixedMetadataValue((Plugin) PlotSquared.get().IMP, toPlot));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2640,30 +2503,41 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else if (!plot.isAdded(pp.getUUID())) {
|
||||
Entity entity = event.getRightClicked();
|
||||
if (entity instanceof Monster && plot.getFlag(HostileInteractFlag.class)) {
|
||||
final Entity entity = event.getRightClicked();
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(entity.getType());
|
||||
|
||||
if (EntityCategories.HOSTILE.contains(entityType) && plot.getFlag(HostileInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
if ((entity instanceof Animals || entity instanceof Golem) && plot.getFlag(
|
||||
AnimalInteractFlag.class)) {
|
||||
|
||||
if (EntityCategories.ANIMAL.contains(entityType) && plot.getFlag(AnimalInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This actually makes use of the interface, so we don't use the
|
||||
// category
|
||||
if (entity instanceof Tameable && ((Tameable) entity).isTamed() && plot
|
||||
.getFlag(TamedInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
if (entity instanceof Vehicle && plot.getFlag(VehicleUseFlag.class)) {
|
||||
|
||||
if (EntityCategories.VEHICLE.contains(entityType) && plot.getFlag(VehicleUseFlag.class)) {
|
||||
return;
|
||||
}
|
||||
if (entity instanceof Player && plot.getFlag(PlayerInteractFlag.class)) {
|
||||
|
||||
if (EntityCategories.PLAYER.contains(entityType) && plot.getFlag(PlayerInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
if (entity instanceof Villager && plot.getFlag(VillagerInteractFlag.class)) {
|
||||
|
||||
if (EntityCategories.VILLAGER.contains(entityType) && plot.getFlag(VillagerInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
if (entity instanceof ItemFrame && plot.getFlag(MiscInteractFlag.class)) {
|
||||
|
||||
if ((EntityCategories.HANGING.contains(entityType) ||
|
||||
EntityCategories.OTHER.contains(entityType)) && plot.getFlag(MiscInteractFlag.class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_OTHER)) {
|
||||
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
|
||||
Captions.PERMISSION_ADMIN_INTERACT_OTHER);
|
||||
@ -2866,7 +2740,9 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
}
|
||||
if (player != null) {
|
||||
PlotPlayer plotPlayer = BukkitUtil.getPlayer(player);
|
||||
if (victim instanceof Hanging) { // hanging
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType =
|
||||
BukkitAdapter.adapt(victim.getType());
|
||||
if (EntityCategories.HANGING.contains(entityType)) { // hanging
|
||||
if (plot != null && (plot.getFlag(HangingBreakFlag.class)) || plot
|
||||
.isAdded(plotPlayer.getUUID())) {
|
||||
if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
|
||||
@ -2894,8 +2770,7 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
"plots.admin.destroy." + stub);
|
||||
return false;
|
||||
}
|
||||
} else if (victim instanceof Monster
|
||||
|| victim instanceof EnderDragon) { // victim is monster
|
||||
} else if (EntityCategories.HOSTILE.contains(entityType)) {
|
||||
if (plot != null && (plot.getFlag(HostileAttackFlag.class) || plot
|
||||
.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
|
||||
return true;
|
||||
@ -2905,7 +2780,7 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
"plots.admin.pve." + stub);
|
||||
return false;
|
||||
}
|
||||
} else if (victim instanceof Tameable) { // victim is tameable
|
||||
} else if (EntityCategories.TAMEABLE.contains(entityType)) { // victim is tameable
|
||||
if (plot != null && (plot.getFlag(TamedAttackFlag.class) || plot
|
||||
.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
|
||||
return true;
|
||||
@ -2915,7 +2790,7 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
"plots.admin.pve." + stub);
|
||||
return false;
|
||||
}
|
||||
} else if (victim instanceof Player) {
|
||||
} else if (EntityCategories.PLAYER.contains(entityType)) {
|
||||
if (plot != null) {
|
||||
if (!plot.getFlag(PvpFlag.class) && !Permissions
|
||||
.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) {
|
||||
@ -2931,7 +2806,7 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
"plots.admin.pvp." + stub);
|
||||
return false;
|
||||
}
|
||||
} else if (victim instanceof Creature) { // victim is animal
|
||||
} else if (EntityCategories.ANIMAL.contains(entityType)) { // victim is animal
|
||||
if (plot != null && (plot.getFlag(AnimalAttackFlag.class) || plot
|
||||
.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
|
||||
return true;
|
||||
@ -2941,7 +2816,7 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
"plots.admin.pve." + stub);
|
||||
return false;
|
||||
}
|
||||
} else if (victim instanceof Vehicle) { // Vehicles are managed in vehicle destroy event
|
||||
} else if (EntityCategories.VEHICLE.contains(entityType)) { // Vehicles are managed in vehicle destroy event
|
||||
return true;
|
||||
} else { // victim is something else
|
||||
if (plot != null && (plot.getFlag(PveFlag.class) || plot
|
||||
@ -3104,4 +2979,5 @@ public class PlayerEvents extends PlotListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -58,13 +58,42 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
import org.bukkit.entity.Ambient;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.AreaEffectCloud;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Boss;
|
||||
import org.bukkit.entity.EnderCrystal;
|
||||
import org.bukkit.entity.EnderSignal;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.EvokerFangs;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.Explosive;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.Ghast;
|
||||
import org.bukkit.entity.Hanging;
|
||||
import org.bukkit.entity.IronGolem;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LightningStrike;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.NPC;
|
||||
import org.bukkit.entity.Phantom;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.Shulker;
|
||||
import org.bukkit.entity.Slime;
|
||||
import org.bukkit.entity.Snowman;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.entity.WaterMob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -72,7 +101,6 @@ import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class BukkitUtil extends WorldUtil {
|
||||
|
||||
@ -543,6 +571,76 @@ public class BukkitUtil extends WorldUtil {
|
||||
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<com.sk89q.worldedit.world.entity.EntityType> getTypesInCategory(final String category) {
|
||||
final Collection<Class<?>> allowedInterfaces = new HashSet<>();
|
||||
switch (category) {
|
||||
case "animal": {
|
||||
allowedInterfaces.add(IronGolem.class);
|
||||
allowedInterfaces.add(Snowman.class);
|
||||
allowedInterfaces.add(Animals.class);
|
||||
allowedInterfaces.add(WaterMob.class);
|
||||
allowedInterfaces.add(Ambient.class);
|
||||
} break;
|
||||
case "tameable": {
|
||||
allowedInterfaces.add(Tameable.class);
|
||||
} break;
|
||||
case "vehicle": {
|
||||
allowedInterfaces.add(Vehicle.class);
|
||||
} break;
|
||||
case "hostile": {
|
||||
allowedInterfaces.add(Shulker.class);
|
||||
allowedInterfaces.add(Monster.class);
|
||||
allowedInterfaces.add(Boss.class);
|
||||
allowedInterfaces.add(Slime.class);
|
||||
allowedInterfaces.add(Ghast.class);
|
||||
allowedInterfaces.add(Phantom.class);
|
||||
allowedInterfaces.add(EnderCrystal.class);
|
||||
} break;
|
||||
case "hanging": {
|
||||
allowedInterfaces.add(Hanging.class);
|
||||
} break;
|
||||
case "villager": {
|
||||
allowedInterfaces.add(NPC.class);
|
||||
} break;
|
||||
case "projectile": {
|
||||
allowedInterfaces.add(Projectile.class);
|
||||
} break;
|
||||
case "other": {
|
||||
allowedInterfaces.add(ArmorStand.class);
|
||||
allowedInterfaces.add(FallingBlock.class);
|
||||
allowedInterfaces.add(Item.class);
|
||||
allowedInterfaces.add(Explosive.class);
|
||||
allowedInterfaces.add(AreaEffectCloud.class);
|
||||
allowedInterfaces.add(EvokerFangs.class);
|
||||
allowedInterfaces.add(LightningStrike.class);
|
||||
allowedInterfaces.add(ExperienceOrb.class);
|
||||
allowedInterfaces.add(EnderSignal.class);
|
||||
allowedInterfaces.add(Firework.class);
|
||||
} break;
|
||||
case "player": {
|
||||
allowedInterfaces.add(Player.class);
|
||||
} break;
|
||||
default: {
|
||||
PlotSquared.log(Captions.PREFIX + "Unknown entity category requested: " + category);
|
||||
} break;
|
||||
}
|
||||
final Set<com.sk89q.worldedit.world.entity.EntityType> types = new HashSet<>();
|
||||
outer: for (final EntityType bukkitType : EntityType.values()) {
|
||||
final Class<? extends Entity> entityClass = bukkitType.getEntityClass();
|
||||
if (entityClass == null) {
|
||||
continue;
|
||||
}
|
||||
for (final Class<?> allowedInterface : allowedInterfaces) {
|
||||
if (allowedInterface.isAssignableFrom(entityClass)) {
|
||||
types.add(BukkitAdapter.adapt(bukkitType));
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private static void ensureLoaded(final String world, final int x, final int z, final Consumer<Chunk> chunkConsumer) {
|
||||
PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true).thenAccept(chunk ->
|
||||
ensureMainThread(chunkConsumer, chunk));
|
||||
|
@ -1,739 +0,0 @@
|
||||
/*
|
||||
* _____ _ _ _____ _
|
||||
* | __ \| | | | / ____| | |
|
||||
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
|
||||
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
|
||||
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
|
||||
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
|
||||
* | |
|
||||
* |_|
|
||||
* PlotSquared plot management system for Minecraft
|
||||
* Copyright (C) 2020 IntellectualSites
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.plotsquared.bukkit.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* bStats collects some data for plugin authors.
|
||||
* <p>
|
||||
* Check out https://bStats.org/ to learn more about bStats!
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public class Metrics {
|
||||
|
||||
static {
|
||||
// You can use the property to disable the check in your test environment
|
||||
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
|
||||
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
|
||||
final String defaultPackage = new String(
|
||||
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
||||
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
// We want to make sure nobody just copy & pastes the example and use the wrong package names
|
||||
|
||||
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
|
||||
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The version of this bStats class
|
||||
public static final int B_STATS_VERSION = 1;
|
||||
|
||||
// The url to which the data is sent
|
||||
private static final String URL = "https://bStats.org/submitData/bukkit";
|
||||
|
||||
// Is bStats enabled on this server?
|
||||
private boolean enabled;
|
||||
|
||||
// Should failed requests be logged?
|
||||
private static boolean logFailedRequests;
|
||||
|
||||
// Should the sent data be logged?
|
||||
private static boolean logSentData;
|
||||
|
||||
// Should the response text be logged?
|
||||
private static boolean logResponseStatusText;
|
||||
|
||||
// The uuid of the server
|
||||
private static String serverUUID;
|
||||
|
||||
// The plugin
|
||||
private final Plugin plugin;
|
||||
|
||||
// The plugin id
|
||||
private final int bstatsId;
|
||||
|
||||
// A list with all custom charts
|
||||
private final List<CustomChart> charts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param plugin The plugin which stats should be submitted.
|
||||
* @param bstatsId The ID of the plugin. It can be found in the url when you open the plugin on bStats.
|
||||
*/
|
||||
public Metrics(Plugin plugin, int bstatsId) {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||
}
|
||||
this.plugin = plugin;
|
||||
this.bstatsId = bstatsId;
|
||||
|
||||
// Get the config file
|
||||
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
|
||||
File configFile = new File(bStatsFolder, "config.yml");
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
// Check if the config file exists
|
||||
if (!config.isSet("serverUuid")) {
|
||||
|
||||
// Add default values
|
||||
config.addDefault("enabled", true);
|
||||
// Every server gets it's unique random id.
|
||||
config.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||
// Should failed request be logged?
|
||||
config.addDefault("logFailedRequests", false);
|
||||
// Should the sent data be logged?
|
||||
config.addDefault("logSentData", false);
|
||||
// Should the response text be logged?
|
||||
config.addDefault("logResponseStatusText", false);
|
||||
|
||||
// Inform the server owners about bStats
|
||||
config.options().header(
|
||||
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
|
||||
"To honor their work, you should not disable it.\n" +
|
||||
"This has nearly no effect on the server performance!\n" +
|
||||
"Check out https://bStats.org/ to learn more :)"
|
||||
).copyDefaults(true);
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
// Load the data
|
||||
enabled = config.getBoolean("enabled", true);
|
||||
serverUUID = config.getString("serverUuid");
|
||||
logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
logSentData = config.getBoolean("logSentData", false);
|
||||
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
|
||||
|
||||
if (enabled) {
|
||||
boolean found = false;
|
||||
// Search for all other bStats Metrics classes to see if we are the first one
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
found = true; // We aren't the first
|
||||
break;
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
// Register our service
|
||||
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
|
||||
if (!found) {
|
||||
// We are the first!
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if bStats is enabled.
|
||||
*
|
||||
* @return Whether bStats is enabled or not.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom chart.
|
||||
*
|
||||
* @param chart The chart to add.
|
||||
*/
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
if (chart == null) {
|
||||
throw new IllegalArgumentException("Chart cannot be null!");
|
||||
}
|
||||
charts.add(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Scheduler which submits our data every 30 minutes.
|
||||
*/
|
||||
private void startSubmitting() {
|
||||
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!plugin.isEnabled()) { // Plugin was disabled
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
|
||||
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
|
||||
Bukkit.getScheduler().runTask(plugin, () -> submitData());
|
||||
}
|
||||
}, 1000 * 60 * 5, 1000 * 60 * 30);
|
||||
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
|
||||
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
|
||||
// WARNING: Just don't do it!
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin specific data.
|
||||
* This method is called using Reflection.
|
||||
*
|
||||
* @return The plugin specific data.
|
||||
*/
|
||||
public JSONObject getPluginData() {
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
String pluginName = plugin.getDescription().getName();
|
||||
String pluginVersion = plugin.getDescription().getVersion();
|
||||
|
||||
data.put("pluginName", pluginName); // Append the name of the plugin
|
||||
data.put("id", bstatsId); // Append the id of the plugin
|
||||
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
|
||||
JSONArray customCharts = new JSONArray();
|
||||
for (CustomChart customChart : charts) {
|
||||
// Add the data of the custom charts
|
||||
JSONObject chart = customChart.getRequestJsonObject();
|
||||
if (chart == null) { // If the chart is null, we skip it
|
||||
continue;
|
||||
}
|
||||
customCharts.add(chart);
|
||||
}
|
||||
data.put("customCharts", customCharts);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server specific data.
|
||||
*
|
||||
* @return The server specific data.
|
||||
*/
|
||||
private JSONObject getServerData() {
|
||||
// Minecraft specific data
|
||||
int playerAmount;
|
||||
try {
|
||||
// Around MC 1.8 the return type was changed to a collection from an array,
|
||||
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
|
||||
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
|
||||
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
|
||||
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
|
||||
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
|
||||
} catch (Exception e) {
|
||||
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
|
||||
}
|
||||
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
|
||||
String bukkitVersion = Bukkit.getVersion();
|
||||
|
||||
// OS/Java specific data
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String osName = System.getProperty("os.name");
|
||||
String osArch = System.getProperty("os.arch");
|
||||
String osVersion = System.getProperty("os.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
data.put("serverUUID", serverUUID);
|
||||
|
||||
data.put("playerAmount", playerAmount);
|
||||
data.put("onlineMode", onlineMode);
|
||||
data.put("bukkitVersion", bukkitVersion);
|
||||
|
||||
data.put("javaVersion", javaVersion);
|
||||
data.put("osName", osName);
|
||||
data.put("osArch", osArch);
|
||||
data.put("osVersion", osVersion);
|
||||
data.put("coreCount", coreCount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the data and sends it afterwards.
|
||||
*/
|
||||
private void submitData() {
|
||||
final JSONObject data = getServerData();
|
||||
|
||||
JSONArray pluginData = new JSONArray();
|
||||
// Search for all other bStats Metrics classes to get their plugin data
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
|
||||
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
|
||||
try {
|
||||
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
|
||||
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
|
||||
data.put("plugins", pluginData);
|
||||
|
||||
// Create a new thread for the connection to the bStats server
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(plugin, data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the data to the bStats server.
|
||||
*
|
||||
* @param plugin Any plugin. It's just used to get a logger instance.
|
||||
* @param data The data to send.
|
||||
* @throws Exception If the request failed.
|
||||
*/
|
||||
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Data cannot be null!");
|
||||
}
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
throw new IllegalAccessException("This method must not be called from the main thread!");
|
||||
}
|
||||
if (logSentData) {
|
||||
plugin.getLogger().info("Sending data to bStats: " + data.toString());
|
||||
}
|
||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
||||
|
||||
// Compress the data to save bandwidth
|
||||
byte[] compressedData = compress(data.toString());
|
||||
|
||||
// Add headers
|
||||
connection.setRequestMethod("POST");
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
|
||||
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
||||
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
|
||||
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
||||
|
||||
// Send data
|
||||
connection.setDoOutput(true);
|
||||
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
||||
outputStream.write(compressedData);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
bufferedReader.close();
|
||||
if (logResponseStatusText) {
|
||||
plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzips the given String.
|
||||
*
|
||||
* @param str The string to gzip.
|
||||
* @return The gzipped String.
|
||||
* @throws IOException If the compression failed.
|
||||
*/
|
||||
private static byte[] compress(final String str) throws IOException {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
||||
gzip.write(str.getBytes(StandardCharsets.UTF_8));
|
||||
gzip.close();
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom chart.
|
||||
*/
|
||||
public static abstract class CustomChart {
|
||||
|
||||
// The id of the chart
|
||||
final String chartId;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
*/
|
||||
CustomChart(String chartId) {
|
||||
if (chartId == null || chartId.isEmpty()) {
|
||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
||||
}
|
||||
this.chartId = chartId;
|
||||
}
|
||||
|
||||
private JSONObject getRequestJsonObject() {
|
||||
JSONObject chart = new JSONObject();
|
||||
chart.put("chartId", chartId);
|
||||
try {
|
||||
JSONObject data = getChartData();
|
||||
if (data == null) {
|
||||
// If the data is null we don't send the chart.
|
||||
return null;
|
||||
}
|
||||
chart.put("data", data);
|
||||
} catch (Throwable t) {
|
||||
if (logFailedRequests) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
protected abstract JSONObject getChartData() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple pie.
|
||||
*/
|
||||
public static class SimplePie extends CustomChart {
|
||||
|
||||
private final Callable<String> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SimplePie(String chartId, Callable<String> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
String value = callable.call();
|
||||
if (value == null || value.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom advanced pie.
|
||||
*/
|
||||
public static class AdvancedPie extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom drilldown pie.
|
||||
*/
|
||||
public static class DrilldownPie extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Map<String, Integer>>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Map<String, Integer>> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean reallyAllSkipped = true;
|
||||
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
||||
JSONObject value = new JSONObject();
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
||||
value.put(valueEntry.getKey(), valueEntry.getValue());
|
||||
allSkipped = false;
|
||||
}
|
||||
if (!allSkipped) {
|
||||
reallyAllSkipped = false;
|
||||
values.put(entryValues.getKey(), value);
|
||||
}
|
||||
}
|
||||
if (reallyAllSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom single line chart.
|
||||
*/
|
||||
public static class SingleLineChart extends CustomChart {
|
||||
|
||||
private final Callable<Integer> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SingleLineChart(String chartId, Callable<Integer> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
int value = callable.call();
|
||||
if (value == 0) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom multi line chart.
|
||||
*/
|
||||
public static class MultiLineChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple bar chart.
|
||||
*/
|
||||
public static class SimpleBarChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
categoryValues.add(entry.getValue());
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom advanced bar chart.
|
||||
*/
|
||||
public static class AdvancedBarChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, int[]>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, int[]> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
||||
if (entry.getValue().length == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
for (int categoryValue : entry.getValue()) {
|
||||
categoryValues.add(categoryValue);
|
||||
}
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,29 +25,27 @@
|
||||
*/
|
||||
package com.plotsquared.bukkit.util.uuid;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.core.config.Captions;
|
||||
import com.plotsquared.core.config.Settings;
|
||||
import com.plotsquared.core.player.OfflinePlotPlayer;
|
||||
import com.plotsquared.core.util.task.RunnableVal;
|
||||
import com.plotsquared.core.util.StringWrapper;
|
||||
import com.plotsquared.core.plot.expiration.ExpireManager;
|
||||
import com.plotsquared.core.util.StringMan;
|
||||
import com.plotsquared.core.util.StringWrapper;
|
||||
import com.plotsquared.core.util.task.RunnableVal;
|
||||
import com.plotsquared.core.util.task.TaskManager;
|
||||
import com.plotsquared.core.util.uuid.UUIDHandler;
|
||||
import com.plotsquared.core.util.uuid.UUIDHandlerImplementation;
|
||||
import com.plotsquared.core.plot.expiration.ExpireManager;
|
||||
import com.plotsquared.core.util.uuid.UUIDWrapper;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -56,7 +54,9 @@ import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class FileUUIDHandler extends UUIDHandlerImplementation {
|
||||
|
||||
|
Reference in New Issue
Block a user