1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 03:35:51 +00:00

More work on holograms

This commit is contained in:
TheBusyBiscuit 2021-01-15 00:16:58 +01:00
parent 84d2d99097
commit a7d0758692
15 changed files with 401 additions and 232 deletions

View File

@ -1,12 +1,15 @@
package io.github.thebusybiscuit.slimefun4.core.attributes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.core.services.holograms.HologramsService;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.HologramProjector;
@ -16,18 +19,53 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.HologramPr
* @author TheBusyBiscuit
*
* @see HologramProjector
* @see HologramsService
*
*/
public interface HologramOwner extends ItemAttribute {
/**
* This will update the hologram text for the given {@link Block}.
*
* @param b
* The {@link Block} to which the hologram belongs
*
* @param text
* The nametag for the hologram
*/
default void updateHologram(@Nonnull Block b, @Nonnull String text) {
Location loc = b.getLocation().add(getHologramOffset());
SlimefunPlugin.getHologramsService().updateHologram(loc, hologram -> {
hologram.setCustomName(ChatColors.color(text));
hologram.setCustomNameVisible(true);
});
}
@Nullable
default ArmorStand getHologram(@Nonnull Block b, boolean createIfNoneExists) {
Location loc = b.getLocation().add(getHologramOffset());
return SlimefunPlugin.getHologramsService().getHologram(loc, createIfNoneExists);
}
/**
* This will remove the hologram for the given {@link Block}.
*
* @param b
* The {@link Block} to which the hologram blocks
*/
default void removeHologram(@Nonnull Block b) {
Location loc = b.getLocation().add(getHologramOffset());
SlimefunPlugin.getHologramsService().removeHologram(loc);
}
/**
* This returns the offset of the hologram as a {@link Vector}.
* This offset is applied to {@link Block#getLocation()} when spawning
* the hologram.
*
* @return The hologram offset
*/
@Nonnull
default Vector getHologramOffset() {
return new Vector(0.5, 0.75, 0.5);

View File

@ -17,8 +17,8 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
/**
@ -36,7 +36,7 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
* @author DNx5
*
*/
public class CargoNet extends AbstractItemNetwork {
public class CargoNet extends AbstractItemNetwork implements HologramOwner {
private static final int RANGE = 5;
private static final int TICK_DELAY = SlimefunPlugin.getCfg().getInt("networks.cargo-ticker-delay");
@ -142,16 +142,16 @@ public class CargoNet extends AbstractItemNetwork {
public void tick(Block b) {
if (!regulator.equals(b.getLocation())) {
SimpleHologram.update(b, "&4Multiple Cargo Regulators connected");
updateHologram(b, "&4Multiple Cargo Regulators connected");
return;
}
super.tick();
if (connectorNodes.isEmpty() && terminusNodes.isEmpty()) {
SimpleHologram.update(b, "&cNo Cargo Nodes found");
updateHologram(b, "&cNo Cargo Nodes found");
} else {
SimpleHologram.update(b, "&7Status: &a&lONLINE");
updateHologram(b, "&7Status: &a&lONLINE");
// Skip ticking if the threshold is not reached. The delay is not same as minecraft tick,
// but it's based on 'custom-ticker-delay' config.

View File

@ -20,10 +20,10 @@ import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -41,7 +41,7 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
* @see EnergyNetComponentType
*
*/
public class EnergyNet extends Network {
public class EnergyNet extends Network implements HologramOwner {
private static final int RANGE = 6;
@ -116,7 +116,7 @@ public class EnergyNet extends Network {
AtomicLong timestamp = new AtomicLong(SlimefunPlugin.getProfiler().newEntry());
if (!regulator.equals(b.getLocation())) {
SimpleHologram.update(b, "&4Multiple Energy Regulators connected");
updateHologram(b, "&4Multiple Energy Regulators connected");
SlimefunPlugin.getProfiler().closeEntry(b.getLocation(), SlimefunItems.ENERGY_REGULATOR.getItem(), timestamp.get());
return;
}
@ -124,7 +124,7 @@ public class EnergyNet extends Network {
super.tick();
if (connectorNodes.isEmpty() && terminusNodes.isEmpty()) {
SimpleHologram.update(b, "&4No Energy Network found");
updateHologram(b, "&4No Energy Network found");
} else {
int supply = tickAllGenerators(timestamp::getAndAdd) + tickAllCapacitors();
int remainingEnergy = supply;
@ -258,10 +258,10 @@ public class EnergyNet extends Network {
private void updateHologram(@Nonnull Block b, double supply, double demand) {
if (demand > supply) {
String netLoss = NumberUtils.getCompactDouble(demand - supply);
SimpleHologram.update(b, "&4&l- &c" + netLoss + " &7J &e\u26A1");
updateHologram(b, "&4&l- &c" + netLoss + " &7J &e\u26A1");
} else {
String netGain = NumberUtils.getCompactDouble(supply - demand);
SimpleHologram.update(b, "&2&l+ &a" + netGain + " &7J &e\u26A1");
updateHologram(b, "&2&l+ &a" + netGain + " &7J &e\u26A1");
}
}

View File

@ -1,138 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
/**
* This service is responsible for handling holograms.
* This includes error management when something goes wrong.
*
* @author TheBusyBiscuit
*
* @see HologramOwner
*/
public class HologramsService {
/**
* The radius in which we scan for holograms.
*/
private static final double RADIUS = 0.45;
/**
* The {@link NamespacedKey} used to store data on a hologram
*/
private final NamespacedKey persistentDataKey;
/**
* Our cache to save {@link Entity} lookups
*/
private final Map<BlockPosition, UUID> entityCache = new HashMap<>();
public HologramsService(@Nonnull Plugin plugin) {
// Null-Validation is performed in the NamespacedKey constructor
persistentDataKey = new NamespacedKey(plugin, "hologram_id");
}
@Nullable
public ArmorStand getHologram(@Nonnull Location loc, boolean createIfNoneExists) {
Validate.notNull(loc, "Location cannot be null");
BlockPosition position = new BlockPosition(loc);
UUID uuid = entityCache.get(position);
if (uuid != null) {
Entity entity = Bukkit.getEntity(uuid);
if (entity instanceof ArmorStand) {
return (ArmorStand) entity;
}
}
Collection<Entity> holograms = loc.getWorld().getNearbyEntities(loc, RADIUS, RADIUS, RADIUS, this::isHologram);
for (Entity n : holograms) {
if (n instanceof ArmorStand) {
PersistentDataContainer container = n.getPersistentDataContainer();
if (container.has(persistentDataKey, PersistentDataType.LONG)) {
// Check if it is ours or a different one.
if (container.get(persistentDataKey, PersistentDataType.LONG).equals(position.getPosition())) {
return (ArmorStand) n;
}
} else {
// Set a persistent tag to re-identify the correct hologram later
container.set(persistentDataKey, PersistentDataType.LONG, position.getPosition());
return (ArmorStand) n;
}
}
}
if (createIfNoneExists) {
// Spawn a new ArmorStand
ArmorStand hologram = (ArmorStand) loc.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND);
// Set a persistent tag to re-identify the correct hologram later
PersistentDataContainer container = hologram.getPersistentDataContainer();
container.set(persistentDataKey, PersistentDataType.LONG, position.getPosition());
hologram.setSilent(true);
hologram.setMarker(true);
hologram.setAI(false);
hologram.setGravity(false);
return hologram;
} else {
return null;
}
}
public boolean removeHologram(@Nonnull Location loc) {
Validate.notNull(loc, "Location cannot be null");
ArmorStand hologram = getHologram(loc, false);
if (hologram != null) {
hologram.remove();
return true;
} else {
return false;
}
}
private boolean isHologram(@Nonnull Entity n) {
if (n instanceof ArmorStand) {
ArmorStand armorstand = (ArmorStand) n;
return armorstand.isValid() && armorstand.isSilent() && armorstand.isMarker() && !armorstand.hasAI() && !armorstand.hasGravity();
} else {
return false;
}
}
public void updateHologram(@Nonnull Location loc, @Nonnull Consumer<ArmorStand> consumer) {
Validate.notNull(loc, "Location cannot be null");
Validate.notNull(consumer, "Callbacks must not be null");
consumer.accept(getHologram(loc, true));
}
}

View File

@ -0,0 +1,79 @@
package io.github.thebusybiscuit.slimefun4.core.services.holograms;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
/**
* This represents an {@link ArmorStand} or hologram that can expire.
*
* @author TheBusyBiscuit
*
*/
class CachedArmorStand {
/**
* This is the minimum duration after which the {@link CachedArmorStand} will expire.
*/
private static final long EXPIRES_AFTER = TimeUnit.MINUTES.toMillis(10);
/**
* The {@link UUID} of the {@link ArmorStand}.
*/
private final UUID uniqueId;
/**
* The timestamp of when the {@link ArmorStand} was last accessed.
*/
private long lastAccess;
/**
* This creates a new {@link CachedArmorStand} for the given {@link UUID}.
*
* @param uniqueId
* The {@link UUID} of the corresponding {@link ArmorStand}
*/
public CachedArmorStand(@Nonnull UUID uniqueId) {
this.uniqueId = uniqueId;
this.lastAccess = System.currentTimeMillis();
}
/**
* This returns the corresponding {@link ArmorStand}
* and also updates the "lastAccess" timestamp.
* <p>
* If the {@link ArmorStand} was removed, it will return null.
*
* @return The {@link ArmorStand} or null.
*/
@Nullable
public ArmorStand getArmorStand() {
Entity n = Bukkit.getEntity(uniqueId);
if (n instanceof ArmorStand && n.isValid()) {
this.lastAccess = System.currentTimeMillis();
return (ArmorStand) n;
} else {
this.lastAccess = 0;
return null;
}
}
/**
* This returns whether this {@link CachedArmorStand} has expired.
* The armorstand will expire if the last access has been more than 10
* minutes ago.
*
* @return Whether this {@link CachedArmorStand} has expired
*/
public boolean isExpired() {
return System.currentTimeMillis() - lastAccess > EXPIRES_AFTER;
}
}

View File

@ -0,0 +1,236 @@
package io.github.thebusybiscuit.slimefun4.core.services.holograms;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This service is responsible for handling holograms.
* This includes error management when something goes wrong.
*
* @author TheBusyBiscuit
*
* @see HologramOwner
*/
public class HologramsService {
/**
* The radius in which we scan for holograms
*/
private static final double RADIUS = 0.45;
/**
* The frequency at which to purge
*/
private static final long PURGE_RATE = 60L * 20L;
/**
* Our {@link Plugin} instance
*/
private final Plugin plugin;
/**
* The {@link NamespacedKey} used to store data on a hologram
*/
private final NamespacedKey persistentDataKey;
/**
* Our cache to save {@link Entity} lookups
*/
private final Map<BlockPosition, CachedArmorStand> cache = new HashMap<>();
/**
* This constructs a new {@link HologramsService}.
*
* @param plugin
* Our {@link Plugin} instance
*/
public HologramsService(@Nonnull Plugin plugin) {
this.plugin = plugin;
// Null-Validation is performed in the NamespacedKey constructor
persistentDataKey = new NamespacedKey(plugin, "hologram_id");
}
/**
* This will start the {@link HologramsService} and schedule a repeating
* purge-task.
*/
public void start() {
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this::purge, PURGE_RATE, PURGE_RATE);
}
/**
* This purges all expired {@link CachedArmorStand CachedArmorStands}.
*/
private void purge() {
Iterator<CachedArmorStand> iterator = cache.values().iterator();
while (iterator.hasNext()) {
if (iterator.next().isExpired()) {
iterator.remove();
}
}
}
/**
* This returns the hologram associated with the given {@link Location}.
* If createIfNoneExists is set to true a new {@link ArmorStand} will be spawned
* if no existing one could be found.
*
* @param loc
* The {@link Location}
* @param createIfNoneExists
* Whether to create a new {@link ArmorStand} if none was found
*
* @return The existing (or newly created) hologram
*/
@Nullable
public ArmorStand getHologram(@Nonnull Location loc, boolean createIfNoneExists) {
Validate.notNull(loc, "Location cannot be null");
if (!Bukkit.isPrimaryThread()) {
throw new UnsupportedOperationException("A hologram cannot be accessed asynchronously.");
}
BlockPosition position = new BlockPosition(loc);
CachedArmorStand cachedEntity = cache.get(position);
// Check if the ArmorStand was cached
if (cachedEntity != null) {
ArmorStand armorstand = cachedEntity.getArmorStand();
// If the Entity still exists, return it
if (armorstand != null) {
return armorstand;
}
}
// Scan all nearby entities which could be possible holograms
Collection<Entity> holograms = loc.getWorld().getNearbyEntities(loc, RADIUS, RADIUS, RADIUS, this::isHologram);
for (Entity n : holograms) {
if (n instanceof ArmorStand) {
PersistentDataContainer container = n.getPersistentDataContainer();
if (container.has(persistentDataKey, PersistentDataType.LONG)) {
// Check if it is ours or a different one.
if (container.get(persistentDataKey, PersistentDataType.LONG).equals(position.getPosition())) {
return (ArmorStand) n;
}
} else {
// Set a persistent tag to re-identify the correct hologram later
container.set(persistentDataKey, PersistentDataType.LONG, position.getPosition());
return (ArmorStand) n;
}
}
}
if (createIfNoneExists) {
// Spawn a new ArmorStand
ArmorStand hologram = (ArmorStand) loc.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND);
// Set a persistent tag to re-identify the correct hologram later
PersistentDataContainer container = hologram.getPersistentDataContainer();
container.set(persistentDataKey, PersistentDataType.LONG, position.getPosition());
hologram.setSilent(true);
hologram.setMarker(true);
hologram.setAI(false);
hologram.setGravity(false);
return hologram;
} else {
return null;
}
}
/**
* This removes the hologram at that given {@link Location}.
* <p>
* <strong>This method must be executed on the main {@link Server} {@link Thread}.</strong>
*
* @param loc
* The {@link Location}
*
* @return Whether the hologram could be removed, false if the hologram does not exist or was already removed
*/
public boolean removeHologram(@Nonnull Location loc) {
Validate.notNull(loc, "Location cannot be null");
if (Bukkit.isPrimaryThread()) {
ArmorStand hologram = getHologram(loc, false);
if (hologram != null) {
hologram.remove();
return true;
} else {
return false;
}
} else {
throw new UnsupportedOperationException("You cannot remove a hologram asynchronously.");
}
}
/**
* This updates the hologram.
* You can use it to set the nametag or other properties.
* <p>
* <strong>This method must be executed on the main {@link Server} {@link Thread}.</strong>
*
* @param loc
* The {@link Location}
* @param consumer
* The callback to run
*/
public void updateHologram(@Nonnull Location loc, @Nonnull Consumer<ArmorStand> consumer) {
Validate.notNull(loc, "Location must not be null");
Validate.notNull(consumer, "Callbacks must not be null");
if (Bukkit.isPrimaryThread()) {
consumer.accept(getHologram(loc, true));
} else {
SlimefunPlugin.runSync(() -> consumer.accept(getHologram(loc, true)));
}
}
/**
* This checks if a given {@link Entity} is an {@link ArmorStand}
* and whether it has the correct attributes to be considered a hologram.
*
* @param n
* The {@link Entity} to check
*
* @return Whether this could be a hologram
*/
private boolean isHologram(@Nonnull Entity n) {
if (n instanceof ArmorStand) {
ArmorStand armorstand = (ArmorStand) n;
return armorstand.isValid() && armorstand.isSilent() && armorstand.isMarker() && !armorstand.hasAI() && !armorstand.hasGravity();
} else {
return false;
}
}
}

View File

@ -0,0 +1,5 @@
/**
* This package contains everything related to the
* {@link io.github.thebusybiscuit.slimefun4.core.services.holograms.HologramsService}.
*/
package io.github.thebusybiscuit.slimefun4.core.services.holograms;

View File

@ -43,7 +43,6 @@ import io.github.thebusybiscuit.slimefun4.core.services.BackupService;
import io.github.thebusybiscuit.slimefun4.core.services.BlockDataService;
import io.github.thebusybiscuit.slimefun4.core.services.CustomItemDataService;
import io.github.thebusybiscuit.slimefun4.core.services.CustomTextureService;
import io.github.thebusybiscuit.slimefun4.core.services.HologramsService;
import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService;
import io.github.thebusybiscuit.slimefun4.core.services.MetricsService;
import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService;
@ -51,6 +50,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService;
import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.holograms.HologramsService;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
@ -348,6 +348,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Starting our tasks
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
hologramsService.start();
ticker.start(this);
// Loading integrations

View File

@ -2,15 +2,17 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -19,13 +21,14 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class CargoManager extends SlimefunItem {
public class CargoManager extends SlimefunItem implements HologramOwner {
@ParametersAreNonnullByDefault
public CargoManager(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
registerBlockHandler(getId(), (p, b, tool, reason) -> {
SimpleHologram.remove(b);
removeHologram(b);
return true;
});
}

View File

@ -8,9 +8,9 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -28,14 +28,14 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see EnergyNetComponent
*
*/
public class EnergyRegulator extends SlimefunItem {
public class EnergyRegulator extends SlimefunItem implements HologramOwner {
@ParametersAreNonnullByDefault
public EnergyRegulator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
SlimefunItem.registerBlockHandler(getId(), (p, b, stack, reason) -> {
SimpleHologram.remove(b);
removeHologram(b);
return true;
});
}
@ -46,7 +46,7 @@ public class EnergyRegulator extends SlimefunItem {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
SimpleHologram.update(e.getBlock(), "&7Connecting...");
updateHologram(e.getBlock(), "&7Connecting...");
}
};

View File

@ -14,7 +14,6 @@ import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.holograms.ReactorHologram;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
@ -44,7 +43,8 @@ public abstract class NetherStarReactor extends Reactor {
@Override
public void extraTick(@Nonnull Location l) {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = ReactorHologram.getArmorStand(l, true);
ArmorStand hologram = getHologram(l.getBlock(), true);
for (Entity entity : hologram.getNearbyEntities(5, 5, 5)) {
if (entity instanceof LivingEntity && entity.isValid()) {
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.WITHER, 60, 1));

View File

@ -23,14 +23,13 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncReactorProcessCompleteEvent;
import io.github.thebusybiscuit.slimefun4.api.events.ReactorExplodeEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.cargo.ReactorAccessPort;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.AbstractEnergyProvider;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.ReactorHologram;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -56,7 +55,7 @@ import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
* @see NetherStarReactor
*
*/
public abstract class Reactor extends AbstractEnergyProvider {
public abstract class Reactor extends AbstractEnergyProvider implements HologramOwner {
public static Map<Location, MachineFuel> processing = new HashMap<>();
public static Map<Location, Integer> progress = new HashMap<>();
@ -118,7 +117,7 @@ public abstract class Reactor extends AbstractEnergyProvider {
progress.remove(b.getLocation());
processing.remove(b.getLocation());
SimpleHologram.remove(b);
removeHologram(b);
return true;
});
@ -332,7 +331,7 @@ public abstract class Reactor extends AbstractEnergyProvider {
Bukkit.getPluginManager().callEvent(event);
BlockStorage.getInventory(l).close();
SimpleHologram.remove(l.getBlock());
removeHologram(l.getBlock());
});
explosionsQueue.remove(l);
@ -427,14 +426,14 @@ public abstract class Reactor extends AbstractEnergyProvider {
for (int slot : getCoolantSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), coolant, true, false)) {
menu.consumeItem(slot);
ReactorHologram.update(reactor, "&b\u2744 &7100%");
updateHologram(reactor.getBlock(), "&b\u2744 &7100%");
return true;
}
}
return false;
} else {
ReactorHologram.update(reactor, "&b\u2744 &7" + getPercentage(timeleft, processing.get(reactor).getTicks()) + "%");
updateHologram(reactor.getBlock(), "&b\u2744 &7" + getPercentage(timeleft, processing.get(reactor).getTicks()) + "%");
}
return true;

View File

@ -14,11 +14,11 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -30,7 +30,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
public class GEOMiner extends AContainer implements RecipeDisplayItem {
public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramOwner {
private static final int[] BORDER = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 26, 27, 35, 36, 44, 45, 53 };
private static final int[] OUTPUT_BORDER = { 19, 20, 21, 22, 23, 24, 25, 28, 34, 37, 43, 46, 47, 48, 49, 50, 51, 52 };
@ -42,7 +42,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem {
addItemHandler(onPlace());
registerBlockHandler(getId(), (p, b, stack, reason) -> {
SimpleHologram.remove(b);
removeHologram(b);
BlockMenu inv = BlockStorage.getInventory(b);
@ -61,7 +61,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
SimpleHologram.update(e.getBlock(), "&7Idling...");
updateHologram(e.getBlock(), "&7Idling...");
}
};
}
@ -156,7 +156,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem {
processing.remove(b);
}
} else if (!BlockStorage.hasChunkInfo(b.getWorld(), b.getX() >> 4, b.getZ() >> 4)) {
SimpleHologram.update(b, "&4GEO-Scan required!");
updateHologram(b, "&4GEO-Scan required!");
} else {
start(b, inv);
}
@ -168,7 +168,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem {
OptionalInt optional = SlimefunPlugin.getGPSNetwork().getResourceManager().getSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4);
if (!optional.isPresent()) {
SimpleHologram.update(b, "&4GEO-Scan required!");
updateHologram(b, "&4GEO-Scan required!");
return;
}
@ -183,13 +183,13 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem {
processing.put(b, r);
progress.put(b, r.getTicks());
SlimefunPlugin.getGPSNetwork().getResourceManager().setSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4, supplies - 1);
SimpleHologram.update(b, "&7Mining: &r" + resource.getName());
updateHologram(b, "&7Mining: &r" + resource.getName());
return;
}
}
}
SimpleHologram.update(b, "&7Finished");
updateHologram(b, "&7Finished");
}
}

View File

@ -1,58 +0,0 @@
package io.github.thebusybiscuit.slimefun4.utils.holograms;
import java.util.Collection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Location;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
public final class ReactorHologram {
private ReactorHologram() {}
@Nullable
public static ArmorStand getArmorStand(@Nonnull Location reactor, boolean createIfNoneExists) {
Location l = new Location(reactor.getWorld(), reactor.getX() + 0.5, reactor.getY() + 0.7, reactor.getZ() + 0.5);
Collection<Entity> holograms = l.getWorld().getNearbyEntities(l, 0.2, 0.2, 0.2, ReactorHologram::isPossibleHologram);
for (Entity n : holograms) {
if (n instanceof ArmorStand) {
return (ArmorStand) n;
}
}
if (!createIfNoneExists) {
return null;
}
ArmorStand hologram = SimpleHologram.create(l);
hologram.setCustomNameVisible(false);
hologram.setCustomName(null);
return hologram;
}
private static boolean isPossibleHologram(@Nonnull Entity n) {
if (n instanceof ArmorStand) {
ArmorStand armorstand = (ArmorStand) n;
return armorstand.isValid() && armorstand.isSilent() && armorstand.isMarker() && !armorstand.hasGravity();
} else {
return false;
}
}
public static void update(@Nonnull Location l, @Nonnull String name) {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = getArmorStand(l, true);
hologram.setCustomNameVisible(true);
hologram.setCustomName(ChatColors.color(name));
});
}
}

View File

@ -12,14 +12,18 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This utility class provides a few static methods for modifying a simple Text-based Hologram.
*
* @deprecated Please use the interface {@link HologramOwner} instead
*
* @author TheBusyBiscuit
*
*/
@Deprecated
public final class SimpleHologram {
private SimpleHologram() {}