Fixed a lot of bugs

Changed events to be builder types.

Refactored island cache.

Fixed island deletion.

Made island distance chunk (16 blocks) based.
This commit is contained in:
Tastybento 2017-11-20 16:05:52 -08:00
parent d04d8b374b
commit 792d1f8ec3
42 changed files with 1794 additions and 1587 deletions

View File

@ -98,21 +98,16 @@ world:
# It acts like a prefix for nether and end (e.g. BSkyBlock, BSkyBlock_nether, BSkyBlock_end)
world-name: BSkyBlock_world
# Distance between islands in blocks IN CHUNKS (1 chunk = 16 blocks)
# Radius of island in blocks. (So distance between islands is twice this)
# Will be rounded up to the nearest 16 blocks.
# It is the same for every dimension : Overworld, Nether and End.
# Recommended values for a new world:
# 24 - puts players distance enough that they usually cannot see each other
# 12 - allows some expansion of the protected zone (recommended)
# 4 - minimum - not recommended
# IF YOU ARE UPGRADING YOU MUST USE YOUR OLD VALUE EXACTLY (E.G.: 24), OR RESET YOUR WORLD
distance-in-chunks: 24
# This value cannot be changed mid-game and the plugin will not start if it is different.
distance: 64
# Default protection range (even number). Min = 0, Recommended = 100
# Larger values will take longer to calculate the island level
# Admins can change protection sizes for players individually using /asadmin setrange
# or set this permission: askyblock.island.range.<number>
# For optimal performance, keep protection range at least 16 blocks less than distance.
protection-range: 100
# Default protection range radius in blocks. Cannot be larger than distance.
# Admins can change protection sizes for players individually using /bsadmin setrange
# or set this permission: bskyblock.island.range.<number>
protection-range: 50
# Start islands at these coordinates. This is where new islands will start in the
# world. These must be a factor of your island distance, but the plugin will auto

View File

@ -10,6 +10,8 @@
# This translation is adapted to version : [alpha-0.0.1]
general:
deaths: "Deaths"
unlimited: "Unlimited"
success: "Success!"
errors:
no-permission: "You don't have permission to execute this command."
@ -21,6 +23,7 @@ general:
not-leader: "You are not the leader of your island!"
offline-player: "That player is offline or doesn't exist."
unknown-player: "Unknown player!"
general: "That command is not ready yet - contact admin"
help:
admin:
@ -151,6 +154,7 @@ adminInfo:
lastLogin: "Last login"
maxSize: "Island max size (distance)"
player: "Player"
resetsLeft: "Resets left"
teamLeader: "Team Leader"
teamMembers: "Team Members"
title: "This is spawn island"

13
pom.xml
View File

@ -8,7 +8,10 @@
<name>BSkyBlock</name>
<description>The next generation of ASkyBlock</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<server.jars>${project.basedir}/lib</server.jars>
</properties>
<build>
@ -61,6 +64,12 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
@ -81,6 +90,10 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>AWE-mvn-repo</id>
<url>https://raw.github.com/SBPrime/AsyncWorldEdit-API/maven-artifact/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>

View File

@ -1,16 +1,9 @@
package us.tastybento.bskyblock;
import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Locale;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
@ -20,13 +13,12 @@ import us.tastybento.bskyblock.commands.AdminCommand;
import us.tastybento.bskyblock.commands.IslandCommand;
import us.tastybento.bskyblock.config.BSBLocale;
import us.tastybento.bskyblock.config.LocaleManager;
import us.tastybento.bskyblock.config.NotSetup.ConfigError;
import us.tastybento.bskyblock.config.PluginConfig;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.managers.IslandsManager;
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages;
import us.tastybento.bskyblock.database.managers.PlayersManager;
import us.tastybento.bskyblock.database.managers.island.IslandsManager;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.listeners.JoinLeaveListener;
import us.tastybento.bskyblock.listeners.NetherPortals;
@ -35,7 +27,6 @@ import us.tastybento.bskyblock.listeners.protection.IslandGuard1_8;
import us.tastybento.bskyblock.listeners.protection.IslandGuard1_9;
import us.tastybento.bskyblock.listeners.protection.NetherEvents;
import us.tastybento.bskyblock.schematics.SchematicsMgr;
import us.tastybento.bskyblock.util.FileLister;
import us.tastybento.bskyblock.util.VaultHelper;
/**
@ -70,6 +61,7 @@ public class BSkyBlock extends JavaPlugin{
// Load configuration and locales. If there are no errors, load the plugin.
if(PluginConfig.loadPluginConfig(this)){
playersManager = new PlayersManager(this);
islandsManager = new IslandsManager(this);
// Only load metrics if set to true in config
@ -103,54 +95,62 @@ public class BSkyBlock extends JavaPlugin{
public void run() {
// Create the world if it does not exist
new IslandWorld(plugin);
// Load islands from database
islandsManager.load();
// Load schematics
// TODO: load these from config.yml
Settings.chestItems = new ItemStack[] {
new ItemStack(Material.LAVA_BUCKET,1),
new ItemStack(Material.ICE,2),
new ItemStack(Material.MELON_SEEDS,1),
new ItemStack(Material.BONE,2),
new ItemStack(Material.COBBLESTONE,5),
new ItemStack(Material.SAPLING,2)
};
schematicsManager = new SchematicsMgr(plugin);
Settings.defaultLanguage = "en-US";
localeManager = new LocaleManager(plugin);
// Register Listeners
registerListeners();
/*
*DEBUG CODE
Island loadedIsland = islandsManager.getIsland(owner);
getLogger().info("Island name = " + loadedIsland.getName());
getLogger().info("Island locked = " + loadedIsland.getLocked());
//getLogger().info("Random set = " + randomSet);
getLogger().info("Island coops = " + loadedIsland.getCoops());
for (Entry<SettingsFlag, Boolean> flag: loadedIsland.getFlags().entrySet()) {
getLogger().info("Flag " + flag.getKey().name() + " = " + flag.getValue());
}
*/
// Save islands & players data asynchronously every X minutes
Settings.databaseBackupPeriod = 10 * 60 * 20;
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
playersManager.save(true);
islandsManager.save(true);
offlineHistoryMessages.save(true);
}
}, Settings.databaseBackupPeriod, Settings.databaseBackupPeriod);
}
// TODO Auto-generated method stub
// Load islands from database
islandsManager.load();
// Load schematics
// TODO: load these from config.yml
Settings.chestItems = new ItemStack[] {
new ItemStack(Material.LAVA_BUCKET,1),
new ItemStack(Material.ICE,2),
new ItemStack(Material.MELON_SEEDS,1),
new ItemStack(Material.BONE,2),
new ItemStack(Material.COBBLESTONE,5),
new ItemStack(Material.SAPLING,2)
};
schematicsManager = new SchematicsMgr(plugin);
Settings.defaultLanguage = "en-US";
localeManager = new LocaleManager(plugin);
// Register Listeners
registerListeners();
/*
*DEBUG CODE
Island loadedIsland = islandsManager.getIsland(owner);
getLogger().info("Island name = " + loadedIsland.getName());
getLogger().info("Island locked = " + loadedIsland.getLocked());
//getLogger().info("Random set = " + randomSet);
getLogger().info("Island coops = " + loadedIsland.getCoops());
for (Entry<SettingsFlag, Boolean> flag: loadedIsland.getFlags().entrySet()) {
getLogger().info("Flag " + flag.getKey().name() + " = " + flag.getValue());
}
*/
// Save islands & players data asynchronously every X minutes
Settings.databaseBackupPeriod = 10 * 60 * 20;
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
@Override
public void run() {
playersManager.save(true);
islandsManager.save(true);
offlineHistoryMessages.save(true);
}
}, Settings.databaseBackupPeriod, Settings.databaseBackupPeriod);
}
// TODO Auto-generated method stub
});
}
});
}
}
@ -176,7 +176,6 @@ public class BSkyBlock extends JavaPlugin{
playersManager.shutdown();
islandsManager.shutdown();
//offlineHistoryMessages.shutdown();
plugin = null;
}
private void registerCustomCharts(){

View File

@ -3,7 +3,6 @@ package us.tastybento.bskyblock.api.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@ -19,11 +18,9 @@ import org.bukkit.entity.Player;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.events.command.CommandEvent;
import us.tastybento.bskyblock.api.events.team.TeamEvent;
import us.tastybento.bskyblock.api.events.team.TeamEvent.TeamReason;
import us.tastybento.bskyblock.config.BSBLocale;
import us.tastybento.bskyblock.database.managers.IslandsManager;
import us.tastybento.bskyblock.database.managers.PlayersManager;
import us.tastybento.bskyblock.database.managers.island.IslandsManager;
import us.tastybento.bskyblock.util.Util;
/**
@ -46,7 +43,7 @@ public abstract class AbstractCommand implements CommandExecutor, TabCompleter {
public UUID playerUUID;
private final boolean help;
private static final int MAX_PER_PAGE = 7;
//private static final int MAX_PER_PAGE = 7;
private static final boolean DEBUG = false;

View File

@ -13,7 +13,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @version 1.0
*/
public class IslandEvent extends Event implements Cancellable{
public class IslandBaseEvent extends Event implements Cancellable{
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
@ -22,7 +22,7 @@ public class IslandEvent extends Event implements Cancellable{
/**
* @param island
*/
public IslandEvent(Island island){
public IslandBaseEvent(Island island){
this.island = island;
}

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.acid;
import org.bukkit.entity.Entity;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -10,7 +10,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class EntityDamageByAcidEvent extends IslandEvent {
public class EntityDamageByAcidEvent extends IslandBaseEvent {
private final Entity entity;
private double damage;

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.acid;
import org.bukkit.entity.Item;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -10,7 +10,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class ItemDestroyByAcidEvent extends IslandEvent {
public class ItemDestroyByAcidEvent extends IslandBaseEvent {
private final Item item;
public ItemDestroyByAcidEvent(Island island, Item item) {

View File

@ -3,7 +3,7 @@ package us.tastybento.bskyblock.api.events.acid;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -11,7 +11,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class ItemFillWithAcidEvent extends IslandEvent {
public class ItemFillWithAcidEvent extends IslandBaseEvent {
private final Player player;
private final ItemStack item;

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.acid;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -10,7 +10,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class PlayerDrinkAcidEvent extends IslandEvent {
public class PlayerDrinkAcidEvent extends IslandBaseEvent {
private final Player player;
public PlayerDrinkAcidEvent(Island island, Player player) {

View File

@ -1,42 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Fired when a player starts a new island
*
* @author tastybento
* @since 1.0
*/
public class IslandCreateEvent extends IslandEvent {
private final Player player;
//private final Schematic schematic;
/**
* @param island
* @param player
* @param schematic
*/
public IslandCreateEvent(Island island, Player player/*, Schematic schematic*/) {
super(island);
this.player = player;
//this.schematic = schematic;
}
/**
* @return the player
*/
public Player getPlayer() {
return player;
}
// /** TODO: schematics
// * @return the schematicName
// */
// public Schematic getSchematicName() {
// return schematic;
// }
}

View File

@ -1,20 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Fired before an island is deleted.
*
* @author tastybento
* @since 1.0
*/
public class IslandDeleteEvent extends IslandEvent {
/**
* @param island
*/
public IslandDeleteEvent(Island island) {
super(island);
}
}

View File

@ -1,47 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import java.util.UUID;
import org.bukkit.Location;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Fired when a player enters an island's area
*
* @author tastybento
* @since 1.0
*/
public class IslandEnterEvent extends IslandEvent {
private final UUID player;
private final Location location;
/**
* Called to create the event
* @param island - island the player is entering
* @param player
* @param location - Location of where the player entered the island or tried to enter
*/
public IslandEnterEvent(Island island, UUID player, Location location) {
super(island);
this.player = player;
this.location = location;
}
/**
* @return the player
*/
public UUID getPlayer() {
return player;
}
/**
* Location of where the player entered the island or tried to enter
* @return the location
*/
public Location getLocation() {
return location;
}
}

View File

@ -0,0 +1,139 @@
package us.tastybento.bskyblock.api.events.island;
import java.util.UUID;
import org.bukkit.Location;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Fired when a team event happens.
*
* @author tastybento
* @since 1.0
*/
public class IslandEvent extends IslandBaseEvent {
public enum Reason {
CREATE,
CREATED,
DELETE,
DELETED,
ENTER,
EXIT,
LOCK,
RESET,
RESETTED,
UNLOCK,
UNKNOWN
};
/**
* Player involved with this event
*/
private final UUID player;
/**
* True if this is an admin action
*/
private final boolean admin;
/**
* Reason for this event
*/
private final Reason reason;
/**
* Location related to the event
*/
private Location location;
private IslandEvent(Island island, UUID player, boolean admin, Reason reason, Location location) {
// Final variables have to be declared in the constuctor
super(island);
this.player = player;
this.admin = admin;
this.reason = reason;
this.location = location;
}
public static IslandEventBuilder builder() {
return new IslandEventBuilder();
}
public static class IslandEventBuilder {
// Here field are NOT final. They are just used for the building.
private Island island;
private UUID player;
private Reason reason = Reason.UNKNOWN;
private boolean admin;
private Location location;
public IslandEventBuilder island(Island island) {
this.island = island;
return this;
}
/**
* True if this is an admin driven event
* @param admin
* @return TeamEvent
*/
public IslandEventBuilder admin(boolean admin) {
this.admin = admin;
return this;
}
/**
* @param reason for the event
* @return
*/
public IslandEventBuilder reason(Reason reason) {
this.reason = reason;
return this;
}
/**
* @param player involved in the event
* @return
*/
public IslandEventBuilder involvedPlayer(UUID player) {
this.player = player;
return this;
}
public IslandEvent build() {
return new IslandEvent(island, player, admin, reason, location);
}
public IslandEventBuilder location(Location location) {
this.location = location;
return this;
}
}
/**
* @return the player involved with this event
*/
public UUID getPlayer() {
return player;
}
/**
* @return true if this is an admin action
*/
public boolean isAdmin() {
return admin;
}
/**
* @return the reason for this team event
*/
public Reason getReason() {
return reason;
}
public Location getLocation() {
return location;
}
}

View File

@ -1,46 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import java.util.UUID;
import org.bukkit.Location;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Fired when a player exits an island's protected area
*
* @author tastybento
* @since 1.0
*/
public class IslandExitEvent extends IslandEvent {
private final UUID player;
private final Location location;
/**
* @param island that the player is leaving
* @param player
* @param location - Location of where the player exited the island's protected area
*/
public IslandExitEvent(Island island, UUID player, Location location) {
super(island);
this.player = player;
this.location = location;
}
/**
* @return the player
*/
public UUID getPlayer() {
return player;
}
/**
* Location of where the player exited the island's protected area
* @return the location
*/
public Location getLocation() {
return location;
}
}

View File

@ -1,31 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import org.bukkit.command.CommandSender;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* This event is fired when an island is going to be locked.
* <p>
* Cancelling this event will result in keeping the island unlocked.
*
* @author Poslovitch
* @since 1.0
*/
public class IslandLockEvent extends IslandEvent {
private final CommandSender locker;
/**
* @param island
* @param locker
*/
public IslandLockEvent(Island island, CommandSender locker) {
super(island);
this.locker = locker;
}
public CommandSender getLocker() {
return locker;
}
}

View File

@ -1,32 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* This event is fired when a player resets an island
*
* @author tastybento
* @since 1.0
*/
public class IslandResetEvent extends IslandEvent {
private final Player player;
/**
* @param island
* @param player
*/
public IslandResetEvent(Island island, Player player) {
super(island);
this.player = player;
}
/**
* @return the player
*/
public Player getPlayer() {
return player;
}
}

View File

@ -1,31 +0,0 @@
package us.tastybento.bskyblock.api.events.island;
import org.bukkit.command.CommandSender;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
* This event is fired when an island is going to be unlocked.
* <p>
* Cancelling this event will result in keeping the island locked.
*
* @author Poslovitch
* @since 1.0
*/
public class IslandUnlockEvent extends IslandEvent {
private final CommandSender unlocker;
/**
* @param island
* @param unlocker
*/
public IslandUnlockEvent(Island island, CommandSender unlocker) {
super(island);
this.unlocker = unlocker;
}
public CommandSender getUnlocker(){
return unlocker;
}
}

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.island;
import java.util.UUID;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
@ -14,7 +14,7 @@ import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
* @author Poslovitch
* @since 1.0
*/
public class SettingChangeEvent extends IslandEvent {
public class SettingChangeEvent extends IslandBaseEvent {
private final UUID player;
private final SettingsFlag editedSetting;
private final boolean setTo;

View File

@ -1,6 +1,6 @@
package us.tastybento.bskyblock.api.events.purge;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -10,7 +10,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class PurgeDeleteIslandEvent extends IslandEvent {
public class PurgeDeleteIslandEvent extends IslandBaseEvent {
/**
* Called to create the event

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.team;
import java.util.UUID;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -11,7 +11,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author tastybento
* @since 1.0
*/
public class CoopJoinEvent extends IslandEvent {
public class CoopJoinEvent extends IslandBaseEvent {
private final UUID player, inviter;
/**

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.team;
import java.util.UUID;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -11,7 +11,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author tastybento
* @since 1.0
*/
public class CoopLeaveEvent extends IslandEvent {
public class CoopLeaveEvent extends IslandBaseEvent {
private final UUID player, expeller;
/**

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.team;
import java.util.UUID;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -11,7 +11,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author Poslovitch
* @since 1.0
*/
public class TeamChatEvent extends IslandEvent {
public class TeamChatEvent extends IslandBaseEvent {
private final UUID player;
private String message;

View File

@ -2,7 +2,7 @@ package us.tastybento.bskyblock.api.events.team;
import java.util.UUID;
import us.tastybento.bskyblock.api.events.IslandEvent;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.database.objects.Island;
/**
@ -11,7 +11,7 @@ import us.tastybento.bskyblock.database.objects.Island;
* @author tastybento
* @since 1.0
*/
public class TeamEvent extends IslandEvent {
public class TeamEvent extends IslandBaseEvent {
public enum TeamReason {
INVITE,
JOIN,

View File

@ -1,5 +1,7 @@
package us.tastybento.bskyblock.commands;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@ -45,25 +47,147 @@ public class AdminCommand extends AbstractCommand {
@Override
public CanUseResp canUse(CommandSender sender) {
return new CanUseResp(true);
return new CanUseResp(!(sender instanceof Player)
|| VaultHelper.hasPerm(player, Settings.PERMPREFIX + "admin.delete"));
}
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length > 0) {
// Convert name to a UUID
UUID targetPlayer = getPlayers().getUUID(args[0]);
if (targetPlayer == null) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("general.errors.unknown-player"));
return;
}
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("delete.removing").replace("[name]", args[0]));
getIslands().deleteIsland(targetPlayer, true);
}
}
@Override
public Set<String> tabComplete(CommandSender sender, String[] args) {
return null;
Set<String> result = new HashSet<>();
if (args.length == 1) {
result.addAll(Util.getOnlinePlayerList(player));
}
return result;
}
@Override
public String[] usage(CommandSender sender){
return new String[] {null, plugin.getLocale(sender).get("help.admin.delete")};
return new String[] {null, getLocale(sender).get("help.admin.delete")};
}
}.alias("delete"));
/* /asadmin unregister <name> - unregister name's island */
addArgument(new ArgumentHandler(label) {
@Override
public CanUseResp canUse(CommandSender sender) {
return new CanUseResp(!(sender instanceof Player)
|| VaultHelper.hasPerm(player, Settings.PERMPREFIX + "admin.unregister"));
}
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length > 0) {
// Convert name to a UUID
UUID targetPlayer = getPlayers().getUUID(args[0]);
if (targetPlayer == null) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("general.errors.unknown-player"));
return;
}
Island island = getIslands().getIsland(targetPlayer);
if (island != null) {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminUnregister.keepBlocks").replace("[location]", island.getCenter().toString()));
getIslands().deleteIsland(targetPlayer, false);
} else {
// Error
}
}
}
@Override
public Set<String> tabComplete(CommandSender sender, String[] args) {
Set<String> result = new HashSet<>();
if (args.length == 1) {
result.addAll(Util.getOnlinePlayerList(player));
}
return result;
}
@Override
public String[] usage(CommandSender sender){
return new String[] {null, getLocale(sender).get("adminHelp.unregister")};
}
}.alias("unregister"));
/* /asadmin info - show info on island */
addArgument(new ArgumentHandler(label) {
@Override
public CanUseResp canUse(CommandSender sender) {
return new CanUseResp(!(sender instanceof Player)
|| VaultHelper.hasPerm(player, Settings.PERMPREFIX + "admin.info"));
}
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length > 0) {
// Convert name to a UUID
UUID targetPlayer = getPlayers().getUUID(args[0]);
if (targetPlayer == null) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("general.errors.unknown-player"));
return;
}
showInfo(targetPlayer, sender);
} else {
if (!(sender instanceof Player)) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("general.errors.use-in-game"));
return;
}
Island island = getIslands().getIslandAt(((Player)sender).getLocation());
if (island == null) {
Util.sendMessage(sender, ChatColor.RED + "Sorry, could not find an island. Move closer?");
return;
}
if (island.isSpawn()) {
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfo.title"));
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminSetSpawncenter").replace("[location]", island.getCenter().getBlockX() + "," + island.getCenter().getBlockZ()));
Util.sendMessage(sender, ChatColor.YELLOW + (getLocale(sender).get("adminSetSpawnlimits").replace("[min]", island.getMinX() + "," + island.getMinZ())).replace("[max]",
(island.getMinX() + island.getRange() - 1) + "," + (island.getMinZ() + island.getRange() - 1)));
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminSetSpawnrange").replace("[number]",String.valueOf(island.getProtectionRange())));
Util.sendMessage(sender, ChatColor.YELLOW + (getLocale(sender).get("adminSetSpawncoords").replace("[min]", island.getMinProtectedX() + ", " + island.getMinProtectedZ())).replace("[max]",
+ (island.getMinProtectedX() + island.getProtectionRange() - 1) + ", "
+ (island.getMinProtectedZ() + island.getProtectionRange() - 1)));
if (island.isLocked()) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("adminSetSpawnlocked"));
}
return;
}
showInfo(island.getOwner(), sender);
return;
}
}
@Override
public Set<String> tabComplete(CommandSender sender, String[] args) {
Set<String> result = new HashSet<>();
if (args.length == 1) {
result.addAll(Util.getOnlinePlayerList(player));
}
return result;
}
@Override
public String[] usage(CommandSender sender){
return new String[] {null, getLocale(sender).get("adminHelp.infoisland")};
}
}.alias("info"));
/* /asadmin team - manage teams */
addArgument(new ArgumentHandler(label) {
@ -103,9 +227,9 @@ public class AdminCommand extends AbstractCommand {
case "info":
// Fire event so add-ons can run commands, etc.
TeamEvent event = TeamEvent.builder().island(getIslands().getIsland(targetPlayer))
.admin(true)
.reason(TeamReason.INFO)
.involvedPlayer(targetPlayer).build();
.admin(true)
.reason(TeamReason.INFO)
.involvedPlayer(targetPlayer).build();
plugin.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) return;
// Display info
@ -336,27 +460,126 @@ public class AdminCommand extends AbstractCommand {
}
}
// Wrong command syntax or arguments, show help
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.command"));
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.info"));
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.makeleader"));
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.add"));
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.kick"));
Util.sendMessage(sender, plugin.getLocale(sender).get("help.admin.team.delete"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.command"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.info"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.makeleader"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.add"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.kick"));
Util.sendMessage(sender, getLocale(sender).get("help.admin.team.delete"));
}
@Override
public Set<String> tabComplete(CommandSender sender, String[] args) {
return null;
Set<String> result = new HashSet<>();
if (args.length == 1) {
result.add("info");
result.add("makeleader");
result.add("kick");
result.add("delete");
result.add("add");
} else if (args.length == 1) {
result.addAll(Util.getOnlinePlayerList(player));
}
return result;
}
@Override
public String[] usage(CommandSender sender){
return new String[] {null, plugin.getLocale(sender).get("help.admin.team.command")};
return new String[] {null, getLocale(sender).get("help.admin.team.command")};
}
}.alias("team"));
}
/**
* Shows info on a player
*
* @param playerUUID
* @param sender
*/
private void showInfo(UUID playerUUID, CommandSender sender) {
// Show info on player
Util.sendMessage(sender, getLocale(sender).get("adminInfo.player") + ": " + ChatColor.GREEN + getPlayers().getName(playerUUID));
Util.sendMessage(sender, ChatColor.WHITE + "UUID: " + playerUUID.toString());
// Last login
try {
Date d = new Date(plugin.getServer().getOfflinePlayer(playerUUID).getLastPlayed());
Util.sendMessage(sender, ChatColor.GOLD + getLocale(sender).get("adminInfo.lastLogin") + ": " + d.toString());
} catch (Exception e) {
}
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("general.deaths") + ": " + getPlayers().getDeaths(playerUUID));
String resetsLeft = getLocale(sender).get("general.unlimited");
if (getPlayers().getResetsLeft(playerUUID) >= 0) {
resetsLeft = String.valueOf(getPlayers().getResetsLeft(playerUUID)) + " / " + String.valueOf(Settings.resetLimit);
}
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfo.resetsLeft") + ": " + resetsLeft);
// Teams
if (getPlayers().inTeam(playerUUID)) {
final UUID leader = getIslands().getTeamLeader(playerUUID);
final Set<UUID> pList = getIslands().getMembers(leader);
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfo.teamLeader") + ": " + getPlayers().getName(leader));
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfo.teamMembers") + ":");
for (UUID member : pList) {
if (!member.equals(leader)) {
Util.sendMessage(sender, ChatColor.WHITE + " - " + getPlayers().getName(member));
}
}
} else {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("error.noTeam"));
if (getIslands().getMembers(playerUUID).size() > 1) {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("adminInfo.errorTeamMembersExist"));
}
}
// Island info
Island island = getIslands().getIsland(playerUUID);
if (island != null) {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfo.islandLocation") + ":" + ChatColor.WHITE + " (" + island.getCenter().getBlockX() + ","
+ island.getCenter().getBlockY() + "," + island.getCenter().getBlockZ() + ")");
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminSetSpawn.center").replace("[location]", island.getCenter().getBlockX() + "," + island.getCenter().getBlockZ()));
Util.sendMessage(sender, ChatColor.YELLOW + (getLocale(sender).get("adminSetSpawn.limits").replace("[min]", island.getMinX() + "," + island.getMinZ())).replace("[max]",
(island.getMinX() + island.getRange()*2 - 1) + "," + (island.getMinZ() + island.getRange()*2 - 1)));
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminSetSpawn.range").replace("[number]",String.valueOf(island.getProtectionRange())));
Util.sendMessage(sender, ChatColor.YELLOW + (getLocale(sender).get("adminSetSpawn.coords").replace("[min]", island.getMinProtectedX() + ", " + island.getMinProtectedZ())).replace("[max]",
+ (island.getMinProtectedX() + island.getProtectionRange()*2 - 1) + ", "
+ (island.getMinProtectedZ() + island.getProtectionRange()*2 - 1)));
if (island.isSpawn()) {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfo.isSpawn"));
}
if (island.isLocked()) {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfo.isLocked"));
} else {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfo.isUnlocked"));
}
/*
if (island.isPurgeProtected()) {
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfoIsProtected"));
} else {
Util.sendMessage(sender, ChatColor.GREEN + getLocale(sender).get("adminInfoIsUnprotected"));
}*/
Set<UUID> banList = getIslands().getBanList(playerUUID);
if (!banList.isEmpty()) {
Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfo.bannedPlayers") + ":");
String list = "";
for (UUID uuid : banList) {
Player target = plugin.getServer().getPlayer(uuid);
if (target != null) {
//online
list += target.getName() + ", ";
} else {
list += getPlayers().getName(uuid) + ", ";
}
}
if (!list.isEmpty()) {
Util.sendMessage(sender, ChatColor.RED + list.substring(0, list.length()-2));
}
}
// Number of hoppers
// Util.sendMessage(sender, ChatColor.YELLOW + getLocale(sender).get("adminInfoHoppers").replace("[number]", String.valueOf(island.getHopperCount())));
} else {
Util.sendMessage(sender, ChatColor.RED + getLocale(sender).get("error.noIslandOther"));
}
}
@Override
public CanUseResp canUse(CommandSender sender) {
return new CanUseResp(true);

View File

@ -1,5 +1,6 @@
package us.tastybento.bskyblock.commands;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
@ -26,6 +27,7 @@ import us.tastybento.bskyblock.api.commands.CanUseResp;
import us.tastybento.bskyblock.api.events.team.TeamEvent;
import us.tastybento.bskyblock.api.events.team.TeamEvent.TeamReason;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.managers.island.NewIsland;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.schematics.Schematic;
import us.tastybento.bskyblock.util.Util;
@ -303,7 +305,7 @@ public class IslandCommand extends AbstractCommand {
if (!VaultHelper.hasPerm(player, Settings.PERMPREFIX + "island.reset")) {
return new CanUseResp(getLocale(sender).get("general.errors.no-permission"));
}
if (getIslands().hasIsland(playerUUID)) {
if (!getIslands().hasIsland(playerUUID)) {
return new CanUseResp(getLocale(sender).get("general.errors.no-island"));
}
if (!getIslands().isOwner(playerUUID)) {
@ -329,7 +331,13 @@ public class IslandCommand extends AbstractCommand {
if (DEBUG)
plugin.getLogger().info("DEBUG: making new island ");
Schematic schematic = plugin.getSchematics().getSchematic("default");
getIslands().newIsland(player, schematic, oldIsland);
try {
new NewIsland.Builder().player(player).schematic(schematic).oldIsland(oldIsland).build();
} catch (IOException e) {
plugin.getLogger().severe("Could not create island for player.");
Util.sendMessage(sender, ChatColor.RED + plugin.getLocale(sender).get("general.errors.general"));
e.printStackTrace();
}
}
@Override
@ -1514,7 +1522,13 @@ public class IslandCommand extends AbstractCommand {
protected void createIsland(Player player) {
//TODO: Add panels, make a selection.
Schematic schematic = plugin.getSchematics().getSchematic("default");
getIslands().newIsland(player, schematic);
try {
new NewIsland.Builder().player(player).schematic(schematic).build();
} catch (IOException e) {
plugin.getLogger().severe("Could not create island for player.");
Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player).get("general.errors.general"));
e.printStackTrace();
}
}
}

View File

@ -1,7 +1,6 @@
package us.tastybento.bskyblock.config;
import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
@ -11,8 +10,6 @@ import java.util.ResourceBundle;
import org.bukkit.ChatColor;
import org.bukkit.plugin.Plugin;
import us.tastybento.bskyblock.util.FileLister;
public class BSBLocale {
final static String LOCALE_FOLDER = "locales";

View File

@ -84,13 +84,11 @@ public class PluginConfig {
Settings.worldName = plugin.getConfig().getString("world.world-name", "BSkyBlock_world");
//TODO check if it is the same than before
int distance = plugin.getConfig().getInt("world.distance-in-chunks", 24);
// TODO this is an arbitrary number
Settings.islandDistance = distance * 16;
if(distance < 50) errors.put(ConfigError.ISLAND_DISTANCE_TOO_LOW, Settings.islandDistance);
int distance = plugin.getConfig().getInt("world.distance", 208);
Settings.islandDistance = Math.round((long)distance/16) * 16;
if(distance < 48) errors.put(ConfigError.ISLAND_DISTANCE_TOO_LOW, Settings.islandDistance);
Settings.islandProtectionRange = plugin.getConfig().getInt("world.protection-range", 100);
if(Settings.islandProtectionRange % 2 != 0) errors.put(ConfigError.NOT_EVEN_PROTECTION_RANGE, Settings.islandProtectionRange);
if(Settings.islandProtectionRange < 0) errors.put(ConfigError.PROTECTION_RANGE_TOO_LOW, Settings.islandProtectionRange);
if(Settings.islandProtectionRange > Settings.islandDistance) errors.put(ConfigError.PROTECTION_RANGE_HIGHER_THAN_ISLAND_DISTANCE, Settings.islandProtectionRange);

View File

@ -38,7 +38,7 @@ import us.tastybento.bskyblock.util.Util;
public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
private static final String DATABASE_FOLDER_NAME = "database";
private static final boolean DEBUG = false;
private static final boolean DEBUG = true;
public FlatFileDatabaseHandler(BSkyBlock plugin, Class<T> type, DatabaseConnecter databaseConnecter) {
super(plugin, type, databaseConnecter);
}

View File

@ -1,7 +1,6 @@
package us.tastybento.bskyblock.database.managers;
import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.List;

View File

@ -3,6 +3,8 @@ package us.tastybento.bskyblock.database.managers;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
@ -68,8 +70,22 @@ public class PlayersManager{
public void save(boolean async){
if (DEBUG)
plugin.getLogger().info("DEBUG: saving " + async);
Runnable save = () -> {
for(Players player : playerCache.values()){
Collection<Players> set = Collections.unmodifiableCollection(playerCache.values());
if(async){
Runnable save = () -> {
for(Players player : set){
if (DEBUG)
plugin.getLogger().info("DEBUG: saving player " + player.getPlayerName() + " "+ player.getUniqueId());
try {
handler.saveObject(player);
} catch (Exception e) {
e.printStackTrace();
}
}
};
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, save);
} else {
for(Players player : set){
if (DEBUG)
plugin.getLogger().info("DEBUG: saving player " + player.getPlayerName() + " "+ player.getUniqueId());
try {
@ -78,12 +94,6 @@ public class PlayersManager{
e.printStackTrace();
}
}
};
if(async){
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, save);
} else {
save.run();
}
}

View File

@ -0,0 +1,362 @@
package us.tastybento.bskyblock.database.managers.island;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.util.Util;
public class IslandCache {
private static final boolean DEBUG2 = false;
private static final boolean DEBUG = false;
private BSkyBlock plugin = BSkyBlock.getPlugin();
private BiMap<Location, Island> islandsByLocation;
/**
* Every player who is associated with an island is in this map.
*/
private HashMap<UUID, Island> islandsByUUID;
// 2D islandGrid of islands, x,z
private TreeMap<Integer, TreeMap<Integer, Island>> islandGrid = new TreeMap<>();
public IslandCache() {
islandsByLocation = HashBiMap.create();
islandsByUUID = new HashMap<>();
}
public void addIsland(Island island) {
islandsByLocation.put(island.getCenter(), island);
if (DEBUG)
plugin.getLogger().info("DEBUG: owner = " + island.getOwner());
islandsByUUID.put(island.getOwner(), island);
if (DEBUG)
plugin.getLogger().info("DEBUG: island has " + island.getMembers().size() + " members");
for (UUID member: island.getMembers()) {
if (DEBUG)
plugin.getLogger().info("DEBUG: " + member);
islandsByUUID.put(member, island);
}
addToGrid(island);
}
public void addPlayer(UUID playerUUID, Island teamIsland) {
islandsByUUID.put(playerUUID, teamIsland);
}
/**
* Adds an island to the grid register
* @param newIsland
*/
private void addToGrid(Island newIsland) {
if (islandGrid.containsKey(newIsland.getMinX())) {
if (DEBUG)
plugin.getLogger().info("DEBUG: min x is in the grid :" + newIsland.getMinX());
TreeMap<Integer, Island> zEntry = islandGrid.get(newIsland.getMinX());
if (zEntry.containsKey(newIsland.getMinZ())) {
if (DEBUG)
plugin.getLogger().info("DEBUG: min z is in the grid :" + newIsland.getMinZ());
// Island already exists
Island conflict = islandGrid.get(newIsland.getMinX()).get(newIsland.getMinZ());
plugin.getLogger().warning("*** Duplicate or overlapping islands! ***");
plugin.getLogger().warning(
"Island at (" + newIsland.getCenter().getBlockX() + ", " + newIsland.getCenter().getBlockZ() + ") conflicts with ("
+ conflict.getCenter().getBlockX() + ", " + conflict.getCenter().getBlockZ() + ")");
if (conflict.getOwner() != null) {
plugin.getLogger().warning("Accepted island is owned by " + plugin.getPlayers().getName(conflict.getOwner()));
plugin.getLogger().warning(conflict.getOwner().toString() + ".yml");
} else {
plugin.getLogger().warning("Accepted island is unowned.");
}
if (newIsland.getOwner() != null) {
plugin.getLogger().warning("Denied island is owned by " + plugin.getPlayers().getName(newIsland.getOwner()));
plugin.getLogger().warning(newIsland.getOwner().toString() + ".yml");
} else {
plugin.getLogger().warning("Denied island is unowned and was just found in the islands folder. Skipping it...");
}
plugin.getLogger().warning("Recommend that the denied player file is deleted otherwise weird things can happen.");
return;
} else {
// Add island
if (DEBUG)
plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ());
zEntry.put(newIsland.getMinZ(), newIsland);
islandGrid.put(newIsland.getMinX(), zEntry);
// plugin.getLogger().info("Debug: " + newIsland.toString());
}
} else {
// Add island
if (DEBUG)
plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ());
TreeMap<Integer, Island> zEntry = new TreeMap<Integer, Island>();
zEntry.put(newIsland.getMinZ(), newIsland);
islandGrid.put(newIsland.getMinX(), zEntry);
}
}
public void clear() {
islandsByLocation.clear();
islandsByUUID.clear();
}
public Island createIsland(Island island) {
islandsByLocation.put(island.getCenter(), island);
if (island.getOwner() != null)
islandsByUUID.put(island.getOwner(), island);
addToGrid(island);
return island;
}
/**
* Create an island with no owner at location
* @param location
*/
public Island createIsland(Location location){
return createIsland(location, null);
}
/**
* Create an island with owner. Note this does not create the schematic. It just creates the island data object.
* @param location
* @param owner UUID
*/
public Island createIsland(Location location, UUID owner){
if (DEBUG)
plugin.getLogger().info("DEBUG: adding island for " + owner + " at " + location);
Island island = new Island(location, owner, Settings.islandProtectionRange);
islandsByLocation.put(location, island);
if (owner != null)
islandsByUUID.put(owner, island);
addToGrid(island);
return island;
}
/**
* Deletes an island from the database. Does not remove blocks
* @param island
*/
public void deleteIslandFromCache(Island island) {
if (!islandsByLocation.remove(island.getCenter(), island)) {
plugin.getLogger().severe("Could not remove island from cache!");
}
Iterator<Entry<UUID, Island>> it = islandsByUUID.entrySet().iterator();
while (it.hasNext()) {
Entry<UUID, Island> en = it.next();
if (en.getValue().equals(island)) {
it.remove();
}
}
// Remove from grid
if (DEBUG)
plugin.getLogger().info("DEBUG: deleting island at " + island.getCenter());
if (island != null) {
int x = island.getMinX();
int z = island.getMinZ();
if (DEBUG)
plugin.getLogger().info("DEBUG: x = " + x + " z = " + z);
if (islandGrid.containsKey(x)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: x found");
TreeMap<Integer, Island> zEntry = islandGrid.get(x);
if (zEntry.containsKey(z)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: z found - deleting the island");
// Island exists - delete it
zEntry.remove(z);
islandGrid.put(x, zEntry);
} else {
if (DEBUG)
plugin.getLogger().info("DEBUG: could not find z");
}
}
}
}
public Island get(Location location) {
return islandsByLocation.get(location);
}
public Island get(UUID uuid) {
return islandsByUUID.get(uuid);
}
/**
* Gets the island for this player. If they are in a team, the team island is returned
* @param uuid
* @return
*/
public Island getIsland(UUID uuid){
return islandsByUUID.get(uuid);
}
/**
* Returns the island at the x,z location or null if there is none.
* This includes the full island space, not just the protected area.
*
* @param x
* @param z
* @return Island or null
*/
public Island getIslandAt(int x, int z) {
if (DEBUG2) {
plugin.getLogger().info("DEBUG: getting island at " + x + "," + z);
plugin.getLogger().info("DEBUG: island grid is " + islandGrid.size());
}
Entry<Integer, TreeMap<Integer, Island>> en = islandGrid.floorEntry(x);
if (en != null) {
Entry<Integer, Island> ent = en.getValue().floorEntry(z);
if (ent != null) {
// Check if in the island range
Island island = ent.getValue();
if (island.inIslandSpace(x, z)) {
if (DEBUG2)
plugin.getLogger().info("DEBUG: In island space");
return island;
}
if (DEBUG2)
plugin.getLogger().info("DEBUG: not in island space");
}
}
return null;
}
/**
* Returns the island at the location or null if there is none.
* This includes the full island space, not just the protected area
*
* @param location
* @return Island object
*/
public Island getIslandAt(Location location) {
if (location == null) {
//plugin.getLogger().info("DEBUG: location is null");
return null;
}
// World check
if (!Util.inWorld(location)) {
//plugin.getLogger().info("DEBUG: not in right world");
return null;
}
return getIslandAt(location.getBlockX(), location.getBlockZ());
}
/**
* Returns the player's island location.
* Returns an island location OR a team island location
*
* @param playerUUID
* @return Location of player's island or null if one does not exist
*/
public Location getIslandLocation(UUID playerUUID) {
if (hasIsland(playerUUID))
return getIsland(playerUUID).getCenter();
return null;
}
/**
* Get name of the island owned by owner
* @param owner
* @return Returns the name of owner's island, or the owner's name if there is none.
*/
public String getIslandName(UUID owner) {
String result = plugin.getPlayers().getName(owner);
if (islandsByUUID.containsKey(owner)) {
Island island = islandsByUUID.get(owner);
if (!island.getName().isEmpty()) {
result = island.getName();
}
}
return ChatColor.translateAlternateColorCodes('&', result) + ChatColor.RESET;
}
public Collection<Island> getIslands() {
return Collections.unmodifiableCollection(islandsByLocation.values());
}
public Set<UUID> getMembers(UUID playerUUID) {
Island island = islandsByUUID.get(playerUUID);
if (island != null)
return new HashSet<UUID>(island.getMembers());
return new HashSet<UUID>(0);
}
public UUID getTeamLeader(UUID playerUUID) {
if (islandsByUUID.containsKey(playerUUID))
return islandsByUUID.get(playerUUID).getOwner();
return null;
}
/**
* @param playerUUID
* @return true if player has island and owns it
*/
public boolean hasIsland(UUID playerUUID) {
if (DEBUG) {
plugin.getLogger().info("DEBUG: checking if " + playerUUID + " has an island");
plugin.getLogger().info("DEBUG: islandsByUUID : " + islandsByUUID.toString());
if (!islandsByUUID.containsKey(playerUUID)) {
plugin.getLogger().info("DEBUG: player is not in islandsByUUID");
} else {
plugin.getLogger().info("DEBUG: owner = " + islandsByUUID.get(playerUUID).getOwner());
}
}
if (islandsByUUID.containsKey(playerUUID) && islandsByUUID.get(playerUUID).getOwner() != null) {
if (DEBUG)
plugin.getLogger().info("DEBUG: checking for equals");
if (islandsByUUID.get(playerUUID).getOwner().equals(playerUUID)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: has island");
return true;
}
}
if (DEBUG)
plugin.getLogger().info("DEBUG: doesn't have island");
return false;
}
public void removePlayer(UUID playerUUID) {
Island island = islandsByUUID.get(playerUUID);
if (island != null) {
if (DEBUG)
plugin.getLogger().info("DEBUG: island found");
if (island.getOwner() != null && island.getOwner().equals(playerUUID)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: player is the owner of this island");
// Clear ownership and members
island.getMembers().clear();
island.setOwner(null);
}
island.getMembers().remove(playerUUID);
}
if (DEBUG)
plugin.getLogger().info("DEBUG: removing reference to island by UUID");
islandsByUUID.remove(playerUUID);
}
public void setIslandName(UUID owner, String name) {
if (islandsByUUID.containsKey(owner)) {
Island island = islandsByUUID.get(owner);
island.setName(name);
}
}
public int size() {
return islandsByLocation.size();
}
}

View File

@ -0,0 +1,255 @@
package us.tastybento.bskyblock.database.managers.island;
import java.io.IOException;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.schematics.Schematic;
import us.tastybento.bskyblock.schematics.Schematic.PasteReason;
/**
* Create and paste a new island
* @author ben
*
*/
public class NewIsland {
private static final boolean DEBUG = false;
private final BSkyBlock plugin = BSkyBlock.getPlugin();
private Island island;
private final Island oldIsland;
private final Schematic schematic;
private final Player player;
private NewIsland(Island oldIsland, Schematic schematic, Player player) {
super();
this.oldIsland = oldIsland;
this.schematic = schematic;
this.player = player;
newIsland();
if (oldIsland != null) {
// Delete the old island
plugin.getIslands().deleteIsland(oldIsland, true);
}
}
/**
* @return the island that was created
*/
public Island getIsland() {
return island;
}
/**
* Start building a new island
* @return New island builder object
*/
public static Builder builder() {
return new Builder();
}
/**
* Build a new island for a player using a schematic
* @author ben
*
*/
public static class Builder {
private Island oldIsland;
private Schematic schematic;
private Player player;
public Builder oldIsland(Island oldIsland) {
this.oldIsland = oldIsland;
return this;
}
public Builder schematic(Schematic schematic) {
this.schematic = schematic;
return this;
}
public Builder player(Player player) {
this.player = player;
return this;
}
public Island build() throws IOException {
if (schematic != null && player != null) {
NewIsland newIsland = new NewIsland(oldIsland,schematic, player);
return newIsland.getIsland();
}
throw new IOException("Insufficient parameters. Must have a schematic and a player");
}
}
/**
* Makes an island using schematic. No permission checks are made. They have to be decided
* before this method is called.
*/
public void newIsland() {
if (DEBUG)
plugin.getLogger().info("DEBUG: new island");
//long time = System.nanoTime();
final UUID playerUUID = player.getUniqueId();
boolean firstTime = false;
if (!plugin.getPlayers().hasIsland(playerUUID)) {
firstTime = true;
}
if (DEBUG)
plugin.getLogger().info("DEBUG: finding island location");
Location next = getNextIsland(player.getUniqueId());
if (DEBUG)
plugin.getLogger().info("DEBUG: found " + next);
// Add to the grid
Island myIsland = plugin.getIslands().createIsland(next, playerUUID);
myIsland.setLevelHandicap(schematic.getLevelHandicap());
// Save the player so that if the server is reset weird things won't happen
plugin.getPlayers().save(true);
plugin.getIslands().save(true);
// Clear any old home locations (they should be clear, but just in case)
plugin.getPlayers().clearHomeLocations(playerUUID);
// Set the biome
//BiomesPanel.setIslandBiome(next, schematic.getBiome());
// Teleport to the new home
if (schematic.isPlayerSpawn()) {
// Set home and teleport
plugin.getPlayers().setHomeLocation(playerUUID, schematic.getPlayerSpawn(next), 1);
}
// Create island based on schematic
if (schematic != null) {
//plugin.getLogger().info("DEBUG: pasting schematic " + schematic.getName() + " " + schematic.getPerm());
//plugin.getLogger().info("DEBUG: nether world is " + BSkyBlock.getNetherWorld());
// Paste the starting island. If it is a HELL biome, then we start in the Nether
if (Settings.netherGenerate && schematic.isInNether() && Settings.netherIslands && IslandWorld.getNetherWorld() != null) {
// Nether start
// Paste the overworld if it exists
if (!schematic.getPartnerName().isEmpty()) {
// A partner schematic is available
pastePartner(plugin.getSchematics().getSchematic(schematic.getPartnerName()),next, player);
}
// Switch home location to the Nether
next = next.toVector().toLocation(IslandWorld.getNetherWorld());
// Set the player's island location to this new spot
//plugin.getPlayers().setIslandLocation(playerUUID, next);
schematic.pasteSchematic(next, player, true, firstTime ? PasteReason.NEW_ISLAND: PasteReason.RESET, oldIsland);
} else {
// Over world start
//plugin.getLogger().info("DEBUG: pasting");
//long timer = System.nanoTime();
// Paste the island and teleport the player home
schematic.pasteSchematic(next, player, true, firstTime ? PasteReason.NEW_ISLAND: PasteReason.RESET, oldIsland);
//double diff = (System.nanoTime() - timer)/1000000;
//plugin.getLogger().info("DEBUG: nano time = " + diff + " ms");
//plugin.getLogger().info("DEBUG: pasted overworld");
if (Settings.netherGenerate && Settings.netherIslands && IslandWorld.getNetherWorld() != null) {
// Paste the other world schematic
final Location netherLoc = next.toVector().toLocation(IslandWorld.getNetherWorld());
if (schematic.getPartnerName().isEmpty()) {
// This will paste the over world schematic again
//plugin.getLogger().info("DEBUG: pasting nether");
pastePartner(schematic, netherLoc, player);
//plugin.getLogger().info("DEBUG: pasted nether");
} else {
if (plugin.getSchematics().getAll().containsKey(schematic.getPartnerName())) {
//plugin.getLogger().info("DEBUG: pasting partner");
// A partner schematic is available
pastePartner(plugin.getSchematics().getAll().get(schematic.getPartnerName()),netherLoc, player);
} else {
plugin.getLogger().severe("Partner schematic heading '" + schematic.getPartnerName() + "' does not exist");
}
}
}
}
}
}
/**
* Does a delayed pasting of the partner island
* @param schematic
* @param player
*/
private void pastePartner(final Schematic schematic, final Location loc, final Player player) {
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
schematic.pasteSchematic(loc, player, false, PasteReason.PARTNER, null);
}}, 60L);
}
/**
* Get the location of next free island spot
* @param playerUUID
* @return Location of island spot
*/
private Location getNextIsland(UUID playerUUID) {
Location last = plugin.getIslands().getLast();
if (DEBUG)
plugin.getLogger().info("DEBUG: last = " + last);
// Find the next free spot
if (last == null) {
last = new Location(IslandWorld.getIslandWorld(), Settings.islandXOffset + Settings.islandStartX, Settings.islandHeight, Settings.islandZOffset + Settings.islandStartZ);
}
Location next = last.clone();
if (DEBUG)
plugin.getLogger().info("DEBUG: last 2 = " + last);
while (plugin.getIslands().isIsland(next)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: getting next loc");
next = nextGridLocation(next);
};
// Make the last next, last
last = next.clone();
if (DEBUG)
plugin.getLogger().info("DEBUG: last 3 = " + last);
return next;
}
/**
* Finds the next free island spot based off the last known island Uses
* island_distance setting from the config file Builds up in a grid fashion
*
* @param lastIsland
* @return Location of next free island
*/
private Location nextGridLocation(final Location lastIsland) {
int x = lastIsland.getBlockX();
int z = lastIsland.getBlockZ();
Location nextPos = lastIsland;
if (x < z) {
if (-1 * x < z) {
nextPos.setX(nextPos.getX() + Settings.islandDistance*2);
return nextPos;
}
nextPos.setZ(nextPos.getZ() + Settings.islandDistance*2);
return nextPos;
}
if (x > z) {
if (-1 * x >= z) {
nextPos.setX(nextPos.getX() - Settings.islandDistance*2);
return nextPos;
}
nextPos.setZ(nextPos.getZ() - Settings.islandDistance*2);
return nextPos;
}
if (x <= 0) {
nextPos.setZ(nextPos.getZ() + Settings.islandDistance*2);
return nextPos;
}
nextPos.setZ(nextPos.getZ() - Settings.islandDistance*2);
return nextPos;
}
}

View File

@ -13,8 +13,8 @@ import org.bukkit.World;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import us.tastybento.bskyblock.api.events.island.IslandLockEvent;
import us.tastybento.bskyblock.api.events.island.IslandUnlockEvent;
import us.tastybento.bskyblock.api.events.island.IslandEvent;
import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.util.Util;
@ -261,7 +261,7 @@ public class Island extends DataObject {
private Location center;
// Island range
private int range;
private int range = Settings.islandDistance;
// Coordinates of the island area
private int minX;
@ -320,8 +320,9 @@ public class Island extends DataObject {
this.updatedDate = System.currentTimeMillis();
this.world = location.getWorld();
this.center = location;
this.minX = center.getBlockX() - Settings.islandDistance;
this.minZ = center.getBlockZ() - Settings.islandDistance;
this.range = Settings.islandDistance;
this.minX = center.getBlockX() - range;
this.minZ = center.getBlockZ() - range;
this.protectionRange = protectionRange;
this.minProtectedX = center.getBlockX() - protectionRange;
this.minProtectedZ = center.getBlockZ() - protectionRange;
@ -534,11 +535,7 @@ public class Island extends DataObject {
*/
public boolean inIslandSpace(int x, int z) {
//Bukkit.getLogger().info("DEBUG: center - " + center);
if (x >= center.getBlockX() - Settings.islandDistance / 2 && x < center.getBlockX() + Settings.islandDistance / 2 && z >= center.getBlockZ() - Settings.islandDistance / 2
&& z < center.getBlockZ() + Settings.islandDistance / 2) {
return true;
}
return false;
return (x >= minX && x < minX + range*2 && z >= minZ && z < minZ + range*2) ? true: false;
}
/**
@ -578,9 +575,9 @@ public class Island extends DataObject {
* @return true if it is, false if not
*/
public boolean onIsland(Location target) {
if (center.getWorld() != null) {
if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange*2)
&& target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange*2)) {
if (center != null && center.getWorld() != null) {
if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange * 2)
&& target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange * 2)) {
return true;
}
}
@ -660,7 +657,7 @@ public class Island extends DataObject {
public void setLocked(boolean locked){
if(locked){
// Lock the island
IslandLockEvent event = new IslandLockEvent(this, null); // TODO: Maybe a custom CommandSender for BSkyBlock ?
IslandEvent event = IslandEvent.builder().island(this).reason(Reason.LOCK).build();
Bukkit.getServer().getPluginManager().callEvent(event);
if(!event.isCancelled()){
@ -668,7 +665,7 @@ public class Island extends DataObject {
}
} else {
// Unlock the island
IslandUnlockEvent event = new IslandUnlockEvent(this, null);
IslandEvent event = IslandEvent.builder().island(this).reason(Reason.UNLOCK).build();
Bukkit.getServer().getPluginManager().callEvent(event);
if(!event.isCancelled()){

View File

@ -18,7 +18,7 @@ import us.tastybento.bskyblock.config.Settings;
*/
public class Players extends DataObject {
private HashMap<Integer, Location> homeLocations;
private UUID uniqueId;
private String uniqueId;
private String playerName;
private int resetsLeft;
private String locale = "";
@ -37,7 +37,7 @@ public class Players extends DataObject {
*
*/
public Players(final UUID uniqueId) {
this.uniqueId = uniqueId;
this.uniqueId = uniqueId.toString();
this.homeLocations = new HashMap<>();
this.playerName = "";
this.resetsLeft = Settings.resetLimit;
@ -124,11 +124,11 @@ public class Players extends DataObject {
}
public Player getPlayer() {
return Bukkit.getPlayer(uniqueId);
return Bukkit.getPlayer(UUID.fromString(uniqueId));
}
public UUID getPlayerUUID() {
return uniqueId;
return UUID.fromString(uniqueId);
}
public String getPlayerName() {
@ -178,7 +178,7 @@ public class Players extends DataObject {
* @param uuid
*/
public void setPlayerUUID(final UUID uuid) {
this.uniqueId = uuid;
this.uniqueId = uuid.toString();
}
/**
@ -299,7 +299,9 @@ public class Players extends DataObject {
@Override
public void setUniqueId(String uniqueId) {
this.uniqueId = UUID.fromString(uniqueId);
//Bukkit.getLogger().info("DEBUG: uniqueId = " + uniqueId);
this.uniqueId = uniqueId;
//Bukkit.getLogger().info("DEBUG: UUID = " + this.uniqueId);
}
}

View File

@ -15,7 +15,7 @@ import org.bukkit.event.player.PlayerPortalEvent;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.managers.IslandsManager;
import us.tastybento.bskyblock.database.managers.island.IslandsManager;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
import us.tastybento.bskyblock.generators.IslandWorld;

View File

@ -75,8 +75,8 @@ import org.bukkit.util.BlockIterator;
import org.bukkit.util.Vector;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.events.island.IslandEnterEvent;
import us.tastybento.bskyblock.api.events.island.IslandExitEvent;
import us.tastybento.bskyblock.api.events.island.IslandEvent;
import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
@ -383,7 +383,12 @@ public class IslandGuard implements Listener {
}
}
// Fire entry event
final IslandEnterEvent event = new IslandEnterEvent(islandTo, e.getPlayer().getUniqueId(), e.getTo());
final IslandEvent event = IslandEvent.builder()
.island(islandTo)
.reason(Reason.ENTER)
.involvedPlayer(e.getPlayer().getUniqueId())
.location(e.getTo())
.build();
plugin.getServer().getPluginManager().callEvent(event);
} else if (islandTo == null && islandFrom != null && (islandFrom.getOwner() != null || islandFrom.isSpawn())) {
// Leaving
@ -397,7 +402,12 @@ public class IslandGuard implements Listener {
Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowleaving").replace("[name]", plugin.getIslands().getIslandName(islandFrom.getOwner()))); }
}
// Fire exit event
final IslandExitEvent event = new IslandExitEvent(islandFrom, e.getPlayer().getUniqueId(), e.getFrom());
final IslandEvent event = IslandEvent.builder()
.island(islandTo)
.reason(Reason.EXIT)
.involvedPlayer(e.getPlayer().getUniqueId())
.location(e.getFrom())
.build();
plugin.getServer().getPluginManager().callEvent(event);
} else if (islandTo != null && islandFrom != null && !islandTo.equals(islandFrom)) {
// Adjacent islands or overlapping protections
@ -421,10 +431,20 @@ public class IslandGuard implements Listener {
}
}
// Fire exit event
final IslandExitEvent event = new IslandExitEvent(islandFrom, e.getPlayer().getUniqueId(), e.getFrom());
final IslandEvent event = IslandEvent.builder()
.island(islandTo)
.reason(Reason.EXIT)
.involvedPlayer(e.getPlayer().getUniqueId())
.location(e.getFrom())
.build();
plugin.getServer().getPluginManager().callEvent(event);
// Fire entry event
final IslandEnterEvent event2 = new IslandEnterEvent(islandTo, e.getPlayer().getUniqueId(), e.getTo());
final IslandEvent event2 = IslandEvent.builder()
.island(islandTo)
.reason(Reason.ENTER)
.involvedPlayer(e.getPlayer().getUniqueId())
.location(e.getTo())
.build();
plugin.getServer().getPluginManager().callEvent(event2);
}
}

View File

@ -511,6 +511,7 @@ public class IslandBlock {
// Only paste air if it is below the sea level and in the overworld
Block block = new Location(blockLoc.getWorld(), x, y, z).add(blockLoc).getBlock();
block.setBiome(biome);
block.getChunk().load();
nms.setBlockSuperFast(block, typeId, data, usePhysics);
if (signText != null) {
if (block.getTypeId() != typeId) {

View File

@ -55,7 +55,7 @@ import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.config.Settings.GameType;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.util.DeleteIslandBlocks;
import us.tastybento.bskyblock.util.DeleteIslandChunks;
import us.tastybento.bskyblock.util.Util;
import us.tastybento.bskyblock.util.VaultHelper;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
@ -1092,7 +1092,7 @@ public class Schematic {
// Delete the old island if required
if (oldIsland != null) {
plugin.getLogger().info("DEBUG: Deleting old island");
new DeleteIslandBlocks(plugin, oldIsland);
new DeleteIslandChunks(plugin, oldIsland);
try {
plugin.getIslands().getHandler().deleteObject(oldIsland);
} catch (Exception e) {

View File

@ -1,253 +0,0 @@
package us.tastybento.bskyblock.util;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.scheduler.BukkitRunnable;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
//import com.wasteofplastic.askyblock.nms.NMSAbstraction;
/**
* Deletes islands fast using chunk regeneration
*
* @author tastybento
*
*/
public class DeleteIslandBlocks {
protected static final int CLEAN_RATE = 2;
private Set<Pair> chunksToClear = new HashSet<>();
//private HashMap<Location, Material> blocksToClear = new HashMap<Location,Material>();
private NMSAbstraction nms = null;
/**
* Deletes the island
* @param plugin
* @param island
*/
public DeleteIslandBlocks(final BSkyBlock plugin, final Island island) {
plugin.getLogger().info("DEBUG: deleting the island");
final World world = island.getCenter().getWorld();
if (world == null)
return;
// Determine if blocks need to be cleaned up or not
boolean cleanUpBlocks = false;
plugin.getLogger().info("DEBUG: island protection = " + island.getProtectionRange());
// DEBUG
island.setProtectionRange(Settings.islandDistance);
if (Settings.islandDistance - island.getProtectionRange() < 16) {
cleanUpBlocks = true;
}
int range = island.getProtectionRange() / 2 * +1;
final int minx = island.getMinProtectedX();
final int minz = island.getMinProtectedZ();
final int maxx = island.getMinProtectedX() + island.getProtectionRange();
final int maxz = island.getMinProtectedZ() + island.getProtectionRange();
plugin.getLogger().info("DEBUG: protection limits are: " + minx + ", " + minz + " to " + maxx + ", " + maxz );
int islandSpacing = Settings.islandDistance - island.getProtectionRange();
int minxX = (island.getCenter().getBlockX() - range - islandSpacing);
int minzZ = (island.getCenter().getBlockZ() - range - islandSpacing);
int maxxX = (island.getCenter().getBlockX() + range + islandSpacing);
int maxzZ = (island.getCenter().getBlockZ() + range + islandSpacing);
// plugin.getLogger().info("DEBUG: absolute max limits are: " + minxX +
// ", " + minzZ + " to " + maxxX + ", " + maxzZ );
// get the chunks for these locations
final Chunk minChunk = world.getBlockAt(minx,0,minz).getChunk();
final Chunk maxChunk = world.getBlockAt(maxx, 0, maxz).getChunk();
// Find out what chunks are within the island protection range
// plugin.getLogger().info("DEBUG: chunk limits are: " +
// (minChunk.getBlock(0, 0, 0).getLocation().getBlockX()) + ", " +
// (minChunk.getBlock(0, 0, 0).getLocation().getBlockZ())
// + " to " + (maxChunk.getBlock(15, 0, 15).getLocation().getBlockX()) +
// ", " + (maxChunk.getBlock(15, 0, 15).getLocation().getBlockZ()));
for (int x = minChunk.getX(); x <= maxChunk.getX(); x++) {
for (int z = minChunk.getZ(); z <= maxChunk.getZ(); z++) {
boolean regen = true;
if (world.getChunkAt(x, z).getBlock(0, 0, 0).getX() < minxX) {
// plugin.getLogger().info("DEBUG: min x coord is less than absolute min! "
// + minxX);
regen = false;
}
if (world.getChunkAt(x, z).getBlock(0, 0, 0).getZ() < minzZ) {
// plugin.getLogger().info("DEBUG: min z coord is less than absolute min! "
// + minzZ);
regen = false;
}
if (world.getChunkAt(x, z).getBlock(15, 0, 15).getX() > maxxX) {
// plugin.getLogger().info("DEBUG: max x coord is more than absolute max! "
// + maxxX);
regen = false;
}
if (world.getChunkAt(x, z).getBlock(15, 0, 15).getZ() > maxzZ) {
// plugin.getLogger().info("DEBUG: max z coord in chunk is more than absolute max! "
// + maxzZ);
regen = false;
}
if (regen) {
world.regenerateChunk(x, z);
if (Settings.netherIslands && Settings.netherGenerate) {
if (world.equals(IslandWorld.getIslandWorld())) {
IslandWorld.getNetherWorld().regenerateChunk(x, z);
}
if (world.equals(IslandWorld.getNetherWorld())) {
IslandWorld.getIslandWorld().regenerateChunk(x, z);
}
}
} else {
// Add to clear up list if requested
if (cleanUpBlocks) {
chunksToClear.add(new Pair(x,z));
}
}
}
}
// Do not do this: Remove from database
//plugin.getIslands().deleteIsland(island.getCenter());
// Clear up any chunks
if (!chunksToClear.isEmpty()) {
try {
nms = Util.getNMSHandler();
} catch (Exception ex) {
plugin.getLogger().warning("Cannot clean up blocks because there is no NMS acceleration available");
return;
}
plugin.getLogger().info("Island delete: There are " + chunksToClear.size() + " chunks that need to be cleared up.");
plugin.getLogger().info("Clean rate is " + CLEAN_RATE + " chunks per second. Should take ~" + Math.round(chunksToClear.size()/CLEAN_RATE) + "s");
new BukkitRunnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
Iterator<Pair> it = chunksToClear.iterator();
int count = 0;
while (it.hasNext() && count++ < CLEAN_RATE) {
Pair pair = it.next();
//plugin.getLogger().info("DEBUG: There are " + chunksToClear.size() + " chunks that need to be cleared up");
//plugin.getLogger().info("DEBUG: Deleting chunk " + pair.getLeft() + ", " + pair.getRight());
// Check if coords are in island space
for (int x = 0; x < 16; x ++) {
for (int z = 0; z < 16; z ++) {
int xCoord = pair.getLeft() * 16 + x;
int zCoord = pair.getRight() * 16 + z;
if (island.inIslandSpace(xCoord, zCoord)) {
//plugin.getLogger().info(xCoord + "," + zCoord + " is in island space - deleting column");
// Delete all the blocks here
for (int y = 0; y < IslandWorld.getIslandWorld().getMaxHeight(); y ++) {
// Overworld
Block b = IslandWorld.getIslandWorld().getBlockAt(xCoord, y, zCoord);
Material bt = b.getType();
Material setTo = Material.AIR;
// Split depending on below or above water line
if (y < Settings.seaHeight) {
setTo = Material.STATIONARY_WATER;
}
// Grab anything out of containers (do that it is
// destroyed)
switch (bt) {
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case HOPPER:
final InventoryHolder ih = ((InventoryHolder)b.getState());
ih.getInventory().clear();
b.setType(setTo);
break;
case AIR:
if (setTo.equals(Material.STATIONARY_WATER)) {
nms.setBlockSuperFast(b, setTo.getId(), (byte)0, false);
}
case STATIONARY_WATER:
if (setTo.equals(Material.AIR)) {
nms.setBlockSuperFast(b, setTo.getId(), (byte)0, false);
}
default:
nms.setBlockSuperFast(b, setTo.getId(), (byte)0, false);
break;
}
// Nether, if it exists
if (Settings.netherIslands && Settings.netherGenerate && y < IslandWorld.getNetherWorld().getMaxHeight() - 8) {
b = IslandWorld.getNetherWorld().getBlockAt(xCoord, y, zCoord);
bt = b.getType();
if (!bt.equals(Material.AIR)) {
setTo = Material.AIR;
// Grab anything out of containers (do that it is
// destroyed)
switch (bt) {
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case HOPPER:
final InventoryHolder ih = ((InventoryHolder)b.getState());
ih.getInventory().clear();
b.setType(setTo);
break;
default:
nms.setBlockSuperFast(b, setTo.getId(), (byte)0, false);
break;
}
}
}
}
}
}
}
it.remove();
}
if (chunksToClear.isEmpty()){
plugin.getLogger().info("Finished island deletion");
this.cancel();
}
}
}.runTaskTimer(plugin, 0L, 20L);
}
}
/**
* Class that pairs two ints together
* @author tastybento
*
*/
public class Pair {
private final int left;
private final int right;
public Pair(int left, int right) {
this.left = left;
this.right = right;
}
public int getLeft() {
return left;
}
public int getRight() {
return right;
}
@Override
public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof Pair))
return false;
Pair pairo = (Pair) o;
return (this.left == pairo.getLeft()) && (this.right == pairo.getRight());
}
}
}

View File

@ -0,0 +1,59 @@
package us.tastybento.bskyblock.util;
import org.bukkit.World;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.events.island.IslandEvent;
import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.generators.IslandWorld;
//import com.wasteofplastic.askyblock.nms.NMSAbstraction;
/**
* Deletes islands fast using chunk regeneration
*
* @author tastybento
*
*/
public class DeleteIslandChunks {
/**
* Deletes the island
* @param plugin
* @param island
*/
public DeleteIslandChunks(final BSkyBlock plugin, final Island island) {
plugin.getLogger().info("DEBUG: deleting the island");
// Fire event
IslandEvent event = IslandEvent.builder().island(island).reason(Reason.DELETE).build();
plugin.getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
return;
final World world = island.getCenter().getWorld();
if (world == null)
return;
int minXChunk = island.getMinX() / 16;
int maxXChunk = (island.getRange() * 2 + island.getMinX() - 1) /16;
int minZChunk = island.getMinZ() / 16;
int maxZChunk = (island.getRange() * 2 + island.getMinZ() - 1) /16;
for (int x = minXChunk; x <= maxXChunk; x++) {
for (int z = minZChunk; z<=maxZChunk; z++) {
world.regenerateChunk(x, z);
if (Settings.netherIslands && Settings.netherGenerate) {
IslandWorld.getNetherWorld().regenerateChunk(x, z);
}
if (Settings.endIslands && Settings.endGenerate) {
IslandWorld.getEndWorld().regenerateChunk(x, z);
}
}
}
// Fire event
IslandEvent event1 = IslandEvent.builder().island(island).reason(Reason.DELETED).build();
plugin.getServer().getPluginManager().callEvent(event1);
}
}