mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-19 19:25:48 +00:00
Fixes #2576
This commit is contained in:
parent
c4619ecbaa
commit
1d4cb85cb1
@ -80,6 +80,8 @@
|
|||||||
* Fixed #2518
|
* Fixed #2518
|
||||||
* Fixed #2421
|
* Fixed #2421
|
||||||
* Fixed #2574
|
* Fixed #2574
|
||||||
|
* Fixed color in android script downloading screen
|
||||||
|
* Fixed #2576
|
||||||
|
|
||||||
## Release Candidate 17 (17 Oct 2020)
|
## Release Candidate 17 (17 Oct 2020)
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ public class EnergyNet extends Network {
|
|||||||
if (!explodedBlocks.isEmpty()) {
|
if (!explodedBlocks.isEmpty()) {
|
||||||
generators.keySet().removeAll(explodedBlocks);
|
generators.keySet().removeAll(explodedBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
return supply;
|
return supply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +77,9 @@ public class AutoSavingService {
|
|||||||
Set<BlockStorage> worlds = new HashSet<>();
|
Set<BlockStorage> worlds = new HashSet<>();
|
||||||
|
|
||||||
for (World world : Bukkit.getWorlds()) {
|
for (World world : Bukkit.getWorlds()) {
|
||||||
if (BlockStorage.isWorldRegistered(world.getName())) {
|
BlockStorage storage = BlockStorage.getStorage(world);
|
||||||
BlockStorage storage = BlockStorage.getStorage(world);
|
|
||||||
|
if (storage != null) {
|
||||||
storage.computeChanges();
|
storage.computeChanges();
|
||||||
|
|
||||||
if (storage.getChanges() > 0) {
|
if (storage.getChanges() > 0) {
|
||||||
|
@ -20,6 +20,7 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||||
@ -48,10 +49,21 @@ public class SlimefunProfiler {
|
|||||||
*/
|
*/
|
||||||
private static final int MAX_TICK_DURATION = 100;
|
private static final int MAX_TICK_DURATION = 100;
|
||||||
|
|
||||||
private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(8);
|
/**
|
||||||
|
* Our internal instance of {@link SlimefunThreadFactory}, it provides the naming
|
||||||
|
* convention for our {@link Thread} pool and also the count of this pool.
|
||||||
|
*/
|
||||||
|
private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is our {@link Thread} pool to evaluate timings data.
|
||||||
|
* We cannot use the {@link BukkitScheduler} here because we need to evaluate
|
||||||
|
* this data in split seconds.
|
||||||
|
* So we cannot simply wait until the next server tick for this.
|
||||||
|
*/
|
||||||
private final ExecutorService executor = Executors.newFixedThreadPool(threadFactory.getThreadCount(), threadFactory);
|
private final ExecutorService executor = Executors.newFixedThreadPool(threadFactory.getThreadCount(), threadFactory);
|
||||||
|
|
||||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
private final AtomicBoolean isProfiling = new AtomicBoolean(false);
|
||||||
private final AtomicInteger queued = new AtomicInteger(0);
|
private final AtomicInteger queued = new AtomicInteger(0);
|
||||||
|
|
||||||
private long totalElapsedTime;
|
private long totalElapsedTime;
|
||||||
@ -59,11 +71,20 @@ public class SlimefunProfiler {
|
|||||||
private final Map<ProfiledBlock, Long> timings = new ConcurrentHashMap<>();
|
private final Map<ProfiledBlock, Long> timings = new ConcurrentHashMap<>();
|
||||||
private final Queue<CommandSender> requests = new ConcurrentLinkedQueue<>();
|
private final Queue<CommandSender> requests = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method terminates the {@link SlimefunProfiler}.
|
||||||
|
* We need to call this method when the {@link Server} shuts down to prevent any
|
||||||
|
* of our {@link Thread Threads} from being kept alive.
|
||||||
|
*/
|
||||||
|
public void kill() {
|
||||||
|
executor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method starts the profiling, data from previous runs will be cleared.
|
* This method starts the profiling, data from previous runs will be cleared.
|
||||||
*/
|
*/
|
||||||
public void start() {
|
public void start() {
|
||||||
running.set(true);
|
isProfiling.set(true);
|
||||||
queued.set(0);
|
queued.set(0);
|
||||||
timings.clear();
|
timings.clear();
|
||||||
}
|
}
|
||||||
@ -74,7 +95,7 @@ public class SlimefunProfiler {
|
|||||||
* @return A timestamp, best fed back into {@link #closeEntry(Location, SlimefunItem, long)}
|
* @return A timestamp, best fed back into {@link #closeEntry(Location, SlimefunItem, long)}
|
||||||
*/
|
*/
|
||||||
public long newEntry() {
|
public long newEntry() {
|
||||||
if (!running.get()) {
|
if (!isProfiling.get()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +114,7 @@ public class SlimefunProfiler {
|
|||||||
* The amount of entries that should be scheduled. Can be negative
|
* The amount of entries that should be scheduled. Can be negative
|
||||||
*/
|
*/
|
||||||
public void scheduleEntries(int amount) {
|
public void scheduleEntries(int amount) {
|
||||||
if (running.get()) {
|
if (isProfiling.get()) {
|
||||||
queued.getAndAdd(amount);
|
queued.getAndAdd(amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +157,7 @@ public class SlimefunProfiler {
|
|||||||
* This stops the profiling.
|
* This stops the profiling.
|
||||||
*/
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running.set(false);
|
isProfiling.set(false);
|
||||||
|
|
||||||
if (SlimefunPlugin.instance() == null || !SlimefunPlugin.instance().isEnabled()) {
|
if (SlimefunPlugin.instance() == null || !SlimefunPlugin.instance().isEnabled()) {
|
||||||
// Slimefun has been disabled
|
// Slimefun has been disabled
|
||||||
@ -151,7 +172,7 @@ public class SlimefunProfiler {
|
|||||||
int iterations = 4000;
|
int iterations = 4000;
|
||||||
|
|
||||||
// Wait for all timing results to come in
|
// Wait for all timing results to come in
|
||||||
while (!running.get() && queued.get() > 0) {
|
while (!isProfiling.get() && queued.get() > 0) {
|
||||||
try {
|
try {
|
||||||
/**
|
/**
|
||||||
* Since we got more than one Thread in our pool,
|
* Since we got more than one Thread in our pool,
|
||||||
@ -177,7 +198,7 @@ public class SlimefunProfiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (running.get() && queued.get() > 0) {
|
if (isProfiling.get() && queued.get() > 0) {
|
||||||
// Looks like the next profiling has already started, abort!
|
// Looks like the next profiling has already started, abort!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -356,6 +356,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
|||||||
ticker.halt();
|
ticker.halt();
|
||||||
ticker.run();
|
ticker.run();
|
||||||
|
|
||||||
|
// Kill our Profiler Threads
|
||||||
|
profiler.kill();
|
||||||
|
|
||||||
// Save all Player Profiles that are still in memory
|
// Save all Player Profiles that are still in memory
|
||||||
PlayerProfile.iterator().forEachRemaining(profile -> {
|
PlayerProfile.iterator().forEachRemaining(profile -> {
|
||||||
if (profile.isDirty()) {
|
if (profile.isDirty()) {
|
||||||
|
@ -151,7 +151,7 @@ public final class Script {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
private String getScriptRatingPercentage() {
|
private String getScriptRatingPercentage() {
|
||||||
float percentage = getRating();
|
float percentage = getRating();
|
||||||
return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.RESET + "% ";
|
return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.WHITE + "% ";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,10 +61,15 @@ public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCapacity() {
|
public final int getCapacity() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean isChargeable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getGeneratedOutput(Location l, Config data) {
|
public int getGeneratedOutput(Location l, Config data) {
|
||||||
World world = l.getWorld();
|
World world = l.getWorld();
|
||||||
|
@ -53,7 +53,7 @@ public class BlockPhysicsListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPistonExtend(BlockPistonExtendEvent e) {
|
public void onPistonExtend(BlockPistonExtendEvent e) {
|
||||||
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
@ -67,7 +67,7 @@ public class BlockPhysicsListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPistonRetract(BlockPistonRetractEvent e) {
|
public void onPistonRetract(BlockPistonRetractEvent e) {
|
||||||
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
|
@ -22,7 +22,7 @@ public class WorldListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldLoad(WorldLoadEvent e) {
|
public void onWorldLoad(WorldLoadEvent e) {
|
||||||
SlimefunPlugin.getWorldSettingsService().load(e.getWorld());
|
SlimefunPlugin.getWorldSettingsService().load(e.getWorld());
|
||||||
BlockStorage.getForcedStorage(e.getWorld());
|
BlockStorage.getOrCreate(e.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
@ -30,8 +30,8 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
|||||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker}, synchronous
|
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker},
|
||||||
* or not.
|
* synchronous or not.
|
||||||
*
|
*
|
||||||
* @author TheBusyBiscuit
|
* @author TheBusyBiscuit
|
||||||
*
|
*
|
||||||
@ -75,7 +75,7 @@ public class TickerTask implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* This method resets this {@link TickerTask} to run again.
|
* This method resets this {@link TickerTask} to run again.
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
private void reset() {
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ public class TickerTask implements Runnable {
|
|||||||
SlimefunPlugin.getProfiler().start();
|
SlimefunPlugin.getProfiler().start();
|
||||||
Set<BlockTicker> tickers = new HashSet<>();
|
Set<BlockTicker> tickers = new HashSet<>();
|
||||||
|
|
||||||
|
// Remove any deleted blocks
|
||||||
Iterator<Map.Entry<Location, Boolean>> removals = deletionQueue.entrySet().iterator();
|
Iterator<Map.Entry<Location, Boolean>> removals = deletionQueue.entrySet().iterator();
|
||||||
while (removals.hasNext()) {
|
while (removals.hasNext()) {
|
||||||
Map.Entry<Location, Boolean> entry = removals.next();
|
Map.Entry<Location, Boolean> entry = removals.next();
|
||||||
@ -98,12 +99,24 @@ public class TickerTask implements Runnable {
|
|||||||
removals.remove();
|
removals.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fixes #2576 - Remove any deleted instances of BlockStorage
|
||||||
|
Iterator<BlockStorage> worlds = SlimefunPlugin.getRegistry().getWorlds().values().iterator();
|
||||||
|
while (worlds.hasNext()) {
|
||||||
|
BlockStorage storage = worlds.next();
|
||||||
|
|
||||||
|
if (storage.isMarkedForRemoval()) {
|
||||||
|
worlds.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run our ticker code
|
||||||
if (!halted) {
|
if (!halted) {
|
||||||
for (Map.Entry<ChunkPosition, Set<Location>> entry : tickingLocations.entrySet()) {
|
for (Map.Entry<ChunkPosition, Set<Location>> entry : tickingLocations.entrySet()) {
|
||||||
tickChunk(entry.getKey(), tickers, entry.getValue());
|
tickChunk(entry.getKey(), tickers, entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move any moved block data
|
||||||
Iterator<Map.Entry<Location, Location>> moves = movingQueue.entrySet().iterator();
|
Iterator<Map.Entry<Location, Location>> moves = movingQueue.entrySet().iterator();
|
||||||
while (moves.hasNext()) {
|
while (moves.hasNext()) {
|
||||||
Map.Entry<Location, Location> entry = moves.next();
|
Map.Entry<Location, Location> entry = moves.next();
|
||||||
|
@ -10,6 +10,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -55,14 +56,24 @@ public class BlockStorage {
|
|||||||
private final Map<String, Config> blocksCache = new ConcurrentHashMap<>();
|
private final Map<String, Config> blocksCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static int chunkChanges = 0;
|
private static int chunkChanges = 0;
|
||||||
private int changes = 0;
|
|
||||||
|
|
||||||
|
private int changes = 0;
|
||||||
|
private AtomicBoolean isMarkedForRemoval = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static BlockStorage getStorage(@Nonnull World world) {
|
public static BlockStorage getStorage(@Nonnull World world) {
|
||||||
return SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
|
return SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockStorage getForcedStorage(@Nonnull World world) {
|
@Nonnull
|
||||||
return isWorldRegistered(world.getName()) ? SlimefunPlugin.getRegistry().getWorlds().get(world.getName()) : new BlockStorage(world);
|
public static BlockStorage getOrCreate(@Nonnull World world) {
|
||||||
|
BlockStorage storage = SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
|
||||||
|
|
||||||
|
if (storage == null) {
|
||||||
|
return new BlockStorage(world);
|
||||||
|
} else {
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String serializeLocation(Location l) {
|
private static String serializeLocation(Location l) {
|
||||||
@ -321,7 +332,11 @@ public class BlockStorage {
|
|||||||
|
|
||||||
public void saveAndRemove() {
|
public void saveAndRemove() {
|
||||||
save();
|
save();
|
||||||
SlimefunPlugin.getRegistry().getWorlds().remove(world.getName());
|
isMarkedForRemoval.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMarkedForRemoval() {
|
||||||
|
return isMarkedForRemoval.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveChunks() {
|
public static void saveChunks() {
|
||||||
@ -496,15 +511,13 @@ public class BlockStorage {
|
|||||||
|
|
||||||
storage.storage.put(l, cfg);
|
storage.storage.put(l, cfg);
|
||||||
String id = cfg.getString("id");
|
String id = cfg.getString("id");
|
||||||
|
BlockMenuPreset preset = BlockMenuPreset.getPreset(id);
|
||||||
|
|
||||||
if (BlockMenuPreset.isInventory(id)) {
|
if (preset != null) {
|
||||||
if (BlockMenuPreset.isUniversalInventory(id)) {
|
if (BlockMenuPreset.isUniversalInventory(id)) {
|
||||||
if (!SlimefunPlugin.getRegistry().getUniversalInventories().containsKey(id)) {
|
SlimefunPlugin.getRegistry().getUniversalInventories().computeIfAbsent(id, key -> new UniversalBlockMenu(preset));
|
||||||
storage.loadUniversalInventory(BlockMenuPreset.getPreset(id));
|
|
||||||
}
|
|
||||||
} else if (!storage.hasInventory(l)) {
|
} else if (!storage.hasInventory(l)) {
|
||||||
File file = new File(PATH_INVENTORIES + serializeLocation(l) + ".sfi");
|
File file = new File(PATH_INVENTORIES + serializeLocation(l) + ".sfi");
|
||||||
BlockMenuPreset preset = BlockMenuPreset.getPreset(id);
|
|
||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
BlockMenu inventory = new BlockMenu(preset, l, new io.github.thebusybiscuit.cscorelib2.config.Config(file));
|
BlockMenu inventory = new BlockMenu(preset, l, new io.github.thebusybiscuit.cscorelib2.config.Config(file));
|
||||||
@ -560,6 +573,10 @@ public class BlockStorage {
|
|||||||
public static void deleteLocationInfoUnsafely(Location l, boolean destroy) {
|
public static void deleteLocationInfoUnsafely(Location l, boolean destroy) {
|
||||||
BlockStorage storage = getStorage(l.getWorld());
|
BlockStorage storage = getStorage(l.getWorld());
|
||||||
|
|
||||||
|
if (storage == null) {
|
||||||
|
throw new IllegalStateException("World \"" + l.getWorld().getName() + "\" seems to have been deleted. Do not call unsafe methods directly!");
|
||||||
|
}
|
||||||
|
|
||||||
if (hasBlockInfo(l)) {
|
if (hasBlockInfo(l)) {
|
||||||
refreshCache(storage, l, getLocationInfo(l).getString("id"), null, destroy);
|
refreshCache(storage, l, getLocationInfo(l).getString("id"), null, destroy);
|
||||||
storage.storage.remove(l);
|
storage.storage.remove(l);
|
||||||
@ -686,8 +703,8 @@ public class BlockStorage {
|
|||||||
return id != null && id.equals(slimefunItem);
|
return id != null && id.equals(slimefunItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isWorldRegistered(String name) {
|
public static boolean isWorldLoaded(World world) {
|
||||||
return SlimefunPlugin.getRegistry().getWorlds().containsKey(name);
|
return SlimefunPlugin.getRegistry().getWorlds().containsKey(world.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockMenu loadInventory(Location l, BlockMenuPreset preset) {
|
public BlockMenu loadInventory(Location l, BlockMenuPreset preset) {
|
||||||
@ -715,11 +732,6 @@ public class BlockStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadUniversalInventory(BlockMenuPreset preset) {
|
|
||||||
UniversalBlockMenu inventory = new UniversalBlockMenu(preset);
|
|
||||||
SlimefunPlugin.getRegistry().getUniversalInventories().put(preset.getID(), inventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearInventory(Location l) {
|
public void clearInventory(Location l) {
|
||||||
BlockMenu menu = getInventory(l);
|
BlockMenu menu = getInventory(l);
|
||||||
|
|
||||||
@ -788,7 +800,7 @@ public class BlockStorage {
|
|||||||
|
|
||||||
public static Config getChunkInfo(World world, int x, int z) {
|
public static Config getChunkInfo(World world, int x, int z) {
|
||||||
try {
|
try {
|
||||||
if (!isWorldRegistered(world.getName())) {
|
if (!isWorldLoaded(world)) {
|
||||||
return emptyBlockData;
|
return emptyBlockData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ public abstract class BlockMenuPreset extends ChestMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static BlockMenuPreset getPreset(String id) {
|
public static BlockMenuPreset getPreset(@Nullable String id) {
|
||||||
return id == null ? null : SlimefunPlugin.getRegistry().getMenuPresets().get(id);
|
return id == null ? null : SlimefunPlugin.getRegistry().getMenuPresets().get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user