Finished version (for now).

Adds top ten and integration with welcome warps addon.
This commit is contained in:
Tastybento 2018-02-19 13:06:58 -08:00
parent 01d2bba4c5
commit ab39dd4ac5
8 changed files with 345 additions and 255 deletions

View File

@ -13,14 +13,17 @@ admin:
island: island:
level: level:
parameters: "[player]" parameters: "[player]"
description: "calculate your island level or show the level of [player]" description: "calculate your island level or show the level of [player]"
island-level-is: "Island level is [level]" calculating: "&aCalculating level..."
required-points-to-next-level: "[points] points required until the next level" island-level-is: "&aIsland level is &b[level]"
deaths: "([number] deaths)" required-points-to-next-level: "&a[points] points required until the next level"
deaths: "&c([number] deaths)"
cooldown: "&cYou must wait &b[time] &cseconds until you can do that again"
top: top:
description: "show the Top Ten" description: "show the Top Ten"
gui-title: "Top Ten" gui-title: "&aTop Ten"
gui-heading: "[name]:[rank]" gui-heading: "&6[name]: &B[rank]"
island-level: "Level [level]" island-level: "&BLevel [level]"
warp-to: "&AWarping to [name]'s island"

17
pom.xml
View File

@ -43,14 +43,18 @@
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId> <artifactId>bukkit</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>us.tastybento</groupId> <groupId>us.tastybento</groupId>
<artifactId>bskyblock</artifactId> <artifactId>bskyblock</artifactId>
<version>LATEST</version> <version>alpha-0.0.1</version>
</dependency> </dependency>
<dependency>
<groupId>bskyblock.addon</groupId>
<artifactId>WelcomeWarpSigns</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>
@ -59,4 +63,13 @@
</repository> </repository>
</repositories> </repositories>
<groupId>bskyblock.addon</groupId> <groupId>bskyblock.addon</groupId>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project> </project>

View File

@ -4,18 +4,16 @@ import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import org.bukkit.scheduler.BukkitTask;
import bskyblock.addon.level.commands.AdminLevel; import bskyblock.addon.level.commands.AdminLevel;
import bskyblock.addon.level.commands.AdminTop; import bskyblock.addon.level.commands.AdminTop;
import bskyblock.addon.level.commands.IslandLevel; import bskyblock.addon.level.commands.IslandLevel;
import bskyblock.addon.level.commands.IslandTop; import bskyblock.addon.level.commands.IslandTop;
import bskyblock.addon.level.config.Settings; import bskyblock.addon.level.config.Settings;
import bskyblock.addon.level.database.object.LevelsData; import bskyblock.addon.level.database.object.LevelsData;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.addons.Addon; import us.tastybento.bskyblock.api.addons.Addon;
import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.commands.CompositeCommand;
@ -24,22 +22,15 @@ import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler;
/** /**
* Addin to BSkyBlock that enables island level scoring and top ten functionality * Addon to BSkyBlock that enables island level scoring and top ten functionality
* @author tastybento * @author tastybento
* *
*/ */
public class Level extends Addon { public class Level extends Addon {
// The BSkyBlock plugin instance.
private BSkyBlock bSkyBlock;
// Settings // Settings
private Settings settings; private Settings settings;
// Level calc checker
BukkitTask checker = null;
// Database handler for level data // Database handler for level data
private AbstractDatabaseHandler<LevelsData> handler; private AbstractDatabaseHandler<LevelsData> handler;
@ -49,7 +40,7 @@ public class Level extends Addon {
// A cache of island levels. Island levels are not kept in memory unless required. // A cache of island levels. Island levels are not kept in memory unless required.
// The cache is saved when the server shuts down and the plugin is disabled. // The cache is saved when the server shuts down and the plugin is disabled.
// TODO: Save regularly to avoid crash issues. // TODO: Save regularly to avoid crash issues.
private HashMap<UUID, Long> levelsCache; private Map<UUID, Long> levelsCache;
// The Top Ten object // The Top Ten object
private TopTen topTen; private TopTen topTen;
@ -57,18 +48,87 @@ public class Level extends Addon {
// Level calculator // Level calculator
private LevelPresenter levelCalc; private LevelPresenter levelCalc;
/**
* Calculates a user's island
* @param user
* @param playerUUID - the player's UUID
* @param b
*/
public void calculateIslandLevel(User user, UUID playerUUID, boolean b) {
levelCalc.calculateIslandLevel(user, playerUUID, b);
}
public AbstractDatabaseHandler<LevelsData> getHandler() {
return handler;
}
/**
* Get level from cache for a player
* @param targetPlayer
* @return Level of player
*/
public long getIslandLevel(UUID targetPlayer) {
if (levelsCache.containsKey(targetPlayer)) {
return levelsCache.get(targetPlayer);
}
// Get from database
LevelsData level;
try {
level = handler.loadObject(targetPlayer.toString());
if (level == null) {
// We do not know this player, set to zero
return 0;
}
levelsCache.put(targetPlayer, level.getLevel());
return level.getLevel();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException
| ClassNotFoundException | IntrospectionException | SQLException e) {
getLogger().severe("Could not load player's level! " + e.getMessage());
}
return 0;
}
/**
* @return the settings
*/
public final Settings getSettings() {
return settings;
}
public TopTen getTopTen() {
return topTen;
}
private void load() {
try {
for (LevelsData level : handler.loadObjects()) {
levelsCache.put(UUID.fromString(level.getUniqueId()), level.getLevel());
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException
| ClassNotFoundException | IntrospectionException | SQLException e) {
getLogger().severe("Could not load levels cache data! " + e.getMessage());
}
}
@Override
public void onDisable(){
// Save the cache
if (levelsCache != null) {
save(false);
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void onEnable() { public void onEnable() {
// Load the plugin's config
settings = new Settings(this);
// Get the BSkyBlock plugin. This will be available because this plugin depends on it in plugin.yml.
bSkyBlock = BSkyBlock.getInstance();
// Check if it is enabled - it might be loaded, but not enabled. // Check if it is enabled - it might be loaded, but not enabled.
if (!bSkyBlock.isEnabled()) { if (getBSkyBlock() == null || !getBSkyBlock().isEnabled()) {
getLogger().severe("BSkyBlock does not exist or is not enabled. Stopping.");
this.setEnabled(false); this.setEnabled(false);
return; return;
} }
// Load the plugin's config
settings = new Settings(this);
// Get the BSkyBlock database // Get the BSkyBlock database
database = BSBDatabase.getDatabase(); database = BSBDatabase.getDatabase();
// Set up the database handler to store and retrieve Island classes // Set up the database handler to store and retrieve Island classes
@ -83,45 +143,16 @@ public class Level extends Addon {
// Start the top ten and register it for clicks // Start the top ten and register it for clicks
topTen = new TopTen(this); topTen = new TopTen(this);
registerListener(topTen); registerListener(topTen);
// Local locales
//localeManager = new LocaleManager(this);
// Register commands // Register commands
CompositeCommand bsbIslandCmd = (CompositeCommand) BSkyBlock.getInstance().getCommandsManager().getCommand(Constants.ISLANDCOMMAND); CompositeCommand bsbIslandCmd = getBSkyBlock().getCommandsManager().getCommand(Constants.ISLANDCOMMAND);
new IslandLevel(this, bsbIslandCmd); new IslandLevel(this, bsbIslandCmd);
new IslandTop(this, bsbIslandCmd); new IslandTop(this, bsbIslandCmd);
CompositeCommand bsbAdminCmd = (CompositeCommand) BSkyBlock.getInstance().getCommandsManager().getCommand(Constants.ADMINCOMMAND); CompositeCommand bsbAdminCmd = getBSkyBlock().getCommandsManager().getCommand(Constants.ADMINCOMMAND);
new AdminLevel(this, bsbAdminCmd); new AdminLevel(this, bsbAdminCmd);
new AdminTop(this, bsbAdminCmd); new AdminTop(this, bsbAdminCmd);
// Done // Done
} }
@Override
public void onDisable(){
// Save the cache
if (levelsCache != null) {
save(false);
}
}
/**
* @return the settings
*/
public final Settings getSettings() {
return settings;
}
public void load() {
try {
for (LevelsData level : handler.loadObjects()) {
levelsCache.put(UUID.fromString(level.getUniqueId()), level.getLevel());
}
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| SecurityException | ClassNotFoundException | IntrospectionException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/** /**
* Save the levels to the database * Save the levels to the database
* @param async - if true, saving will be done async * @param async - if true, saving will be done async
@ -135,10 +166,9 @@ public class Level extends Addon {
lv.setUniqueId(en.getKey().toString()); lv.setUniqueId(en.getKey().toString());
handler.saveObject(lv); handler.saveObject(lv);
} }
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException } catch (IllegalAccessException | InvocationTargetException
| InstantiationException | NoSuchMethodException | IntrospectionException | SQLException e) { | InstantiationException | NoSuchMethodException | IntrospectionException | SQLException e) {
// TODO Auto-generated catch block getLogger().severe("Could not save levels async! " + e.getMessage());
e.printStackTrace();
} }
}; };
if(async){ if(async){
@ -149,55 +179,14 @@ public class Level extends Addon {
} }
/** /**
* Get level from cache for a player * Sets the player's level to a value
* @param targetPlayer
* @return Level of player
*/
public long getIslandLevel(UUID targetPlayer) {
//getLogger().info("DEBUG: getting island level for " + bSkyBlock.getPlayers().getName(targetPlayer));
if (levelsCache.containsKey(targetPlayer)) {
return levelsCache.get(targetPlayer);
}
// Get from database
LevelsData level;
try {
level = handler.loadObject(targetPlayer.toString());
if (level == null) {
// We do not know this player, set to zero
return 0;
}
levelsCache.put(targetPlayer, level.getLevel());
return level.getLevel();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| SecurityException | ClassNotFoundException | IntrospectionException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
/**
* Save the player's level
* @param targetPlayer * @param targetPlayer
* @param level * @param level
*/ */
public void setIslandLevel(UUID targetPlayer, long level) { protected void setIslandLevel(UUID targetPlayer, long level) {
//getLogger().info("DEBUG: set island level to " + level + " for " + bSkyBlock.getPlayers().getName(targetPlayer));
// Add to cache // Add to cache
levelsCache.put(targetPlayer, level); levelsCache.put(targetPlayer, level);
topTen.addEntry(targetPlayer, level); topTen.addEntry(targetPlayer, level);
} }
public AbstractDatabaseHandler<LevelsData> getHandler() {
return handler;
}
public TopTen getTopTen() {
return topTen;
}
public void calculateIslandLevel(User user, UUID playerUUID, boolean b) {
levelCalc.calculateIslandLevel(user, playerUUID, b);
}
} }

View File

@ -1,15 +1,21 @@
package bskyblock.addon.level; package bskyblock.addon.level;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.ChunkSnapshot; import org.bukkit.ChunkSnapshot;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.material.MaterialData; import org.bukkit.material.MaterialData;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import com.google.common.collect.HashMultiset; import com.google.common.collect.HashMultiset;
@ -17,15 +23,18 @@ import com.google.common.collect.Multiset;
import com.google.common.collect.Multiset.Entry; import com.google.common.collect.Multiset.Entry;
import com.google.common.collect.Multisets; import com.google.common.collect.Multisets;
import us.tastybento.bskyblock.BSkyBlock; import bskyblock.addon.level.event.IslandPostLevelEvent;
import bskyblock.addon.level.event.IslandPreLevelEvent;
import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.util.Pair; import us.tastybento.bskyblock.util.Pair;
public class Scanner {
private static final int MAX_CHUNKS = 50; public class LevelCalcByChunk {
private static final long SPEED = 5;
private static final int MAX_CHUNKS = 200;
private static final long SPEED = 1;
private boolean checking = true; private boolean checking = true;
private BukkitTask task; private BukkitTask task;
@ -33,18 +42,27 @@ public class Scanner {
private Set<Pair<Integer, Integer>> chunksToScan; private Set<Pair<Integer, Integer>> chunksToScan;
private Island island; private Island island;
private World world;
private User asker; private User asker;
private UUID targetPlayer;
private Results result; private Results result;
// Copy the limits hashmap // Copy the limits hashmap
HashMap<MaterialData, Integer> limitCount; HashMap<MaterialData, Integer> limitCount;
private boolean report;
private long oldLevel;
public Scanner(Level addon, Island island, User asker) { public LevelCalcByChunk(final Level addon, final Island island, final UUID targetPlayer, final User asker, final boolean report) {
this.addon = addon; this.addon = addon;
this.island = island; this.island = island;
this.world = island != null ? island.getCenter().getWorld() : null;
this.asker = asker; this.asker = asker;
this.targetPlayer = targetPlayer;
this.limitCount = new HashMap<>(addon.getSettings().getBlockLimits()); this.limitCount = new HashMap<>(addon.getSettings().getBlockLimits());
this.report = report;
this.oldLevel = addon.getIslandLevel(targetPlayer);
// Results go here // Results go here
result = new Results(); result = new Results();
@ -67,7 +85,13 @@ public class Scanner {
// Add chunk snapshots to the list // Add chunk snapshots to the list
while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) { while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) {
Pair<Integer, Integer> pair = it.next(); Pair<Integer, Integer> pair = it.next();
chunkSnapshot.add(island.getWorld().getChunkAt(pair.x, pair.z).getChunkSnapshot()); if (!world.isChunkLoaded(pair.x, pair.z)) {
world.loadChunk(pair.x, pair.z);
chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
world.unloadChunk(pair.x, pair.z);
} else {
chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
}
it.remove(); it.remove();
} }
// Move to next step // Move to next step
@ -77,10 +101,9 @@ public class Scanner {
}, 0L, SPEED); }, 0L, SPEED);
} }
private void checkChunksAsync(Set<ChunkSnapshot> chunkSnapshot) { private void checkChunksAsync(final Set<ChunkSnapshot> chunkSnapshot) {
// Run async task to scan chunks // Run async task to scan chunks
addon.getServer().getScheduler().runTaskAsynchronously(addon.getBSkyBlock(), () -> { addon.getServer().getScheduler().runTaskAsynchronously(addon.getBSkyBlock(), () -> {
for (ChunkSnapshot chunk: chunkSnapshot) { for (ChunkSnapshot chunk: chunkSnapshot) {
scanChunk(chunk); scanChunk(chunk);
} }
@ -94,16 +117,16 @@ public class Scanner {
private void scanChunk(ChunkSnapshot chunk) { private void scanChunk(ChunkSnapshot chunk) {
for (int x = 0; x< 16; x++) { for (int x = 0; x< 16; x++) {
// Check if the block coord is inside the protection zone and if not, don't count it // Check if the block coord is inside the protection zone and if not, don't count it
if (chunk.getX() * 16 + x < island.getMinProtectedX() || chunk.getX() * 16 + x >= island.getMinProtectedX() + (island.getProtectionRange() * 2)) { if (chunk.getX() * 16 + x < island.getMinProtectedX() || chunk.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionRange()) {
continue; continue;
} }
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
// Check if the block coord is inside the protection zone and if not, don't count it // Check if the block coord is inside the protection zone and if not, don't count it
if (chunk.getZ() * 16 + z < island.getMinProtectedZ() || chunk.getZ() * 16 + z >= island.getMinProtectedZ() + (island.getProtectionRange() * 2)) { if (chunk.getZ() * 16 + z < island.getMinProtectedZ() || chunk.getZ() * 16 + z >= island.getMinProtectedZ() + island.getProtectionRange()) {
continue; continue;
} }
for (int y = 0; y < island.getWorld().getMaxHeight(); y++) { for (int y = 0; y < island.getCenter().getWorld().getMaxHeight(); y++) {
Material blockType = chunk.getBlockType(x, y, z); Material blockType = chunk.getBlockType(x, y, z);
boolean belowSeaLevel = (addon.getSettings().getSeaHeight() > 0 && y<=addon.getSettings().getSeaHeight()) ? true : false; boolean belowSeaLevel = (addon.getSettings().getSeaHeight() > 0 && y<=addon.getSettings().getSeaHeight()) ? true : false;
// Air is free // Air is free
@ -172,11 +195,11 @@ public class Scanner {
* @return * @return
*/ */
private Set<Pair<Integer, Integer>> getChunksToScan(Island island) { private Set<Pair<Integer, Integer>> getChunksToScan(Island island) {
// Get the chunks coords
Set<Pair<Integer, Integer>> chunkSnapshot = new HashSet<>(); Set<Pair<Integer, Integer>> chunkSnapshot = new HashSet<>();
for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + (island.getProtectionRange() *2) + 16); x += 16) { for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + island.getProtectionRange() + 16); x += 16) {
for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + (island.getProtectionRange() * 2) + 16); z += 16) { for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + island.getProtectionRange() + 16); z += 16) {
chunkSnapshot.add(new Pair<>(x/16,z/16)); Pair<Integer, Integer> pair = new Pair<>(world.getBlockAt(x, 0, z).getChunk().getX(), world.getBlockAt(x, 0, z).getChunk().getZ());
chunkSnapshot.add(pair);
} }
} }
return chunkSnapshot; return chunkSnapshot;
@ -188,23 +211,109 @@ public class Scanner {
// Finalize calculations // Finalize calculations
result.rawBlockCount += (long)((double)result.underWaterBlockCount * addon.getSettings().getUnderWaterMultiplier()); result.rawBlockCount += (long)((double)result.underWaterBlockCount * addon.getSettings().getUnderWaterMultiplier());
// Set the death penalty // Set the death penalty
result.deathHandicap = BSkyBlock.getInstance().getPlayers().getDeaths(island.getOwner()) * addon.getSettings().getDeathPenalty(); result.deathHandicap = addon.getPlayers().getDeaths(island.getOwner());
// Set final score // Set final score
result.score = (result.rawBlockCount / addon.getSettings().getLevelCost()) - result.deathHandicap; result.score = (result.rawBlockCount / addon.getSettings().getLevelCost()) - result.deathHandicap - island.getLevelHandicap();
// Run any modifications // Run any modifications
// Save the value // Get the permission multiplier if it is available
addon.setIslandLevel(island.getOwner(), result.score); int levelMultiplier = 1;
Player player = addon.getServer().getPlayer(targetPlayer);
if (player != null) {
// Get permission multiplier
for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) {
if (perms.getPermission().startsWith(Constants.PERMPREFIX + "island.multiplier.")) {
String spl[] = perms.getPermission().split(Constants.PERMPREFIX + "island.multiplier.");
if (spl.length > 1) {
if (!NumberUtils.isDigits(spl[1])) {
addon.getLogger().severe("Player " + player.getName() + " has permission: " + perms.getPermission() + " <-- the last part MUST be a number! Ignoring...");
} else {
// Get the max value should there be more than one
levelMultiplier = Math.max(levelMultiplier, Integer.valueOf(spl[1]));
}
}
}
// Do some sanity checking
if (levelMultiplier < 1) {
levelMultiplier = 1;
}
}
}
// Calculate how many points are required to get to the next level
long pointsToNextLevel = (addon.getSettings().getLevelCost() * (result.score + 1 + island.getLevelHandicap())) - ((result.rawBlockCount * levelMultiplier) - (result.deathHandicap * addon.getSettings().getDeathPenalty()));
// Sometimes it will return 0, so calculate again to make sure it will display a good value
if(pointsToNextLevel == 0) pointsToNextLevel = (addon.getSettings().getLevelCost() * (result.score + 2 + island.getLevelHandicap()) - ((result.rawBlockCount * levelMultiplier) - (result.deathHandicap * addon.getSettings().getDeathPenalty())));
// All done. // All done.
// Tell the asker the result informPlayers(saveLevel(island, targetPlayer, pointsToNextLevel));
if (asker.isPlayer() && asker.isOnline()) {
asker.sendMessage("island.level.island-level-is", "[level]", String.valueOf(result.score)); }
} else {
// Console private void informPlayers(IslandPreLevelEvent event) {
sendConsoleReport(asker, island); // Fire the island post level calculation event
final IslandPostLevelEvent event3 = new IslandPostLevelEvent(targetPlayer, island, event.getLevel(), event.getPointsToNextLevel());
addon.getServer().getPluginManager().callEvent(event3);
if(event3.isCancelled() || asker == null) {
return;
}
// Tell the asker
asker.sendMessage("island.level.island-level-is", "[level]", String.valueOf(addon.getIslandLevel(targetPlayer)));
// Console
if (report) {
sendConsoleReport(asker);
}
// Check if player - if so show some more info
if (!(asker instanceof Player)) {
return;
}
// Player
if (addon.getSettings().getDeathPenalty() != 0) {
asker.sendMessage("island.level.deaths", "[number]", String.valueOf(result.deathHandicap));
}
// Send player how many points are required to reach next island level
if (event.getPointsToNextLevel() >= 0) {
asker.sendMessage("island.level.required-points-to-next-level", "[points]", String.valueOf(event.getPointsToNextLevel()));
}
// Tell other team members
if (addon.getIslandLevel(targetPlayer) != oldLevel) {
for (UUID member : island.getMemberSet()) {
if (!member.equals(asker.getUniqueId())) {
User.getInstance(member).sendMessage("island.level.island-level-is", "[level]", String.valueOf(addon.getIslandLevel(targetPlayer)));
}
}
} }
} }
private void sendConsoleReport(User asker, Island island) { private IslandPreLevelEvent saveLevel(Island island, UUID targetPlayer, long pointsToNextLevel) {
// Fire the pre-level event
final IslandPreLevelEvent event = new IslandPreLevelEvent(targetPlayer, island, result.score);
event.setPointsToNextLevel(pointsToNextLevel);
addon.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
// Save the value
addon.setIslandLevel(island.getOwner(), event.getLevel());
if (addon.getPlayers().inTeam(targetPlayer)) {
//plugin.getLogger().info("DEBUG: player is in team");
for (UUID member : addon.getIslands().getMembers(targetPlayer)) {
//plugin.getLogger().info("DEBUG: updating team member level too");
if (addon.getIslandLevel(member) != event.getLevel()) {
addon.setIslandLevel(member, event.getLevel());
}
}
if (addon.getPlayers().inTeam(targetPlayer)) {
UUID leader = addon.getIslands().getTeamLeader(targetPlayer);
if (leader != null) {
addon.getTopTen().addEntry(leader, event.getLevel());
}
} else {
addon.getTopTen().addEntry(targetPlayer, event.getLevel());
}
}
}
return event;
}
private void sendConsoleReport(User asker) {
List<String> reportLines = new ArrayList<>(); List<String> reportLines = new ArrayList<>();
// provide counts // provide counts
reportLines.add("Level Log for island at " + island.getCenter()); reportLines.add("Level Log for island at " + island.getCenter());
@ -220,58 +329,16 @@ public class Scanner {
if (!result.uwCount.isEmpty()) { if (!result.uwCount.isEmpty()) {
reportLines.add("Underwater block count (Multiplier = x" + addon.getSettings().getUnderWaterMultiplier() + ") value"); reportLines.add("Underwater block count (Multiplier = x" + addon.getSettings().getUnderWaterMultiplier() + ") value");
reportLines.add("Total number of underwater blocks = " + String.format("%,d",result.uwCount.size())); reportLines.add("Total number of underwater blocks = " + String.format("%,d",result.uwCount.size()));
Iterable<Multiset.Entry<MaterialData>> entriesSortedByCount = reportLines.addAll(sortedReport(total, result.uwCount));
Multisets.copyHighestCountFirst(result.uwCount).entrySet();
Iterator<Entry<MaterialData>> it = entriesSortedByCount.iterator();
while (it.hasNext()) {
Entry<MaterialData> en = it.next();
MaterialData type = en.getElement();
int value = 0;
if (addon.getSettings().getBlockValues().containsKey(type)) {
// Specific
value = addon.getSettings().getBlockValues().get(type);
} else if (addon.getSettings().getBlockValues().containsKey(new MaterialData(type.getItemType()))) {
// Generic
value = addon.getSettings().getBlockValues().get(new MaterialData(type.getItemType()));
}
if (value > 0) {
reportLines.add(type.toString() + ":"
+ String.format("%,d",en.getCount()) + " blocks x " + value + " = " + (value * en.getCount()));
total += (value * en.getCount());
}
}
reportLines.add("Subtotal = " + total);
reportLines.add("==================================");
} }
reportLines.add("Regular block count"); reportLines.add("Regular block count");
reportLines.add("Total number of blocks = " + String.format("%,d",result.mdCount.size())); reportLines.add("Total number of blocks = " + String.format("%,d",result.mdCount.size()));
Iterable<Multiset.Entry<MaterialData>> entriesSortedByCount = reportLines.addAll(sortedReport(total, result.mdCount));
result.mdCount.entrySet();
Iterator<Entry<MaterialData>> it = entriesSortedByCount.iterator();
while (it.hasNext()) {
Entry<MaterialData> en = it.next();
MaterialData type = en.getElement();
int value = 0;
if (addon.getSettings().getBlockValues().containsKey(type)) {
// Specific
value = addon.getSettings().getBlockValues().get(type);
} else if (addon.getSettings().getBlockValues().containsKey(new MaterialData(type.getItemType()))) {
// Generic
value = addon.getSettings().getBlockValues().get(new MaterialData(type.getItemType()));
}
if (value > 0) {
reportLines.add(type.toString() + ":"
+ String.format("%,d",en.getCount()) + " blocks x " + value + " = " + (value * en.getCount()));
total += (value * en.getCount());
}
}
reportLines.add("Total = " + total);
reportLines.add("==================================");
reportLines.add("Blocks not counted because they exceeded limits: " + String.format("%,d",result.ofCount.size())); reportLines.add("Blocks not counted because they exceeded limits: " + String.format("%,d",result.ofCount.size()));
//entriesSortedByCount = Multisets.copyHighestCountFirst(ofCount).entrySet(); //entriesSortedByCount = Multisets.copyHighestCountFirst(ofCount).entrySet();
entriesSortedByCount = result.ofCount.entrySet(); Iterable<Multiset.Entry<MaterialData>> entriesSortedByCount = result.ofCount.entrySet();
it = entriesSortedByCount.iterator(); Iterator<Entry<MaterialData>> it = entriesSortedByCount.iterator();
while (it.hasNext()) { while (it.hasNext()) {
Entry<MaterialData> type = it.next(); Entry<MaterialData> type = it.next();
Integer limit = addon.getSettings().getBlockLimits().get(type.getElement()); Integer limit = addon.getSettings().getBlockLimits().get(type.getElement());
@ -300,9 +367,35 @@ public class Scanner {
} }
} }
private Collection<String> sortedReport(int total, Multiset<MaterialData> materialDataCount) {
Collection<String> result = new ArrayList<>();
Iterable<Multiset.Entry<MaterialData>> entriesSortedByCount = Multisets.copyHighestCountFirst(materialDataCount).entrySet();
Iterator<Entry<MaterialData>> it = entriesSortedByCount.iterator();
while (it.hasNext()) {
Entry<MaterialData> en = it.next();
MaterialData type = en.getElement();
int value = 0;
if (addon.getSettings().getBlockValues().containsKey(type)) {
// Specific
value = addon.getSettings().getBlockValues().get(type);
} else if (addon.getSettings().getBlockValues().containsKey(new MaterialData(type.getItemType()))) {
// Generic
value = addon.getSettings().getBlockValues().get(new MaterialData(type.getItemType()));
}
if (value > 0) {
result.add(type.toString() + ":"
+ String.format("%,d",en.getCount()) + " blocks x " + value + " = " + (value * en.getCount()));
total += (value * en.getCount());
}
}
result.add("Subtotal = " + total);
result.add("==================================");
return result;
}
/** /**
* Results class * Results class
* @author ben
* *
*/ */
public class Results { public class Results {

View File

@ -4,8 +4,6 @@ import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.bukkit.ChatColor;
import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.commands.User;
@ -42,23 +40,24 @@ public class LevelPresenter extends LevelPlugin {
public boolean calculateIslandLevel(final User sender, final UUID targetPlayer, boolean report) { public boolean calculateIslandLevel(final User sender, final UUID targetPlayer, boolean report) {
// Check if sender has island // Check if sender has island
if (!bSkyBlock.getIslands().hasIsland(targetPlayer)) { if (!bSkyBlock.getIslands().hasIsland(targetPlayer)) {
sender.sendRawMessage("Target does not have an island"); sender.sendMessage("general.errors.player-has-no-island");
return false; return false;
} }
// Player asking for their own island calc // Player asking for their own island calc
if (!sender.isPlayer() || sender.getUniqueId().equals(targetPlayer) || sender.isOp() || sender.hasPermission(Constants.PERMPREFIX + "mod.info")) { if (!sender.isPlayer() || sender.getUniqueId().equals(targetPlayer) || sender.isOp() || sender.hasPermission(Constants.PERMPREFIX + "mod.info")) {
// Newer better system - uses chunks // Newer better system - uses chunks
if (!onLevelWaitTime(sender) || levelWait <= 0 || sender.isOp() || sender.hasPermission(Constants.PERMPREFIX + "mod.info")) { if (!onLevelWaitTime(sender) || levelWait <= 0 || sender.isOp() || sender.hasPermission(Constants.PERMPREFIX + "mod.info")) {
sender.sendRawMessage(ChatColor.GREEN + "Calculating level, please wait..."); sender.sendMessage("island.level.calculating");
setLevelWaitTime(sender); setLevelWaitTime(sender);
new Scanner(plugin, bSkyBlock.getIslands().getIsland(targetPlayer), sender); new LevelCalcByChunk(plugin, bSkyBlock.getIslands().getIsland(targetPlayer), targetPlayer, sender, report);
} else { } else {
sender.sendRawMessage( ChatColor.YELLOW + String.valueOf(getLevelWaitTime(sender))); // Cooldown
sender.sendMessage("island.level.cooldown", "[time]", String.valueOf(getLevelWaitTime(sender)));
} }
} else { } else {
// Asking for the level of another player // Asking for the level of another player
sender.sendMessage("island.islandLevelIs","[level]", String.valueOf(plugin.getIslandLevel(targetPlayer))); sender.sendMessage("island.level.island-level-is","[level]", String.valueOf(plugin.getIslandLevel(targetPlayer)));
} }
return true; return true;
} }

View File

@ -1,20 +1,3 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock 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.
*
* ASkyBlock 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 ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package bskyblock.addon.level; package bskyblock.addon.level;
import java.beans.IntrospectionException; import java.beans.IntrospectionException;
@ -25,27 +8,21 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import bskyblock.addin.warps.Warp;
import bskyblock.addon.level.database.object.LevelsData; import bskyblock.addon.level.database.object.LevelsData;
import bskyblock.addon.level.database.object.TopTenData; import bskyblock.addon.level.database.object.TopTenData;
import bskyblock.addon.level.event.TopTenClick;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.addons.Addon;
import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.api.panels.ClickType;
import us.tastybento.bskyblock.api.panels.PanelItem; import us.tastybento.bskyblock.api.panels.PanelItem;
import us.tastybento.bskyblock.api.panels.PanelItem.ClickHandler; import us.tastybento.bskyblock.api.panels.PanelItem.ClickHandler;
import us.tastybento.bskyblock.api.panels.builders.PanelBuilder; import us.tastybento.bskyblock.api.panels.builders.PanelBuilder;
@ -60,20 +37,17 @@ import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler;
* *
*/ */
public class TopTen implements Listener { public class TopTen implements Listener {
private Level plugin; private Level addon;
// Top ten list of players // Top ten list of players
private TopTenData topTenList; private TopTenData topTenList;
private final int GUISIZE = 27; // Must be a multiple of 9
private final int[] SLOTS = new int[] {4, 12, 14, 19, 20, 21, 22, 23, 24, 25}; private final int[] SLOTS = new int[] {4, 12, 14, 19, 20, 21, 22, 23, 24, 25};
private final boolean DEBUG = false; private final boolean DEBUG = false;
// Store this as a because it's the same for everyone and saves memory cleanup
private Inventory gui;
private BSBDatabase database; private BSBDatabase database;
private AbstractDatabaseHandler<TopTenData> handler; private AbstractDatabaseHandler<TopTenData> handler;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public TopTen(Level plugin) { public TopTen(Level addon) {
this.plugin = plugin; this.addon = addon;
// Set up database // Set up database
database = BSBDatabase.getDatabase(); database = BSBDatabase.getDatabase();
// Set up the database handler to store and retrieve the TopTenList class // Set up the database handler to store and retrieve the TopTenList class
@ -90,7 +64,7 @@ public class TopTen implements Listener {
*/ */
public void addEntry(UUID ownerUUID, long l) { public void addEntry(UUID ownerUUID, long l) {
// Try and see if the player is online // Try and see if the player is online
Player player = plugin.getServer().getPlayer(ownerUUID); Player player = addon.getServer().getPlayer(ownerUUID);
if (player != null) { if (player != null) {
// Online // Online
if (!player.hasPermission(Constants.PERMPREFIX + "intopten")) { if (!player.hasPermission(Constants.PERMPREFIX + "intopten")) {
@ -109,17 +83,17 @@ public class TopTen implements Listener {
*/ */
public void create() { public void create() {
// Obtain all the levels for each known player // Obtain all the levels for each known player
AbstractDatabaseHandler<LevelsData> levelHandler = plugin.getHandler(); AbstractDatabaseHandler<LevelsData> levelHandler = addon.getHandler();
try { try {
long index = 0; long index = 0;
for (LevelsData lv : levelHandler.loadObjects()) { for (LevelsData lv : levelHandler.loadObjects()) {
if (index++ % 1000 == 0) { if (index++ % 1000 == 0) {
plugin.getLogger().info("Processed " + index + " players for top ten"); addon.getLogger().info("Processed " + index + " players for top ten");
} }
// Convert to UUID // Convert to UUID
UUID playerUUID = UUID.fromString(lv.getUniqueId()); UUID playerUUID = UUID.fromString(lv.getUniqueId());
// Check if the player is an owner or team leader // Check if the player is an owner or team leader
if (BSkyBlock.getInstance().getIslands().isOwner(playerUUID)) { if (addon.getIslands().isOwner(playerUUID)) {
topTenList.addLevel(playerUUID, lv.getLevel()); topTenList.addLevel(playerUUID, lv.getLevel());
} }
} }
@ -132,7 +106,7 @@ public class TopTen implements Listener {
} }
/** /**
* Displays the Top Ten list if it exists in chat * Displays the Top Ten list
* *
* @param user * @param user
* - the requesting player * - the requesting player
@ -140,12 +114,12 @@ public class TopTen implements Listener {
*/ */
public boolean getGUI(final User user) { public boolean getGUI(final User user) {
if (DEBUG) if (DEBUG)
plugin.getLogger().info("DEBUG: GUI display"); addon.getLogger().info("DEBUG: GUI display");
// New GUI display (shown by default) // New GUI display (shown by default)
if (topTenList == null) create(); if (topTenList == null) create();
PanelBuilder panel = new PanelBuilder() PanelBuilder panel = new PanelBuilder()
.setName("island.top.guiTitle") .setName(user.getTranslation("island.top.gui-title"))
.setUser(user); .setUser(user);
int i = 1; int i = 1;
@ -154,9 +128,9 @@ public class TopTen implements Listener {
Map.Entry<UUID, Long> m = it.next(); Map.Entry<UUID, Long> m = it.next();
UUID topTenUUID = m.getKey(); UUID topTenUUID = m.getKey();
if (DEBUG) if (DEBUG)
plugin.getLogger().info("DEBUG: " + i + ": " + topTenUUID); addon.getLogger().info("DEBUG: " + i + ": " + topTenUUID);
// Remove from TopTen if the player is online and has the permission // Remove from TopTen if the player is online and has the permission
Player entry = plugin.getServer().getPlayer(topTenUUID); Player entry = addon.getServer().getPlayer(topTenUUID);
boolean show = true; boolean show = true;
if (entry != null) { if (entry != null) {
if (!entry.hasPermission(Constants.PERMPREFIX + "intopten")) { if (!entry.hasPermission(Constants.PERMPREFIX + "intopten")) {
@ -165,11 +139,11 @@ public class TopTen implements Listener {
} }
} else { } else {
if (DEBUG) if (DEBUG)
plugin.getLogger().info("DEBUG: player not online, so no per check"); addon.getLogger().info("DEBUG: player not online, so no per check");
} }
if (show) { if (show) {
panel.addItem(SLOTS[i-1], getSkulls(i, m.getValue(), topTenUUID, user)); panel.addItem(SLOTS[i-1], getHead(i, m.getValue(), topTenUUID, user));
if (i++ == 10) break; if (i++ == 10) break;
} }
} }
@ -177,36 +151,55 @@ public class TopTen implements Listener {
return true; return true;
} }
private PanelItem getSkulls(int rank, Long value, UUID topTenUUID, User user) { /**
final String name = BSkyBlock.getInstance().getPlayers().getName(topTenUUID); * Get the head panel item
ItemStack playerSkull = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); * @param rank - the top ten rank of this player/team. Can be used in the name of the island for vanity.
* @param level - the level of the island
* @param playerUUID - the UUID of the top ten player
* @param asker - the asker of the top ten
* @return PanelItem
*/
private PanelItem getHead(int rank, Long level, UUID playerUUID, User asker) {
final String name = addon.getPlayers().getName(playerUUID);
List<String> description = new ArrayList<>(); List<String> description = new ArrayList<>();
if (name != null) { if (name != null) {
SkullMeta meta = (SkullMeta) playerSkull.getItemMeta(); description.add(asker.getTranslation("island.top.gui-heading", "[name]", addon.getIslands().getIslandName(playerUUID), "[rank]", String.valueOf(rank)));
meta.setOwner(name); description.add(asker.getTranslation("island.top.island-level","[level]", String.valueOf(level)));
playerSkull.setItemMeta(meta); if (addon.getPlayers().inTeam(playerUUID)) {
description.add(user.getTranslation("island.top.guiHeading", "[name]", BSkyBlock.getInstance().getIslands().getIslandName(topTenUUID), "[rank]", String.valueOf(rank)));
description.add(user.getTranslation("island.top.islandLevel","[level]", String.valueOf(value)));
if (BSkyBlock.getInstance().getPlayers().inTeam(topTenUUID)) {
List<String> memberList = new ArrayList<>(); List<String> memberList = new ArrayList<>();
for (UUID members : BSkyBlock.getInstance().getIslands().getMembers(topTenUUID)) { for (UUID members : addon.getIslands().getMembers(playerUUID)) {
memberList.add(ChatColor.AQUA + BSkyBlock.getInstance().getPlayers().getName(members)); memberList.add(ChatColor.AQUA + addon.getPlayers().getName(members));
} }
description.addAll(memberList); description.addAll(memberList);
} }
} }
return new PanelItemBuilder() PanelItemBuilder builder = new PanelItemBuilder()
.icon(playerSkull) .icon(name)
.name(name) .name(name)
.description(description) .description(description);
.clickHandler(new ClickHandler() {
// If welcome warps is present then add warping
addon.getAddonByName("BSkyBlock-WelcomeWarps").ifPresent(warp -> {
if (((Warp)warp).getWarpSignsManager().hasWarp(playerUUID)) {
builder.clickHandler(new ClickHandler() {
@Override @Override
public boolean onClick(User user, us.tastybento.bskyblock.api.panels.ClickType click) { public boolean onClick(User user, ClickType click) {
user.sendRawMessage("Warp to " + name); if (click.equals(ClickType.LEFT)) {
return false; user.sendMessage("island.top.warp-to", "[name]", name);
}})
.build();
((Warp)warp).getWarpSignsManager().warpPlayer(user, playerUUID);
}
return true;
}
});
}
});
return builder.build();
} }
public TopTenData getTopTenList() { public TopTenData getTopTenList() {
@ -227,7 +220,7 @@ public class TopTen implements Listener {
e.printStackTrace(); e.printStackTrace();
} }
} }
/*
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
public void onInventoryClick(InventoryClickEvent event) { public void onInventoryClick(InventoryClickEvent event) {
@ -246,7 +239,7 @@ public class TopTen implements Listener {
player.closeInventory(); player.closeInventory();
// Fire click event // Fire click event
TopTenClick clickEvent = new TopTenClick(((SkullMeta)event.getCurrentItem().getItemMeta()).getOwningPlayer().getName()); TopTenClick clickEvent = new TopTenClick(((SkullMeta)event.getCurrentItem().getItemMeta()).getOwningPlayer().getName());
plugin.getServer().getPluginManager().callEvent(clickEvent); addon.getServer().getPluginManager().callEvent(clickEvent);
return; return;
} }
if (event.getSlotType().equals(SlotType.OUTSIDE)) { if (event.getSlotType().equals(SlotType.OUTSIDE)) {
@ -258,7 +251,7 @@ public class TopTen implements Listener {
return; return;
} }
} }
*/
/** /**
* Removes ownerUUID from the top ten list * Removes ownerUUID from the top ten list
* *

View File

@ -25,13 +25,13 @@ public class IslandLevel extends CompositeCommand {
final UUID playerUUID = getPlugin().getPlayers().getUUID(args.get(0)); final UUID playerUUID = getPlugin().getPlayers().getUUID(args.get(0));
//getLogger().info("DEBUG: console player info UUID = " + playerUUID); //getLogger().info("DEBUG: console player info UUID = " + playerUUID);
if (playerUUID == null) { if (playerUUID == null) {
user.sendMessage("error.UnknownPlayer"); user.sendMessage("general.errors.unknown-player");
return true; return true;
} else if (user.getUniqueId().equals(playerUUID) ) { } else if (user.getUniqueId().equals(playerUUID) ) {
// Self level request // Self level request
levelPlugin.calculateIslandLevel(user, user.getUniqueId(), false); levelPlugin.calculateIslandLevel(user, user.getUniqueId(), false);
} else { } else {
user.sendMessage("island.level.islandLevelIs", "[level]", String.valueOf(levelPlugin.getIslandLevel(playerUUID))); user.sendMessage("island.level.island-level-is", "[level]", String.valueOf(levelPlugin.getIslandLevel(playerUUID)));
return true; return true;
} }
} else { } else {

View File

@ -10,7 +10,7 @@ import bskyblock.addon.level.Level;
public class Settings { public class Settings {
private static final boolean DEBUG = true; private static final boolean DEBUG = false;
private boolean sumTeamDeaths; private boolean sumTeamDeaths;
private int seaHeight; private int seaHeight;
private HashMap<MaterialData, Integer> blockLimits = new HashMap<>(); private HashMap<MaterialData, Integer> blockLimits = new HashMap<>();