mirror of
https://github.com/BentoBoxWorld/Level.git
synced 2025-01-25 00:41:21 +01:00
Adds an admin stats command. See #293
This commit is contained in:
parent
eb71b35c5c
commit
3a3c8a320c
@ -24,6 +24,7 @@ import world.bentobox.level.calculators.Pipeliner;
|
||||
import world.bentobox.level.commands.AdminLevelCommand;
|
||||
import world.bentobox.level.commands.AdminLevelStatusCommand;
|
||||
import world.bentobox.level.commands.AdminSetInitialLevelCommand;
|
||||
import world.bentobox.level.commands.AdminStatsCommand;
|
||||
import world.bentobox.level.commands.AdminTopCommand;
|
||||
import world.bentobox.level.commands.IslandLevelCommand;
|
||||
import world.bentobox.level.commands.IslandTopCommand;
|
||||
@ -39,411 +40,411 @@ import world.bentobox.level.requests.TopTenRequestHandler;
|
||||
import world.bentobox.visit.VisitAddon;
|
||||
import world.bentobox.warps.Warp;
|
||||
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
public class Level extends Addon {
|
||||
|
||||
// The 10 in top ten
|
||||
public static final int TEN = 10;
|
||||
// The 10 in top ten
|
||||
public static final int TEN = 10;
|
||||
|
||||
// Settings
|
||||
private ConfigSettings settings;
|
||||
private Config<ConfigSettings> configObject = new Config<>(this, ConfigSettings.class);
|
||||
private BlockConfig blockConfig;
|
||||
private Pipeliner pipeliner;
|
||||
private LevelsManager manager;
|
||||
private boolean stackersEnabled;
|
||||
private boolean advChestEnabled;
|
||||
private boolean roseStackersEnabled;
|
||||
private boolean ultimateStackerEnabled;
|
||||
private final List<GameModeAddon> registeredGameModes = new ArrayList<>();
|
||||
// Settings
|
||||
private ConfigSettings settings;
|
||||
private Config<ConfigSettings> configObject = new Config<>(this, ConfigSettings.class);
|
||||
private BlockConfig blockConfig;
|
||||
private Pipeliner pipeliner;
|
||||
private LevelsManager manager;
|
||||
private boolean stackersEnabled;
|
||||
private boolean advChestEnabled;
|
||||
private boolean roseStackersEnabled;
|
||||
private boolean ultimateStackerEnabled;
|
||||
private final List<GameModeAddon> registeredGameModes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Local variable that stores if warpHook is present.
|
||||
*/
|
||||
private Warp warpHook;
|
||||
/**
|
||||
* Local variable that stores if warpHook is present.
|
||||
*/
|
||||
private Warp warpHook;
|
||||
|
||||
/**
|
||||
* Local variable that stores if visitHook is present.
|
||||
*/
|
||||
private VisitAddon visitHook;
|
||||
/**
|
||||
* Local variable that stores if visitHook is present.
|
||||
*/
|
||||
private VisitAddon visitHook;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Save the default config from config.yml
|
||||
saveDefaultConfig();
|
||||
if (loadSettings()) {
|
||||
// Disable
|
||||
logError("Level settings could not load! Addon disabled.");
|
||||
setState(State.DISABLED);
|
||||
} else {
|
||||
configObject.saveConfigObject(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Save the default config from config.yml
|
||||
saveDefaultConfig();
|
||||
if (loadSettings()) {
|
||||
// Disable
|
||||
logError("Level settings could not load! Addon disabled.");
|
||||
setState(State.DISABLED);
|
||||
} else {
|
||||
configObject.saveConfigObject(settings);
|
||||
}
|
||||
// Save existing panels.
|
||||
this.saveResource("panels/top_panel.yml", false);
|
||||
this.saveResource("panels/detail_panel.yml", false);
|
||||
this.saveResource("panels/value_panel.yml", false);
|
||||
}
|
||||
|
||||
// Save existing panels.
|
||||
this.saveResource("panels/top_panel.yml", false);
|
||||
this.saveResource("panels/detail_panel.yml", false);
|
||||
this.saveResource("panels/value_panel.yml", false);
|
||||
}
|
||||
private boolean loadSettings() {
|
||||
// Load settings again to get worlds
|
||||
settings = configObject.loadConfigObject();
|
||||
|
||||
private boolean loadSettings() {
|
||||
// Load settings again to get worlds
|
||||
settings = configObject.loadConfigObject();
|
||||
return settings == null;
|
||||
}
|
||||
|
||||
return settings == null;
|
||||
}
|
||||
@Override
|
||||
public void onEnable() {
|
||||
loadBlockSettings();
|
||||
// Start pipeline
|
||||
pipeliner = new Pipeliner(this);
|
||||
// Start Manager
|
||||
manager = new LevelsManager(this);
|
||||
// Register listeners
|
||||
this.registerListener(new IslandActivitiesListeners(this));
|
||||
this.registerListener(new JoinLeaveListener(this));
|
||||
this.registerListener(new MigrationListener(this));
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
loadBlockSettings();
|
||||
// Start pipeline
|
||||
pipeliner = new Pipeliner(this);
|
||||
// Start Manager
|
||||
manager = new LevelsManager(this);
|
||||
// Register listeners
|
||||
this.registerListener(new IslandActivitiesListeners(this));
|
||||
this.registerListener(new JoinLeaveListener(this));
|
||||
this.registerListener(new MigrationListener(this));
|
||||
// Register commands for GameModes
|
||||
registeredGameModes.clear();
|
||||
getPlugin().getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName())).forEach(gm -> {
|
||||
log("Level hooking into " + gm.getDescription().getName());
|
||||
registerCommands(gm);
|
||||
new PlaceholderManager(this).registerPlaceholders(gm);
|
||||
registeredGameModes.add(gm);
|
||||
});
|
||||
// Register request handlers
|
||||
registerRequestHandler(new LevelRequestHandler(this));
|
||||
registerRequestHandler(new TopTenRequestHandler(this));
|
||||
|
||||
// Register commands for GameModes
|
||||
registeredGameModes.clear();
|
||||
getPlugin().getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName()))
|
||||
.forEach(gm -> {
|
||||
log("Level hooking into " + gm.getDescription().getName());
|
||||
registerCommands(gm);
|
||||
new PlaceholderManager(this).registerPlaceholders(gm);
|
||||
registeredGameModes.add(gm);
|
||||
});
|
||||
// Register request handlers
|
||||
registerRequestHandler(new LevelRequestHandler(this));
|
||||
registerRequestHandler(new TopTenRequestHandler(this));
|
||||
// Check if WildStackers is enabled on the server
|
||||
// I only added support for counting blocks into the island level
|
||||
// Someone else can PR if they want spawners added to the Leveling system :)
|
||||
if (!settings.getDisabledPluginHooks().contains("WildStacker")) {
|
||||
stackersEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker");
|
||||
if (stackersEnabled) {
|
||||
log("Hooked into WildStackers.");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if WildStackers is enabled on the server
|
||||
// I only added support for counting blocks into the island level
|
||||
// Someone else can PR if they want spawners added to the Leveling system :)
|
||||
if ( !settings.getDisabledPluginHooks().contains("WildStacker") ) {
|
||||
stackersEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker");
|
||||
if (stackersEnabled) {
|
||||
log("Hooked into WildStackers.");
|
||||
}
|
||||
}
|
||||
// Check if AdvancedChests is enabled on the server
|
||||
if (!settings.getDisabledPluginHooks().contains("AdvancedChests")) {
|
||||
Plugin advChest = Bukkit.getPluginManager().getPlugin("AdvancedChests");
|
||||
advChestEnabled = advChest != null;
|
||||
if (advChestEnabled) {
|
||||
// Check version
|
||||
if (compareVersions(advChest.getDescription().getVersion(), "23.0") > 0) {
|
||||
log("Hooked into AdvancedChests.");
|
||||
} else {
|
||||
logError("Could not hook into AdvancedChests " + advChest.getDescription().getVersion()
|
||||
+ " - requires version 23.0 or later");
|
||||
advChestEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if AdvancedChests is enabled on the server
|
||||
if ( !settings.getDisabledPluginHooks().contains("AdvancedChests") ) {
|
||||
Plugin advChest = Bukkit.getPluginManager().getPlugin("AdvancedChests");
|
||||
advChestEnabled = advChest != null;
|
||||
if (advChestEnabled) {
|
||||
// Check version
|
||||
if (compareVersions(advChest.getDescription().getVersion(), "23.0") > 0) {
|
||||
log("Hooked into AdvancedChests.");
|
||||
} else {
|
||||
logError("Could not hook into AdvancedChests " + advChest.getDescription().getVersion() + " - requires version 23.0 or later");
|
||||
advChestEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if RoseStackers is enabled
|
||||
if (!settings.getDisabledPluginHooks().contains("RoseStacker")) {
|
||||
roseStackersEnabled = Bukkit.getPluginManager().isPluginEnabled("RoseStacker");
|
||||
if (roseStackersEnabled) {
|
||||
log("Hooked into RoseStackers.");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if RoseStackers is enabled
|
||||
if ( !settings.getDisabledPluginHooks().contains("RoseStacker") ) {
|
||||
roseStackersEnabled = Bukkit.getPluginManager().isPluginEnabled("RoseStacker");
|
||||
if (roseStackersEnabled) {
|
||||
log("Hooked into RoseStackers.");
|
||||
}
|
||||
}
|
||||
// Check if UltimateStacker is enabled
|
||||
if (!settings.getDisabledPluginHooks().contains("UltimateStacker")) {
|
||||
ultimateStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("UltimateStacker");
|
||||
if (ultimateStackerEnabled) {
|
||||
log("Hooked into UltimateStacker.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if UltimateStacker is enabled
|
||||
if ( !settings.getDisabledPluginHooks().contains("UltimateStacker") ) {
|
||||
ultimateStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("UltimateStacker");
|
||||
if (ultimateStackerEnabled) {
|
||||
log("Hooked into UltimateStacker.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void allLoaded() {
|
||||
super.allLoaded();
|
||||
|
||||
@Override
|
||||
public void allLoaded()
|
||||
{
|
||||
super.allLoaded();
|
||||
if (this.isEnabled()) {
|
||||
this.hookExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isEnabled())
|
||||
{
|
||||
this.hookExtensions();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method tries to hook into addons and plugins
|
||||
*/
|
||||
private void hookExtensions() {
|
||||
// Try to find Visit addon and if it does not exist, display a warning
|
||||
this.getAddonByName("Visit").ifPresentOrElse(addon -> {
|
||||
this.visitHook = (VisitAddon) addon;
|
||||
this.log("Level Addon hooked into Visit addon.");
|
||||
}, () -> this.visitHook = null);
|
||||
|
||||
// Try to find Warps addon and if it does not exist, display a warning
|
||||
this.getAddonByName("Warps").ifPresentOrElse(addon -> {
|
||||
this.warpHook = (Warp) addon;
|
||||
this.log("Level Addon hooked into Warps addon.");
|
||||
}, () -> this.warpHook = null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tries to hook into addons and plugins
|
||||
*/
|
||||
private void hookExtensions()
|
||||
{
|
||||
// Try to find Visit addon and if it does not exist, display a warning
|
||||
this.getAddonByName("Visit").ifPresentOrElse(addon ->
|
||||
{
|
||||
this.visitHook = (VisitAddon) addon;
|
||||
this.log("Level Addon hooked into Visit addon.");
|
||||
}, () -> this.visitHook = null);
|
||||
/**
|
||||
* Compares versions
|
||||
*
|
||||
* @param version1 version 1
|
||||
* @param version2 version 2
|
||||
* @return {@code <0 if version 1 is older than version 2, =0 if the same, >0 if version 1 is newer than version 2}
|
||||
*/
|
||||
public static int compareVersions(String version1, String version2) {
|
||||
int comparisonResult = 0;
|
||||
|
||||
// Try to find Warps addon and if it does not exist, display a warning
|
||||
this.getAddonByName("Warps").ifPresentOrElse(addon ->
|
||||
{
|
||||
this.warpHook = (Warp) addon;
|
||||
this.log("Level Addon hooked into Warps addon.");
|
||||
}, () -> this.warpHook = null);
|
||||
}
|
||||
String[] version1Splits = version1.split("\\.");
|
||||
String[] version2Splits = version2.split("\\.");
|
||||
int maxLengthOfVersionSplits = Math.max(version1Splits.length, version2Splits.length);
|
||||
|
||||
for (int i = 0; i < maxLengthOfVersionSplits; i++) {
|
||||
Integer v1 = i < version1Splits.length ? Integer.parseInt(version1Splits[i]) : 0;
|
||||
Integer v2 = i < version2Splits.length ? Integer.parseInt(version2Splits[i]) : 0;
|
||||
int compare = v1.compareTo(v2);
|
||||
if (compare != 0) {
|
||||
comparisonResult = compare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return comparisonResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares versions
|
||||
* @param version1 version 1
|
||||
* @param version2 version 2
|
||||
* @return {@code <0 if version 1 is older than version 2, =0 if the same, >0 if version 1 is newer than version 2}
|
||||
*/
|
||||
public static int compareVersions(String version1, String version2) {
|
||||
int comparisonResult = 0;
|
||||
private void registerCommands(GameModeAddon gm) {
|
||||
gm.getAdminCommand().ifPresent(adminCommand -> {
|
||||
new AdminLevelCommand(this, adminCommand);
|
||||
new AdminTopCommand(this, adminCommand);
|
||||
new AdminLevelStatusCommand(this, adminCommand);
|
||||
if (getSettings().isZeroNewIslandLevels()) {
|
||||
new AdminSetInitialLevelCommand(this, adminCommand);
|
||||
}
|
||||
new AdminStatsCommand(this, adminCommand);
|
||||
});
|
||||
gm.getPlayerCommand().ifPresent(playerCmd -> {
|
||||
new IslandLevelCommand(this, playerCmd);
|
||||
new IslandTopCommand(this, playerCmd);
|
||||
new IslandValueCommand(this, playerCmd);
|
||||
});
|
||||
}
|
||||
|
||||
String[] version1Splits = version1.split("\\.");
|
||||
String[] version2Splits = version2.split("\\.");
|
||||
int maxLengthOfVersionSplits = Math.max(version1Splits.length, version2Splits.length);
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Stop the pipeline
|
||||
this.getPipeliner().stop();
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxLengthOfVersionSplits; i++){
|
||||
Integer v1 = i < version1Splits.length ? Integer.parseInt(version1Splits[i]) : 0;
|
||||
Integer v2 = i < version2Splits.length ? Integer.parseInt(version2Splits[i]) : 0;
|
||||
int compare = v1.compareTo(v2);
|
||||
if (compare != 0) {
|
||||
comparisonResult = compare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return comparisonResult;
|
||||
}
|
||||
private void loadBlockSettings() {
|
||||
// Save the default blockconfig.yml
|
||||
this.saveResource("blockconfig.yml", false);
|
||||
|
||||
private void registerCommands(GameModeAddon gm) {
|
||||
gm.getAdminCommand().ifPresent(adminCommand -> {
|
||||
new AdminLevelCommand(this, adminCommand);
|
||||
new AdminTopCommand(this, adminCommand);
|
||||
new AdminLevelStatusCommand(this, adminCommand);
|
||||
if (getSettings().isZeroNewIslandLevels()) {
|
||||
new AdminSetInitialLevelCommand(this, adminCommand);
|
||||
}
|
||||
});
|
||||
gm.getPlayerCommand().ifPresent(playerCmd -> {
|
||||
new IslandLevelCommand(this, playerCmd);
|
||||
new IslandTopCommand(this, playerCmd);
|
||||
new IslandValueCommand(this, playerCmd);
|
||||
});
|
||||
}
|
||||
YamlConfiguration blockValues = new YamlConfiguration();
|
||||
try {
|
||||
File file = new File(this.getDataFolder(), "blockconfig.yml");
|
||||
blockValues.load(file);
|
||||
// Load the block config class
|
||||
blockConfig = new BlockConfig(this, blockValues, file);
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
// Disable
|
||||
logError("Level blockconfig.yml settings could not load! Addon disabled.");
|
||||
setState(State.DISABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Stop the pipeline
|
||||
this.getPipeliner().stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBlockSettings() {
|
||||
// Save the default blockconfig.yml
|
||||
this.saveResource("blockconfig.yml", false);
|
||||
/**
|
||||
* @return the blockConfig
|
||||
*/
|
||||
public BlockConfig getBlockConfig() {
|
||||
return blockConfig;
|
||||
}
|
||||
|
||||
YamlConfiguration blockValues = new YamlConfiguration();
|
||||
try {
|
||||
File file = new File(this.getDataFolder(), "blockconfig.yml");
|
||||
blockValues.load(file);
|
||||
// Load the block config class
|
||||
blockConfig = new BlockConfig(this, blockValues, file);
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
// Disable
|
||||
logError("Level blockconfig.yml settings could not load! Addon disabled.");
|
||||
setState(State.DISABLED);
|
||||
}
|
||||
/**
|
||||
* @return the settings
|
||||
*/
|
||||
public ConfigSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @return the pipeliner
|
||||
*/
|
||||
public Pipeliner getPipeliner() {
|
||||
return pipeliner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the manager
|
||||
*/
|
||||
public LevelsManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the blockConfig
|
||||
*/
|
||||
public BlockConfig getBlockConfig() {
|
||||
return blockConfig;
|
||||
}
|
||||
/**
|
||||
* Set the config settings - used for tests only
|
||||
*
|
||||
* @param configSettings - config settings
|
||||
*/
|
||||
void setSettings(ConfigSettings configSettings) {
|
||||
this.settings = configSettings;
|
||||
|
||||
/**
|
||||
* @return the settings
|
||||
*/
|
||||
public ConfigSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pipeliner
|
||||
*/
|
||||
public Pipeliner getPipeliner() {
|
||||
return pipeliner;
|
||||
}
|
||||
/**
|
||||
* @return the stackersEnabled
|
||||
*/
|
||||
public boolean isStackersEnabled() {
|
||||
return stackersEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the manager
|
||||
*/
|
||||
public LevelsManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
/**
|
||||
* @return the advChestEnabled
|
||||
*/
|
||||
public boolean isAdvChestEnabled() {
|
||||
return advChestEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the config settings - used for tests only
|
||||
* @param configSettings - config settings
|
||||
*/
|
||||
void setSettings(ConfigSettings configSettings) {
|
||||
this.settings = configSettings;
|
||||
/**
|
||||
* Get level from cache for a player.
|
||||
*
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Level of player or zero if player is unknown or UUID is null
|
||||
*/
|
||||
public long getIslandLevel(World world, @Nullable UUID targetPlayer) {
|
||||
return getManager().getIslandLevel(world, targetPlayer);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Sets the player's level to a value
|
||||
*
|
||||
* @param world - world
|
||||
* @param targetPlayer - target player
|
||||
* @param level - level
|
||||
*/
|
||||
public void setIslandLevel(World world, UUID targetPlayer, long level) {
|
||||
getManager().setIslandLevel(world, targetPlayer, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the stackersEnabled
|
||||
*/
|
||||
public boolean isStackersEnabled() {
|
||||
return stackersEnabled;
|
||||
}
|
||||
/**
|
||||
* Zeros the initial island level
|
||||
*
|
||||
* @param island - island
|
||||
* @param level - initial calculated island level
|
||||
*/
|
||||
public void setInitialIslandLevel(@NonNull Island island, long level) {
|
||||
getManager().setInitialIslandLevel(island, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the advChestEnabled
|
||||
*/
|
||||
public boolean isAdvChestEnabled() {
|
||||
return advChestEnabled;
|
||||
}
|
||||
/**
|
||||
* Get the initial island level
|
||||
*
|
||||
* @param island - island
|
||||
* @return level or 0 by default
|
||||
*/
|
||||
public long getInitialIslandLevel(@NonNull Island island) {
|
||||
return getManager().getInitialLevel(island);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get level from cache for a player.
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Level of player or zero if player is unknown or UUID is null
|
||||
*/
|
||||
public long getIslandLevel(World world, @Nullable UUID targetPlayer) {
|
||||
return getManager().getIslandLevel(world, targetPlayer);
|
||||
}
|
||||
/**
|
||||
* Calculates a user's island
|
||||
*
|
||||
* @param world - the world where this island is
|
||||
* @param user - not used! See depecration message
|
||||
* @param playerUUID - the target island member's UUID
|
||||
* @deprecated Do not use this anymore. Use
|
||||
* getManager().calculateLevel(playerUUID, island)
|
||||
*/
|
||||
@Deprecated(since = "2.3.0", forRemoval = true)
|
||||
public void calculateIslandLevel(World world, @Nullable User user, @NonNull UUID playerUUID) {
|
||||
Island island = getIslands().getIsland(world, playerUUID);
|
||||
if (island != null)
|
||||
getManager().calculateLevel(playerUUID, island);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's level to a value
|
||||
* @param world - world
|
||||
* @param targetPlayer - target player
|
||||
* @param level - level
|
||||
*/
|
||||
public void setIslandLevel(World world, UUID targetPlayer, long level) {
|
||||
getManager().setIslandLevel(world, targetPlayer, level);
|
||||
}
|
||||
/**
|
||||
* Provide the levels data for the target player
|
||||
*
|
||||
* @param targetPlayer - UUID of target player
|
||||
* @return LevelsData object or null if not found. Only island levels are set!
|
||||
* @deprecated Do not use this anymore. Use {@link #getIslandLevel(World, UUID)}
|
||||
*/
|
||||
@Deprecated(since = "2.3.0", forRemoval = true)
|
||||
public LevelsData getLevelsData(UUID targetPlayer) {
|
||||
LevelsData ld = new LevelsData(targetPlayer);
|
||||
getPlugin().getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName())).forEach(gm -> {
|
||||
if (getSettings().isZeroNewIslandLevels()) {
|
||||
Island island = getIslands().getIsland(gm.getOverWorld(), targetPlayer);
|
||||
if (island != null) {
|
||||
ld.setInitialLevel(gm.getOverWorld(), this.getInitialIslandLevel(island));
|
||||
}
|
||||
}
|
||||
ld.setLevel(gm.getOverWorld(), this.getIslandLevel(gm.getOverWorld(), targetPlayer));
|
||||
});
|
||||
return ld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeros the initial island level
|
||||
* @param island - island
|
||||
* @param level - initial calculated island level
|
||||
*/
|
||||
public void setInitialIslandLevel(@NonNull Island island, long level) {
|
||||
getManager().setInitialIslandLevel(island, level);
|
||||
}
|
||||
/**
|
||||
* @return the registeredGameModes
|
||||
*/
|
||||
public List<GameModeAddon> getRegisteredGameModes() {
|
||||
return registeredGameModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the initial island level
|
||||
* @param island - island
|
||||
* @return level or 0 by default
|
||||
*/
|
||||
public long getInitialIslandLevel(@NonNull Island island) {
|
||||
return getManager().getInitialLevel(island);
|
||||
}
|
||||
/**
|
||||
* Check if Level addon is active in game mode
|
||||
*
|
||||
* @param gm Game Mode Addon
|
||||
* @return true if active, false if not
|
||||
*/
|
||||
public boolean isRegisteredGameMode(GameModeAddon gm) {
|
||||
return registeredGameModes.contains(gm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a user's island
|
||||
* @param world - the world where this island is
|
||||
* @param user - not used! See depecration message
|
||||
* @param playerUUID - the target island member's UUID
|
||||
* @deprecated Do not use this anymore. Use getManager().calculateLevel(playerUUID, island)
|
||||
*/
|
||||
@Deprecated(since="2.3.0", forRemoval=true)
|
||||
public void calculateIslandLevel(World world, @Nullable User user, @NonNull UUID playerUUID) {
|
||||
Island island = getIslands().getIsland(world, playerUUID);
|
||||
if (island != null) getManager().calculateLevel(playerUUID, island);
|
||||
}
|
||||
/**
|
||||
* Checks if Level addon is active in world
|
||||
*
|
||||
* @param world world
|
||||
* @return true if active, false if not
|
||||
*/
|
||||
public boolean isRegisteredGameModeWorld(World world) {
|
||||
return registeredGameModes.stream().map(GameModeAddon::getOverWorld).anyMatch(w -> Util.sameWorld(world, w));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the levels data for the target player
|
||||
* @param targetPlayer - UUID of target player
|
||||
* @return LevelsData object or null if not found. Only island levels are set!
|
||||
* @deprecated Do not use this anymore. Use {@link #getIslandLevel(World, UUID)}
|
||||
*/
|
||||
@Deprecated(since="2.3.0", forRemoval=true)
|
||||
public LevelsData getLevelsData(UUID targetPlayer) {
|
||||
LevelsData ld = new LevelsData(targetPlayer);
|
||||
getPlugin().getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName()))
|
||||
.forEach(gm -> {
|
||||
if (getSettings().isZeroNewIslandLevels()) {
|
||||
Island island = getIslands().getIsland(gm.getOverWorld(), targetPlayer);
|
||||
if (island != null) {
|
||||
ld.setInitialLevel(gm.getOverWorld(), this.getInitialIslandLevel(island));
|
||||
}
|
||||
}
|
||||
ld.setLevel(gm.getOverWorld(), this.getIslandLevel(gm.getOverWorld(), targetPlayer));
|
||||
});
|
||||
return ld;
|
||||
}
|
||||
/**
|
||||
* @return the roseStackersEnabled
|
||||
*/
|
||||
public boolean isRoseStackersEnabled() {
|
||||
return roseStackersEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the registeredGameModes
|
||||
*/
|
||||
public List<GameModeAddon> getRegisteredGameModes() {
|
||||
return registeredGameModes;
|
||||
}
|
||||
/**
|
||||
* @return the ultimateStackerEnabled
|
||||
*/
|
||||
public boolean isUltimateStackerEnabled() {
|
||||
return ultimateStackerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Level addon is active in game mode
|
||||
* @param gm Game Mode Addon
|
||||
* @return true if active, false if not
|
||||
*/
|
||||
public boolean isRegisteredGameMode(GameModeAddon gm) {
|
||||
return registeredGameModes.contains(gm);
|
||||
}
|
||||
/**
|
||||
* Method Level#getVisitHook returns the visitHook of this object.
|
||||
*
|
||||
* @return {@code Visit} of this object, {@code null} otherwise.
|
||||
*/
|
||||
public VisitAddon getVisitHook() {
|
||||
return this.visitHook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Level addon is active in world
|
||||
* @param world world
|
||||
* @return true if active, false if not
|
||||
*/
|
||||
public boolean isRegisteredGameModeWorld(World world) {
|
||||
return registeredGameModes.stream().map(GameModeAddon::getOverWorld).anyMatch(w -> Util.sameWorld(world, w));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the roseStackersEnabled
|
||||
*/
|
||||
public boolean isRoseStackersEnabled() {
|
||||
return roseStackersEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ultimateStackerEnabled
|
||||
*/
|
||||
public boolean isUltimateStackerEnabled() {
|
||||
return ultimateStackerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method Level#getVisitHook returns the visitHook of this object.
|
||||
*
|
||||
* @return {@code Visit} of this object, {@code null} otherwise.
|
||||
*/
|
||||
public VisitAddon getVisitHook()
|
||||
{
|
||||
return this.visitHook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method Level#getWarpHook returns the warpHook of this object.
|
||||
*
|
||||
* @return {@code Warp} of this object, {@code null} otherwise.
|
||||
*/
|
||||
public Warp getWarpHook()
|
||||
{
|
||||
return this.warpHook;
|
||||
}
|
||||
/**
|
||||
* Method Level#getWarpHook returns the warpHook of this object.
|
||||
*
|
||||
* @return {@code Warp} of this object, {@code null} otherwise.
|
||||
*/
|
||||
public Warp getWarpHook() {
|
||||
return this.warpHook;
|
||||
}
|
||||
}
|
||||
|
@ -31,417 +31,453 @@ import world.bentobox.level.objects.IslandLevels;
|
||||
import world.bentobox.level.objects.LevelsData;
|
||||
import world.bentobox.level.objects.TopTenData;
|
||||
|
||||
|
||||
public class LevelsManager {
|
||||
private static final String INTOPTEN = "intopten";
|
||||
private static final TreeMap<BigInteger, String> LEVELS;
|
||||
private static final BigInteger THOUSAND = BigInteger.valueOf(1000);
|
||||
static {
|
||||
LEVELS = new TreeMap<>();
|
||||
private static final String INTOPTEN = "intopten";
|
||||
private static final TreeMap<BigInteger, String> LEVELS;
|
||||
private static final BigInteger THOUSAND = BigInteger.valueOf(1000);
|
||||
static {
|
||||
LEVELS = new TreeMap<>();
|
||||
|
||||
LEVELS.put(THOUSAND, "k");
|
||||
LEVELS.put(THOUSAND.pow(2), "M");
|
||||
LEVELS.put(THOUSAND.pow(3), "G");
|
||||
LEVELS.put(THOUSAND.pow(4), "T");
|
||||
}
|
||||
private final Level addon;
|
||||
LEVELS.put(THOUSAND, "k");
|
||||
LEVELS.put(THOUSAND.pow(2), "M");
|
||||
LEVELS.put(THOUSAND.pow(3), "G");
|
||||
LEVELS.put(THOUSAND.pow(4), "T");
|
||||
}
|
||||
private final Level addon;
|
||||
|
||||
// Database handler for level data
|
||||
private final Database<IslandLevels> handler;
|
||||
// A cache of island levels.
|
||||
private final Map<String, IslandLevels> levelsCache;
|
||||
// Top ten lists
|
||||
private final Map<World,TopTenData> topTenLists;
|
||||
// Database handler for level data
|
||||
private final Database<IslandLevels> handler;
|
||||
// A cache of island levels.
|
||||
private final Map<String, IslandLevels> levelsCache;
|
||||
// Top ten lists
|
||||
private final Map<World, TopTenData> topTenLists;
|
||||
|
||||
public LevelsManager(Level addon) {
|
||||
this.addon = addon;
|
||||
// Get the BentoBox database
|
||||
// Set up the database handler to store and retrieve data
|
||||
// Note that these are saved by the BentoBox database
|
||||
handler = new Database<>(addon, IslandLevels.class);
|
||||
// Initialize the cache
|
||||
levelsCache = new HashMap<>();
|
||||
// Initialize top ten lists
|
||||
topTenLists = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public LevelsManager(Level addon) {
|
||||
this.addon = addon;
|
||||
// Get the BentoBox database
|
||||
// Set up the database handler to store and retrieve data
|
||||
// Note that these are saved by the BentoBox database
|
||||
handler = new Database<>(addon, IslandLevels.class);
|
||||
// Initialize the cache
|
||||
levelsCache = new HashMap<>();
|
||||
// Initialize top ten lists
|
||||
topTenLists = new ConcurrentHashMap<>();
|
||||
}
|
||||
public void migrate() {
|
||||
Database<LevelsData> oldDb = new Database<>(addon, LevelsData.class);
|
||||
oldDb.loadObjects().forEach(ld -> {
|
||||
try {
|
||||
UUID owner = UUID.fromString(ld.getUniqueId());
|
||||
// Step through each world
|
||||
ld.getLevels().keySet().stream()
|
||||
// World
|
||||
.map(Bukkit::getWorld).filter(Objects::nonNull)
|
||||
// Island
|
||||
.map(w -> addon.getIslands().getIsland(w, owner)).filter(Objects::nonNull).forEach(i -> {
|
||||
// Make new database entry
|
||||
World w = i.getWorld();
|
||||
IslandLevels il = new IslandLevels(i.getUniqueId());
|
||||
il.setInitialLevel(ld.getInitialLevel(w));
|
||||
il.setLevel(ld.getLevel(w));
|
||||
il.setMdCount(ld.getMdCount(w));
|
||||
il.setPointsToNextLevel(ld.getPointsToNextLevel(w));
|
||||
il.setUwCount(ld.getUwCount(w));
|
||||
// Save it
|
||||
handler.saveObjectAsync(il);
|
||||
});
|
||||
// Now delete the old database entry
|
||||
oldDb.deleteID(ld.getUniqueId());
|
||||
} catch (Exception e) {
|
||||
addon.logError("Could not migrate level data database! " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void migrate() {
|
||||
Database<LevelsData> oldDb = new Database<>(addon, LevelsData.class);
|
||||
oldDb.loadObjects().forEach(ld -> {
|
||||
try {
|
||||
UUID owner = UUID.fromString(ld.getUniqueId());
|
||||
// Step through each world
|
||||
ld.getLevels().keySet().stream()
|
||||
// World
|
||||
.map(Bukkit::getWorld).filter(Objects::nonNull)
|
||||
// Island
|
||||
.map(w -> addon.getIslands().getIsland(w, owner)).filter(Objects::nonNull)
|
||||
.forEach(i -> {
|
||||
// Make new database entry
|
||||
World w = i.getWorld();
|
||||
IslandLevels il = new IslandLevels(i.getUniqueId());
|
||||
il.setInitialLevel(ld.getInitialLevel(w));
|
||||
il.setLevel(ld.getLevel(w));
|
||||
il.setMdCount(ld.getMdCount(w));
|
||||
il.setPointsToNextLevel(ld.getPointsToNextLevel(w));
|
||||
il.setUwCount(ld.getUwCount(w));
|
||||
// Save it
|
||||
handler.saveObjectAsync(il);
|
||||
});
|
||||
// Now delete the old database entry
|
||||
oldDb.deleteID(ld.getUniqueId());
|
||||
} catch (Exception e) {
|
||||
addon.logError("Could not migrate level data database! " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Add a score to the top players list
|
||||
*
|
||||
* @param world - world
|
||||
* @param targetPlayer - target player
|
||||
* @param lv - island level
|
||||
*/
|
||||
private void addToTopTen(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
|
||||
// Get top ten
|
||||
Map<UUID, Long> topTen = topTenLists.computeIfAbsent(world, k -> new TopTenData(world)).getTopTen();
|
||||
// Remove this player from the top list no matter what (we'll put them back
|
||||
// later if required)
|
||||
topTen.remove(targetPlayer);
|
||||
|
||||
/**
|
||||
* Add a score to the top players list
|
||||
* @param world - world
|
||||
* @param targetPlayer - target player
|
||||
* @param lv - island level
|
||||
*/
|
||||
private void addToTopTen(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
|
||||
// Get top ten
|
||||
Map<UUID, Long> topTen = topTenLists.computeIfAbsent(world, k -> new TopTenData(world)).getTopTen();
|
||||
// Remove this player from the top list no matter what (we'll put them back later if required)
|
||||
topTen.remove(targetPlayer);
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
if (island != null && island.getOwner() != null && hasTopTenPerm(world, island.getOwner())) {
|
||||
// Insert the owner into the top ten
|
||||
topTen.put(island.getOwner(), lv);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
if (island != null && island.getOwner() != null && hasTopTenPerm(world, island.getOwner())) {
|
||||
// Insert the owner into the top ten
|
||||
topTen.put(island.getOwner(), lv);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add an island to a top ten
|
||||
*
|
||||
* @param island - island to add
|
||||
* @param lv - level
|
||||
* @return true if successful, false if not added
|
||||
*/
|
||||
private boolean addToTopTen(Island island, long lv) {
|
||||
if (island != null && island.getOwner() != null && hasTopTenPerm(island.getWorld(), island.getOwner())) {
|
||||
topTenLists.computeIfAbsent(island.getWorld(), k -> new TopTenData(island.getWorld())).getTopTen()
|
||||
.put(island.getOwner(), lv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an island to a top ten
|
||||
* @param island - island to add
|
||||
* @param lv - level
|
||||
* @return true if successful, false if not added
|
||||
*/
|
||||
private boolean addToTopTen(Island island, long lv) {
|
||||
if (island != null && island.getOwner() != null && hasTopTenPerm(island.getWorld(), island.getOwner())) {
|
||||
topTenLists.computeIfAbsent(island.getWorld(), k -> new TopTenData(island.getWorld()))
|
||||
.getTopTen().put(island.getOwner(), lv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Calculate the island level, set all island member's levels to the result and
|
||||
* try to add the owner to the top ten
|
||||
*
|
||||
* @param targetPlayer - uuid of targeted player - owner or team member
|
||||
* @param island - island to calculate
|
||||
* @return completable future with the results of the calculation
|
||||
*/
|
||||
public CompletableFuture<Results> calculateLevel(UUID targetPlayer, Island island) {
|
||||
CompletableFuture<Results> result = new CompletableFuture<>();
|
||||
// Fire pre-level calc event
|
||||
IslandPreLevelEvent e = new IslandPreLevelEvent(targetPlayer, island);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled()) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
// Add island to the pipeline
|
||||
addon.getPipeliner().addIsland(island).thenAccept(r -> {
|
||||
// Results are irrelevant because the island is unowned or deleted, or
|
||||
// IslandLevelCalcEvent is cancelled
|
||||
if (r == null || fireIslandLevelCalcEvent(targetPlayer, island, r)) {
|
||||
result.complete(null);
|
||||
}
|
||||
// Save result
|
||||
setIslandResults(island.getWorld(), island.getOwner(), r);
|
||||
// Save the island scan details
|
||||
result.complete(r);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the island level, set all island member's levels to the result and try to add the owner to the top ten
|
||||
* @param targetPlayer - uuid of targeted player - owner or team member
|
||||
* @param island - island to calculate
|
||||
* @return completable future with the results of the calculation
|
||||
*/
|
||||
public CompletableFuture<Results> calculateLevel(UUID targetPlayer, Island island) {
|
||||
CompletableFuture<Results> result = new CompletableFuture<>();
|
||||
// Fire pre-level calc event
|
||||
IslandPreLevelEvent e = new IslandPreLevelEvent(targetPlayer, island);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled()) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
// Add island to the pipeline
|
||||
addon.getPipeliner().addIsland(island).thenAccept(r -> {
|
||||
// Results are irrelevant because the island is unowned or deleted, or IslandLevelCalcEvent is cancelled
|
||||
if (r == null || fireIslandLevelCalcEvent(targetPlayer, island, r)) {
|
||||
result.complete(null);
|
||||
}
|
||||
// Save result
|
||||
setIslandResults(island.getWorld(), island.getOwner(), r);
|
||||
// Save the island scan details
|
||||
result.complete(r);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Fires the IslandLevelCalculatedEvent and returns true if it is canceled
|
||||
*
|
||||
* @param targetPlayer - target player
|
||||
* @param island - island
|
||||
* @param results - results set
|
||||
* @return true if canceled
|
||||
*/
|
||||
private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Results results) {
|
||||
// Fire post calculation event
|
||||
IslandLevelCalculatedEvent ilce = new IslandLevelCalculatedEvent(targetPlayer, island, results);
|
||||
Bukkit.getPluginManager().callEvent(ilce);
|
||||
if (ilce.isCancelled())
|
||||
return true;
|
||||
// Set the values if they were altered
|
||||
results.setLevel((Long) ilce.getKeyValues().getOrDefault("level", results.getLevel()));
|
||||
results.setInitialLevel((Long) ilce.getKeyValues().getOrDefault("initialLevel", results.getInitialLevel()));
|
||||
results.setDeathHandicap((int) ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap()));
|
||||
results.setPointsToNextLevel(
|
||||
(Long) ilce.getKeyValues().getOrDefault("pointsToNextLevel", results.getPointsToNextLevel()));
|
||||
results.setTotalPoints((Long) ilce.getKeyValues().getOrDefault("totalPoints", results.getTotalPoints()));
|
||||
return ((Boolean) ilce.getKeyValues().getOrDefault("isCancelled", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires the IslandLevelCalculatedEvent and returns true if it is canceled
|
||||
* @param targetPlayer - target player
|
||||
* @param island - island
|
||||
* @param results - results set
|
||||
* @return true if canceled
|
||||
*/
|
||||
private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Results results) {
|
||||
// Fire post calculation event
|
||||
IslandLevelCalculatedEvent ilce = new IslandLevelCalculatedEvent(targetPlayer, island, results);
|
||||
Bukkit.getPluginManager().callEvent(ilce);
|
||||
if (ilce.isCancelled()) return true;
|
||||
// Set the values if they were altered
|
||||
results.setLevel((Long)ilce.getKeyValues().getOrDefault("level", results.getLevel()));
|
||||
results.setInitialLevel((Long)ilce.getKeyValues().getOrDefault("initialLevel", results.getInitialLevel()));
|
||||
results.setDeathHandicap((int)ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap()));
|
||||
results.setPointsToNextLevel((Long)ilce.getKeyValues().getOrDefault("pointsToNextLevel", results.getPointsToNextLevel()));
|
||||
results.setTotalPoints((Long)ilce.getKeyValues().getOrDefault("totalPoints", results.getTotalPoints()));
|
||||
return ((Boolean)ilce.getKeyValues().getOrDefault("isCancelled", false));
|
||||
}
|
||||
/**
|
||||
* Get the string representation of the level. May be converted to shorthand
|
||||
* notation, e.g., 104556 = 10.5k
|
||||
*
|
||||
* @param lvl - long value to represent
|
||||
* @return string of the level.
|
||||
*/
|
||||
public String formatLevel(@Nullable Long lvl) {
|
||||
if (lvl == null)
|
||||
return "";
|
||||
String level = String.valueOf(lvl);
|
||||
// Asking for the level of another player
|
||||
if (addon.getSettings().isShorthand()) {
|
||||
BigInteger levelValue = BigInteger.valueOf(lvl);
|
||||
|
||||
/**
|
||||
* Get the string representation of the level. May be converted to shorthand notation, e.g., 104556 = 10.5k
|
||||
* @param lvl - long value to represent
|
||||
* @return string of the level.
|
||||
*/
|
||||
public String formatLevel(@Nullable Long lvl) {
|
||||
if (lvl == null) return "";
|
||||
String level = String.valueOf(lvl);
|
||||
// Asking for the level of another player
|
||||
if(addon.getSettings().isShorthand()) {
|
||||
BigInteger levelValue = BigInteger.valueOf(lvl);
|
||||
Map.Entry<BigInteger, String> stage = LEVELS.floorEntry(levelValue);
|
||||
|
||||
Map.Entry<BigInteger, String> stage = LEVELS.floorEntry(levelValue);
|
||||
if (stage != null) { // level > 1000
|
||||
// 1 052 -> 1.0k
|
||||
// 1 527 314 -> 1.5M
|
||||
// 3 874 130 021 -> 3.8G
|
||||
// 4 002 317 889 -> 4.0T
|
||||
level = new DecimalFormat("#.#").format(
|
||||
levelValue.divide(stage.getKey().divide(THOUSAND)).doubleValue() / 1000.0) + stage.getValue();
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
if (stage != null) { // level > 1000
|
||||
// 1 052 -> 1.0k
|
||||
// 1 527 314 -> 1.5M
|
||||
// 3 874 130 021 -> 3.8G
|
||||
// 4 002 317 889 -> 4.0T
|
||||
level = new DecimalFormat("#.#").format(levelValue.divide(stage.getKey().divide(THOUSAND)).doubleValue()/1000.0) + stage.getValue();
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
/**
|
||||
* Get the initial level of the island. Used to zero island levels
|
||||
*
|
||||
* @param island - island
|
||||
* @return initial level of island
|
||||
*/
|
||||
public long getInitialLevel(Island island) {
|
||||
return getLevelsData(island).getInitialLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the initial level of the island. Used to zero island levels
|
||||
* @param island - island
|
||||
* @return initial level of island
|
||||
*/
|
||||
public long getInitialLevel(Island island) {
|
||||
return getLevelsData(island).getInitialLevel();
|
||||
}
|
||||
/**
|
||||
* Get level of island from cache for a player.
|
||||
*
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Level of the player's island or zero if player is unknown or UUID is
|
||||
* null
|
||||
*/
|
||||
public long getIslandLevel(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null)
|
||||
return 0L;
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? 0L : getLevelsData(island).getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get level of island from cache for a player.
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Level of the player's island or zero if player is unknown or UUID is null
|
||||
*/
|
||||
public long getIslandLevel(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null) return 0L;
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? 0L : getLevelsData(island).getLevel();
|
||||
}
|
||||
/**
|
||||
* Get the maximum level ever given to this island
|
||||
*
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Max level of the player's island or zero if player is unknown or UUID
|
||||
* is null
|
||||
*/
|
||||
public long getIslandMaxLevel(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null)
|
||||
return 0L;
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? 0L : getLevelsData(island).getMaxLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum level ever given to this island
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return Max level of the player's island or zero if player is unknown or UUID is null
|
||||
*/
|
||||
public long getIslandMaxLevel(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null) return 0L;
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? 0L : getLevelsData(island).getMaxLevel();
|
||||
}
|
||||
/**
|
||||
* Returns a formatted string of the target player's island level
|
||||
*
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player's UUID
|
||||
* @return Formatted level of player or zero if player is unknown or UUID is
|
||||
* null
|
||||
*/
|
||||
public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
return formatLevel(getIslandLevel(world, targetPlayer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted string of the target player's island level
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player's UUID
|
||||
* @return Formatted level of player or zero if player is unknown or UUID is null
|
||||
*/
|
||||
public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
return formatLevel(getIslandLevel(world, targetPlayer));
|
||||
}
|
||||
/**
|
||||
* Load a level data for the island from the cache or database.
|
||||
*
|
||||
* @param island - UUID of island
|
||||
* @return IslandLevels object
|
||||
*/
|
||||
@NonNull
|
||||
public IslandLevels getLevelsData(@NonNull Island island) {
|
||||
String id = island.getUniqueId();
|
||||
if (levelsCache.containsKey(id)) {
|
||||
return levelsCache.get(id);
|
||||
}
|
||||
// Get from database if not in cache
|
||||
if (handler.objectExists(id)) {
|
||||
IslandLevels ld = handler.loadObject(id);
|
||||
if (ld != null) {
|
||||
levelsCache.put(id, ld);
|
||||
} else {
|
||||
handler.deleteID(id);
|
||||
levelsCache.put(id, new IslandLevels(id));
|
||||
}
|
||||
} else {
|
||||
levelsCache.put(id, new IslandLevels(id));
|
||||
}
|
||||
// Return cached value
|
||||
return levelsCache.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a level data for the island from the cache or database.
|
||||
* @param island - UUID of island
|
||||
* @return IslandLevels object
|
||||
*/
|
||||
@NonNull
|
||||
public IslandLevels getLevelsData(@NonNull Island island) {
|
||||
String id = island.getUniqueId();
|
||||
if (levelsCache.containsKey(id)) {
|
||||
return levelsCache.get(id);
|
||||
}
|
||||
// Get from database if not in cache
|
||||
if (handler.objectExists(id)) {
|
||||
IslandLevels ld = handler.loadObject(id);
|
||||
if (ld != null) {
|
||||
levelsCache.put(id, ld);
|
||||
} else {
|
||||
handler.deleteID(id);
|
||||
levelsCache.put(id, new IslandLevels(id));
|
||||
}
|
||||
} else {
|
||||
levelsCache.put(id, new IslandLevels(id));
|
||||
}
|
||||
// Return cached value
|
||||
return levelsCache.get(id);
|
||||
}
|
||||
/**
|
||||
* Get the number of points required until the next level since the last level
|
||||
* calc
|
||||
*
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return string with the number required or blank if the player is unknown
|
||||
*/
|
||||
public String getPointsToNextString(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null)
|
||||
return "";
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of points required until the next level since the last level calc
|
||||
* @param world - world where the island is
|
||||
* @param targetPlayer - target player UUID
|
||||
* @return string with the number required or blank if the player is unknown
|
||||
*/
|
||||
public String getPointsToNextString(@NonNull World world, @Nullable UUID targetPlayer) {
|
||||
if (targetPlayer == null) return "";
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
|
||||
}
|
||||
/**
|
||||
* Get the top ten for this world. Returns offline players or players with the
|
||||
* intopten permission.
|
||||
*
|
||||
* @param world - world requested
|
||||
* @param size - size of the top ten
|
||||
* @return sorted top ten map
|
||||
*/
|
||||
@NonNull
|
||||
public Map<UUID, Long> getTopTen(@NonNull World world, int size) {
|
||||
createAndCleanRankings(world);
|
||||
// Return the sorted map
|
||||
return Collections.unmodifiableMap(topTenLists.get(world).getTopTen().entrySet().stream()
|
||||
.filter(e -> addon.getIslands().hasIsland(world, e.getKey())).filter(l -> l.getValue() > 0)
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(size)
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top ten for this world. Returns offline players or players with the intopten permission.
|
||||
* @param world - world requested
|
||||
* @param size - size of the top ten
|
||||
* @return sorted top ten map
|
||||
*/
|
||||
@NonNull
|
||||
public Map<UUID, Long> getTopTen(@NonNull World world, int size) {
|
||||
createAndCleanRankings(world);
|
||||
// Return the sorted map
|
||||
return Collections.unmodifiableMap(topTenLists.get(world).getTopTen().entrySet().stream()
|
||||
.filter(e -> addon.getIslands().isOwner(world, e.getKey()))
|
||||
.filter(l -> l.getValue() > 0)
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(size)
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)));
|
||||
}
|
||||
void createAndCleanRankings(@NonNull World world) {
|
||||
topTenLists.computeIfAbsent(world, TopTenData::new);
|
||||
// Remove player from top ten if they are online and do not have the perm
|
||||
topTenLists.get(world).getTopTen().keySet().removeIf(u -> !hasTopTenPerm(world, u));
|
||||
}
|
||||
|
||||
void createAndCleanRankings(@NonNull World world) {
|
||||
topTenLists.computeIfAbsent(world, TopTenData::new);
|
||||
// Remove player from top ten if they are online and do not have the perm
|
||||
topTenLists.get(world).getTopTen().keySet().removeIf(u -> !hasTopTenPerm(world, u));
|
||||
}
|
||||
/**
|
||||
* @return the topTenLists
|
||||
*/
|
||||
public Map<World, TopTenData> getTopTenLists() {
|
||||
return topTenLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the topTenLists
|
||||
*/
|
||||
protected Map<World, TopTenData> getTopTenLists() {
|
||||
return topTenLists;
|
||||
}
|
||||
/**
|
||||
* Get the rank of the player in the rankings
|
||||
*
|
||||
* @param world - world
|
||||
* @param uuid - player UUID
|
||||
* @return rank placing - note - placing of 1 means top ranked
|
||||
*/
|
||||
public int getRank(@NonNull World world, UUID uuid) {
|
||||
createAndCleanRankings(world);
|
||||
Stream<Entry<UUID, Long>> stream = topTenLists.get(world).getTopTen().entrySet().stream()
|
||||
.filter(e -> addon.getIslands().isOwner(world, e.getKey())).filter(l -> l.getValue() > 0)
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
|
||||
return (int) (stream.takeWhile(x -> !x.getKey().equals(uuid)).map(Map.Entry::getKey).count() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rank of the player in the rankings
|
||||
* @param world - world
|
||||
* @param uuid - player UUID
|
||||
* @return rank placing - note - placing of 1 means top ranked
|
||||
*/
|
||||
public int getRank(@NonNull World world, UUID uuid) {
|
||||
createAndCleanRankings(world);
|
||||
Stream<Entry<UUID, Long>> stream = topTenLists.get(world).getTopTen().entrySet().stream()
|
||||
.filter(e -> addon.getIslands().isOwner(world, e.getKey()))
|
||||
.filter(l -> l.getValue() > 0)
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
|
||||
return (int) (stream.takeWhile(x -> !x.getKey().equals(uuid)).map(Map.Entry::getKey).count() + 1);
|
||||
}
|
||||
/**
|
||||
* Checks if player has the correct top ten perm to have their level saved
|
||||
*
|
||||
* @param world
|
||||
* @param targetPlayer
|
||||
* @return true if player has the perm or the player is offline
|
||||
*/
|
||||
boolean hasTopTenPerm(@NonNull World world, @NonNull UUID targetPlayer) {
|
||||
String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world);
|
||||
return Bukkit.getPlayer(targetPlayer) == null
|
||||
|| Bukkit.getPlayer(targetPlayer).hasPermission(permPrefix + INTOPTEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if player has the correct top ten perm to have their level saved
|
||||
* @param world
|
||||
* @param targetPlayer
|
||||
* @return true if player has the perm or the player is offline
|
||||
*/
|
||||
boolean hasTopTenPerm(@NonNull World world, @NonNull UUID targetPlayer) {
|
||||
String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world);
|
||||
return Bukkit.getPlayer(targetPlayer) == null || Bukkit.getPlayer(targetPlayer).hasPermission(permPrefix + INTOPTEN);
|
||||
}
|
||||
/**
|
||||
* Loads all the top tens from the database
|
||||
*/
|
||||
public void loadTopTens() {
|
||||
topTenLists.clear();
|
||||
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
|
||||
addon.log("Generating rankings");
|
||||
handler.loadObjects().forEach(il -> {
|
||||
if (il.getLevel() > 0) {
|
||||
addon.getIslands().getIslandById(il.getUniqueId())
|
||||
.ifPresent(i -> this.addToTopTen(i, il.getLevel()));
|
||||
}
|
||||
});
|
||||
topTenLists.keySet().forEach(w -> addon.log("Generated rankings for " + w.getName()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the top tens from the database
|
||||
*/
|
||||
public void loadTopTens() {
|
||||
topTenLists.clear();
|
||||
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
|
||||
addon.log("Generating rankings");
|
||||
handler.loadObjects().forEach(il -> {
|
||||
if (il.getLevel() > 0) {
|
||||
addon.getIslands().getIslandById(il.getUniqueId()).ifPresent(i -> this.addToTopTen(i, il.getLevel()));
|
||||
}
|
||||
});
|
||||
topTenLists.keySet().forEach(w -> addon.log("Generated rankings for " + w.getName()));
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Removes a player from a world's top ten and removes world from player's level
|
||||
* data
|
||||
*
|
||||
* @param world - world
|
||||
* @param uuid - the player's uuid
|
||||
*/
|
||||
public void removeEntry(World world, UUID uuid) {
|
||||
if (topTenLists.containsKey(world)) {
|
||||
topTenLists.get(world).getTopTen().remove(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a player from a world's top ten and removes world from player's level data
|
||||
* @param world - world
|
||||
* @param uuid - the player's uuid
|
||||
*/
|
||||
public void removeEntry(World world, UUID uuid) {
|
||||
if (topTenLists.containsKey(world)) {
|
||||
topTenLists.get(world).getTopTen().remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Set an initial island level
|
||||
*
|
||||
* @param island - the island to set. Must have a non-null world
|
||||
* @param lv - initial island level
|
||||
*/
|
||||
public void setInitialIslandLevel(@NonNull Island island, long lv) {
|
||||
if (island.getWorld() == null)
|
||||
return;
|
||||
levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv);
|
||||
handler.saveObjectAsync(levelsCache.get(island.getUniqueId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an initial island level
|
||||
* @param island - the island to set. Must have a non-null world
|
||||
* @param lv - initial island level
|
||||
*/
|
||||
public void setInitialIslandLevel(@NonNull Island island, long lv) {
|
||||
if (island.getWorld() == null) return;
|
||||
levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv);
|
||||
handler.saveObjectAsync(levelsCache.get(island.getUniqueId()));
|
||||
}
|
||||
/**
|
||||
* Set the island level for the owner of the island that targetPlayer is a
|
||||
* member
|
||||
*
|
||||
* @param world - world
|
||||
* @param targetPlayer - player, may be a team member
|
||||
* @param lv - level
|
||||
*/
|
||||
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
if (island != null) {
|
||||
String id = island.getUniqueId();
|
||||
IslandLevels il = levelsCache.computeIfAbsent(id, IslandLevels::new);
|
||||
// Remove the initial level
|
||||
if (addon.getSettings().isZeroNewIslandLevels()) {
|
||||
il.setLevel(lv - il.getInitialLevel());
|
||||
} else {
|
||||
il.setLevel(lv);
|
||||
}
|
||||
handler.saveObjectAsync(levelsCache.get(id));
|
||||
// Update TopTen
|
||||
addToTopTen(world, targetPlayer, levelsCache.get(id).getLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the island level for the owner of the island that targetPlayer is a member
|
||||
* @param world - world
|
||||
* @param targetPlayer - player, may be a team member
|
||||
* @param lv - level
|
||||
*/
|
||||
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, targetPlayer);
|
||||
if (island != null) {
|
||||
String id = island.getUniqueId();
|
||||
IslandLevels il = levelsCache.computeIfAbsent(id, IslandLevels::new);
|
||||
// Remove the initial level
|
||||
if (addon.getSettings().isZeroNewIslandLevels()) {
|
||||
il.setLevel(lv - il.getInitialLevel());
|
||||
} else {
|
||||
il.setLevel(lv);
|
||||
}
|
||||
handler.saveObjectAsync(levelsCache.get(id));
|
||||
// Update TopTen
|
||||
addToTopTen(world, targetPlayer, levelsCache.get(id).getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Set the island level for the owner of the island that targetPlayer is a
|
||||
* member
|
||||
*
|
||||
* @param world - world
|
||||
* @param owner - owner of the island
|
||||
* @param r - results of the calculation
|
||||
*/
|
||||
private void setIslandResults(World world, @NonNull UUID owner, Results r) {
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, owner);
|
||||
if (island == null)
|
||||
return;
|
||||
IslandLevels ld = levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new);
|
||||
ld.setLevel(r.getLevel());
|
||||
ld.setUwCount(Maps.asMap(r.getUwCount().elementSet(), elem -> r.getUwCount().count(elem)));
|
||||
ld.setMdCount(Maps.asMap(r.getMdCount().elementSet(), elem -> r.getMdCount().count(elem)));
|
||||
ld.setPointsToNextLevel(r.getPointsToNextLevel());
|
||||
ld.setTotalPoints(r.getTotalPoints());
|
||||
levelsCache.put(island.getUniqueId(), ld);
|
||||
handler.saveObjectAsync(ld);
|
||||
// Update TopTen
|
||||
addToTopTen(world, owner, ld.getLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the island level for the owner of the island that targetPlayer is a member
|
||||
* @param world - world
|
||||
* @param owner - owner of the island
|
||||
* @param r - results of the calculation
|
||||
*/
|
||||
private void setIslandResults(World world, @NonNull UUID owner, Results r) {
|
||||
// Get the island
|
||||
Island island = addon.getIslands().getIsland(world, owner);
|
||||
if (island == null) return;
|
||||
IslandLevels ld = levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new);
|
||||
ld.setLevel(r.getLevel());
|
||||
ld.setUwCount(Maps.asMap(r.getUwCount().elementSet(), elem -> r.getUwCount().count(elem)));
|
||||
ld.setMdCount(Maps.asMap(r.getMdCount().elementSet(), elem -> r.getMdCount().count(elem)));
|
||||
ld.setPointsToNextLevel(r.getPointsToNextLevel());
|
||||
ld.setTotalPoints(r.getTotalPoints());
|
||||
levelsCache.put(island.getUniqueId(), ld);
|
||||
handler.saveObjectAsync(ld);
|
||||
// Update TopTen
|
||||
addToTopTen(world, owner, ld.getLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes island from cache when it is deleted
|
||||
* @param uniqueId - id of island
|
||||
*/
|
||||
public void deleteIsland(String uniqueId) {
|
||||
levelsCache.remove(uniqueId);
|
||||
handler.deleteID(uniqueId);
|
||||
}
|
||||
/**
|
||||
* Removes island from cache when it is deleted
|
||||
*
|
||||
* @param uniqueId - id of island
|
||||
*/
|
||||
public void deleteIsland(String uniqueId) {
|
||||
levelsCache.remove(uniqueId);
|
||||
handler.deleteID(uniqueId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
package world.bentobox.level.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.level.Level;
|
||||
import world.bentobox.level.objects.TopTenData;
|
||||
|
||||
public class AdminStatsCommand extends CompositeCommand {
|
||||
|
||||
private final Level level;
|
||||
|
||||
public AdminStatsCommand(Level addon, CompositeCommand parent) {
|
||||
super(parent, "stats");
|
||||
this.level = addon;
|
||||
new AdminTopRemoveCommand(addon, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
this.setPermission("admin.stats");
|
||||
this.setOnlyPlayer(false);
|
||||
this.setDescription("admin.stats.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
user.sendMessage("admin.stats.title");
|
||||
for (Entry<World, TopTenData> en : level.getManager().getTopTenLists().entrySet()) {
|
||||
user.sendMessage("admin.stats.world", TextVariables.NAME,
|
||||
level.getPlugin().getIWM().getWorldName(en.getKey()));
|
||||
Map<UUID, Long> topTen = en.getValue().getTopTen();
|
||||
if (topTen.isEmpty()) {
|
||||
user.sendMessage("admin.stats.no-data");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculating basic statistics
|
||||
long sum = 0, max = Long.MIN_VALUE, min = Long.MAX_VALUE;
|
||||
Map<Long, Integer> levelFrequency = new HashMap<>();
|
||||
|
||||
for (Long level : topTen.values()) {
|
||||
sum += level;
|
||||
max = Math.max(max, level);
|
||||
min = Math.min(min, level);
|
||||
levelFrequency.merge(level, 1, Integer::sum);
|
||||
}
|
||||
|
||||
double average = sum / (double) topTen.size();
|
||||
List<Long> sortedLevels = topTen.values().stream().sorted().collect(Collectors.toList());
|
||||
long median = sortedLevels.get(sortedLevels.size() / 2);
|
||||
Long mode = Collections.max(levelFrequency.entrySet(), Map.Entry.comparingByValue()).getKey();
|
||||
|
||||
// Logging basic statistics
|
||||
user.sendMessage("admin.stats.average-level", TextVariables.NUMBER, String.valueOf(average));
|
||||
user.sendMessage("admin.stats.median-level", TextVariables.NUMBER, String.valueOf(median));
|
||||
user.sendMessage("admin.stats.mode-level", TextVariables.NUMBER, String.valueOf(mode));
|
||||
user.sendMessage("admin.stats.highest-level", TextVariables.NUMBER, String.valueOf(max));
|
||||
user.sendMessage("admin.stats.lowest-level", TextVariables.NUMBER, String.valueOf(min));
|
||||
|
||||
// Grouping data for distribution analysis
|
||||
Map<String, Integer> rangeMap = new TreeMap<>();
|
||||
for (Long level : topTen.values()) {
|
||||
String range = getRange(level);
|
||||
rangeMap.merge(range, 1, Integer::sum);
|
||||
}
|
||||
|
||||
// Logging distribution
|
||||
user.sendMessage("admin.stats.distribution");
|
||||
for (Map.Entry<String, Integer> entry : rangeMap.entrySet()) {
|
||||
user.sendMessage(
|
||||
entry.getKey() + ": " + entry.getValue() + " " + user.getTranslation("admin.stats.islands"));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getRange(long level) {
|
||||
long rangeStart = level / 100 * 100;
|
||||
long rangeEnd = rangeStart + 99;
|
||||
return rangeStart + "-" + rangeEnd;
|
||||
}
|
||||
}
|
@ -22,8 +22,18 @@ admin:
|
||||
remove:
|
||||
description: "remove player from Top Ten"
|
||||
parameters: "<player>"
|
||||
|
||||
|
||||
stats:
|
||||
description: "show stats on islands on this server"
|
||||
title: "Server Island Stats"
|
||||
world: "&a [name]"
|
||||
no-data: "&c No data to process."
|
||||
average-level: "Average Island Level: [number]"
|
||||
median-level: "Median Island Level: [number]"
|
||||
mode-level: "Mode Island Level: [number]"
|
||||
highest-level: "Highest Island Level: [number]"
|
||||
lowest-level: "Lowest Island Level: [number]"
|
||||
distribution: "Island Level Distribution:"
|
||||
islands: "islands"
|
||||
island:
|
||||
level:
|
||||
parameters: "[player]"
|
||||
|
Loading…
Reference in New Issue
Block a user