Invisible Sign Packet fixed.

This sends a packet to each player every tick to set the sign infront of the chest as AIR.
Also fixes some issues with AutoCrafting stations.
This commit is contained in:
jameslfc19 2020-07-12 14:00:38 +01:00
parent 8c2df21a58
commit ae0e35fe3b
9 changed files with 139 additions and 91 deletions

View File

@ -47,7 +47,7 @@ public class StorageListener implements Listener {
if (storageType.getStorageUtils().isValidSignPosition(signLocation)) {
StorageInfo info = storageType.getStorageUtils().getStorageInfo(sign, signChangeEvent.getLines(), event.getPlayer().getUniqueId());
if (info != null) {
if (!storageType.add(event.getPlayer(), info.getGroup(), event.getBlockAgainst().getLocation(), info.getPlayer())) {
if (!storageType.add(event.getPlayer(), info.getGroup(), event.getBlockAgainst().getLocation(), event.getBlockPlaced().getLocation(), info.getPlayer())) {
sign.getBlock().breakNaturally();
done();
return;

View File

@ -14,7 +14,7 @@ import java.util.Optional;
@SerializableAs("LocationInfo")
public class LocationInfo implements ConfigurationSerializable {
private Location location;
private Location location, signLocation;
private ArmorStand itemStand, blockStand, toolItemStand;
@Override
@ -36,6 +36,10 @@ public class LocationInfo implements ConfigurationSerializable {
return location;
}
public Location getSignLocation() {
return signLocation;
}
public ArmorStand getBlockStand() {
return blockStand;
}
@ -60,6 +64,10 @@ public class LocationInfo implements ConfigurationSerializable {
this.toolItemStand = toolItemStand;
}
public void setSignLocation(Location signLocation) {
this.signLocation = signLocation;
}
public static List<LocationInfo> convert(List<Location> locationList){
List<LocationInfo> locationInfos = new ArrayList<>();
for (Location location : locationList) {

View File

@ -1,5 +1,6 @@
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.Values;
@ -14,6 +15,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
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;
@ -44,12 +46,13 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private List<LocationInfo> locationInfoList;
private Inventory inventory;
public AbstractStorage(OfflinePlayer player, String identifier, Location location){
public AbstractStorage(OfflinePlayer player, String identifier, Location location, Location signLocation){
this.player = player;
this.playerUUID = player.getUniqueId();
this.isPublic = false;
setIdentifier(identifier);
LocationInfo locationInfo = new LocationInfo(location);
locationInfo.setSignLocation(signLocation);
locationInfoList = new ArrayList<>(Collections.singleton(locationInfo));
inventory = initInventory();
init();
@ -97,8 +100,6 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
ItemStack[] itemStacks = ((ArrayList<ItemStack>) map.get("inventory")).toArray(new ItemStack[0]);
inventory.setContents(itemStacks);
}
init();
}
@Override
@ -116,7 +117,33 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
}
private void init(){
// if(shouldDisplayArmourStands()) Bukkit.getScheduler().scheduleSyncRepeatingTask(ChestsPlusPlus.PLUGIN, this::updateClients, 1, 5);
if(shouldDisplayArmourStands()) {
Bukkit.getScheduler().scheduleSyncRepeatingTask(ChestsPlusPlus.PLUGIN, () -> {
for (LocationInfo locationInfo : locationInfoList) {
World world = locationInfo.getLocation().getWorld();
if (world != null) {
//Make client think sign is invisible.
if (displayItem != null) world.getPlayers().forEach(player -> player.sendBlockChange(locationInfo.getSignLocation(), air));
else locationInfo.getSignLocation().getBlock().getState().update();
}
}
}, 1, 1);
} else {
for (LocationInfo locationInfo : locationInfoList) {
locationInfo.getSignLocation().getBlock().getState().update();
}
}
}
/**
* This is called after the config has loaded into memory.
*/
public void postConfigLoad(){
for(LocationInfo locationInfo : locationInfoList) {
locationInfo.setSignLocation(getSignLocation(locationInfo.getLocation()));
}
init();
}
public abstract StorageType getStorageType();
@ -143,11 +170,6 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
public abstract String getIdentifier();
public abstract boolean shouldDisplayArmourStands();
/**
* This is called after the config has loaded into memory.
*/
public abstract void postConfigLoad();
/**
* @return whether to drop the inventory of this storage when it's removed.
*/
@ -178,8 +200,11 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
* Adds a location to this storage.
* @param location - location to be added.
*/
public void addLocation(Location location){
locationInfoList.add(new LocationInfo(location));
public void addLocation(Location location, Location signLocation){
LocationInfo locationInfo = new LocationInfo(location);
locationInfo.setSignLocation(signLocation);
locationInfoList.add(locationInfo);
updateClient(locationInfo);
}
/**
@ -251,6 +276,21 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
}
}
public Location getSignLocation(Location storageBlock){
World world = storageBlock.getWorld();
Block block = storageBlock.getBlock();
if(world != null) {
BlockFace facing = getStorageType().getStorageFacing(block);
if (facing != null) {
Block sign = block.getRelative(facing);
return sign.getLocation();
}
}
return null;
}
/* MEMBER METHODS */
/**
@ -315,7 +355,7 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
/* ARMOR STAND METHODS */
private static ItemStack displayItem;
private ItemStack displayItem;
public void onItemDisplayUpdate(ItemStack newItem){
displayItem = newItem;
@ -334,67 +374,65 @@ public abstract class AbstractStorage implements ConfigurationSerializable {
private void updateClients(){
if(locationInfoList == null) return;
for (LocationInfo location : locationInfoList){
World world = location.getLocation().getWorld();
Block block = location.getLocation().getBlock();
BlockData air = Material.AIR.createBlockData();
if(world != null) {
Collection<Entity> players = world.getNearbyEntities(location.getLocation(), 20, 20, 20, entity -> entity instanceof Player);
players.forEach(entity -> {
if(entity instanceof Player){
Player player = (Player) entity;
BlockFace facing = getStorageType().getStorageFacing(block);
if(facing != null) {
Block anchor = block.getRelative(facing);
if(displayItem != null && !ApiSpecific.getMaterialChecker().isIgnored(displayItem)) {
boolean isBlock = !ApiSpecific.getMaterialChecker().isGraphically2D(displayItem);
boolean isTool = ApiSpecific.getMaterialChecker().isTool(displayItem);
Location standLoc = isTool ? getHeldItemArmorStandLoc(anchor, facing) : getArmorStandLoc(anchor, facing, isBlock);
//Make client think sign is invisible.
player.sendBlockChange(anchor.getLocation(), air);
//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()) {
stand = createArmorStand(world, standLoc, isBlock, isTool);
addArmorStand(isBlock, isTool, location, stand);
}
stand.setItemInHand(displayItem);
//Set on fire to correct lighting.
stand.setFireTicks(Integer.MAX_VALUE);
//Set other armor stand helmet to null.
if(isBlock) {
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
} else {
setArmorStandHelmet(location.getBlockStand(), null);
if(isTool) setArmorStandHelmet(location.getItemStand(), null);
else setArmorStandHelmet(location.getToolItemStand(), null);
}
} else {
anchor.getState().update();
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
setArmorStandHelmet(location.getBlockStand(), null);
}
}
}
});
}
updateClient(location);
}
}
private BlockData air = Material.AIR.createBlockData();
private void updateClient(LocationInfo location){
World world = location.getLocation().getWorld();
if(world != null) {
Block anchor = location.getSignLocation().getBlock();
BlockFace facing;
if(anchor.getBlockData() instanceof Directional){
facing = ((Directional) anchor.getBlockData()).getFacing();
} else {
Bukkit.broadcastMessage("Not directional");
return;
}
if(displayItem != null && !ApiSpecific.getMaterialChecker().isIgnored(displayItem)) {
boolean isBlock = !ApiSpecific.getMaterialChecker().isGraphically2D(displayItem);
boolean isTool = ApiSpecific.getMaterialChecker().isTool(displayItem);
Location standLoc = isTool ? getHeldItemArmorStandLoc(anchor, facing) : getArmorStandLoc(anchor, facing, isBlock);
//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()) {
stand = createArmorStand(world, standLoc, isBlock, isTool);
addArmorStand(isBlock, isTool, location, stand);
}
stand.setItemInHand(displayItem);
//Set on fire to correct lighting.
stand.setFireTicks(Integer.MAX_VALUE);
//Set other armor stand helmet to null.
if(isBlock) {
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
} else {
setArmorStandHelmet(location.getBlockStand(), null);
if(isTool) setArmorStandHelmet(location.getItemStand(), null);
else setArmorStandHelmet(location.getToolItemStand(), null);
}
} else {
anchor.getState().update();
setArmorStandHelmet(location.getToolItemStand(), null);
setArmorStandHelmet(location.getItemStand(), null);
setArmorStandHelmet(location.getBlockStand(), null);
}
}
}
/**
* Creates an empty @{@link ArmorStand} with properties to make it invisible, invulnerable etc.
* @param world - the world to spawn in.

View File

@ -33,7 +33,7 @@ public class StorageInfo<T extends AbstractStorage> {
Block storageBlock = sign.getBlock().getRelative(storageFace);
Player player = Bukkit.getPlayer(playerUUID);
if(player != null) {
boolean added = storageType.add(player, group, storageBlock.getLocation(), this.player);
boolean added = storageType.add(player, group, storageBlock.getLocation(), sign.getLocation(), this.player);
if(added) {
this.storage = storageType.getStorage(playerUUID, group);
// storageType.getMessages().foundUnlinkedStorage(player,group);
@ -58,7 +58,7 @@ public class StorageInfo<T extends AbstractStorage> {
*/
public T getStorage(Location location) {
if(!storage.containsLocation(location)){
storage.addLocation(location);
storage.addLocation(location, storage.getSignLocation(location));
Player player = storage.getOwner().getPlayer();
if(player != null) storage.getStorageType().getMessages().foundUnlinkedStorage(player,getGroup());
}

View File

@ -50,7 +50,7 @@ public abstract class StorageType<T extends AbstractStorage> {
public abstract HashMap<String, HashMap<String, T>> getStorageMap(ConfigStorage store);
public abstract T createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location);
public abstract T createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location, Location signLocation);
/**
* This is the tag used in Signs such as [ChestLink] or [AutoCraft]
@ -157,7 +157,7 @@ public abstract class StorageType<T extends AbstractStorage> {
ADD/REMOVE UTILS
*/
public boolean add(Player player, String identifier, Location chestLocation, OfflinePlayer owner) {
public boolean add(Player player, String identifier, Location chestLocation, Location sign, OfflinePlayer owner) {
//List of groups this player has.
HashMap<String, T> map = getStorageMap(owner.getUniqueId());
@ -168,7 +168,7 @@ public abstract class StorageType<T extends AbstractStorage> {
Messages.OWNER_HAS_TOO_MANY_CHESTS(player, owner);
return false;
}
T storage = createNewStorageInstance(owner, identifier, chestLocation);
T storage = createNewStorageInstance(owner, identifier, chestLocation, sign);
map.put(identifier, storage);
}
@ -177,7 +177,7 @@ public abstract class StorageType<T extends AbstractStorage> {
//If the location isn't already part of the system add it.
if (!storage.containsLocation(chestLocation)) {
storage.addLocation(chestLocation);
storage.addLocation(chestLocation, sign);
}
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1f);

View File

@ -35,8 +35,8 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
return Config.getAutoCraft();
}
public AutoCraftingStorage(OfflinePlayer player, String identifier, Location location){
super(player, identifier, location);
public AutoCraftingStorage(OfflinePlayer player, String identifier, Location location, Location signLocation){
super(player, identifier, location, signLocation);
this.identifier = identifier;
initInventory();
}
@ -77,11 +77,6 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
return Settings.isShouldDisplayAutoCraftStand();
}
@Override
public void postConfigLoad() {
}
@Override
public boolean doesDropInventory() {
return false;
@ -127,4 +122,10 @@ public class AutoCraftingStorage extends AbstractStorage implements Configuratio
public void onStorageAdded(Block block, Player player) {
//Don't need to do anything with the Crafting table.
}
@Override
public void postConfigLoad() {
super.postConfigLoad();
if(recipeSerializable != null) onItemDisplayUpdate(recipeSerializable.getRecipe().getResult());
}
}

View File

@ -36,8 +36,8 @@ public class AutoCraftingStorageType extends StorageType<AutoCraftingStorage> {
}
@Override
public AutoCraftingStorage createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location) {
return new AutoCraftingStorage(player, inventoryName, location);
public AutoCraftingStorage createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location, Location sign) {
return new AutoCraftingStorage(player, inventoryName, location, sign);
}
@Override

View File

@ -41,8 +41,8 @@ public class ChestLinkStorage extends AbstractStorage implements ConfigurationSe
super(map);
}
public ChestLinkStorage(OfflinePlayer player, String group, Location location){
super(player, group, location);
public ChestLinkStorage(OfflinePlayer player, String group, Location location, Location signLocation){
super(player, group, location, signLocation);
this.inventoryName = group;
this.sortMethod = SortMethod.OFF;
@ -194,6 +194,7 @@ public class ChestLinkStorage extends AbstractStorage implements ConfigurationSe
@Override
public void postConfigLoad() {
super.postConfigLoad();
onItemDisplayUpdate(InventorySorter.getMostCommonItem(getInventory()));
}

View File

@ -32,8 +32,8 @@ public class ChestLinkStorageType extends StorageType<ChestLinkStorage> {
}
@Override
public ChestLinkStorage createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location) {
return new ChestLinkStorage(player, inventoryName, location);
public ChestLinkStorage createNewStorageInstance(OfflinePlayer player, String inventoryName, Location location, Location signLocation) {
return new ChestLinkStorage(player, inventoryName, location, signLocation);
}
@Override