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:
parent
84d2d99097
commit
a7d0758692
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
@ -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
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
@ -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...");
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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));
|
||||
});
|
||||
}
|
||||
}
|
@ -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() {}
|
||||
|
Loading…
Reference in New Issue
Block a user