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

More performance and memory improvements

This commit is contained in:
TheBusyBiscuit 2020-11-19 22:20:43 +01:00
parent bb764b7584
commit 15f281504f
27 changed files with 237 additions and 74 deletions

View File

@ -44,6 +44,8 @@
* Performance improvements to Cargo network visualizations * Performance improvements to Cargo network visualizations
* General performance improvements * General performance improvements
* Improved performance for radioactive items * Improved performance for radioactive items
* Memory/GC improvements for the profiler
* Performance improvements for the Fluid Pump
#### Fixes #### Fixes
* Fixed #2448 * Fixed #2448

View File

@ -33,7 +33,7 @@ public class PlayerPreResearchEvent extends Event implements Cancellable {
private final Research research; private final Research research;
private final SlimefunItem slimefunItem; private final SlimefunItem slimefunItem;
private boolean cancelled; private boolean cancelled;
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public PlayerPreResearchEvent(Player p, Research research, SlimefunItem slimefunItem) { public PlayerPreResearchEvent(Player p, Research research, SlimefunItem slimefunItem) {
Validate.notNull(p, "The Player cannot be null"); Validate.notNull(p, "The Player cannot be null");

View File

@ -49,7 +49,9 @@ public interface DamageableItem extends ItemAttribute {
*/ */
default void damageItem(@Nonnull Player p, @Nullable ItemStack item) { default void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
if (isDamageable() && item != null && item.getType() != Material.AIR && item.getAmount() > 0) { if (isDamageable() && item != null && item.getType() != Material.AIR && item.getAmount() > 0) {
if (item.getEnchantments().containsKey(Enchantment.DURABILITY) && Math.random() * 100 <= (60 + Math.floorDiv(40, (item.getEnchantmentLevel(Enchantment.DURABILITY) + 1)))) { int unbreakingLevel = item.getEnchantmentLevel(Enchantment.DURABILITY);
if (unbreakingLevel > 0 && Math.random() * 100 <= (60 + Math.floorDiv(40, (unbreakingLevel + 1)))) {
return; return;
} }

View File

@ -68,8 +68,11 @@ public abstract class FlexCategory extends Category {
@Override @Override
public final boolean isHidden(@Nonnull Player p) { public final boolean isHidden(@Nonnull Player p) {
// We can stop this method right here. /**
// We provide a custom method with more parameters for this. See isVisible(...) * We can stop this method right here.
* We provide a custom method with more parameters for this.
* See isVisible(...)
*/
return false; return false;
} }

View File

@ -153,9 +153,11 @@ public class LockedCategory extends Category {
public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) { public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) {
for (Category category : parents) { for (Category category : parents) {
for (SlimefunItem item : category.getItems()) { for (SlimefunItem item : category.getItems()) {
// Should probably be replaced with Slimefun.hasUnlocked(...) /**
// However this will result in better performance because we don't * Should probably be replaced with Slimefun.hasUnlocked(...)
// request the PlayerProfile everytime * However this will result in better performance because we don't
* request the PlayerProfile everytime
*/
if (Slimefun.isEnabled(p, item, false) && Slimefun.hasPermission(p, item, false) && !profile.hasUnlocked(item.getResearch())) { if (Slimefun.isEnabled(p, item, false) && Slimefun.hasPermission(p, item, false) && !profile.hasUnlocked(item.getResearch())) {
return false; return false;
} }

View File

@ -27,7 +27,7 @@ public class SeasonalCategory extends Category {
private final Month month; private final Month month;
/** /**
* The constructor for a SeasonCategory. * The constructor for a {@link SeasonalCategory}.
* *
* @param key * @param key
* The {@link NamespacedKey} that is used to identify this {@link Category} * The {@link NamespacedKey} that is used to identify this {@link Category}

View File

@ -83,9 +83,12 @@ public class SlimefunCommand implements CommandExecutor, Listener {
sendHelp(sender); sendHelp(sender);
// We could just return true here, but if there's no subcommands, then /**
// something went horribly wrong anyway. This will also stop sonarcloud * We could just return true here, but if there's no subcommands,
// from nagging about this always returning true... * then something went horribly wrong anyway.
* This will also stop sonarcloud from nagging about
* this always returning true...
*/
return !commands.isEmpty(); return !commands.isEmpty();
} }

View File

@ -77,6 +77,7 @@ public abstract class SubCommand {
* *
* @param sender * @param sender
* The {@link CommandSender} who requested the description * The {@link CommandSender} who requested the description
*
* @return A possibly localized description of this {@link SubCommand} * @return A possibly localized description of this {@link SubCommand}
*/ */
@Nonnull @Nonnull

View File

@ -108,6 +108,7 @@ public class NetworkManager {
} }
Validate.notNull(type, "Type must not be null"); Validate.notNull(type, "Type must not be null");
for (Network network : networks) { for (Network network : networks) {
if (type.isInstance(network) && network.connectsTo(l)) { if (type.isInstance(network) && network.connectsTo(l)) {
return Optional.of(type.cast(network)); return Optional.of(type.cast(network));

View File

@ -117,6 +117,7 @@ public class Research implements Keyed {
* *
* @param p * @param p
* The {@link Player} to translate this name for. * The {@link Player} to translate this name for.
*
* @return The localized Name of this {@link Research}. * @return The localized Name of this {@link Research}.
*/ */
@Nonnull @Nonnull
@ -197,12 +198,18 @@ public class Research implements Keyed {
* Handle what to do when a {@link Player} clicks on an un-researched item in * Handle what to do when a {@link Player} clicks on an un-researched item in
* a {@link SlimefunGuideImplementation}. * a {@link SlimefunGuideImplementation}.
* *
* @param guide The {@link SlimefunGuideImplementation} used. * @param guide
* @param player The {@link Player} who clicked on the item. * The {@link SlimefunGuideImplementation} used.
* @param profile The {@link PlayerProfile} of that {@link Player}. * @param player
* @param sfItem The {@link SlimefunItem} on which the {@link Player} clicked. * The {@link Player} who clicked on the item.
* @param category The {@link Category} where the {@link Player} was. * @param profile
* @param page The page number of where the {@link Player} was in the {@link Category}; * The {@link PlayerProfile} of that {@link Player}.
* @param sfItem
* The {@link SlimefunItem} on which the {@link Player} clicked.
* @param category
* The {@link Category} where the {@link Player} was.
* @param page
* The page number of where the {@link Player} was in the {@link Category};
* *
*/ */
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@ -230,6 +237,7 @@ public class Research implements Keyed {
* *
* @param p * @param p
* The {@link Player} to check * The {@link Player} to check
*
* @return Whether that {@link Player} can unlock this {@link Research} * @return Whether that {@link Player} can unlock this {@link Research}
*/ */
public boolean canUnlock(@Nonnull Player p) { public boolean canUnlock(@Nonnull Player p) {

View File

@ -52,8 +52,10 @@ class GitHubTask implements Runnable {
* the {@link UUID} and received skin inside a local cache {@link File}. * the {@link UUID} and received skin inside a local cache {@link File}.
*/ */
private void grabTextures() { private void grabTextures() {
// Store all queried usernames to prevent 429 responses for pinging the /**
// same URL twice in one run. * Store all queried usernames to prevent 429 responses for pinging
* the same URL twice in one run.
*/
Map<String, String> skins = new HashMap<>(); Map<String, String> skins = new HashMap<>();
int requests = 0; int requests = 0;
@ -77,8 +79,11 @@ class GitHubTask implements Runnable {
} }
} }
// We only wanna save this if all Connectors finished already /**
// This will run multiple times but thats okay, this way we get as much data as possible stored * We only wanna save this if all Connectors finished already.
* This will run multiple times but thats okay, this way we get as much
* data as possible stored.
*/
gitHubService.saveCache(); gitHubService.saveCache();
} }

View File

@ -45,7 +45,7 @@ public enum PerformanceRating implements Predicate<Float> {
@Override @Override
public boolean test(@Nullable Float value) { public boolean test(@Nullable Float value) {
if (value == null) { if (value == null) {
// null will only test true for UNKNOWN // This way null will only test true for UNKNOWN
return threshold < 0; return threshold < 0;
} }

View File

@ -1,8 +1,11 @@
package io.github.thebusybiscuit.slimefun4.core.services.profiler; package io.github.thebusybiscuit.slimefun4.core.services.profiler;
import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition; import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
@ -11,44 +14,129 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/** /**
* This represents an entry in our {@link SlimefunProfiler}. * This represents an entry in our {@link SlimefunProfiler}.
* It is a modification of {@link BlockPosition} to be as memory-efficient as possible.
* *
* @author TheBusyBiscuit * @author TheBusyBiscuit
* *
*/ */
class ProfiledBlock { final class ProfiledBlock {
private final BlockPosition position; /**
* The {@link World} this {@link Block} is in.
* It is fine to keep an actual reference here since this is a throwaway object anyway.
*/
private final World world;
/**
* A {@link Long} representation of our {@link Location} (x, y, z).
*/
private final long position;
/**
* The {@link SlimefunItem} whihc is located at this {@link Location}.
*/
private final SlimefunItem item; private final SlimefunItem item;
/**
* This creates a new {@link ProfiledBlock} for the given {@link Location} and
* the {@link SlimefunItem} found at this {@link Location}.
*
* @param l
* The {@link Location}
* @param item
* The {@link SlimefunItem} found at that {@link Location}
*/
ProfiledBlock(@Nonnull Location l, @Nonnull SlimefunItem item) { ProfiledBlock(@Nonnull Location l, @Nonnull SlimefunItem item) {
this.position = new BlockPosition(l); this.world = l.getWorld();
this.item = item; this.position = getLocationAsLong((int) l.getX(), (int) l.getY(), (int) l.getZ());
}
ProfiledBlock(@Nonnull BlockPosition position, @Nonnull SlimefunItem item) {
this.position = position;
this.item = item; this.item = item;
} }
/** /**
* This is just a <strong>dummy</strong> constructor. * This is just a <strong>dummy</strong> constructor.
* Please only use this for comparisons or lookups.
* *
* @param b * @param b
* A {@link Block} * A {@link Block}
*/ */
ProfiledBlock(@Nonnull Block b) { ProfiledBlock(@Nonnull Block b) {
this.position = new BlockPosition(b); this.world = b.getWorld();
this.position = getLocationAsLong(b.getX(), b.getY(), b.getZ());
this.item = null; this.item = null;
} }
public BlockPosition getPosition() { /**
return position; * This compresses our {@link Location} into a long for more efficient memory usage
*
* @param x
* The x value
* @param y
* The y value
* @param z
* The z value
*
* @return A {@link Long} representation of this {@link Location}
*/
private static long getLocationAsLong(int x, int y, int z) {
return ((long) (x & 0x3FFFFFF) << 38) | ((long) (z & 0x3FFFFFF) << 12) | (long) (y & 0xFFF);
} }
@Nonnull
public World getWorld() {
return world;
}
/**
* Gets the x for this block.
*
* @return This blocks x coordinate.
*/
public int getX() {
return (int) (this.position >> 38);
}
/**
* Gets the y for this block.
*
* @return This blocks y coordinate.
*/
public int getY() {
return (int) (this.position & 0xFFF);
}
/**
* Gets the z for this block.
*
* @return This blocks z coordinate.
*/
public int getZ() {
return (int) (this.position << 26 >> 38);
}
/**
* Gets the chunks x coordinate for this block.
*
* @return The blocks chunks x coordinate.
*/
public int getChunkX() {
return this.getX() >> 4;
}
/**
* Gets the chunks z coordinate for this block.
*
* @return The blocks chunks z coordinate.
*/
public int getChunkZ() {
return this.getZ() >> 4;
}
@Nonnull
public String getId() { public String getId() {
return item.getId(); return item.getId();
} }
@Nonnull
public SlimefunAddon getAddon() { public SlimefunAddon getAddon() {
return item.getAddon(); return item.getAddon();
} }
@ -56,7 +144,8 @@ class ProfiledBlock {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj instanceof ProfiledBlock) { if (obj instanceof ProfiledBlock) {
return position.equals(((ProfiledBlock) obj).position); ProfiledBlock block = (ProfiledBlock) obj;
return position == block.position && Objects.equals(world, block.world);
} }
return false; return false;
@ -64,7 +153,8 @@ class ProfiledBlock {
@Override @Override
public int hashCode() { public int hashCode() {
return position.hashCode(); long hilo = world.getUID().getMostSignificantBits() ^ world.getUID().getLeastSignificantBits();
return (int) (position ^ (position >> 32) ^ hilo ^ (hilo >> 32));
} }
} }

View File

@ -50,6 +50,7 @@ public class SlimefunProfiler {
private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(5); private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(5);
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 running = new AtomicBoolean(false);
private final AtomicInteger queued = new AtomicInteger(0); private final AtomicInteger queued = new AtomicInteger(0);
@ -234,9 +235,10 @@ public class SlimefunProfiler {
Map<String, Long> map = new HashMap<>(); Map<String, Long> map = new HashMap<>();
for (Map.Entry<ProfiledBlock, Long> entry : timings.entrySet()) { for (Map.Entry<ProfiledBlock, Long> entry : timings.entrySet()) {
String world = entry.getKey().getPosition().getWorld().getName(); ProfiledBlock block = entry.getKey();
int x = entry.getKey().getPosition().getChunkX(); String world = block.getWorld().getName();
int z = entry.getKey().getPosition().getChunkZ(); int x = block.getChunkX();
int z = block.getChunkZ();
map.merge(world + " (" + x + ',' + z + ')', entry.getValue(), Long::sum); map.merge(world + " (" + x + ',' + z + ')', entry.getValue(), Long::sum);
} }
@ -249,9 +251,9 @@ public class SlimefunProfiler {
int blocks = 0; int blocks = 0;
for (ProfiledBlock block : timings.keySet()) { for (ProfiledBlock block : timings.keySet()) {
String world = block.getPosition().getWorld().getName(); String world = block.getWorld().getName();
int x = block.getPosition().getChunkX(); int x = block.getChunkX();
int z = block.getPosition().getChunkZ(); int z = block.getChunkZ();
if (chunk.equals(world + " (" + x + ',' + z + ')')) { if (chunk.equals(world + " (" + x + ',' + z + ')')) {
blocks++; blocks++;
@ -290,6 +292,7 @@ public class SlimefunProfiler {
protected float getPercentageOfTick() { protected float getPercentageOfTick() {
float millis = totalElapsedTime / 1000000.0F; float millis = totalElapsedTime / 1000000.0F;
float fraction = (millis * 100.0F) / MAX_TICK_DURATION; float fraction = (millis * 100.0F) / MAX_TICK_DURATION;
return Math.round((fraction * 100.0F) / 100.0F); return Math.round((fraction * 100.0F) / 100.0F);
} }
@ -311,6 +314,7 @@ public class SlimefunProfiler {
return PerformanceRating.UNKNOWN; return PerformanceRating.UNKNOWN;
} }
@Nonnull
public String getTime() { public String getTime() {
return NumberUtils.getAsMillis(totalElapsedTime); return NumberUtils.getAsMillis(totalElapsedTime);
} }
@ -330,6 +334,7 @@ public class SlimefunProfiler {
*/ */
public boolean hasTimings(@Nonnull Block b) { public boolean hasTimings(@Nonnull Block b) {
Validate.notNull("Cannot get timings for a null Block"); Validate.notNull("Cannot get timings for a null Block");
return timings.containsKey(new ProfiledBlock(b)); return timings.containsKey(new ProfiledBlock(b));
} }

View File

@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.core.services.profiler;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import javax.annotation.Nonnull;
/** /**
* This is our {@link ThreadFactory} for the {@link SlimefunProfiler}. * This is our {@link ThreadFactory} for the {@link SlimefunProfiler}.
* It holds the amount of {@link Thread Threads} we dedicate towards our {@link SlimefunProfiler} * It holds the amount of {@link Thread Threads} we dedicate towards our {@link SlimefunProfiler}
@ -16,16 +18,31 @@ final class SlimefunThreadFactory implements ThreadFactory {
private final int threadCount; private final int threadCount;
/**
* This constructs a new {@link SlimefunThreadFactory} with the given {@link Thread} count.
*
* @param threadCount
* The amount of {@link Thread Threads} to provide to the {@link SlimefunProfiler}
*/
SlimefunThreadFactory(int threadCount) { SlimefunThreadFactory(int threadCount) {
this.threadCount = threadCount; this.threadCount = threadCount;
} }
/**
* This returns the amount of {@link Thread Threads} we dedicate towards
* the {@link SlimefunProfiler}.
*
* @return The {@link Thread} count
*/
int getThreadCount() { int getThreadCount() {
return threadCount; return threadCount;
} }
/**
* This creates a new {@link Thread} for the {@link SlimefunProfiler}.
*/
@Override @Override
public Thread newThread(Runnable runnable) { public Thread newThread(@Nonnull Runnable runnable) {
return new Thread(runnable, "Slimefun Profiler"); return new Thread(runnable, "Slimefun Profiler");
} }

View File

@ -215,11 +215,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n"); ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n");
component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)")); component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)"));
component.setClickEvent(new ClickEvent(key, player -> component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> research.unlockFromGuide(this, player, profile, item, category, page))));
SlimefunPlugin.runSync(() ->
research.unlockFromGuide(this, player, profile, item, category, page)
)
));
items.add(component); items.add(component);
} else { } else {

View File

@ -2,6 +2,10 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -13,12 +17,12 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.Vein; import io.github.thebusybiscuit.cscorelib2.blocks.Vein;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
@ -49,6 +53,9 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
private final int[] inputBorder = { 9, 10, 11, 12, 18, 21, 27, 28, 29, 30 }; private final int[] inputBorder = { 9, 10, 11, 12, 18, 21, 27, 28, 29, 30 };
private final int[] outputBorder = { 14, 15, 16, 17, 23, 26, 32, 33, 34, 35 }; private final int[] outputBorder = { 14, 15, 16, 17, 23, 26, 32, 33, 34, 35 };
private final ItemStack emptyBucket = new ItemStackWrapper(Material.BUCKET);
@ParametersAreNonnullByDefault
public FluidPump(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { public FluidPump(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe); super(category, item, recipeType, recipe);
@ -66,16 +73,16 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
}); });
} }
private void constructMenu(BlockMenuPreset preset) { private void constructMenu(@Nonnull BlockMenuPreset preset) {
for (int i : border) { for (int i : border) {
preset.addItem(i, new CustomItem(Material.GRAY_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler()); preset.addItem(i, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
} }
for (int i : inputBorder) { for (int i : inputBorder) {
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler()); preset.addItem(i, ChestMenuUtils.getInputSlotTexture(), ChestMenuUtils.getEmptyClickHandler());
} }
for (int i : outputBorder) { for (int i : outputBorder) {
preset.addItem(i, new CustomItem(Material.ORANGE_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler()); preset.addItem(i, ChestMenuUtils.getOutputSlotTexture(), ChestMenuUtils.getEmptyClickHandler());
} }
for (int i : getOutputSlots()) { for (int i : getOutputSlots()) {
@ -114,14 +121,14 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
return 512; return 512;
} }
protected void tick(Block b) { protected void tick(@Nonnull Block b) {
Block fluid = b.getRelative(BlockFace.DOWN); Block fluid = b.getRelative(BlockFace.DOWN);
if (fluid.isLiquid() && getCharge(b.getLocation()) >= ENERGY_CONSUMPTION) { if (fluid.isLiquid() && getCharge(b.getLocation()) >= ENERGY_CONSUMPTION) {
BlockMenu menu = BlockStorage.getInventory(b); BlockMenu menu = BlockStorage.getInventory(b);
for (int slot : getInputSlots()) { for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.BUCKET), true, false)) { if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), emptyBucket, true, false)) {
ItemStack bucket = getFilledBucket(fluid); ItemStack bucket = getFilledBucket(fluid);
if (!menu.fits(bucket, getOutputSlots())) { if (!menu.fits(bucket, getOutputSlots())) {
@ -143,11 +150,14 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
} }
} }
private Block findNextFluid(Block fluid) { @Nullable
private Block findNextFluid(@Nonnull Block fluid) {
if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) { if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
// With water we can be sure to find an infinite source whenever we go /**
// further than a block, so we can just remove the water here and save * With water we can be sure to find an infinite source whenever we
// ourselves all of that computing... * go further than a block, so we can just remove the water here and
* save ourselves all of that computing...
*/
if (isSource(fluid)) { if (isSource(fluid)) {
return fluid; return fluid;
} }
@ -162,10 +172,12 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
} }
} }
} }
return null; return null;
} }
private ItemStack getFilledBucket(Block fluid) { @Nonnull
private ItemStack getFilledBucket(@Nonnull Block fluid) {
if (fluid.getType() == Material.LAVA) { if (fluid.getType() == Material.LAVA) {
return new ItemStack(Material.LAVA_BUCKET); return new ItemStack(Material.LAVA_BUCKET);
} else if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) { } else if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
@ -184,7 +196,7 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
* *
* @return Whether that {@link Block} is a liquid and a source {@link Block}. * @return Whether that {@link Block} is a liquid and a source {@link Block}.
*/ */
private boolean isSource(Block block) { private boolean isSource(@Nonnull Block block) {
if (block.isLiquid()) { if (block.isLiquid()) {
BlockData data = block.getBlockData(); BlockData data = block.getBlockData();

View File

@ -35,6 +35,7 @@ public class TeleporterListener implements Listener {
} }
String id = BlockStorage.checkID(e.getClickedBlock()); String id = BlockStorage.checkID(e.getClickedBlock());
if (id == null) { if (id == null) {
return; return;
} }
@ -55,7 +56,13 @@ public class TeleporterListener implements Listener {
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
private boolean isTeleporterPad(String id, Block b, UUID uuid) { private boolean isTeleporterPad(String id, Block b, UUID uuid) {
return id.equals(SlimefunItems.GPS_ACTIVATION_DEVICE_SHARED.getItemId()) || (id.equals(SlimefunItems.GPS_ACTIVATION_DEVICE_PERSONAL.getItemId()) && BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(uuid.toString())); if (id.equals(SlimefunItems.GPS_ACTIVATION_DEVICE_SHARED.getItemId())) {
return true;
} else if (id.equals(SlimefunItems.GPS_ACTIVATION_DEVICE_PERSONAL.getItemId())) {
return BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(uuid.toString());
} else {
return false;
}
} }
private boolean checkForPylons(@Nonnull Block teleporter) { private boolean checkForPylons(@Nonnull Block teleporter) {

View File

@ -7,12 +7,12 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
abstract class PlayerTask implements Runnable { abstract class AbstractPlayerTask implements Runnable {
protected int id; protected int id;
protected Player p; protected Player p;
PlayerTask(@Nonnull Player p) { AbstractPlayerTask(@Nonnull Player p) {
this.p = p; this.p = p;
} }
@ -36,10 +36,10 @@ abstract class PlayerTask implements Runnable {
} }
/** /**
* This method checks if this {@link PlayerTask} should be continued or cancelled. * This method checks if this {@link AbstractPlayerTask} should be continued or cancelled.
* It will also cancel this {@link PlayerTask} if it became invalid. * It will also cancel this {@link AbstractPlayerTask} if it became invalid.
* *
* @return Whether this {@link PlayerTask} is still valid * @return Whether this {@link AbstractPlayerTask} is still valid
*/ */
protected boolean isValid() { protected boolean isValid() {
if (!p.isOnline() || !p.isValid() || p.isDead() || !p.isSneaking()) { if (!p.isOnline() || !p.isValid() || p.isDead() || !p.isSneaking()) {

View File

@ -34,8 +34,9 @@ public class CapacitorTextureUpdateTask implements Runnable {
@Override @Override
public void run() { public void run() {
Block b = l.getBlock(); Block b = l.getBlock();
Material type = b.getType();
if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.PLAYER_WALL_HEAD) { if (type == Material.PLAYER_HEAD || type == Material.PLAYER_WALL_HEAD) {
if (filledPercentage <= 0.25) { if (filledPercentage <= 0.25) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture()); SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());
} else if (filledPercentage <= 0.5) { } else if (filledPercentage <= 0.5) {

View File

@ -14,7 +14,7 @@ import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler; import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.JetBoots; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.JetBoots;
public class JetBootsTask extends PlayerTask { public class JetBootsTask extends AbstractPlayerTask {
private static final float COST = 0.075F; private static final float COST = 0.075F;

View File

@ -11,7 +11,7 @@ import org.bukkit.util.Vector;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Jetpack; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Jetpack;
public class JetpackTask extends PlayerTask { public class JetpackTask extends AbstractPlayerTask {
private static final float COST = 0.08F; private static final float COST = 0.08F;

View File

@ -13,7 +13,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedMa
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
/** /**
* This {@link PlayerTask} is run when a {@link Player} carries an {@link InfusedMagnet}. * This {@link AbstractPlayerTask} is run when a {@link Player} carries an {@link InfusedMagnet}.
* It manages the automatic pickup of nearby items. * It manages the automatic pickup of nearby items.
* *
* @author TheBusyBiscuit * @author TheBusyBiscuit
@ -21,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
* @see InfusedMagnet * @see InfusedMagnet
* *
*/ */
public class MagnetTask extends PlayerTask { public class MagnetTask extends AbstractPlayerTask {
private final double radius; private final double radius;

View File

@ -6,7 +6,7 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
public class ParachuteTask extends PlayerTask { public class ParachuteTask extends AbstractPlayerTask {
public ParachuteTask(@Nonnull Player p) { public ParachuteTask(@Nonnull Player p) {
super(p); super(p);

View File

@ -83,6 +83,7 @@ public class SlimefunStartupTask implements Runnable {
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -146,8 +146,11 @@ public class TickerTask implements Runnable {
if (item.getBlockTicker().isSynchronized()) { if (item.getBlockTicker().isSynchronized()) {
SlimefunPlugin.getProfiler().scheduleEntries(1); SlimefunPlugin.getProfiler().scheduleEntries(1);
item.getBlockTicker().update(); item.getBlockTicker().update();
// We are inserting a new timestamp because synchronized
// actions are always ran with a 50ms delay (1 game tick) /**
* We are inserting a new timestamp because synchronized actions
* are always ran with a 50ms delay (1 game tick)
*/
SlimefunPlugin.runSync(() -> { SlimefunPlugin.runSync(() -> {
Block b = l.getBlock(); Block b = l.getBlock();
tickBlock(l, b, item, data, System.nanoTime()); tickBlock(l, b, item, data, System.nanoTime());

View File

@ -42,6 +42,10 @@ public final class ItemStackWrapper extends ItemStack {
} }
} }
public ItemStackWrapper(@Nonnull Material material) {
this(new ItemStack(material));
}
@Override @Override
public boolean hasItemMeta() { public boolean hasItemMeta() {
return hasItemMeta; return hasItemMeta;