1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00
This commit is contained in:
TheBusyBiscuit 2020-11-30 17:03:17 +01:00
parent c4619ecbaa
commit 1d4cb85cb1
12 changed files with 94 additions and 37 deletions

View File

@ -80,6 +80,8 @@
* Fixed #2518
* Fixed #2421
* Fixed #2574
* Fixed color in android script downloading screen
* Fixed #2576
## Release Candidate 17 (17 Oct 2020)

View File

@ -241,7 +241,7 @@ public class EnergyNet extends Network {
if (!explodedBlocks.isEmpty()) {
generators.keySet().removeAll(explodedBlocks);
}
return supply;
}

View File

@ -77,8 +77,9 @@ public class AutoSavingService {
Set<BlockStorage> worlds = new HashSet<>();
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();
if (storage.getChanges() > 0) {

View File

@ -20,6 +20,7 @@ import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitScheduler;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -48,10 +49,21 @@ public class SlimefunProfiler {
*/
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 AtomicBoolean running = new AtomicBoolean(false);
private final AtomicBoolean isProfiling = new AtomicBoolean(false);
private final AtomicInteger queued = new AtomicInteger(0);
private long totalElapsedTime;
@ -59,11 +71,20 @@ public class SlimefunProfiler {
private final Map<ProfiledBlock, Long> timings = new ConcurrentHashMap<>();
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.
*/
public void start() {
running.set(true);
isProfiling.set(true);
queued.set(0);
timings.clear();
}
@ -74,7 +95,7 @@ public class SlimefunProfiler {
* @return A timestamp, best fed back into {@link #closeEntry(Location, SlimefunItem, long)}
*/
public long newEntry() {
if (!running.get()) {
if (!isProfiling.get()) {
return 0;
}
@ -93,7 +114,7 @@ public class SlimefunProfiler {
* The amount of entries that should be scheduled. Can be negative
*/
public void scheduleEntries(int amount) {
if (running.get()) {
if (isProfiling.get()) {
queued.getAndAdd(amount);
}
}
@ -136,7 +157,7 @@ public class SlimefunProfiler {
* This stops the profiling.
*/
public void stop() {
running.set(false);
isProfiling.set(false);
if (SlimefunPlugin.instance() == null || !SlimefunPlugin.instance().isEnabled()) {
// Slimefun has been disabled
@ -151,7 +172,7 @@ public class SlimefunProfiler {
int iterations = 4000;
// Wait for all timing results to come in
while (!running.get() && queued.get() > 0) {
while (!isProfiling.get() && queued.get() > 0) {
try {
/**
* 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!
return;
}

View File

@ -356,6 +356,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
ticker.halt();
ticker.run();
// Kill our Profiler Threads
profiler.kill();
// Save all Player Profiles that are still in memory
PlayerProfile.iterator().forEachRemaining(profile -> {
if (profile.isDirty()) {

View File

@ -151,7 +151,7 @@ public final class Script {
@Nonnull
private String getScriptRatingPercentage() {
float percentage = getRating();
return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.RESET + "% ";
return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.WHITE + "% ";
}
/**

View File

@ -61,10 +61,15 @@ public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
}
@Override
public int getCapacity() {
public final int getCapacity() {
return 0;
}
@Override
public final boolean isChargeable() {
return false;
}
@Override
public int getGeneratedOutput(Location l, Config data) {
World world = l.getWorld();

View File

@ -53,7 +53,7 @@ public class BlockPhysicsListener implements Listener {
}
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onPistonExtend(BlockPistonExtendEvent e) {
if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true);
@ -67,7 +67,7 @@ public class BlockPhysicsListener implements Listener {
}
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onPistonRetract(BlockPistonRetractEvent e) {
if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true);

View File

@ -22,7 +22,7 @@ public class WorldListener implements Listener {
@EventHandler
public void onWorldLoad(WorldLoadEvent e) {
SlimefunPlugin.getWorldSettingsService().load(e.getWorld());
BlockStorage.getForcedStorage(e.getWorld());
BlockStorage.getOrCreate(e.getWorld());
}
@EventHandler

View File

@ -30,8 +30,8 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker}, synchronous
* or not.
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker},
* synchronous or not.
*
* @author TheBusyBiscuit
*
@ -75,7 +75,7 @@ public class TickerTask implements Runnable {
/**
* This method resets this {@link TickerTask} to run again.
*/
public void reset() {
private void reset() {
running = false;
}
@ -91,6 +91,7 @@ public class TickerTask implements Runnable {
SlimefunPlugin.getProfiler().start();
Set<BlockTicker> tickers = new HashSet<>();
// Remove any deleted blocks
Iterator<Map.Entry<Location, Boolean>> removals = deletionQueue.entrySet().iterator();
while (removals.hasNext()) {
Map.Entry<Location, Boolean> entry = removals.next();
@ -98,12 +99,24 @@ public class TickerTask implements Runnable {
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) {
for (Map.Entry<ChunkPosition, Set<Location>> entry : tickingLocations.entrySet()) {
tickChunk(entry.getKey(), tickers, entry.getValue());
}
}
// Move any moved block data
Iterator<Map.Entry<Location, Location>> moves = movingQueue.entrySet().iterator();
while (moves.hasNext()) {
Map.Entry<Location, Location> entry = moves.next();

View File

@ -10,6 +10,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -55,14 +56,24 @@ public class BlockStorage {
private final Map<String, Config> blocksCache = new ConcurrentHashMap<>();
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) {
return SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
}
public static BlockStorage getForcedStorage(@Nonnull World world) {
return isWorldRegistered(world.getName()) ? SlimefunPlugin.getRegistry().getWorlds().get(world.getName()) : new BlockStorage(world);
@Nonnull
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) {
@ -321,7 +332,11 @@ public class BlockStorage {
public void saveAndRemove() {
save();
SlimefunPlugin.getRegistry().getWorlds().remove(world.getName());
isMarkedForRemoval.set(true);
}
public boolean isMarkedForRemoval() {
return isMarkedForRemoval.get();
}
public static void saveChunks() {
@ -496,15 +511,13 @@ public class BlockStorage {
storage.storage.put(l, cfg);
String id = cfg.getString("id");
BlockMenuPreset preset = BlockMenuPreset.getPreset(id);
if (BlockMenuPreset.isInventory(id)) {
if (preset != null) {
if (BlockMenuPreset.isUniversalInventory(id)) {
if (!SlimefunPlugin.getRegistry().getUniversalInventories().containsKey(id)) {
storage.loadUniversalInventory(BlockMenuPreset.getPreset(id));
}
SlimefunPlugin.getRegistry().getUniversalInventories().computeIfAbsent(id, key -> new UniversalBlockMenu(preset));
} else if (!storage.hasInventory(l)) {
File file = new File(PATH_INVENTORIES + serializeLocation(l) + ".sfi");
BlockMenuPreset preset = BlockMenuPreset.getPreset(id);
if (file.exists()) {
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) {
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)) {
refreshCache(storage, l, getLocationInfo(l).getString("id"), null, destroy);
storage.storage.remove(l);
@ -686,8 +703,8 @@ public class BlockStorage {
return id != null && id.equals(slimefunItem);
}
public static boolean isWorldRegistered(String name) {
return SlimefunPlugin.getRegistry().getWorlds().containsKey(name);
public static boolean isWorldLoaded(World world) {
return SlimefunPlugin.getRegistry().getWorlds().containsKey(world.getName());
}
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) {
BlockMenu menu = getInventory(l);
@ -788,7 +800,7 @@ public class BlockStorage {
public static Config getChunkInfo(World world, int x, int z) {
try {
if (!isWorldRegistered(world.getName())) {
if (!isWorldLoaded(world)) {
return emptyBlockData;
}

View File

@ -300,7 +300,7 @@ public abstract class BlockMenuPreset extends ChestMenu {
}
@Nullable
public static BlockMenuPreset getPreset(String id) {
public static BlockMenuPreset getPreset(@Nullable String id) {
return id == null ? null : SlimefunPlugin.getRegistry().getMenuPresets().get(id);
}