StorageOpener Optimisations

Fixes for sign bug when more than 64 signs get updated in a chunk. #12
Optimised ChestOpener code to cache the tile entity.
Armour stands no longer calculate unneed location and postions.
Display type enum that gets set when the display item is chaned.
This commit is contained in:
jameslfc19 2020-07-26 18:27:44 +01:00
parent 4b3d009541
commit f0a7d3231f
16 changed files with 293 additions and 123 deletions

View File

@ -1,9 +1,8 @@
package com.jamesdpeters.minecraft.chests;
import org.bukkit.block.Chest;
import org.bukkit.block.Container;
import org.bukkit.inventory.Inventory;
public interface ChestOpener {
void setLidOpen(Inventory inventory, Container chest, boolean open);
TileEntityOpener updateState(Inventory inventory, Container chest, TileEntityOpener tileEntityOpener);
}

View File

@ -8,10 +8,11 @@ import net.minecraft.server.v1_14_R1.BlockPosition;
import net.minecraft.server.v1_14_R1.TileEntity;
import net.minecraft.server.v1_14_R1.TileEntityBarrel;
import net.minecraft.server.v1_14_R1.TileEntityChest;
import net.minecraft.server.v1_14_R1.TileEntityChestTrapped;
import net.minecraft.server.v1_14_R1.TileEntityTypes;
import net.minecraft.server.v1_14_R1.World;
import org.bukkit.block.Container;
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_14_R1.block.CraftChest;
import org.bukkit.craftbukkit.v1_14_R1.block.CraftContainer;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.Inventory;
@ -21,24 +22,35 @@ import java.util.List;
public class ChestOpener_1_14 implements ChestOpener {
@Override
public void setLidOpen(Inventory inventory, Container chest, boolean open) {
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if(tileEntity instanceof TileEntityOpener){
((TileEntityOpener) tileEntity).setViewers(inventory.getViewers());
public TileEntityOpener updateState(Inventory inventory, Container chest, TileEntityOpener tileEntityOpener) {
if(tileEntityOpener != null) {
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
setTileEnt(world, position, new CustomTileEntityChest(), inventory.getViewers());
} else if (tileEntity instanceof TileEntityBarrel) {
setTileEnt(world, position, new CustomTileEntityBarrel(), inventory.getViewers());
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if (tileEntity instanceof TileEntityOpener) {
tileEntityOpener = (TileEntityOpener) tileEntity;
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
CustomTileEntityChest tileEntityChest = new CustomTileEntityChest(tileEntity instanceof TileEntityChestTrapped ? TileEntityTypes.TRAPPED_CHEST : TileEntityTypes.CHEST);
setTileEnt(world, position, tileEntityChest, inventory.getViewers());
return tileEntityChest;
} else if (tileEntity instanceof TileEntityBarrel) {
CustomTileEntityBarrel barrel = new CustomTileEntityBarrel();
setTileEnt(world, position, barrel, inventory.getViewers());
return barrel;
}
}
return null;
}
}

View File

@ -9,6 +9,7 @@ import net.minecraft.server.v1_14_R1.SoundCategory;
import net.minecraft.server.v1_14_R1.SoundEffect;
import net.minecraft.server.v1_14_R1.SoundEffects;
import net.minecraft.server.v1_14_R1.TileEntityChest;
import net.minecraft.server.v1_14_R1.TileEntityTypes;
import org.bukkit.entity.HumanEntity;
import java.util.List;
@ -18,6 +19,10 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
private int phantomViewers = 0;
private List<HumanEntity> viewers;
public CustomTileEntityChest(TileEntityTypes<?> tileEntityTypes){
super(tileEntityTypes);
}
@Override
public List<HumanEntity> getViewers() {
return viewers;
@ -44,7 +49,8 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
this.viewers = viewers;
if(phantomViewers > 1 && previousViewers == 0) this.a(SoundEffects.BLOCK_CHEST_OPEN);
if(phantomViewers == 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers != 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers == 0) return;
onOpen();
}

View File

@ -8,6 +8,8 @@ import net.minecraft.server.v1_15_R1.BlockPosition;
import net.minecraft.server.v1_15_R1.TileEntity;
import net.minecraft.server.v1_15_R1.TileEntityBarrel;
import net.minecraft.server.v1_15_R1.TileEntityChest;
import net.minecraft.server.v1_15_R1.TileEntityChestTrapped;
import net.minecraft.server.v1_15_R1.TileEntityTypes;
import net.minecraft.server.v1_15_R1.World;
import org.bukkit.block.Container;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
@ -20,24 +22,35 @@ import java.util.List;
public class ChestOpener_1_15 implements ChestOpener {
@Override
public void setLidOpen(Inventory inventory, Container chest, boolean open) {
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if(tileEntity instanceof TileEntityOpener){
((TileEntityOpener) tileEntity).setViewers(inventory.getViewers());
public TileEntityOpener updateState(Inventory inventory, Container chest, TileEntityOpener tileEntityOpener) {
if(tileEntityOpener != null) {
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
setTileEnt(world, position, new CustomTileEntityChest(), inventory.getViewers());
} else if (tileEntity instanceof TileEntityBarrel) {
setTileEnt(world, position, new CustomTileEntityBarrel(), inventory.getViewers());
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if (tileEntity instanceof TileEntityOpener) {
tileEntityOpener = (TileEntityOpener) tileEntity;
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
CustomTileEntityChest tileEntityChest = new CustomTileEntityChest(tileEntity instanceof TileEntityChestTrapped ? TileEntityTypes.TRAPPED_CHEST : TileEntityTypes.CHEST);
setTileEnt(world, position, tileEntityChest, inventory.getViewers());
return tileEntityChest;
} else if (tileEntity instanceof TileEntityBarrel) {
CustomTileEntityBarrel barrel = new CustomTileEntityBarrel();
setTileEnt(world, position, barrel, inventory.getViewers());
return barrel;
}
}
return null;
}
}

View File

@ -10,6 +10,7 @@ import net.minecraft.server.v1_15_R1.SoundCategory;
import net.minecraft.server.v1_15_R1.SoundEffect;
import net.minecraft.server.v1_15_R1.SoundEffects;
import net.minecraft.server.v1_15_R1.TileEntityChest;
import net.minecraft.server.v1_15_R1.TileEntityTypes;
import org.bukkit.entity.HumanEntity;
import java.util.List;
@ -19,6 +20,10 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
private int phantomViewers = 0;
private List<HumanEntity> viewers;
public CustomTileEntityChest(TileEntityTypes<?> tileEntityTypes){
super(tileEntityTypes);
}
@Override
public List<HumanEntity> getViewers() {
return viewers;
@ -44,7 +49,8 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
this.viewers = viewers;
if(phantomViewers > 1 && previousViewers == 0) this.a(SoundEffects.BLOCK_CHEST_OPEN);
if(phantomViewers == 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers != 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers == 0) return;
onOpen();
}

View File

@ -8,6 +8,8 @@ import net.minecraft.server.v1_16_R1.BlockPosition;
import net.minecraft.server.v1_16_R1.TileEntity;
import net.minecraft.server.v1_16_R1.TileEntityBarrel;
import net.minecraft.server.v1_16_R1.TileEntityChest;
import net.minecraft.server.v1_16_R1.TileEntityChestTrapped;
import net.minecraft.server.v1_16_R1.TileEntityTypes;
import net.minecraft.server.v1_16_R1.World;
import org.bukkit.block.Container;
import org.bukkit.craftbukkit.v1_16_R1.CraftWorld;
@ -21,24 +23,35 @@ import java.util.List;
public class ChestOpener_1_16 implements ChestOpener {
@Override
public void setLidOpen(Inventory inventory, Container chest, boolean open) {
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if(tileEntity instanceof TileEntityOpener){
((TileEntityOpener) tileEntity).setViewers(inventory.getViewers());
public TileEntityOpener updateState(Inventory inventory, Container chest, TileEntityOpener tileEntityOpener) {
if(tileEntityOpener != null) {
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
setTileEnt(world, position, new CustomTileEntityChest(), inventory.getViewers());
} else if (tileEntity instanceof TileEntityBarrel) {
setTileEnt(world, position, new CustomTileEntityBarrel(), inventory.getViewers());
CraftContainer craftContainer = (CraftContainer) chest;
CraftWorld craftWorld = (CraftWorld) craftContainer.getWorld();
World world = craftWorld.getHandle();
BlockPosition position = craftContainer.getPosition();
TileEntity tileEntity = world.getTileEntity(position);
//Checks if Tile Entity has already got custom Opener.
if (tileEntity instanceof TileEntityOpener) {
tileEntityOpener = (TileEntityOpener) tileEntity;
tileEntityOpener.setViewers(inventory.getViewers());
return tileEntityOpener;
} else {
//If not set the new tile entity and set the viewers.
if (tileEntity instanceof TileEntityChest) {
CustomTileEntityChest tileEntityChest = new CustomTileEntityChest(tileEntity instanceof TileEntityChestTrapped ? TileEntityTypes.TRAPPED_CHEST : TileEntityTypes.CHEST);
setTileEnt(world, position, tileEntityChest, inventory.getViewers());
return tileEntityChest;
} else if (tileEntity instanceof TileEntityBarrel) {
CustomTileEntityBarrel barrel = new CustomTileEntityBarrel();
setTileEnt(world, position, barrel, inventory.getViewers());
return barrel;
}
}
return null;
}
}

View File

@ -4,15 +4,14 @@ import com.jamesdpeters.minecraft.chests.TileEntityOpener;
import net.minecraft.server.v1_16_R1.Block;
import net.minecraft.server.v1_16_R1.BlockChest;
import net.minecraft.server.v1_16_R1.BlockPropertyChestType;
import net.minecraft.server.v1_16_R1.Blocks;
import net.minecraft.server.v1_16_R1.EntityHuman;
import net.minecraft.server.v1_16_R1.EnumDirection;
import net.minecraft.server.v1_16_R1.SoundCategory;
import net.minecraft.server.v1_16_R1.SoundEffect;
import net.minecraft.server.v1_16_R1.SoundEffects;
import net.minecraft.server.v1_16_R1.TileEntityChest;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R1.event.CraftEventFactory;
import net.minecraft.server.v1_16_R1.TileEntityChestTrapped;
import net.minecraft.server.v1_16_R1.TileEntityTypes;
import org.bukkit.entity.HumanEntity;
import java.util.List;
@ -22,6 +21,10 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
private int phantomViewers = 0;
private List<HumanEntity> viewers;
public CustomTileEntityChest(TileEntityTypes<?> tileEntityTypes){
super(tileEntityTypes);
}
@Override
public List<HumanEntity> getViewers() {
return viewers;
@ -48,7 +51,8 @@ public class CustomTileEntityChest extends TileEntityChest implements TileEntity
this.viewers = viewers;
if(phantomViewers > 1 && previousViewers == 0) this.a(SoundEffects.BLOCK_CHEST_OPEN);
if(phantomViewers == 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers != 0) this.a(SoundEffects.BLOCK_CHEST_CLOSE);
if(phantomViewers == 0 && previousViewers == 0) return;
onOpen();
}

View File

@ -9,8 +9,9 @@ import org.bukkit.entity.ItemFrame;
public class NMSProviderDefault implements NMSProvider {
@Override
public ChestOpener getChestOpener() {
return (storage, chest, open) -> {
return (storage, chest, tileEntityOpener) -> {
//Default to doing nothing.
return null;
};
}

View File

@ -42,7 +42,7 @@ public class InventoryListener implements Listener {
event.setCancelled(true);
if (event.getPlayer().hasPermission(Permissions.OPEN) && storage.hasPermission((Player) event.getPlayer())) {
storage.getInventory().getViewers().remove(event.getPlayer());
Utils.openChestInventory((Player) event.getPlayer(), storage, event.getInventory().getLocation());
Utils.openChestInventory((Player) event.getPlayer(), storage, storage.getLocationInfo(event.getInventory().getLocation()));
} else {
Messages.NO_PERMISSION((Player) event.getPlayer());
}

View File

@ -3,6 +3,10 @@ package com.jamesdpeters.minecraft.chests.listeners;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.ConfigStorage;
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
import com.jamesdpeters.minecraft.chests.storage.abstracts.AbstractStorage;
import com.jamesdpeters.minecraft.chests.storage.abstracts.StorageType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
@ -10,6 +14,8 @@ import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
public class WorldListener implements Listener {
private static boolean justSaved = false;
@ -37,6 +43,17 @@ public class WorldListener implements Listener {
public void onChunkLoad(ChunkLoadEvent event){
if(!event.isNewChunk()){
Utils.fixEntities(event.getChunk());
Config.getStorageTypes().forEach(storageType -> {
storageType.getStorageMap().values().forEach(stringHashMap -> {
stringHashMap.values().forEach(o -> {
o.getLocations().forEach(locationInfo -> {
if(locationInfo != null && locationInfo.getSignLocation() != null && locationInfo.getSignLocation().getChunk().equals(event.getChunk())){
o.updateClient(locationInfo);
}
});
});
});
});
}
}
}

View File

@ -5,9 +5,20 @@ import com.jamesdpeters.minecraft.chests.api.ApiSpecific;
import com.jamesdpeters.minecraft.chests.filters.Filter;
import com.jamesdpeters.minecraft.chests.filters.HopperFilter;
import com.jamesdpeters.minecraft.chests.interfaces.VirtualInventoryHolder;
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Container;
import org.bukkit.block.Hopper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
@ -18,41 +29,39 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Vector;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Utils {
public static void openChestInventory(Player player, ChestLinkStorage storage, Location openedChestLocation){
public static void openChestInventory(Player player, ChestLinkStorage storage, LocationInfo openedChestLocation){
//Check if all chests should perform open animation.
if(Settings.isShouldAnimateAllChests()) {
storage.getLocations().forEach(locationInfo -> {
Location location = locationInfo.getLocation();
if (location != null) {
containerOpenAnimation(storage.getInventory(), locationInfo.getLocation());
containerAnimation(storage.getInventory(), locationInfo);
}
});
} else {
containerOpenAnimation(storage.getInventory(), openedChestLocation);
containerAnimation(storage.getInventory(), openedChestLocation);
}
player.openInventory(storage.getInventory());
}
private static void containerOpenAnimation(Inventory inventory, Location location){
if (location != null && Utils.isLocationChunkLoaded(location)) {
Block block = location.getBlock();
private static void containerAnimation(Inventory inventory, LocationInfo location){
if (location != null && Utils.isLocationChunkLoaded(location.getLocation())) {
Block block = location.getLocation().getBlock();
if (block.getState() instanceof Container) {
Container chest = (Container) block.getState();
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN,() -> ApiSpecific.getChestOpener().setLidOpen(inventory, chest, true),1);
Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN,() -> {
location.setTileEntityOpener(ApiSpecific.getChestOpener().updateState(inventory, chest, location.getTileEntityOpener()));
},1);
}
}
}
@ -61,20 +70,11 @@ public class Utils {
storage.getLocations().forEach(locationInfo -> {
Location location = locationInfo.getLocation();
if (location != null) {
containerCloseAnimation(storage.getInventory(), locationInfo.getLocation());
containerAnimation(storage.getInventory(), locationInfo);
}
});
}
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();
@ -262,4 +262,17 @@ public class Utils {
return location.getWorld() != null && location.getWorld().isChunkLoaded(chunkX, chunkZ);
}
public static Collection<Entity> getPlayersInViewDistance(Location location){
if(location.getWorld() == null) return null;
return location.getWorld().getNearbyEntities(location, Bukkit.getViewDistance()*16, 256, Bukkit.getViewDistance()*16, entity -> entity instanceof Player);
}
public static boolean isLocationInViewDistance(Player player, Location location){
Location delta = player.getLocation().subtract(location);
return (delta.getX() <= Bukkit.getViewDistance()*16) && (delta.getZ() <= Bukkit.getViewDistance()*16);
}
}

View File

@ -2,6 +2,7 @@ package com.jamesdpeters.minecraft.chests.serialize;
import com.google.common.base.Charsets;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.storage.abstracts.AbstractStorage;
import com.jamesdpeters.minecraft.chests.storage.autocraft.AutoCraftingStorageType;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorageType;
import com.jamesdpeters.minecraft.chests.storage.abstracts.StorageType;
@ -28,7 +29,7 @@ public class Config {
private static ChestLinkStorageType chestLinkStorageType;
private static AutoCraftingStorageType autoCraftingStorageType;
private static List<StorageType> storageTypes;
private static List<StorageType<? extends AbstractStorage>> storageTypes;
public Config() {
legacyConverter();
@ -79,10 +80,12 @@ public class Config {
return chestLinkStorageType;
}
public static List<StorageType> getStorageTypes(){
public static List<StorageType<? extends AbstractStorage>> getStorageTypes(){
return storageTypes;
}
public static ConfigStorage getStore(){ return store; }
//TODO This needs improving
public static OfflinePlayer getOfflinePlayer(String name) {
for (String uuid : store.chests.keySet()) {

View File

@ -1,9 +1,12 @@
package com.jamesdpeters.minecraft.chests.serialize;
import com.jamesdpeters.minecraft.chests.TileEntityOpener;
import org.bukkit.Location;
import org.bukkit.block.Sign;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
@ -16,6 +19,7 @@ public class LocationInfo implements ConfigurationSerializable {
private Location location, signLocation;
private ArmorStand itemStand, blockStand, toolItemStand;
private TileEntityOpener tileEntityOpener;
@Override
public Map<String, Object> serialize() {
@ -40,6 +44,13 @@ public class LocationInfo implements ConfigurationSerializable {
return signLocation;
}
public Sign getSign(){
if(signLocation.getBlock().getState() instanceof Sign){
return (Sign) signLocation.getBlock().getState();
}
return null;
}
public ArmorStand getBlockStand() {
return blockStand;
}
@ -68,6 +79,14 @@ public class LocationInfo implements ConfigurationSerializable {
this.signLocation = signLocation;
}
public void setTileEntityOpener(TileEntityOpener tileEntityOpener) {
this.tileEntityOpener = tileEntityOpener;
}
public TileEntityOpener getTileEntityOpener() {
return tileEntityOpener;
}
public static List<LocationInfo> convert(List<Location> locationList){
List<LocationInfo> locationInfos = new ArrayList<>();
for (Location location : locationList) {
@ -79,4 +98,8 @@ public class LocationInfo implements ConfigurationSerializable {
public static Optional<LocationInfo> getLocationInfo(List<LocationInfo> locationInfos, Location location){
return locationInfos.stream().filter(locationInfo -> locationInfo.getLocation().equals(location)).findFirst();
}
public boolean isInWorld(Player player){
return getLocation() != null && player.getWorld().equals(getLocation().getWorld());
}
}

View File

@ -98,7 +98,7 @@ public class InventorySorter {
public static ItemStack getMostCommonItem(Inventory inventory){
return getItemAmounts(inventory.getContents()).entrySet().stream()
.max(Comparator.comparing(Map.Entry::getValue))
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null);
}

View File

@ -19,7 +19,6 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -28,7 +27,6 @@ import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -140,12 +138,12 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private void updateSign(){
Bukkit.getOnlinePlayers().forEach(player -> {
for (LocationInfo locationInfo : locationInfoList) {
if (locationInfo.getSignLocation() != null && Utils.isLocationChunkLoaded(locationInfo.getSignLocation())) {
if (displayItem != null) player.sendBlockChange(locationInfo.getSignLocation(), air);
else locationInfo.getSignLocation().getBlock().getState().update();
List<LocationInfo> locationInfos = locationInfoList.stream().filter(locationInfo -> locationInfo.isInWorld(player)).collect(Collectors.toList()); // Create a utility method for this
locationInfos.forEach(locationInfo -> {
if (Utils.isLocationInViewDistance(player, locationInfo.getSignLocation())) {
if(displayItem != null) player.sendBlockChange(locationInfo.getSignLocation(), air);
}
}
});
});
}
@ -219,8 +217,10 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
locationInfo.setSignLocation(signLocation);
locationInfoList.add(locationInfo);
if(shouldDisplayArmourStands()){
updateSign();
updateClient(locationInfo);
if(displayItem != null) {
updateSign();
updateClient(locationInfo);
}
}
}
@ -380,10 +380,27 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
/* ARMOR STAND METHODS */
private ItemStack displayItem;
private DISPLAY_TYPE displayType;
private void resetSign(){
Bukkit.getOnlinePlayers().forEach(player -> {
List<LocationInfo> locationInfos = locationInfoList.stream().filter(locationInfo -> locationInfo.isInWorld(player)).collect(Collectors.toList()); // Create a utility method for this
locationInfos.forEach(locationInfo -> {
if (Utils.isLocationInViewDistance(player, locationInfo.getSignLocation())) {
if( locationInfo.getSignLocation().getBlock().getState() instanceof Sign) {
Sign sign = (Sign) locationInfo.getSignLocation().getBlock().getState();
player.sendBlockChange(locationInfo.getSignLocation(), sign.getBlockData());
player.sendSignChange(locationInfo.getSignLocation(), sign.getLines());
}
}
});
});
}
public void onItemDisplayUpdate(ItemStack newItem){
if(shouldDisplayArmourStands()) {
if (displayItem == null || displayItem.getType().equals(Material.AIR)) {
if (newItem == null || newItem.getType().equals(Material.AIR)) {
if(displayItem != null) resetSign();
Bukkit.getScheduler().cancelTask(signUpdateTask);
signUpdateTask = -1;
} else {
@ -391,6 +408,7 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
}
}
displayItem = newItem;
displayType = DISPLAY_TYPE.getType(displayItem);
if(shouldDisplayArmourStands()) updateClients();
}
@ -412,7 +430,22 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private BlockData air = Material.AIR.createBlockData();
private void updateClient(LocationInfo location){
enum DISPLAY_TYPE {
IGNORE,
TOOL,
BLOCK,
ITEM;
public static DISPLAY_TYPE getType(ItemStack itemStack){
if(itemStack == null) return IGNORE;
if(ApiSpecific.getMaterialChecker().isIgnored(itemStack)) return IGNORE;
if(ApiSpecific.getMaterialChecker().isTool(itemStack)) return TOOL;
if(ApiSpecific.getMaterialChecker().isGraphically2D(itemStack)) return ITEM;
else return BLOCK;
}
}
public void updateClient(LocationInfo location){
if(location.getLocation() == null || !Utils.isLocationChunkLoaded(location.getLocation())) return;
World world = location.getLocation().getWorld();
@ -420,21 +453,19 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
if(location.getSignLocation() == null) return;
Block storageBlock = location.getLocation().getBlock();
Block anchor = location.getSignLocation().getBlock();
BlockFace facing;
if(anchor.getBlockData() instanceof Directional){
facing = ((Directional) anchor.getBlockData()).getFacing();
} else {
return;
}
if(displayItem != null && !ApiSpecific.getMaterialChecker().isIgnored(displayItem)) {
boolean isBlock = !ApiSpecific.getMaterialChecker().isGraphically2D(displayItem);
boolean isTool = ApiSpecific.getMaterialChecker().isTool(displayItem);
Location standLoc = isTool ? getHeldItemArmorStandLoc(storageBlock,anchor, facing) : getArmorStandLoc(storageBlock, anchor, facing, isBlock);
if(displayItem != null && displayType != DISPLAY_TYPE.IGNORE) {
boolean isBlock = displayType == DISPLAY_TYPE.BLOCK;
boolean isTool = displayType == DISPLAY_TYPE.TOOL;
//Get currently stored armorStand if there isn't one spawn it.
ArmorStand stand = isTool ? location.getToolItemStand() : (isBlock ? location.getBlockStand() : location.getItemStand());
if(stand == null || !stand.isValid()) {
BlockFace facing;
if(anchor.getBlockData() instanceof Directional){
facing = ((Directional) anchor.getBlockData()).getFacing();
} else return;
Location standLoc = isTool ? getHeldItemArmorStandLoc(storageBlock,anchor, facing) : getArmorStandLoc(storageBlock, anchor, facing, isBlock);
stand = createArmorStand(world, standLoc, isBlock, isTool);
addArmorStand(isBlock, isTool, location, stand);
}
@ -446,18 +477,18 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
//Set other armor stand helmet to null.
if(isBlock) {
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
removeArmorStandItem(location.getToolItemStand());
removeArmorStandItem(location.getItemStand());
} else {
setArmorStandHelmet(location.getBlockStand(), null);
if(isTool) setArmorStandHelmet(location.getItemStand(), null);
else setArmorStandHelmet(location.getToolItemStand(), null);
removeArmorStandItem(location.getBlockStand());
if(isTool) removeArmorStandItem(location.getItemStand());
else removeArmorStandItem(location.getToolItemStand());
}
} else {
anchor.getState().update();
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
setArmorStandHelmet(location.getBlockStand(), null);
// anchor.getState().update();
removeArmorStandItem(location.getToolItemStand());
removeArmorStandItem(location.getItemStand());
removeArmorStandItem(location.getBlockStand());
}
}
@ -526,8 +557,8 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
return standLoc.subtract(x, y, z);
}
private void setArmorStandHelmet(ArmorStand stand, ItemStack helmet){
if(stand != null) stand.setItemInHand(helmet);
private void removeArmorStandItem(ArmorStand stand){
if(stand != null) stand.setItemInHand(null);
}
private void addArmorStand(boolean isBlock, boolean isTool, LocationInfo location, ArmorStand stand){

View File

@ -8,8 +8,10 @@ import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.misc.Values;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.ConfigStorage;
import com.jamesdpeters.minecraft.chests.serialize.LocationInfo;
import com.jamesdpeters.minecraft.chests.storage.StorageUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@ -29,6 +31,7 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
@ -40,10 +43,12 @@ public abstract class StorageType<T extends AbstractStorage> {
private ConfigStorage store;
private StorageUtils<StorageInfo<T>, T> storageUtils;
private HashMap<Location, T> storageCache;
protected StorageType(ConfigStorage store){
this.store = store;
storageUtils = new StorageUtils<>(this);
storageCache = new HashMap<>();
}
public StorageUtils<StorageInfo<T>, T> getStorageUtils() {
@ -54,6 +59,10 @@ public abstract class StorageType<T extends AbstractStorage> {
public abstract T createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location, Location signLocation);
public HashMap<String, HashMap<String, T>> getStorageMap(){
return getStorageMap(store);
}
/**
* This is the tag used in Signs such as [ChestLink] or [AutoCraft]
* @return String value of the sign tag.
@ -141,10 +150,11 @@ public abstract class StorageType<T extends AbstractStorage> {
}
public T getStorage(Location location) {
T storage = storageCache.get(location);
if(storage != null) return storage;
if (location != null) {
Block block = location.getBlock();
if (isValidBlockType(block)) {
StorageInfo<T> storageInfo = storageUtils.getStorageInfo(location);
if(storageInfo != null){
return storageInfo.getStorage(location);
@ -358,6 +368,25 @@ public abstract class StorageType<T extends AbstractStorage> {
return playerList;
}
public List<LocationInfo> getViewingDistanceStorages(Player player){
List<LocationInfo> list = new ArrayList<>();
getStorageMap(store).values().forEach(map -> map.values().forEach(abstractStorage -> abstractStorage.getLocations().forEach(locationInfo -> {
if(Utils.isLocationInViewDistance(player, locationInfo.getSignLocation())){
list.add(locationInfo);
}
})));
return list;
}
public List<LocationInfo> getLocationsInChunk(Chunk chunk){
List<LocationInfo> list = new ArrayList<>();
getStorageMap().values().forEach(map -> map.values().forEach(abstractStorage -> abstractStorage.getLocations().forEach(locationInfo -> {
if(locationInfo.getSignLocation().getChunk().equals(chunk)){
list.add(locationInfo);
}
})));
return list;
}
/*
POST LOAD