1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Performance and memory improvements

This commit is contained in:
TheBusyBiscuit 2020-11-25 14:27:46 +01:00
parent d77fd498f8
commit d0e7e21877
17 changed files with 214 additions and 108 deletions

View File

@ -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

View File

@ -337,7 +337,7 @@
<dependency>
<groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.27.3</version>
<version>0.27.4</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -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

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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<ItemUseHandler> {
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("");

View File

@ -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);
}
}

View File

@ -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<String, Set<Location>> activeTickers = new ConcurrentHashMap<>();
private final Map<ChunkPosition, Set<Location>> tickingLocations = new ConcurrentHashMap<>();
// These are "Queues" of blocks that need to be removed or moved
private final Map<Location, Location> movingQueue = new ConcurrentHashMap<>();
private final Map<Location, Boolean> 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<BlockPosition, Integer> bugs = new ConcurrentHashMap<>();
@ -97,8 +99,8 @@ public class TickerTask implements Runnable {
}
if (!halted) {
for (Map.Entry<String, Set<Location>> entry : activeTickers.entrySet()) {
tickChunk(tickers, entry.getKey(), entry.getValue());
for (Map.Entry<ChunkPosition, Set<Location>> entry : tickingLocations.entrySet()) {
tickChunk(entry.getKey(), tickers, entry.getValue());
}
}
@ -123,21 +125,16 @@ public class TickerTask implements Runnable {
}
@ParametersAreNonnullByDefault
private void tickChunk(Set<BlockTicker> tickers, String chunk, Set<Location> locations) {
private void tickChunk(ChunkPosition chunk, Set<BlockTicker> tickers, Set<Location> 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 <strong>read-only</strong> {@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<String, Set<Location>> getActiveTickers() {
return activeTickers;
public Map<ChunkPosition, Set<Location>> getLocations() {
return Collections.unmodifiableMap(tickingLocations);
}
/**
* This method returns a <strong>read-only</strong> {@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<Location> getLocations(@Nonnull Chunk chunk) {
Validate.notNull(chunk, "The Chunk cannot be null!");
Set<Location> 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<Location> newValue = new HashSet<>();
Set<Location> 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<Location> locations = tickingLocations.get(chunk);
if (locations != null) {
locations.remove(l);
if (locations.isEmpty()) {
tickingLocations.remove(chunk);
}
}
}
}

View File

@ -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.
*

View File

@ -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

View File

@ -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<Entity> 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));
});
}

View File

@ -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<Entity> 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

View File

@ -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<Integer, Integer> found) {

View File

@ -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<String,String> (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);
}

View File

@ -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<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> 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<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> 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<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> 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<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> locations = tickers.computeIfAbsent(chunkString, id -> new HashSet<>());
locations.add(l);
}
if (item != null && item.isTicking() && value != null) {
SlimefunPlugin.getTickerTask().enableTicker(l);
}
}
}

View File

@ -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");