From d0e7e218779e6b3593467a7db91d57e5a3c36791 Mon Sep 17 00:00:00 2001 From: TheBusyBiscuit Date: Wed, 25 Nov 2020 14:27:46 +0100 Subject: [PATCH] Performance and memory improvements --- CHANGELOG.md | 1 + pom.xml | 2 +- .../slimefun4/api/network/Network.java | 7 +- .../core/handlers/RainbowTickHandler.java | 14 ++- .../core/networks/energy/EnergyNet.java | 6 +- .../services/profiler/SlimefunProfiler.java | 2 +- .../items/electric/gadgets/Multimeter.java | 6 +- .../tasks/CapacitorTextureUpdateTask.java | 14 ++- .../implementation/tasks/TickerTask.java | 109 ++++++++++++++---- .../slimefun4/utils/HeadTexture.java | 17 +++ .../slimefun4/utils/NumberUtils.java | 29 +++++ .../utils/holograms/ReactorHologram.java | 22 +++- .../utils/holograms/SimpleHologram.java | 17 ++- .../abstractItems/AGenerator.java | 2 +- .../Slimefun/api/BlockInfoConfig.java | 10 -- .../Slimefun/api/BlockStorage.java | 57 ++------- .../Slimefun/bstats/bukkit/Metrics.java | 7 ++ 17 files changed, 214 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad603efdc..4fa543509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ * Memory/GC improvements for the profiler * Performance improvements for the Fluid Pump * Removed EmeraldEnchants integration +* Memory and performance improvements for ticking blocks #### Fixes * Fixed #2448 diff --git a/pom.xml b/pom.xml index d2f725cd8..c512da9d2 100644 --- a/pom.xml +++ b/pom.xml @@ -337,7 +337,7 @@ com.github.TheBusyBiscuit CS-CoreLib2 - 0.27.3 + 0.27.4 compile diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java index e4d06619e..9f026b2e5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java @@ -132,10 +132,15 @@ public abstract class Network { * * @param l * The {@link Location} to check for + * * @return Whether the given {@link Location} is part of this {@link Network} */ public boolean connectsTo(@Nonnull Location l) { - return connectedLocations.contains(l); + if (regulator.equals(l)) { + return true; + } else { + return connectedLocations.contains(l); + } } @Nullable diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java index bcd5f0ac8..78fe5c98f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java @@ -75,9 +75,11 @@ public class RainbowTickHandler extends BlockTicker { } for (Material type : materials) { - // This BlockData is purely virtual and only created on startup, it should have - // no impact on performance, in fact it should save performance as it preloads - // the data but also saves heavy calls for other Materials + /** + * This BlockData is purely virtual and only created on startup, it should have + * no impact on performance, in fact it should save performance as it preloads + * the data but also saves heavy calls for other Materials + */ if (type.createBlockData() instanceof GlassPane) { return true; } @@ -89,8 +91,10 @@ public class RainbowTickHandler extends BlockTicker { @Override public void tick(Block b, SlimefunItem item, Config data) { if (b.getType() == Material.AIR) { - // The block was broken, setting the Material now would result in a - // duplication glitch + /** + * The block was broken, setting the Material now would result in a + * duplication glitch + */ return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java index b201c5137..69cd65bc5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java @@ -15,7 +15,6 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; -import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler; import io.github.thebusybiscuit.slimefun4.api.ErrorReport; import io.github.thebusybiscuit.slimefun4.api.network.Network; import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent; @@ -23,6 +22,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider; 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; @@ -254,10 +254,10 @@ public class EnergyNet extends Network { private void updateHologram(@Nonnull Block b, double supply, double demand) { if (demand > supply) { - String netLoss = DoubleHandler.getFancyDouble(Math.abs(supply - demand)); + String netLoss = NumberUtils.getCompactDouble(demand - supply); SimpleHologram.update(b, "&4&l- &c" + netLoss + " &7J &e\u26A1"); } else { - String netGain = DoubleHandler.getFancyDouble(supply - demand); + String netGain = NumberUtils.getCompactDouble(supply - demand); SimpleHologram.update(b, "&2&l+ &a" + netGain + " &7J &e\u26A1"); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java index 922fa2ff9..71db3afd1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java @@ -48,7 +48,7 @@ public class SlimefunProfiler { */ private static final int MAX_TICK_DURATION = 100; - private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(5); + private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(8); private final ExecutorService executor = Executors.newFixedThreadPool(threadFactory.getThreadCount(), threadFactory); private final AtomicBoolean running = new AtomicBoolean(false); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/Multimeter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/Multimeter.java index 77c91ce0d..5fa0bb688 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/Multimeter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/gadgets/Multimeter.java @@ -8,12 +8,12 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; +import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; @@ -50,8 +50,8 @@ public class Multimeter extends SimpleSlimefunItem { e.cancel(); Location l = e.getClickedBlock().get().getLocation(); - String stored = DoubleHandler.getFancyDouble(component.getCharge(l)) + " J"; - String capacity = DoubleHandler.getFancyDouble(component.getCapacity()) + " J"; + String stored = NumberUtils.getCompactDouble(component.getCharge(l)) + " J"; + String capacity = NumberUtils.getCompactDouble(component.getCapacity()) + " J"; Player p = e.getPlayer(); p.sendMessage(""); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/CapacitorTextureUpdateTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/CapacitorTextureUpdateTask.java index 2acaef0fd..b427b0008 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/CapacitorTextureUpdateTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/CapacitorTextureUpdateTask.java @@ -11,6 +11,7 @@ import org.bukkit.block.Block; import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; +import io.papermc.lib.PaperLib; /** * This task is run whenever a {@link Capacitor} needs to update their texture. @@ -58,18 +59,23 @@ public class CapacitorTextureUpdateTask implements Runnable { if (type == Material.PLAYER_HEAD || type == Material.PLAYER_WALL_HEAD) { if (filledPercentage <= 0.25) { // 0-25% capacity - SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture()); + setTexture(b, HeadTexture.CAPACITOR_25); } else if (filledPercentage <= 0.5) { // 25-50% capacity - SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_50.getTexture()); + setTexture(b, HeadTexture.CAPACITOR_50); } else if (filledPercentage <= 0.75) { // 50-75% capacity - SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_75.getTexture()); + setTexture(b, HeadTexture.CAPACITOR_75); } else { // 75-100% capacity - SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_100.getTexture()); + setTexture(b, HeadTexture.CAPACITOR_100); } } } + private void setTexture(@Nonnull Block b, @Nonnull HeadTexture texture) { + SkullBlock.setFromHash(b, texture.getUniqueId(), texture.getTexture(), false); + PaperLib.getBlockState(b, false).getState().update(true, false); + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index d4a445d54..9057928e5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.tasks; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -10,17 +11,18 @@ import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.scheduler.BukkitScheduler; import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition; +import io.github.thebusybiscuit.cscorelib2.blocks.ChunkPosition; import io.github.thebusybiscuit.slimefun4.api.ErrorReport; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; -import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; @@ -39,17 +41,17 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; public class TickerTask implements Runnable { /** - * This Map holds all currently actively ticking locations. + * This Map holds all currently actively ticking locations. */ - private final Map> activeTickers = new ConcurrentHashMap<>(); + private final Map> tickingLocations = new ConcurrentHashMap<>(); // These are "Queues" of blocks that need to be removed or moved private final Map movingQueue = new ConcurrentHashMap<>(); private final Map deletionQueue = new ConcurrentHashMap<>(); /** - * This Map tracks how many bugs have occurred in a given Location . - * If too many bugs happen, we delete that Location. + * This Map tracks how many bugs have occurred in a given Location . + * If too many bugs happen, we delete that Location. */ private final Map bugs = new ConcurrentHashMap<>(); @@ -97,8 +99,8 @@ public class TickerTask implements Runnable { } if (!halted) { - for (Map.Entry> entry : activeTickers.entrySet()) { - tickChunk(tickers, entry.getKey(), entry.getValue()); + for (Map.Entry> entry : tickingLocations.entrySet()) { + tickChunk(entry.getKey(), tickers, entry.getValue()); } } @@ -123,21 +125,16 @@ public class TickerTask implements Runnable { } @ParametersAreNonnullByDefault - private void tickChunk(Set tickers, String chunk, Set locations) { + private void tickChunk(ChunkPosition chunk, Set tickers, Set locations) { try { - String[] components = PatternUtils.SEMICOLON.split(chunk); - - World world = Bukkit.getWorld(components[0]); - int x = Integer.parseInt(components[components.length - 2]); - int z = Integer.parseInt(components[components.length - 1]); - - if (world != null && world.isChunkLoaded(x, z)) { + // Only continue if the Chunk is actually loaded + if (chunk.isLoaded()) { for (Location l : locations) { tickLocation(tickers, l); } } } catch (ArrayIndexOutOfBoundsException | NumberFormatException x) { - Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to parse Chunk: " + chunk); + Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk); } } @@ -235,14 +232,82 @@ public class TickerTask implements Runnable { } /** - * This method returns the {@link Map} of actively ticking locations according to - * their chunk id. + * This method returns a read-only {@link Map} + * representation of every {@link ChunkPosition} and its corresponding + * {@link Set} of ticking {@link Location Locations}. * - * @return The {@link Map} of active tickers + * This does include any {@link Location} from an unloaded {@link Chunk} too! + * + * @return A {@link Map} representation of all ticking {@link Location Locations} */ @Nonnull - public Map> getActiveTickers() { - return activeTickers; + public Map> getLocations() { + return Collections.unmodifiableMap(tickingLocations); + } + + /** + * This method returns a read-only {@link Set} + * of all ticking {@link Location Locations} in a given {@link Chunk}. + * The {@link Chunk} does not have to be loaded. + * If no {@link Location} is present, the returned {@link Set} will be empty. + * + * @param chunk + * The {@link Chunk} + * + * @return A {@link Set} of all ticking {@link Location Locations} + */ + @Nonnull + public Set getLocations(@Nonnull Chunk chunk) { + Validate.notNull(chunk, "The Chunk cannot be null!"); + + Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), new HashSet<>()); + return Collections.unmodifiableSet(locations); + } + + /** + * This enables the ticker at the given {@link Location} and adds it to our "queue". + * + * @param l + * The {@link Location} to activate + */ + public void enableTicker(@Nonnull Location l) { + Validate.notNull(l, "Location cannot be null!"); + + ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + Set newValue = new HashSet<>(); + Set oldValue = tickingLocations.putIfAbsent(chunk, newValue); + + /** + * This is faster than doing computeIfAbsent(...) + * on a ConcurrentHashMap because it won't block the Thread for too long + */ + if (oldValue != null) { + oldValue.add(l); + } else { + newValue.add(l); + } + } + + /** + * This method disables the ticker at the given {@link Location} and removes it from our internal + * "queue". + * + * @param l + * The {@link Location} to remove + */ + public void disableTicker(@Nonnull Location l) { + Validate.notNull(l, "Location cannot be null!"); + + ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + Set locations = tickingLocations.get(chunk); + + if (locations != null) { + locations.remove(l); + + if (locations.isEmpty()) { + tickingLocations.remove(chunk); + } + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java index ee8a849d0..d01013582 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java @@ -1,5 +1,7 @@ package io.github.thebusybiscuit.slimefun4.utils; +import java.util.UUID; + import javax.annotation.Nonnull; import org.apache.commons.lang.Validate; @@ -114,11 +116,14 @@ public enum HeadTexture { public static final HeadTexture[] valuesCache = values(); private final String texture; + private final UUID uuid; HeadTexture(@Nonnull String texture) { Validate.notNull(texture, "Texture cannot be null"); Validate.isTrue(PatternUtils.HEXADECIMAL.matcher(texture).matches(), "Textures must be in hexadecimal."); + this.texture = texture; + this.uuid = UUID.nameUUIDFromBytes(texture.getBytes()); } /** @@ -131,6 +136,18 @@ public enum HeadTexture { return texture; } + /** + * This returns the {@link UUID} for this {@link HeadTexture}. + * The {@link UUID} is generated from the texture and cached for + * performance reasons. + * + * @return The {@link UUID} for this {@link HeadTexture} + */ + @Nonnull + public UUID getUniqueId() { + return uuid; + } + /** * This method returns an {@link ItemStack} with the given texture assigned to it. * diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java index f94e50689..e4e23bfc2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/NumberUtils.java @@ -24,6 +24,7 @@ public final class NumberUtils { /** * This is our {@link DecimalFormat} for decimal values. + * This instance is not thread-safe! */ private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.ROOT)); @@ -48,6 +49,34 @@ public final class NumberUtils { return NumberFormat.getNumberInstance(Locale.US).format(number); } + @Nonnull + public static String getCompactDouble(double value) { + if (value < 0) { + // Negative numbers are a special case + return '-' + getCompactDouble(-value); + } + + if (value < 1000.0) { + // Below 1K + return DECIMAL_FORMAT.format(value); + } else if (value < 1000000.0) { + // Thousands + return DECIMAL_FORMAT.format(value / 1000.0) + 'K'; + } else if (value < 1000000000.0) { + // Million + return DECIMAL_FORMAT.format(value / 1000000.0) + 'M'; + } else if (value < 1000000000000.0) { + // Billion + return DECIMAL_FORMAT.format(value / 1000000000.0) + 'B'; + } else if (value < 1000000000000000.0) { + // Trillion + return DECIMAL_FORMAT.format(value / 1000000000000.0) + 'T'; + } else { + // Quadrillion + return DECIMAL_FORMAT.format(value / 1000000000000000.0) + 'Q'; + } + } + /** * This method transforms a String representation of a {@link LocalDateTime} * from GitHub's API back into a {@link LocalDateTime} object diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/ReactorHologram.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/ReactorHologram.java index a0d56e4bf..fc2762c16 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/ReactorHologram.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/ReactorHologram.java @@ -1,5 +1,7 @@ package io.github.thebusybiscuit.slimefun4.utils.holograms; +import java.util.Collection; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -17,9 +19,10 @@ public final class 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 holograms = l.getWorld().getNearbyEntities(l, 0.2, 0.2, 0.2, ReactorHologram::isPossibleHologram); - for (Entity n : l.getChunk().getEntities()) { - if (n instanceof ArmorStand && l.distanceSquared(n.getLocation()) < 0.4D) { + for (Entity n : holograms) { + if (n instanceof ArmorStand) { return (ArmorStand) n; } } @@ -34,14 +37,21 @@ public final class ReactorHologram { 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); - if (!hologram.isCustomNameVisible()) { - hologram.setCustomNameVisible(true); - } - + hologram.setCustomNameVisible(true); hologram.setCustomName(ChatColors.color(name)); }); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/SimpleHologram.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/SimpleHologram.java index f31fce8c1..84f0f01ce 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/SimpleHologram.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/holograms/SimpleHologram.java @@ -1,5 +1,7 @@ package io.github.thebusybiscuit.slimefun4.utils.holograms; +import java.util.Collection; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -42,9 +44,10 @@ public final class SimpleHologram { @Nullable private static ArmorStand getArmorStand(@Nonnull Block b, boolean createIfNoneExists) { Location l = new Location(b.getWorld(), b.getX() + 0.5, b.getY() + 0.7F, b.getZ() + 0.5); + Collection holograms = b.getWorld().getNearbyEntities(l, 0.2, 0.2, 0.2, SimpleHologram::isPossibleHologram); - for (Entity n : l.getChunk().getEntities()) { - if (n instanceof ArmorStand && l.distanceSquared(n.getLocation()) < 0.4D && isPossibleHologram((ArmorStand) n)) { + for (Entity n : holograms) { + if (n instanceof ArmorStand) { return (ArmorStand) n; } } @@ -56,8 +59,14 @@ public final class SimpleHologram { } } - private static boolean isPossibleHologram(@Nonnull ArmorStand armorstand) { - return armorstand.isValid() && armorstand.isSilent() && armorstand.isMarker() && !armorstand.hasGravity() && armorstand.isCustomNameVisible(); + private static boolean isPossibleHologram(@Nonnull Entity n) { + if (n instanceof ArmorStand) { + ArmorStand armorstand = (ArmorStand) n; + return armorstand.isValid() && armorstand.isSilent() && armorstand.isMarker() && !armorstand.hasGravity() && armorstand.isCustomNameVisible(); + } else { + return false; + } + } @Nonnull diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AGenerator.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AGenerator.java index 2d5bc397c..0ae282211 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AGenerator.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/SlimefunItem/abstractItems/AGenerator.java @@ -202,7 +202,7 @@ public abstract class AGenerator extends AbstractEnergyProvider { } ItemStackWrapper wrapper = new ItemStackWrapper(item); - return SlimefunUtils.isItemSimilar(wrapper, new ItemStack(Material.LAVA_BUCKET), true) || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.FUEL_BUCKET, true) || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.OIL_BUCKET, true); + return item.getType() == Material.LAVA_BUCKET || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.FUEL_BUCKET, true) || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.OIL_BUCKET, true); } private MachineFuel findRecipe(BlockMenu menu, Map found) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockInfoConfig.java b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockInfoConfig.java index 8bc5dc5de..e34351800 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockInfoConfig.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockInfoConfig.java @@ -49,8 +49,6 @@ public class BlockInfoConfig extends Config { throw new UnsupportedOperationException("Can't set \"" + path + "\" to \"" + value + "\" (type: " + value.getClass().getSimpleName() + ") because BlockInfoConfig only supports Strings"); } - checkPath(path); - if (value == null) { data.remove(path); } else { @@ -58,15 +56,8 @@ public class BlockInfoConfig extends Config { } } - private void checkPath(String path) { - if (path.indexOf('.') != -1) { - throw new UnsupportedOperationException("BlockInfoConfig only supports Map (path: " + path + ")"); - } - } - @Override public boolean contains(String path) { - checkPath(path); return data.containsKey(path); } @@ -77,7 +68,6 @@ public class BlockInfoConfig extends Config { @Override public String getString(String path) { - checkPath(path); return data.get(path); } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java index 5114d5479..c7441b3df 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java @@ -7,10 +7,8 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -71,10 +69,6 @@ public class BlockStorage { return l.getWorld().getName() + ';' + l.getBlockX() + ';' + l.getBlockY() + ';' + l.getBlockZ(); } - private static String locationToChunkString(Location l) { - return l.getWorld().getName() + ";Chunk;" + (l.getBlockX() >> 4) + ';' + (l.getBlockZ() >> 4); - } - private static String serializeChunk(World world, int x, int z) { return world.getName() + ";Chunk;" + x + ';' + z; } @@ -177,7 +171,6 @@ public class BlockStorage { } try { - String chunkString = locationToChunkString(l); String json = cfg.getString(key); Config blockInfo = parseBlockInfo(l, json); @@ -195,9 +188,7 @@ public class BlockStorage { storage.put(l, blockInfo); if (SlimefunPlugin.getRegistry().getTickerBlocks().contains(file.getName().replace(".sfb", ""))) { - Map> tickers = SlimefunPlugin.getTickerTask().getActiveTickers(); - Set locations = tickers.computeIfAbsent(chunkString, id -> new HashSet<>()); - locations.add(l); + SlimefunPlugin.getTickerTask().enableTicker(l); } } } catch (Exception x) { @@ -495,11 +486,7 @@ public class BlockStorage { } } - public static void setBlockInfo(Block block, Config cfg, boolean updateTicker) { - setBlockInfo(block.getLocation(), cfg, updateTicker); - } - - public static void setBlockInfo(Location l, Config cfg, boolean updateTicker) { + private static void setBlockInfo(Location l, Config cfg, boolean updateTicker) { BlockStorage storage = getStorage(l.getWorld()); if (storage == null) { @@ -590,17 +577,7 @@ public class BlockStorage { universalInventory.save(); } - String chunkString = locationToChunkString(l); - Map> tickers = SlimefunPlugin.getTickerTask().getActiveTickers(); - Set locations = tickers.get(chunkString); - - if (locations != null) { - locations.remove(l); - - if (locations.isEmpty()) { - tickers.remove(chunkString); - } - } + SlimefunPlugin.getTickerTask().disableTicker(l); } } @@ -638,23 +615,15 @@ public class BlockStorage { refreshCache(storage, from, previousData.getString("id"), null, true); storage.storage.remove(from); - String chunkString = locationToChunkString(from); - Map> tickers = SlimefunPlugin.getTickerTask().getActiveTickers(); - Set locations = tickers.get(chunkString); - - if (locations != null) { - locations.remove(from); - - if (locations.isEmpty()) { - tickers.remove(chunkString); - } - } + SlimefunPlugin.getTickerTask().disableTicker(from); } private static void refreshCache(BlockStorage storage, Location l, String key, String value, boolean updateTicker) { if (key == null) { - // This Block is no longer valid... - // Fixes #1577 + /** + * This Block is no longer valid... + * Fixes #1577 + */ return; } @@ -664,14 +633,8 @@ public class BlockStorage { if (updateTicker) { SlimefunItem item = SlimefunItem.getByID(key); - if (item != null && item.isTicking()) { - String chunkString = locationToChunkString(l); - - if (value != null) { - Map> tickers = SlimefunPlugin.getTickerTask().getActiveTickers(); - Set locations = tickers.computeIfAbsent(chunkString, id -> new HashSet<>()); - locations.add(l); - } + if (item != null && item.isTicking() && value != null) { + SlimefunPlugin.getTickerTask().enableTicker(l); } } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/bstats/bukkit/Metrics.java b/src/main/java/me/mrCookieSlime/Slimefun/bstats/bukkit/Metrics.java index 5f44303db..ee727f695 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/bstats/bukkit/Metrics.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/bstats/bukkit/Metrics.java @@ -92,6 +92,13 @@ public class Metrics { this.plugin = plugin; this.pluginId = pluginId; + plugin.getLogger().log(Level.WARNING, "================================================="); + plugin.getLogger().log(Level.WARNING, "{0} is using a deprecated version of", plugin.getName()); + plugin.getLogger().log(Level.WARNING, "bStats which is bundled with Slimefun."); + plugin.getLogger().log(Level.WARNING, "Future versions will not include this file anymore."); + plugin.getLogger().log(Level.WARNING, "{0} needs to be updated as soon as possible.", plugin.getName()); + plugin.getLogger().log(Level.WARNING, "================================================="); + // Get the config file File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); File configFile = new File(bStatsFolder, "config.yml");