diff --git a/pom.xml b/pom.xml
index 5a49d06..b894d55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,12 @@
commons-lang3
3.0
+
+ org.jetbrains
+ annotations
+ 17.0.0
+ compile
+
\ No newline at end of file
diff --git a/src/main/java/ru/meloncode/xmas/Events.java b/src/main/java/ru/meloncode/xmas/Events.java
index b295654..5ce427c 100644
--- a/src/main/java/ru/meloncode/xmas/Events.java
+++ b/src/main/java/ru/meloncode/xmas/Events.java
@@ -13,13 +13,16 @@
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
+import org.jetbrains.annotations.Nullable;
import ru.meloncode.xmas.utils.TextUtils;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -293,4 +296,17 @@ private void disableFireworkDamage(EntityDamageByEntityEvent e)
}
}
}
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ private void chunkLoad(ChunkLoadEvent e)
+ {
+ Collection trees = XMas.getAllTreesInChunk(e.getChunk());
+ if(trees == null)
+ return;
+ for(MagicTree tree : trees)
+ {
+ if(tree.hasScheduledPresents())
+ tree.spawnScheduledPresents();
+ }
+ }
}
diff --git a/src/main/java/ru/meloncode/xmas/MagicTree.java b/src/main/java/ru/meloncode/xmas/MagicTree.java
index 80884a0..da86ce7 100644
--- a/src/main/java/ru/meloncode/xmas/MagicTree.java
+++ b/src/main/java/ru/meloncode/xmas/MagicTree.java
@@ -21,11 +21,11 @@ public class MagicTree {
private final UUID owner;
private final Location location;
private final UUID treeuid;
- private final Set presents = new HashSet<>();
TreeLevel level;
private Map levelupRequirements;
private Set blocks;
- private long presentCounter = 0;
+ private long presentCounter;
+ private int scheduledPresents;
public MagicTree(UUID owner, TreeLevel level, Location location) {
this.treeuid = UUID.randomUUID();
@@ -35,16 +35,22 @@ public MagicTree(UUID owner, TreeLevel level, Location location) {
this.levelupRequirements = new HashMap<>(level.getLevelupRequirements());
if (Main.inProgress)
build();
+ presentCounter = 0;
+ scheduledPresents = 0;
}
- public MagicTree(UUID owner, UUID uid, TreeLevel level, Location location, Map levelupRequirements) {
+ public MagicTree(UUID owner, UUID uid, TreeLevel level, Location location, Map levelupRequirements,
+ long presentCounter, int scheduledPresents) {
this.owner = owner;
this.treeuid = uid;
this.level = level;
this.location = location;
this.levelupRequirements = new HashMap<>(levelupRequirements);
+ this.presentCounter = 0;
+ this.presentCounter = presentCounter;
if (Main.inProgress)
build();
+ this.scheduledPresents = scheduledPresents;
}
public static MagicTree getTreeByBlock(Block block) {
@@ -186,29 +192,35 @@ public void build() {
@SuppressWarnings("deprecation")
public void spawnPresent() {
+ if(!location.getWorld().isChunkLoaded((int)location.getX() / 16, (int)location.getZ() / 16))
+ {
+ if(scheduledPresents + 1 <= 8)
+ scheduledPresents++;
+ return;
+ }
+
Location presentLoc = location.clone().add(-1 + Main.RANDOM.nextInt(3), 0, -1 + Main.RANDOM.nextInt(3));
Block pBlock = presentLoc.getBlock();
- if (presents.size() <= 3) {
- if (!pBlock.getType().isSolid() && pBlock.getType() != Material.SPRUCE_SAPLING) {
- pBlock.setType(Material.PLAYER_HEAD);
- BlockState state = pBlock.getState();
- if (state instanceof Skull) {
- Skull skull = (Skull) state;
- BlockFace face;
- do {
- face = BlockFace.values()[Main.RANDOM.nextInt(BlockFace.values().length)];
- }
- while (face == BlockFace.DOWN || face == BlockFace.UP || face == BlockFace.SELF);
- //skull.setRotation(face);
- Rotatable skullRotatable = (Rotatable) skull.getBlockData();
- skullRotatable.setRotation(face);
- //skull.setSkullType(SkullType.PLAYER);
- skull.setType(Material.PLAYER_HEAD);
- //skull.setOwner();
- skull.setOwningPlayer(Bukkit.getOfflinePlayer(Main.getHeads().get(Main.RANDOM.nextInt(Main.getHeads().size()))));
- skull.update(true);
+ if (!pBlock.getType().isSolid() && pBlock.getType() != Material.SPRUCE_SAPLING)
+ {
+ pBlock.setType(Material.PLAYER_HEAD);
+ BlockState state = pBlock.getState();
+ if (state instanceof Skull) {
+ Skull skull = (Skull) state;
+ BlockFace face;
+ do {
+ face = BlockFace.values()[Main.RANDOM.nextInt(BlockFace.values().length)];
}
+ while (face == BlockFace.DOWN || face == BlockFace.UP || face == BlockFace.SELF);
+ //skull.setRotation(face);
+ Rotatable skullRotatable = (Rotatable) skull.getBlockData();
+ skullRotatable.setRotation(face);
+ //skull.setSkullType(SkullType.PLAYER);
+ skull.setType(Material.PLAYER_HEAD);
+ //skull.setOwner();
+ skull.setOwningPlayer(Bukkit.getOfflinePlayer(Main.getHeads().get(Main.RANDOM.nextInt(Main.getHeads().size()))));
+ skull.update(true);
}
}
}
@@ -279,4 +291,22 @@ public void end() {
}
XMas.removeTree(this);
}
+
+ public long getPresentCounter() {
+ return presentCounter;
+ }
+
+ public int getScheduledPresents() {
+ return scheduledPresents;
+ }
+
+ public boolean hasScheduledPresents() {
+ return scheduledPresents > 0;
+ }
+
+ public void spawnScheduledPresents() {
+ for(int i = scheduledPresents; i > 0; i--)
+ spawnPresent();
+ scheduledPresents = 0;
+ }
}
diff --git a/src/main/java/ru/meloncode/xmas/TreeSerializer.java b/src/main/java/ru/meloncode/xmas/TreeSerializer.java
index 79bf0d6..b4108d9 100644
--- a/src/main/java/ru/meloncode/xmas/TreeSerializer.java
+++ b/src/main/java/ru/meloncode/xmas/TreeSerializer.java
@@ -26,6 +26,8 @@ public static void loadTrees(JavaPlugin plugin, World world) {
TreeLevel level;
int x, y, z;
Location loc;
+ long presentCounter;
+ int scheduledPresents;
if (trees.getConfigurationSection("trees") != null && trees.getConfigurationSection("trees").getKeys(false).size() > 0) {
for (String cKey : trees.getConfigurationSection("trees").getKeys(false)) {
@@ -44,7 +46,10 @@ public static void loadTrees(JavaPlugin plugin, World world) {
} else {
requirements = new HashMap<>();
}
- XMas.addMagicTree(new MagicTree(owner, treeUID, level, loc, requirements));
+ presentCounter = trees.getLong("trees." + cKey + ".present_counter", 0);
+ scheduledPresents = trees.getInt("trees." + cKey + ".scheduled_presents", 0);
+
+ XMas.addMagicTree(new MagicTree(owner, treeUID, level, loc, requirements, presentCounter, scheduledPresents));
} catch (Exception e) {
plugin.getLogger().severe(String.format("Error while loading tree `%s`", cKey));
e.printStackTrace();
@@ -76,6 +81,8 @@ public static void saveTree(MagicTree tree) {
} catch (IOException e) {
e.printStackTrace();
}
+ trees.set("trees." + cKey + ".present_counter", tree.getPresentCounter());
+ trees.set("trees." + cKey + ".scheduled_presents", tree.getScheduledPresents());
}
public static void removeTree(MagicTree tree) {
diff --git a/src/main/java/ru/meloncode/xmas/XMas.java b/src/main/java/ru/meloncode/xmas/XMas.java
index e0c24a2..7335851 100644
--- a/src/main/java/ru/meloncode/xmas/XMas.java
+++ b/src/main/java/ru/meloncode/xmas/XMas.java
@@ -1,5 +1,6 @@
package ru.meloncode.xmas;
+import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@@ -7,6 +8,8 @@
import org.bukkit.block.Skull;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.Nullable;
+import ru.meloncode.xmas.utils.LocationUtils;
import ru.meloncode.xmas.utils.TextUtils;
import java.util.ArrayList;
@@ -20,11 +23,13 @@
class XMas {
private static final ConcurrentHashMap trees = new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap> trees_byChunk = new ConcurrentHashMap<>();
public static ItemStack XMAS_CRYSTAL;
public static void createMagicTree(Player player, Location loc) {
MagicTree tree = new MagicTree(player.getUniqueId(), TreeLevel.SAPLING, loc);
trees.put(tree.getTreeUID(), tree);
+ trees_byChunk.computeIfAbsent(LocationUtils.getChunkKey(tree.getLocation()), aLong -> new ArrayList<>()).add(tree);
tree.save();
}
@@ -37,10 +42,16 @@ public static Collection getAllTrees() {
return trees.values();
}
+ @Nullable
+ public static Collection getAllTreesInChunk(Chunk chunk) {
+ return trees_byChunk.get(LocationUtils.getChunkKey(chunk));
+ }
+
public static void removeTree(MagicTree tree) {
tree.unbuild();
TreeSerializer.removeTree(tree);
trees.remove(tree.getTreeUID());
+ trees_byChunk.remove(LocationUtils.getChunkKey(tree.getLocation()));
}
public static void processPresent(Block block, Player player) {
diff --git a/src/main/java/ru/meloncode/xmas/utils/LocationUtils.java b/src/main/java/ru/meloncode/xmas/utils/LocationUtils.java
new file mode 100644
index 0000000..f6b8283
--- /dev/null
+++ b/src/main/java/ru/meloncode/xmas/utils/LocationUtils.java
@@ -0,0 +1,24 @@
+package ru.meloncode.xmas.utils;
+
+import org.bukkit.Chunk;
+import org.bukkit.Location;
+
+public class LocationUtils {
+ public static long getChunkKey(Chunk chunk) {
+ return getChunkKey(chunk.getX(), chunk.getZ());
+ }
+ public static long getChunkKey(Location location) {
+ return getChunkKey(location.getBlockX(), location.getBlockZ());
+ }
+
+ public static long getChunkKey(int x, int z) {
+ x = floor(x) >> 4;
+ z = floor(z) >> 4;
+ return (((long) x) << 32) | (z & 0xFFFFFFFFL);
+ }
+
+ public static int floor(double num) {
+ int floor = (int) num;
+ return floor == num ? floor : floor - (int) (Double.doubleToRawLongBits(num) >>> 63);
+ }
+}