Fixed Chunk Loading Issues

Lots of processes were causing chunks to stay loaded.
Including the removal of entities in onEnable()
Everything is done on a per chunk basis now.
This commit is contained in:
jameslfc19 2020-07-24 22:41:09 +01:00
parent 6fe6817340
commit 2f72655921
8 changed files with 82 additions and 73 deletions

View File

@ -86,9 +86,6 @@ public class ChestsPlusPlus extends JavaPlugin {
API.register(this);
ApiSpecific.init();
//Remove entities that could have been left behind from bad save files/crashes etc.
Utils.fixEntities();
//Register commands
new ChestLinkCommand().register(this);
new AutoCraftCommand().register(this);
@ -150,6 +147,8 @@ public class ChestsPlusPlus extends JavaPlugin {
public void onDisable() {
super.onDisable();
Config.save();
//Remove entities that could have been left behind from bad save files/crashes etc.
Utils.fixEntities();
}
}

View File

@ -210,6 +210,7 @@ public class VirtualCraftingHolder implements InventoryHolder {
*/
public void craftItem(){
for(LocationInfo location : storage.getLocations()){
if(Utils.isLocationChunkLoaded(location.getLocation())) continue;
Block block = location.getLocation().getBlock();
Block blockBelow = block.getRelative(BlockFace.DOWN);
Block blockAbove = block.getRelative(BlockFace.UP);

View File

@ -55,12 +55,14 @@ public class HopperListener implements Listener {
new BukkitRunnable() {
@Override
public void run() {
int hopperAmount = SpigotConfig.getWorldSettings(location.getWorld().getName()).getHopperAmount();
if(Utils.moveToOtherInventory(event.getSource(), hopperAmount, storage.getInventory())){
storage.updateDisplayItem();
if(location != null) {
int hopperAmount = SpigotConfig.getWorldSettings(location.getWorld()).getHopperAmount();
if (Utils.moveToOtherInventory(event.getSource(), hopperAmount, storage.getInventory())) {
storage.updateDisplayItem();
}
if (event.getDestination().getHolder() != null) event.getDestination().getHolder().getInventory().clear();
if (storage.getInventory().getViewers().size() > 0) storage.sort();
}
event.getDestination().getHolder().getInventory().clear();
if(storage.getInventory().getViewers().size() > 0) storage.sort();
}
}.runTaskLater(ChestsPlusPlus.PLUGIN, 1);
}

View File

@ -74,13 +74,7 @@ public class InventoryListener implements Listener {
Utils.closeInventorySound((Player) event.getPlayer(), event.getInventory());
}
event.getViewers().remove(event.getPlayer());
vHolder.getStorage().getLocations().forEach(locationInfo -> {
Block block = locationInfo.getLocation().getBlock();
if(block.getState() instanceof Container){
Container chest = (Container) block.getState();
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> ApiSpecific.getChestOpener().setLidOpen(event.getInventory(),chest,false),1);
}
});
Utils.closeStorageInventory(vHolder.getStorage());
vHolder.getStorage().onItemDisplayUpdate(InventorySorter.getMostCommonItem(event.getInventory()));
}
if(holder instanceof VirtualCraftingHolder){
@ -114,12 +108,10 @@ public class InventoryListener implements Listener {
Inventory inventory = event.getInventory();
if(inventory.getHolder() instanceof VirtualCraftingHolder){
Player p = (Player) event.getWhoClicked();
// Bukkit.broadcastMessage(event.getRawSlots().toString());
for(int slot : event.getRawSlots()) {
if(slot >= p.getOpenInventory().getTopInventory().getSize())
continue;
// Bukkit.broadcastMessage("Drag! "+slot+" cursor: "+event.getOldCursor());
setCraftingItem(event.getInventory(),slot,event.getOldCursor());
event.setCancelled(true);
}
@ -131,19 +123,15 @@ public class InventoryListener implements Listener {
Player player = (Player) event.getWhoClicked();
if(event.getView().getTopInventory().getHolder() instanceof VirtualCraftingHolder){
// Bukkit.broadcastMessage("Click: "+event.getAction());
if(event.getAction() == InventoryAction.COLLECT_TO_CURSOR ||
event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY ||
event.getAction() == InventoryAction.NOTHING) {
// Bukkit.broadcastMessage("Cancelled!");
event.setCancelled(true);
player.updateInventory();
return;
}
if(event.getClickedInventory() == player.getOpenInventory().getTopInventory()){
// Bukkit.broadcastMessage("Clicked: "+event.getSlot());
if(event.getSlot() == 0) event.setCancelled(true);
if(event.getSlot() >= 1 && event.getSlot() <= 9){
setCraftingItem(event.getInventory(),event.getSlot(),event.getCursor());

View File

@ -5,6 +5,7 @@ import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.scheduler.BukkitRunnable;
@ -31,4 +32,11 @@ public class WorldListener implements Listener {
public void onWorldLoad(WorldLoadEvent event){
Utils.removeEntities(event.getWorld());
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event){
if(!event.isNewChunk()){
Utils.fixEntities(event.getChunk());
}
}
}

View File

@ -8,16 +8,14 @@ import com.jamesdpeters.minecraft.chests.interfaces.VirtualInventoryHolder;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.RegisteredListener;
import org.bukkit.util.Vector;
import java.io.BufferedReader;
@ -30,6 +28,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Utils {
@ -39,22 +38,17 @@ public class Utils {
storage.getLocations().forEach(locationInfo -> {
Location location = locationInfo.getLocation();
if (location != null) {
int chunkX = locationInfo.getLocation().getBlockX() >> 4;
int chunkZ = locationInfo.getLocation().getBlockZ() >> 4;
World world = location.getWorld();
if (world != null && world.isChunkLoaded(chunkX, chunkZ)) {
chestOpenAnimation(storage.getInventory(), locationInfo.getLocation());
}
containerOpenAnimation(storage.getInventory(), locationInfo.getLocation());
}
});
} else {
chestOpenAnimation(storage.getInventory(), openedChestLocation);
containerOpenAnimation(storage.getInventory(), openedChestLocation);
}
player.openInventory(storage.getInventory());
}
private static void chestOpenAnimation(Inventory inventory, Location location){
if (location != null) {
private static void containerOpenAnimation(Inventory inventory, Location location){
if (location != null && Utils.isLocationChunkLoaded(location)) {
Block block = location.getBlock();
if (block.getState() instanceof Container) {
Container chest = (Container) block.getState();
@ -63,6 +57,25 @@ public class Utils {
}
}
public static void closeStorageInventory(ChestLinkStorage storage){
storage.getLocations().forEach(locationInfo -> {
Location location = locationInfo.getLocation();
if (location != null) {
containerCloseAnimation(storage.getInventory(), locationInfo.getLocation());
}
});
}
private static void containerCloseAnimation(Inventory inventory, Location location){
if (location != null && Utils.isLocationChunkLoaded(location)) {
Block block = location.getBlock();
if (block.getState() instanceof Container) {
Container chest = (Container) block.getState();
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN,() -> ApiSpecific.getChestOpener().setLidOpen(inventory, chest, false),1);
}
}
}
public static void openChestInventory(Player player, Inventory inventory){
VirtualInventoryHolder holder = (VirtualInventoryHolder) inventory.getHolder();
if (holder != null) holder.onPlayerRemoteOpened(player.getUniqueId());
@ -196,15 +209,36 @@ public class Utils {
});
}
public static void fixEntities(Chunk chunk){
removeEntities(chunk);
setItemFrames(chunk);
}
public static void removeEntities(World world){
world.getEntities().forEach(entity -> {
Integer val = entity.getPersistentDataContainer().get(Values.PluginKey, PersistentDataType.INTEGER);
if(val != null && val == 1) entity.remove();
});
world.getEntities().forEach(Utils::removeEntity);
}
public static void removeEntities(Chunk chunk){
for (Entity entity : chunk.getEntities()) {
removeEntity(entity);
}
}
private static void removeEntity(Entity entity){
Integer val = entity.getPersistentDataContainer().get(Values.PluginKey, PersistentDataType.INTEGER);
if(val != null && val == 1) entity.remove();
}
public static void setItemFrames(World world){
world.getEntities().stream().filter(entity ->
setItemFrames(world.getEntities().stream());
}
public static void setItemFrames(Chunk chunk){
setItemFrames(Arrays.stream(chunk.getEntities()));
}
private static void setItemFrames(Stream<Entity> entityStream){
entityStream.filter(entity ->
(entity instanceof ItemFrame
&& entity.getLocation().getBlock().getRelative(((ItemFrame) entity).getAttachedFace()).getState() instanceof Hopper))
.forEach(entity -> ApiSpecific.getNmsProvider().setItemFrameVisible((ItemFrame) entity, !Settings.isFilterItemFrameInvisible()));
@ -218,39 +252,14 @@ public class Utils {
if(value != null) list.add(value);
}
public static void saveLoadedChunksToCSV(){
PrintWriter outputFile = getOutputFile("LoadedChunks@"+System.currentTimeMillis()+".csv"); // this sends the output to file1
// Write the file as a comma seperated file (.csv) so it can be read it into EXCEL
outputFile.println("Chunk X, Chunk Z, World");
// now make a loop to write the contents of each step to disk, one number at a time
Bukkit.getWorlds().forEach(world -> {
for (Chunk loadedChunk : world.getLoadedChunks()) {
outputFile.println(loadedChunk.getX()+", "+loadedChunk.getZ()+", "+world.getName());
}
});
outputFile.close(); // close the output file
System.out.println("Saved CSV Data");
}
private static PrintWriter getOutputFile(String filenamePath){
try {
Path path = Paths.get("outputs/"+filenamePath);
Files.createDirectories(path.getParent());
FileWriter file = new FileWriter(String.valueOf(path)); // this creates the file with the given name
return new PrintWriter(file); // this sends the output to file
} catch (IOException e) {
System.err.println("File couldn't be accessed it may be being used by another process!");
System.err.println("Close the file and press Enter to try again!");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try { reader.readLine(); } catch (IOException ex) { ex.printStackTrace(); }
return getOutputFile(filenamePath);
}
}
public static boolean isAir(Block block){
return (block.getType() == Material.AIR) || (block.getType() == Material.CAVE_AIR);
}
public static boolean isLocationChunkLoaded(Location location){
int chunkX = location.getBlockX() >> 4;
int chunkZ = location.getBlockZ() >> 4;
return location.getWorld() != null && location.getWorld().isChunkLoaded(chunkX, chunkZ);
}
}

View File

@ -7,6 +7,7 @@ import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
import com.jamesdpeters.minecraft.chests.serialize.SpigotConfig;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.Hopper;
import org.bukkit.scheduler.BukkitRunnable;
@ -34,14 +35,14 @@ public class VirtualChestToHopper extends BukkitRunnable {
for(LocationInfo location : storage.getLocations()) {
if(location != null) {
if (location.getLocation() != null) {
if(!location.getLocation().getChunk().isLoaded() && !Settings.isRunHoppersInUnloadedChunks()) continue;
if(!Settings.isRunHoppersInUnloadedChunks() && !Utils.isLocationChunkLoaded(location.getLocation())) continue;
Location below = location.getLocation().clone().subtract(0, 1, 0);
if (below.getBlock().getState() instanceof Hopper) {
Hopper hopper = (Hopper) below.getBlock().getState();
if (below.getBlock().isBlockIndirectlyPowered() || below.getBlock().isBlockPowered()) {
continue;
}
int hopperAmount = SpigotConfig.getWorldSettings(location.getLocation().getWorld().getName()).getHopperAmount();
int hopperAmount = SpigotConfig.getWorldSettings(location.getLocation().getWorld()).getHopperAmount();
if(Utils.moveToOtherInventory(storage.getInventory(), hopperAmount, hopper.getInventory(), HopperFilter.getHopperFilters(below.getBlock()))){
storage.updateDisplayItem();
}

View File

@ -3,6 +3,7 @@ package com.jamesdpeters.minecraft.chests.storage.abstracts;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.api.ApiSpecific;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.misc.Values;
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
import org.bukkit.Bukkit;
@ -140,7 +141,7 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private void updateSign(){
Bukkit.getOnlinePlayers().forEach(player -> {
for (LocationInfo locationInfo : locationInfoList) {
if (locationInfo.getSignLocation() != null) {
if (locationInfo.getSignLocation() != null && Utils.isLocationChunkLoaded(locationInfo.getSignLocation())) {
if (displayItem != null) player.sendBlockChange(locationInfo.getSignLocation(), air);
else locationInfo.getSignLocation().getBlock().getState().update();
}
@ -412,7 +413,7 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private BlockData air = Material.AIR.createBlockData();
private void updateClient(LocationInfo location){
if(location.getLocation() == null) return;
if(location.getLocation() == null || !Utils.isLocationChunkLoaded(location.getLocation())) return;
World world = location.getLocation().getWorld();
if(world != null) {