mirror of
https://github.com/BG-Software-LLC/WildLoaders.git
synced 2024-11-23 12:05:22 +01:00
Do not keep references of World objects & handle cases when worlds are loaded & unloaded
This commit is contained in:
parent
f22df7c611
commit
328212b0ca
@ -2,12 +2,28 @@ package com.bgsoftware.wildloaders.api.hooks;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface TickableProvider {
|
||||
|
||||
/**
|
||||
* Simulate a tick on a list of provided chunks.
|
||||
*
|
||||
* @param chunks The chunks to tick.
|
||||
* @deprecated See {@link #tick(Collection)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void tick(Chunk[] chunks) {
|
||||
throw new UnsupportedOperationException("TickableProvider#tick is not supported anymore");
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate a tick on a list of provided chunks.
|
||||
*
|
||||
* @param chunks The chunks to tick.
|
||||
*/
|
||||
void tick(Chunk[] chunks);
|
||||
default void tick(Collection<Chunk> chunks) {
|
||||
tick(chunks.toArray(new Chunk[0]));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,9 +34,17 @@ public interface ChunkLoader {
|
||||
|
||||
/**
|
||||
* Get the chunks that this chunk-loader is loading.
|
||||
*
|
||||
* @deprecated See {@link #getLoadedChunksCollection()}
|
||||
*/
|
||||
@Deprecated
|
||||
Chunk[] getLoadedChunks();
|
||||
|
||||
/**
|
||||
* Get the chunks that this chunk-loader is loading.
|
||||
*/
|
||||
Collection<Chunk> getLoadedChunksCollection();
|
||||
|
||||
/**
|
||||
* Get the NPC of this chunk loader.
|
||||
*/
|
||||
|
@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Set;
|
||||
|
||||
public final class TickableProvider_EpicSpawners6 implements TickableProvider {
|
||||
|
||||
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void tick(Chunk[] chunks) {
|
||||
public void tick(Collection<Chunk> chunks) {
|
||||
if (EpicSpawners.getInstance().getSpawnerManager() == null)
|
||||
return;
|
||||
|
||||
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList());
|
||||
Set<Long> chunkKeys = new HashSet<>();
|
||||
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
|
||||
|
||||
EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream()
|
||||
.filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.forEach(spawner -> {
|
||||
Location location = spawner.getLocation();
|
||||
TickDelay tickDelay = spawnerDelays.get(location);
|
||||
|
@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Set;
|
||||
|
||||
public final class TickableProvider_EpicSpawners7 implements TickableProvider {
|
||||
|
||||
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void tick(Chunk[] chunks) {
|
||||
public void tick(Collection<Chunk> chunks) {
|
||||
if (EpicSpawners.getInstance().getSpawnerManager() == null)
|
||||
return;
|
||||
|
||||
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList());
|
||||
Set<Long> chunkKeys = new HashSet<>();
|
||||
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
|
||||
|
||||
EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream()
|
||||
.filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.forEach(spawner -> {
|
||||
Location location = spawner.getLocation();
|
||||
TickDelay tickDelay = spawnerDelays.get(location);
|
||||
|
@ -5,25 +5,26 @@ import com.craftaro.epicspawners.api.EpicSpawnersApi;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Set;
|
||||
|
||||
public final class TickableProvider_EpicSpawners8 implements TickableProvider {
|
||||
|
||||
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void tick(Chunk[] chunks) {
|
||||
public void tick(Collection<Chunk> chunks) {
|
||||
if (EpicSpawnersApi.getSpawnerManager() == null)
|
||||
return;
|
||||
|
||||
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList());
|
||||
Set<Long> chunkKeys = new HashSet<>();
|
||||
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
|
||||
|
||||
EpicSpawnersApi.getSpawnerManager().getSpawners().stream()
|
||||
.filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4)))
|
||||
.forEach(spawner -> {
|
||||
Location location = spawner.getLocation();
|
||||
TickDelay tickDelay = spawnerDelays.get(location);
|
||||
|
@ -2,18 +2,16 @@ package com.bgsoftware.wildloaders.handlers;
|
||||
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks;
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
import com.bgsoftware.wildloaders.utils.ServerVersion;
|
||||
import com.bgsoftware.wildloaders.utils.database.Database;
|
||||
import com.bgsoftware.wildloaders.utils.locations.LocationUtils;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -38,16 +36,16 @@ public final class DataHandler {
|
||||
Database.executeUpdate("CREATE TABLE IF NOT EXISTS npc_identifiers (location TEXT NOT NULL PRIMARY KEY, uuid TEXT NOT NULL);");
|
||||
Database.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
Location location = LocationUtils.getLocation(resultSet.getString("location"));
|
||||
BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location"));
|
||||
UUID uuid = UUID.fromString(resultSet.getString("uuid"));
|
||||
plugin.getNPCs().registerUUID(location, uuid);
|
||||
plugin.getNPCs().registerUUID(blockPosition, uuid);
|
||||
}
|
||||
});
|
||||
|
||||
Database.executeUpdate("CREATE TABLE IF NOT EXISTS chunk_loaders (location TEXT NOT NULL PRIMARY KEY, placer TEXT NOT NULL, loader_data TEXT NOT NULL, timeLeft BIGINT NOT NULL);");
|
||||
Database.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
Location location = LocationUtils.getLocation(resultSet.getString("location"));
|
||||
BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location"));
|
||||
UUID placer = UUID.fromString(resultSet.getString("placer"));
|
||||
Optional<LoaderData> loaderData = plugin.getLoaders().getLoaderData(resultSet.getString("loader_data"));
|
||||
long timeLeft = resultSet.getLong("timeLeft");
|
||||
@ -55,21 +53,14 @@ public final class DataHandler {
|
||||
if (!loaderData.isPresent())
|
||||
continue;
|
||||
|
||||
Material blockType = location.getBlock().getType();
|
||||
|
||||
if (ServerVersion.isLegacy() && blockType == Material.CAULDRON) {
|
||||
blockType = Material.CAULDRON_ITEM;
|
||||
World world = blockPosition.getWorld();
|
||||
if (world != null) {
|
||||
Location location = blockPosition.getLocation();
|
||||
plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer,
|
||||
location, timeLeft, true);
|
||||
} else {
|
||||
plugin.getLoaders().addUnloadedChunkLoader(loaderData.get(), placer, blockPosition, timeLeft);
|
||||
}
|
||||
|
||||
if (blockType != loaderData.get().getLoaderItem().getType()) {
|
||||
WildLoadersPlugin.log("The chunk-loader at " + LocationUtils.getLocation(location) + " is invalid.");
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Chunk> chunksToLoad = ChunkLoaderChunks.calculateChunks(loaderData.get(), placer, location);
|
||||
chunksToLoad.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent());
|
||||
|
||||
plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer, location, timeLeft, chunksToLoad);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,19 +4,25 @@ import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.api.managers.LoadersManager;
|
||||
import com.bgsoftware.wildloaders.loaders.UnloadedChunkLoader;
|
||||
import com.bgsoftware.wildloaders.loaders.WChunkLoader;
|
||||
import com.bgsoftware.wildloaders.loaders.WLoaderData;
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks;
|
||||
import com.bgsoftware.wildloaders.utils.ServerVersion;
|
||||
import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -24,8 +30,10 @@ import java.util.UUID;
|
||||
|
||||
public final class LoadersHandler implements LoadersManager {
|
||||
|
||||
private final Map<Location, ChunkLoader> chunkLoaders = Maps.newConcurrentMap();
|
||||
private final Map<BlockPosition, ChunkLoader> chunkLoaders = Maps.newConcurrentMap();
|
||||
private final Map<ChunkPosition, ChunkLoader> chunkLoadersByChunks = Maps.newConcurrentMap();
|
||||
private final Map<String, List<ChunkLoader>> chunkLoadersByWorlds = Maps.newConcurrentMap();
|
||||
private final Map<String, List<UnloadedChunkLoader>> unloadedChunkLoadersByWorlds = Maps.newConcurrentMap();
|
||||
private final Map<String, LoaderData> loadersData = Maps.newConcurrentMap();
|
||||
private final WildLoadersPlugin plugin;
|
||||
|
||||
@ -40,12 +48,12 @@ public final class LoadersHandler implements LoadersManager {
|
||||
|
||||
@Override
|
||||
public Optional<ChunkLoader> getChunkLoader(Location location) {
|
||||
return Optional.ofNullable(chunkLoaders.get(location));
|
||||
return Optional.ofNullable(chunkLoaders.get(BlockPosition.of(location)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChunkLoader> getChunkLoaders() {
|
||||
return Collections.unmodifiableList(new ArrayList<>(chunkLoaders.values()));
|
||||
return Collections.unmodifiableList(new LinkedList<>(chunkLoaders.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,41 +68,117 @@ public final class LoadersHandler implements LoadersManager {
|
||||
|
||||
@Override
|
||||
public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) {
|
||||
WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(), location, timeLeft,
|
||||
ChunkLoaderChunks.calculateChunks(loaderData, whoPlaced.getUniqueId(), location));
|
||||
BlockPosition blockPosition = BlockPosition.of(location);
|
||||
|
||||
WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(),
|
||||
location, timeLeft, false);
|
||||
|
||||
Query.INSERT_CHUNK_LOADER.insertParameters()
|
||||
.setLocation(location)
|
||||
.setLocation(blockPosition)
|
||||
.setObject(whoPlaced.getUniqueId().toString())
|
||||
.setObject(loaderData.getName())
|
||||
.setObject(timeLeft)
|
||||
.queue(location);
|
||||
.queue(blockPosition);
|
||||
|
||||
return chunkLoader;
|
||||
}
|
||||
|
||||
public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location, long timeLeft, List<Chunk> loadedChunks) {
|
||||
WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, location, loadedChunks.toArray(new Chunk[0]), timeLeft);
|
||||
chunkLoaders.put(location, chunkLoader);
|
||||
for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) {
|
||||
public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location,
|
||||
long timeLeft, boolean validateBlock) {
|
||||
BlockPosition blockPosition = BlockPosition.of(location);
|
||||
|
||||
if (validateBlock) {
|
||||
Material blockType = location.getBlock().getType();
|
||||
|
||||
if (ServerVersion.isLegacy() && blockType == Material.CAULDRON) {
|
||||
blockType = Material.CAULDRON_ITEM;
|
||||
}
|
||||
|
||||
if (blockType != loaderData.getLoaderItem().getType()) {
|
||||
WildLoadersPlugin.log("The chunk-loader at " + blockPosition.serialize() + " is invalid.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<Chunk> loadedChunks = ChunkLoaderChunks.calculateChunks(loaderData, placer, location);
|
||||
loadedChunks.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent());
|
||||
|
||||
WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, blockPosition, loadedChunks, timeLeft);
|
||||
chunkLoaders.put(blockPosition, chunkLoader);
|
||||
chunkLoadersByWorlds.computeIfAbsent(blockPosition.getWorldName(), i -> new LinkedList<>()).add(chunkLoader);
|
||||
for (Chunk loadedChunk : chunkLoader.getLoadedChunksCollection()) {
|
||||
chunkLoadersByChunks.put(ChunkPosition.of(loadedChunk), chunkLoader);
|
||||
}
|
||||
plugin.getNPCs().createNPC(location);
|
||||
plugin.getNPCs().createNPC(blockPosition);
|
||||
return chunkLoader;
|
||||
}
|
||||
|
||||
public void addUnloadedChunkLoader(LoaderData loaderData, UUID placer, BlockPosition blockPosition, long timeLeft) {
|
||||
UnloadedChunkLoader unloadedChunkLoader = new UnloadedChunkLoader(loaderData, placer, blockPosition, timeLeft);
|
||||
unloadedChunkLoadersByWorlds.computeIfAbsent(blockPosition.getWorldName(), i -> new LinkedList<>())
|
||||
.add(unloadedChunkLoader);
|
||||
}
|
||||
|
||||
public void loadUnloadedChunkLoaders(World world) {
|
||||
List<UnloadedChunkLoader> unloadedChunkLoaders = this.unloadedChunkLoadersByWorlds.remove(world.getName());
|
||||
if (unloadedChunkLoaders == null || unloadedChunkLoaders.isEmpty())
|
||||
return;
|
||||
|
||||
unloadedChunkLoaders.forEach(unloadedChunkLoader -> {
|
||||
Location location = unloadedChunkLoader.getBlockPosition().getLocation();
|
||||
if (location.getWorld() != world)
|
||||
throw new IllegalStateException();
|
||||
|
||||
addChunkLoaderWithoutDBSave(unloadedChunkLoader.getLoaderData(), unloadedChunkLoader.getPlacer(),
|
||||
location, unloadedChunkLoader.getTimeLeft(), true);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void unloadWorld(World world) {
|
||||
List<ChunkLoader> worldChunkLoaders = this.chunkLoadersByWorlds.remove(world.getName());
|
||||
if (worldChunkLoaders == null || worldChunkLoaders.isEmpty())
|
||||
return;
|
||||
|
||||
List<UnloadedChunkLoader> unloadedChunkLoaders = new LinkedList<>();
|
||||
|
||||
worldChunkLoaders.forEach(chunkLoader -> {
|
||||
plugin.getNMSAdapter().removeLoader(chunkLoader, false);
|
||||
BlockPosition blockPosition = removeChunkLoaderWithoutDBSave(chunkLoader);
|
||||
UnloadedChunkLoader unloadedChunkLoader = new UnloadedChunkLoader(chunkLoader.getLoaderData(),
|
||||
chunkLoader.getWhoPlaced().getUniqueId(), blockPosition, chunkLoader.getTimeLeft());
|
||||
unloadedChunkLoaders.add(unloadedChunkLoader);
|
||||
|
||||
Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters()
|
||||
.setObject(unloadedChunkLoader.getTimeLeft())
|
||||
.setLocation(blockPosition)
|
||||
.queue(blockPosition);
|
||||
});
|
||||
|
||||
this.unloadedChunkLoadersByWorlds.put(world.getName(), unloadedChunkLoaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChunkLoader(ChunkLoader chunkLoader) {
|
||||
Location location = chunkLoader.getLocation();
|
||||
chunkLoaders.remove(location);
|
||||
for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) {
|
||||
BlockPosition blockPosition = removeChunkLoaderWithoutDBSave(chunkLoader);
|
||||
Query.DELETE_CHUNK_LOADER.insertParameters()
|
||||
.setLocation(blockPosition)
|
||||
.queue(blockPosition);
|
||||
}
|
||||
|
||||
private BlockPosition removeChunkLoaderWithoutDBSave(ChunkLoader chunkLoader) {
|
||||
BlockPosition blockPosition = BlockPosition.of(chunkLoader.getLocation());
|
||||
chunkLoaders.remove(blockPosition);
|
||||
for (Chunk loadedChunk : chunkLoader.getLoadedChunksCollection()) {
|
||||
chunkLoadersByChunks.remove(ChunkPosition.of(loadedChunk));
|
||||
}
|
||||
chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc));
|
||||
|
||||
Query.DELETE_CHUNK_LOADER.insertParameters()
|
||||
.setLocation(location)
|
||||
.queue(location);
|
||||
List<ChunkLoader> worldChunkLoaders = chunkLoadersByWorlds.get(blockPosition.getWorldName());
|
||||
if (worldChunkLoaders != null)
|
||||
worldChunkLoaders.remove(chunkLoader);
|
||||
|
||||
chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc));
|
||||
return blockPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -114,5 +198,6 @@ public final class LoadersHandler implements LoadersManager {
|
||||
chunkLoaders.values().forEach(chunkLoader -> plugin.getNMSAdapter().removeLoader(chunkLoader, false));
|
||||
chunkLoaders.clear();
|
||||
chunkLoadersByChunks.clear();
|
||||
chunkLoadersByWorlds.clear();
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.bgsoftware.wildloaders.handlers;
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.api.managers.NPCManager;
|
||||
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC;
|
||||
import com.bgsoftware.wildloaders.npc.NPCIdentifier;
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Location;
|
||||
@ -21,8 +21,8 @@ public final class NPCHandler implements NPCManager {
|
||||
private static int NPCS_COUNTER = 0;
|
||||
|
||||
private final WildLoadersPlugin plugin;
|
||||
private final Map<NPCIdentifier, ChunkLoaderNPC> npcs = Maps.newConcurrentMap();
|
||||
private final Map<NPCIdentifier, UUID> npcUUIDs = Maps.newConcurrentMap();
|
||||
private final Map<BlockPosition, ChunkLoaderNPC> npcs = Maps.newConcurrentMap();
|
||||
private final Map<BlockPosition, UUID> npcUUIDs = Maps.newConcurrentMap();
|
||||
|
||||
|
||||
public NPCHandler(WildLoadersPlugin plugin) {
|
||||
@ -31,13 +31,21 @@ public final class NPCHandler implements NPCManager {
|
||||
|
||||
@Override
|
||||
public Optional<ChunkLoaderNPC> getNPC(Location location) {
|
||||
return Optional.ofNullable(npcs.get(new NPCIdentifier(location)));
|
||||
return getNPC(BlockPosition.of(location));
|
||||
}
|
||||
|
||||
public Optional<ChunkLoaderNPC> getNPC(BlockPosition blockPosition) {
|
||||
return Optional.ofNullable(npcs.get(blockPosition));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkLoaderNPC createNPC(Location location) {
|
||||
return npcs.computeIfAbsent(new NPCIdentifier(location), i -> {
|
||||
ChunkLoaderNPC npc = plugin.getNMSAdapter().createNPC(i.getSpawnLocation(), getUUID(i));
|
||||
return createNPC(BlockPosition.of(location));
|
||||
}
|
||||
|
||||
public ChunkLoaderNPC createNPC(BlockPosition blockPosition) {
|
||||
return npcs.computeIfAbsent(blockPosition, i -> {
|
||||
ChunkLoaderNPC npc = plugin.getNMSAdapter().createNPC(i.getLocation(), getUUID(i));
|
||||
Entity npcEntity = npc.getPlayer();
|
||||
npcEntity.setMetadata("NPC", new FixedMetadataValue(plugin, true));
|
||||
return npc;
|
||||
@ -52,13 +60,13 @@ public final class NPCHandler implements NPCManager {
|
||||
|
||||
@Override
|
||||
public void killNPC(ChunkLoaderNPC npc) {
|
||||
NPCIdentifier identifier = new NPCIdentifier(npc.getLocation());
|
||||
npcs.remove(identifier);
|
||||
BlockPosition blockPosition = BlockPosition.of(npc.getLocation());
|
||||
|
||||
npcUUIDs.remove(identifier);
|
||||
npcs.remove(blockPosition);
|
||||
npcUUIDs.remove(blockPosition);
|
||||
|
||||
Query.DELETE_NPC_IDENTIFIER.insertParameters()
|
||||
.setLocation(identifier.getSpawnLocation())
|
||||
.setLocation(blockPosition)
|
||||
.queue(npc.getUniqueId());
|
||||
|
||||
Entity npcEntity = npc.getPlayer();
|
||||
@ -76,28 +84,27 @@ public final class NPCHandler implements NPCManager {
|
||||
npcs.clear();
|
||||
}
|
||||
|
||||
public Map<NPCIdentifier, ChunkLoaderNPC> getNPCs() {
|
||||
public Map<BlockPosition, ChunkLoaderNPC> getNPCs() {
|
||||
return Collections.unmodifiableMap(npcs);
|
||||
}
|
||||
|
||||
public void registerUUID(Location location, UUID uuid) {
|
||||
npcUUIDs.put(new NPCIdentifier(location), uuid);
|
||||
public void registerUUID(BlockPosition blockPosition, UUID uuid) {
|
||||
npcUUIDs.put(blockPosition, uuid);
|
||||
}
|
||||
|
||||
private UUID getUUID(NPCIdentifier identifier) {
|
||||
if (npcUUIDs.containsKey(identifier))
|
||||
return npcUUIDs.get(identifier);
|
||||
|
||||
UUID uuid;
|
||||
private UUID getUUID(BlockPosition blockPosition) {
|
||||
UUID uuid = npcUUIDs.get(blockPosition);
|
||||
if (uuid != null)
|
||||
return uuid;
|
||||
|
||||
do {
|
||||
uuid = UUID.randomUUID();
|
||||
} while (npcUUIDs.containsValue(uuid));
|
||||
|
||||
npcUUIDs.put(identifier, uuid);
|
||||
npcUUIDs.put(blockPosition, uuid);
|
||||
|
||||
Query.INSERT_NPC_IDENTIFIER.insertParameters()
|
||||
.setLocation(identifier.getSpawnLocation())
|
||||
.setLocation(blockPosition)
|
||||
.setObject(uuid.toString())
|
||||
.queue(uuid);
|
||||
|
||||
|
@ -93,7 +93,7 @@ public final class ProvidersHandler implements ProvidersManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void tick(Chunk[] chunks) {
|
||||
public void tick(List<Chunk> chunks) {
|
||||
tickableProviders.forEach(tickableProvider -> tickableProvider.tick(chunks));
|
||||
}
|
||||
|
||||
|
@ -5,22 +5,35 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class ChunksListener implements Listener {
|
||||
|
||||
private final WildLoadersPlugin plugin;
|
||||
|
||||
public ChunksListener(WildLoadersPlugin plugin){
|
||||
public ChunksListener(WildLoadersPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onChunkUnload(ChunkUnloadEvent e){
|
||||
public void onChunkUnload(ChunkUnloadEvent e) {
|
||||
try {
|
||||
if (plugin.getLoaders().getChunkLoader(e.getChunk()).isPresent())
|
||||
e.setCancelled(true);
|
||||
}catch (Throwable ignored){}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onWorldLoad(WorldLoadEvent e) {
|
||||
plugin.getLoaders().loadUnloadedChunkLoaders(e.getWorld());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onWorldUnload(WorldUnloadEvent e) {
|
||||
plugin.getLoaders().unloadWorld(e.getWorld());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.bgsoftware.wildloaders.loaders;
|
||||
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UnloadedChunkLoader {
|
||||
|
||||
private final LoaderData loaderData;
|
||||
private final UUID placer;
|
||||
private final BlockPosition blockPosition;
|
||||
private final long timeLeft;
|
||||
|
||||
public UnloadedChunkLoader(LoaderData loaderData, UUID placer, BlockPosition blockPosition, long timeLeft) {
|
||||
this.loaderData = loaderData;
|
||||
this.placer = placer;
|
||||
this.blockPosition = blockPosition;
|
||||
this.timeLeft = timeLeft;
|
||||
}
|
||||
|
||||
public LoaderData getLoaderData() {
|
||||
return loaderData;
|
||||
}
|
||||
|
||||
public UUID getPlacer() {
|
||||
return placer;
|
||||
}
|
||||
|
||||
public BlockPosition getBlockPosition() {
|
||||
return blockPosition;
|
||||
}
|
||||
|
||||
public long getTimeLeft() {
|
||||
return timeLeft;
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,7 @@ import com.bgsoftware.wildloaders.api.holograms.Hologram;
|
||||
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC;
|
||||
import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks;
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -16,6 +16,7 @@ import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@ -25,18 +26,18 @@ public final class WChunkLoader implements ChunkLoader {
|
||||
private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin();
|
||||
|
||||
private final UUID whoPlaced;
|
||||
private final Location location;
|
||||
private final Chunk[] loadedChunks;
|
||||
private final BlockPosition blockPosition;
|
||||
private final List<Chunk> loadedChunks;
|
||||
private final String loaderName;
|
||||
private final ITileEntityChunkLoader tileEntityChunkLoader;
|
||||
|
||||
private boolean active = true;
|
||||
private long timeLeft;
|
||||
|
||||
public WChunkLoader(LoaderData loaderData, UUID whoPlaced, Location location, Chunk[] loadedChunks, long timeLeft) {
|
||||
public WChunkLoader(LoaderData loaderData, UUID whoPlaced, BlockPosition blockPosition, List<Chunk> loadedChunks, long timeLeft) {
|
||||
this.loaderName = loaderData.getName();
|
||||
this.whoPlaced = whoPlaced;
|
||||
this.location = location.clone();
|
||||
this.blockPosition = blockPosition;
|
||||
this.loadedChunks = loadedChunks;
|
||||
this.timeLeft = timeLeft;
|
||||
this.tileEntityChunkLoader = plugin.getNMSAdapter().createLoader(this);
|
||||
@ -73,8 +74,8 @@ public final class WChunkLoader implements ChunkLoader {
|
||||
} else if (timeLeft > 0 && timeLeft % 10 == 0) {
|
||||
Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters()
|
||||
.setObject(timeLeft)
|
||||
.setLocation(location)
|
||||
.queue(location);
|
||||
.setLocation(this.blockPosition)
|
||||
.queue(this.blockPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,17 +86,23 @@ public final class WChunkLoader implements ChunkLoader {
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location.clone();
|
||||
return this.blockPosition.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Chunk[] getLoadedChunks() {
|
||||
return loadedChunks;
|
||||
return loadedChunks.toArray(new Chunk[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Chunk> getLoadedChunksCollection() {
|
||||
return Collections.unmodifiableCollection(loadedChunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ChunkLoaderNPC> getNPC() {
|
||||
return plugin.getNPCs().getNPC(location);
|
||||
return plugin.getNPCs().getNPC(this.blockPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,41 +0,0 @@
|
||||
package com.bgsoftware.wildloaders.npc;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class NPCIdentifier {
|
||||
|
||||
private final Object identifier;
|
||||
|
||||
public NPCIdentifier(Location location){
|
||||
this.identifier = getBlockLocation(location);
|
||||
}
|
||||
|
||||
public Location getSpawnLocation(){
|
||||
return (Location) identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return identifier.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
NPCIdentifier that = (NPCIdentifier) o;
|
||||
return Objects.equals(identifier, that.identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(identifier);
|
||||
}
|
||||
|
||||
private static Location getBlockLocation(Location location){
|
||||
return new Location(location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.bgsoftware.wildloaders.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockPosition {
|
||||
|
||||
private final String worldName;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private WeakReference<World> cachedWorld = new WeakReference<>(null);
|
||||
|
||||
public static BlockPosition of(Location location) {
|
||||
World world = location.getWorld();
|
||||
return new BlockPosition(world == null ? "null" : world.getName(),
|
||||
location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
public static BlockPosition deserialize(String serialized) {
|
||||
String[] locationSections = serialized.split(",");
|
||||
|
||||
if (locationSections.length != 4)
|
||||
throw new IllegalArgumentException("Cannot parse location " + serialized);
|
||||
|
||||
String worldName = locationSections[0];
|
||||
int x = (int) Double.parseDouble(locationSections[1]);
|
||||
int y = (int) Double.parseDouble(locationSections[2]);
|
||||
int z = (int) Double.parseDouble(locationSections[3]);
|
||||
|
||||
return new BlockPosition(worldName, x, y, z);
|
||||
}
|
||||
|
||||
public BlockPosition(String worldName, int x, int y, int z) {
|
||||
this.worldName = worldName;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
World cachedWorld = this.cachedWorld.get();
|
||||
if (cachedWorld == null) {
|
||||
cachedWorld = Bukkit.getWorld(this.worldName);
|
||||
this.cachedWorld = new WeakReference<>(cachedWorld);
|
||||
}
|
||||
|
||||
return cachedWorld;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return new Location(getWorld(), this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public String serialize() {
|
||||
return this.worldName + "," + this.x + "," + this.y + "," + this.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BlockPosition that = (BlockPosition) o;
|
||||
return x == that.x && y == that.y && z == that.z && Objects.equals(worldName, that.worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(worldName, x, y, z);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import com.bgsoftware.wildloaders.utils.BlockPosition;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
@ -12,7 +13,7 @@ public final class QueryParameters {
|
||||
private final Query query;
|
||||
private final List<Object> parameters;
|
||||
|
||||
public QueryParameters(Query query){
|
||||
public QueryParameters(Query query) {
|
||||
this.query = query;
|
||||
this.parameters = new ArrayList<>(query.getParametersCount());
|
||||
}
|
||||
@ -22,20 +23,24 @@ public final class QueryParameters {
|
||||
}
|
||||
|
||||
public void executeQuery(PreparedStatement preparedStatement) throws SQLException {
|
||||
for(int i = 0; i < parameters.size(); i++)
|
||||
for (int i = 0; i < parameters.size(); i++)
|
||||
preparedStatement.setObject(i + 1, parameters.get(i));
|
||||
}
|
||||
|
||||
public void queue(Object caller){
|
||||
public void queue(Object caller) {
|
||||
DatabaseQueue.queue(caller, this);
|
||||
}
|
||||
|
||||
public QueryParameters setLocation(Location loc){
|
||||
public QueryParameters setLocation(Location loc) {
|
||||
return setObject(loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ());
|
||||
}
|
||||
|
||||
public QueryParameters setObject(Object object){
|
||||
if(object instanceof Location)
|
||||
public QueryParameters setLocation(BlockPosition blockPos) {
|
||||
return setObject(blockPos.getWorldName() + "," + blockPos.getX() + "," + blockPos.getY() + "," + blockPos.getZ());
|
||||
}
|
||||
|
||||
public QueryParameters setObject(Object object) {
|
||||
if (object instanceof Location)
|
||||
return setLocation((Location) object);
|
||||
|
||||
parameters.add(object);
|
||||
|
@ -1,41 +0,0 @@
|
||||
package com.bgsoftware.wildloaders.utils.locations;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public final class LocationUtils {
|
||||
|
||||
private LocationUtils(){}
|
||||
|
||||
public static String getLocation(Location location){
|
||||
try {
|
||||
return location.getWorld().getName() + "," + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ();
|
||||
}catch (Exception ex){
|
||||
System.out.println(location);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public static Location getLocation(String location){
|
||||
String[] locationSections = location.split(",");
|
||||
|
||||
if(locationSections.length != 4)
|
||||
throw new IllegalArgumentException("Cannot parse location " + location);
|
||||
|
||||
String worldName = locationSections[0];
|
||||
double x = parseDouble(locationSections[1]);
|
||||
double y = parseDouble(locationSections[2]);
|
||||
double z = parseDouble(locationSections[3]);
|
||||
|
||||
return new Location(Bukkit.getWorld(worldName), x, y, z);
|
||||
}
|
||||
|
||||
private static double parseDouble(String str){
|
||||
try{
|
||||
return Double.parseDouble(str);
|
||||
}catch (Exception ex){
|
||||
throw new IllegalArgumentException("Cannot parse double " + str);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user