mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-20 03:35:51 +00:00
Merge branch 'master' into fix/sf-machine-hopper
This commit is contained in:
commit
5e0e9d5490
18
CHANGELOG.md
18
CHANGELOG.md
@ -30,6 +30,9 @@
|
||||
* (API) Added PlayerPreResearchEvent
|
||||
* Added a config option to disable network visualizations
|
||||
* (API) Added CoolerFeedPlayerEvent
|
||||
* Added a config option to delete excess cargo network items
|
||||
* Added an item setting to configure the Wind Staff velocity
|
||||
* Added an item setting to the Infused Hopper to toggle it with redstone
|
||||
|
||||
#### Changes
|
||||
* Removed 1.13 support
|
||||
@ -40,6 +43,10 @@
|
||||
* Magnets can no longer be placed down
|
||||
* Electromagnets can no longer be placed down
|
||||
* Performance improvements to Cargo network visualizations
|
||||
* General performance improvements
|
||||
* Improved performance for radioactive items
|
||||
* Memory/GC improvements for the profiler
|
||||
* Performance improvements for the Fluid Pump
|
||||
|
||||
#### Fixes
|
||||
* Fixed #2448
|
||||
@ -59,6 +66,17 @@
|
||||
* Fixed Magician Talisman sometimes drawing invalid enchantments
|
||||
* Fixed id conflicts for external Enchantment sources (e.g. plugins) for the Magician Talisman settings
|
||||
* Fixed network visualizers spawning particles for other player heads
|
||||
* Fixed #2418
|
||||
* Fixed #2446
|
||||
* Fixed CoreProtect not recognizing Slimefun blocks getting broken
|
||||
* Fixed #2447
|
||||
* Fixed #2558
|
||||
* Fixed a duplication bug with the Block Placer
|
||||
* Fixed Slimefun Guide Settings showing "last activity" as a negative number
|
||||
* Fixed Armor Stands getting damaged/pushed by Explosive Bow
|
||||
* Fixed Sword of Beheading dropping Zombie/Skeleton Skulls from Zombie/Skeleton subvariants
|
||||
* Fixed #2518
|
||||
* Fixed #2421
|
||||
|
||||
## Release Candidate 17 (17 Oct 2020)
|
||||
|
||||
|
6
pom.xml
6
pom.xml
@ -315,7 +315,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.seeseemelk</groupId>
|
||||
<artifactId>MockBukkit-v1.16</artifactId>
|
||||
<version>0.15.0</version>
|
||||
<version>0.15.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@ -337,7 +337,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||
<artifactId>CS-CoreLib2</artifactId>
|
||||
<version>0.26</version>
|
||||
<version>0.27.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -381,7 +381,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.1.157</version>
|
||||
<version>2.1.158</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -33,7 +33,7 @@ public class PlayerPreResearchEvent extends Event implements Cancellable {
|
||||
private final Research research;
|
||||
private final SlimefunItem slimefunItem;
|
||||
private boolean cancelled;
|
||||
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public PlayerPreResearchEvent(Player p, Research research, SlimefunItem slimefunItem) {
|
||||
Validate.notNull(p, "The Player cannot be null");
|
||||
|
@ -11,6 +11,7 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -19,12 +20,25 @@ import io.github.thebusybiscuit.cscorelib2.data.ComputedOptional;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
|
||||
public class PlayerRightClickEvent extends Event {
|
||||
/**
|
||||
* The {@link PlayerRightClickEvent} is our custom version of the {@link PlayerInteractEvent}.
|
||||
* But it is only triggered on right click.
|
||||
* The main and (almost) sole purpose of this {@link Event} is to cache the {@link SlimefunItem}
|
||||
* of the {@link ItemStack} and/or {@link Block} involved.
|
||||
* This allows us (and addons) to efficiently check the used {@link SlimefunItem} without the need
|
||||
* to do a heavy lookup or item comparison.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class PlayerRightClickEvent extends PlayerEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
/**
|
||||
* The original {@link PlayerInteractEvent}.
|
||||
*/
|
||||
private final PlayerInteractEvent event;
|
||||
private final Player player;
|
||||
|
||||
private final Optional<ItemStack> itemStack;
|
||||
private final Optional<Block> clickedBlock;
|
||||
@ -35,33 +49,45 @@ public class PlayerRightClickEvent extends Event {
|
||||
private ComputedOptional<SlimefunItem> slimefunItem = ComputedOptional.createNew();
|
||||
private ComputedOptional<SlimefunItem> slimefunBlock = ComputedOptional.createNew();
|
||||
|
||||
private Result itemResult = Result.DEFAULT;
|
||||
private Result blockResult = Result.DEFAULT;
|
||||
private Result itemResult;
|
||||
private Result blockResult;
|
||||
|
||||
public PlayerRightClickEvent(@Nonnull PlayerInteractEvent e) {
|
||||
event = e;
|
||||
player = e.getPlayer();
|
||||
clickedBlock = Optional.ofNullable(e.getClickedBlock());
|
||||
face = e.getBlockFace();
|
||||
hand = e.getHand();
|
||||
/**
|
||||
* This constructs a new {@link PlayerRightClickEvent} based on the original {@link PlayerInteractEvent}.
|
||||
* The {@link Result} of the original {@link PlayerInteractEvent} will be copied.
|
||||
*
|
||||
* @param originalEvent
|
||||
* The original {@link PlayerInteractEvent}
|
||||
*/
|
||||
public PlayerRightClickEvent(@Nonnull PlayerInteractEvent originalEvent) {
|
||||
super(originalEvent.getPlayer());
|
||||
|
||||
if (e.getItem() == null || e.getItem().getType() == Material.AIR || e.getItem().getAmount() == 0) {
|
||||
event = originalEvent;
|
||||
clickedBlock = Optional.ofNullable(originalEvent.getClickedBlock());
|
||||
face = originalEvent.getBlockFace();
|
||||
hand = originalEvent.getHand();
|
||||
|
||||
itemResult = originalEvent.useItemInHand();
|
||||
blockResult = originalEvent.useInteractedBlock();
|
||||
|
||||
if (originalEvent.getItem() == null || originalEvent.getItem().getType() == Material.AIR || originalEvent.getItem().getAmount() == 0) {
|
||||
itemStack = Optional.empty();
|
||||
} else {
|
||||
itemStack = Optional.of(e.getItem());
|
||||
itemStack = Optional.of(originalEvent.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the original {@link PlayerInteractEvent} that triggered this
|
||||
* {@link PlayerRightClickEvent}.
|
||||
*
|
||||
* @return The original {@link PlayerInteractEvent}
|
||||
*/
|
||||
@Nonnull
|
||||
public PlayerInteractEvent getInteractEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the {@link ItemStack} that was held in the hand of the {@link Player}.
|
||||
* It will never return null, should there be no {@link ItemStack} then it will return
|
||||
@ -121,6 +147,10 @@ public class PlayerRightClickEvent extends Event {
|
||||
return slimefunBlock.getAsOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method cancels the {@link PlayerRightClickEvent}.
|
||||
* This will deny the item and block usage.
|
||||
*/
|
||||
public void cancel() {
|
||||
itemResult = Result.DENY;
|
||||
blockResult = Result.DENY;
|
||||
|
@ -113,6 +113,7 @@ public class ItemSetting<T> {
|
||||
*
|
||||
* @param c
|
||||
* The class of data type you want to compare
|
||||
*
|
||||
* @return Whether this {@link ItemSetting} stores the given type
|
||||
*/
|
||||
public boolean isType(@Nonnull Class<?> c) {
|
||||
@ -137,14 +138,19 @@ public class ItemSetting<T> {
|
||||
* @param item
|
||||
* The {@link SlimefunItem} who called this method
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void load(@Nonnull SlimefunItem item) {
|
||||
Validate.notNull(item, "Cannot apply settings for a non-existing SlimefunItem");
|
||||
|
||||
SlimefunPlugin.getItemCfg().setDefaultValue(item.getId() + '.' + getKey(), getDefaultValue());
|
||||
Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getId() + '.' + getKey());
|
||||
|
||||
if (defaultValue.getClass().isInstance(configuredValue)) {
|
||||
if (validateInput((T) configuredValue)) {
|
||||
this.value = (T) configuredValue;
|
||||
// We can suppress the warning here, we did an isInstance(...) check before!
|
||||
@SuppressWarnings("unchecked")
|
||||
T newValue = (T) configuredValue;
|
||||
|
||||
if (validateInput(newValue)) {
|
||||
this.value = newValue;
|
||||
} else {
|
||||
Slimefun.getLogger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
|
||||
Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
|
||||
|
@ -49,7 +49,9 @@ public interface DamageableItem extends ItemAttribute {
|
||||
*/
|
||||
default void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponen
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
|
||||
@ -65,14 +66,36 @@ public interface EnergyNetComponent extends ItemAttribute {
|
||||
* @return The charge stored at that {@link Location}
|
||||
*/
|
||||
default int getCharge(@Nonnull Location l) {
|
||||
// Emergency fallback, this cannot hold a charge, so we'll just return zero
|
||||
if (!isChargeable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getCharge(l, BlockStorage.getLocationInfo(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the currently stored charge at a given {@link Location}.
|
||||
* This is a more performance saving option if you already have a {@link Config}
|
||||
* object for this {@link Location}.
|
||||
*
|
||||
* @param l
|
||||
* The target {@link Location}
|
||||
* @param data
|
||||
* The data at this {@link Location}
|
||||
*
|
||||
* @return The charge stored at that {@link Location}
|
||||
*/
|
||||
default int getCharge(@Nonnull Location l, @Nonnull Config data) {
|
||||
Validate.notNull(l, "Location was null!");
|
||||
Validate.notNull(data, "data was null!");
|
||||
|
||||
// Emergency fallback, this cannot hold a charge, so we'll just return zero
|
||||
if (!isChargeable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String charge = BlockStorage.getLocationInfo(l, "energy-charge");
|
||||
String charge = data.getString("energy-charge");
|
||||
|
||||
if (charge != null) {
|
||||
return Integer.parseInt(charge);
|
||||
|
@ -68,8 +68,11 @@ public abstract class FlexCategory extends Category {
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -153,9 +153,11 @@ public class LockedCategory extends Category {
|
||||
public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) {
|
||||
for (Category category : parents) {
|
||||
for (SlimefunItem item : category.getItems()) {
|
||||
// Should probably be replaced with Slimefun.hasUnlocked(...)
|
||||
// However this will result in better performance because we don't
|
||||
// request the PlayerProfile everytime
|
||||
/**
|
||||
* Should probably be replaced with Slimefun.hasUnlocked(...)
|
||||
* 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())) {
|
||||
return false;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class SeasonalCategory extends Category {
|
||||
private final Month month;
|
||||
|
||||
/**
|
||||
* The constructor for a SeasonCategory.
|
||||
* The constructor for a {@link SeasonalCategory}.
|
||||
*
|
||||
* @param key
|
||||
* The {@link NamespacedKey} that is used to identify this {@link Category}
|
||||
|
@ -83,9 +83,12 @@ public class SlimefunCommand implements CommandExecutor, Listener {
|
||||
|
||||
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
|
||||
// from nagging about this always returning true...
|
||||
/**
|
||||
* We could just return true here, but if there's no subcommands,
|
||||
* then something went horribly wrong anyway.
|
||||
* This will also stop sonarcloud from nagging about
|
||||
* this always returning true...
|
||||
*/
|
||||
return !commands.isEmpty();
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ public abstract class SubCommand {
|
||||
*
|
||||
* @param sender
|
||||
* The {@link CommandSender} who requested the description
|
||||
*
|
||||
* @return A possibly localized description of this {@link SubCommand}
|
||||
*/
|
||||
@Nonnull
|
||||
|
@ -46,7 +46,7 @@ final class ContributorsMenu {
|
||||
});
|
||||
|
||||
List<Contributor> contributors = new ArrayList<>(SlimefunPlugin.getGitHubService().getContributors().values());
|
||||
contributors.sort(Comparator.comparingInt(Contributor::index));
|
||||
contributors.sort(Comparator.comparingInt(Contributor::getPosition));
|
||||
|
||||
for (int i = page * 36; i < contributors.size() && i < (page + 1) * 36; i++) {
|
||||
Contributor contributor = contributors.get(i);
|
||||
|
@ -117,7 +117,7 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace
|
||||
protected MultiBlockInteractionHandler getInteractionHandler() {
|
||||
return (p, mb, b) -> {
|
||||
if (mb.equals(getMultiBlock())) {
|
||||
if (!isDisabled() && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES) && Slimefun.hasUnlocked(p, this, true)) {
|
||||
if (!isDisabled() && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK) && Slimefun.hasUnlocked(p, this, true)) {
|
||||
onInteract(p, b);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import org.bukkit.Server;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||
import io.github.thebusybiscuit.slimefun4.api.network.Network;
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
|
||||
|
||||
/**
|
||||
@ -30,6 +31,7 @@ public class NetworkManager {
|
||||
|
||||
private final int maxNodes;
|
||||
private final boolean enableVisualizer;
|
||||
private final boolean deleteExcessItems;
|
||||
private final List<Network> networks = new LinkedList<>();
|
||||
|
||||
/**
|
||||
@ -37,14 +39,29 @@ public class NetworkManager {
|
||||
*
|
||||
* @param maxStepSize
|
||||
* The maximum amount of nodes a {@link Network} can have
|
||||
* @param enableVisualizer
|
||||
* Whether the {@link Network} visualizer is enabled
|
||||
* @param deleteExcessItems
|
||||
* Whether excess items from a {@link CargoNet} should be voided
|
||||
*/
|
||||
public NetworkManager(int maxStepSize, boolean enableVisualizer) {
|
||||
public NetworkManager(int maxStepSize, boolean enableVisualizer, boolean deleteExcessItems) {
|
||||
Validate.isTrue(maxStepSize > 0, "The maximal Network size must be above zero!");
|
||||
|
||||
this.enableVisualizer = enableVisualizer;
|
||||
this.deleteExcessItems = deleteExcessItems;
|
||||
maxNodes = maxStepSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a new {@link NetworkManager} with the given capacity.
|
||||
*
|
||||
* @param maxStepSize
|
||||
* The maximum amount of nodes a {@link Network} can have
|
||||
*/
|
||||
public NetworkManager(int maxStepSize) {
|
||||
this(maxStepSize, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the limit of nodes a {@link Network} can have.
|
||||
* This value is read from the {@link Config} file.
|
||||
@ -64,6 +81,16 @@ public class NetworkManager {
|
||||
return enableVisualizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns whether excess items from a {@link CargoNet} should be voided
|
||||
* instead of being dropped to the ground.
|
||||
*
|
||||
* @return Whether to delete excess items
|
||||
*/
|
||||
public boolean isItemDeletionEnabled() {
|
||||
return deleteExcessItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a {@link List} of every {@link Network} on the {@link Server}.
|
||||
*
|
||||
@ -81,6 +108,7 @@ public class NetworkManager {
|
||||
}
|
||||
|
||||
Validate.notNull(type, "Type must not be null");
|
||||
|
||||
for (Network network : networks) {
|
||||
if (type.isInstance(network) && network.connectsTo(l)) {
|
||||
return Optional.of(type.cast(network));
|
||||
@ -141,8 +169,11 @@ public class NetworkManager {
|
||||
public void updateAllNetworks(@Nonnull Location l) {
|
||||
Validate.notNull(l, "The Location cannot be null");
|
||||
|
||||
for (Network network : getNetworksFromLocation(l, Network.class)) {
|
||||
network.markDirty(l);
|
||||
// No need to create a sublist and loop through it if there are no Networks
|
||||
if (!networks.isEmpty()) {
|
||||
for (Network network : getNetworksFromLocation(l, Network.class)) {
|
||||
network.markDirty(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.NetworkManager;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
@ -37,6 +38,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||
*/
|
||||
class CargoNetworkTask implements Runnable {
|
||||
|
||||
private final NetworkManager manager;
|
||||
private final CargoNet network;
|
||||
private final Map<Location, Inventory> inventories = new HashMap<>();
|
||||
|
||||
@ -49,6 +51,7 @@ class CargoNetworkTask implements Runnable {
|
||||
@ParametersAreNonnullByDefault
|
||||
CargoNetworkTask(CargoNet network, Map<Location, Integer> inputs, Map<Integer, List<Location>> outputs, Set<Location> chestTerminalInputs, Set<Location> chestTerminalOutputs) {
|
||||
this.network = network;
|
||||
this.manager = SlimefunPlugin.getNetworkManager();
|
||||
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
@ -115,7 +118,7 @@ class CargoNetworkTask implements Runnable {
|
||||
// Try to add the item into another available slot then
|
||||
ItemStack rest = inv.addItem(stack).get(0);
|
||||
|
||||
if (rest != null) {
|
||||
if (rest != null && !manager.isItemDeletionEnabled()) {
|
||||
// If the item still couldn't be inserted, simply drop it on the ground
|
||||
inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), rest);
|
||||
}
|
||||
@ -126,7 +129,7 @@ class CargoNetworkTask implements Runnable {
|
||||
if (menu != null) {
|
||||
if (menu.getItemInSlot(previousSlot) == null) {
|
||||
menu.replaceExistingItem(previousSlot, stack);
|
||||
} else {
|
||||
} else if (!manager.isItemDeletionEnabled()) {
|
||||
inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), stack);
|
||||
}
|
||||
}
|
||||
|
@ -210,14 +210,14 @@ public class EnergyNet extends Network {
|
||||
SlimefunItem item = (SlimefunItem) provider;
|
||||
|
||||
try {
|
||||
Config config = BlockStorage.getLocationInfo(loc);
|
||||
int energy = provider.getGeneratedOutput(loc, config);
|
||||
Config data = BlockStorage.getLocationInfo(loc);
|
||||
int energy = provider.getGeneratedOutput(loc, data);
|
||||
|
||||
if (provider.isChargeable()) {
|
||||
energy += provider.getCharge(loc);
|
||||
energy += provider.getCharge(loc, data);
|
||||
}
|
||||
|
||||
if (provider.willExplode(loc, config)) {
|
||||
if (provider.willExplode(loc, data)) {
|
||||
explodedBlocks.add(loc);
|
||||
BlockStorage.clearBlockInfo(loc);
|
||||
|
||||
@ -228,9 +228,9 @@ public class EnergyNet extends Network {
|
||||
} else {
|
||||
supply += energy;
|
||||
}
|
||||
} catch (Exception | LinkageError t) {
|
||||
} catch (Exception | LinkageError throwable) {
|
||||
explodedBlocks.add(loc);
|
||||
new ErrorReport<>(t, loc, item);
|
||||
new ErrorReport<>(throwable, loc, item);
|
||||
}
|
||||
|
||||
long time = SlimefunPlugin.getProfiler().closeEntry(loc, item, timestamp);
|
||||
|
@ -117,6 +117,7 @@ public class Research implements Keyed {
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} to translate this name for.
|
||||
*
|
||||
* @return The localized Name of this {@link Research}.
|
||||
*/
|
||||
@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
|
||||
* a {@link SlimefunGuideImplementation}.
|
||||
*
|
||||
* @param guide The {@link SlimefunGuideImplementation} used.
|
||||
* @param player The {@link Player} who clicked on the item.
|
||||
* @param profile 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};
|
||||
* @param guide
|
||||
* The {@link SlimefunGuideImplementation} used.
|
||||
* @param player
|
||||
* The {@link Player} who clicked on the item.
|
||||
* @param profile
|
||||
* 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
|
||||
@ -230,6 +237,7 @@ public class Research implements Keyed {
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} to check
|
||||
*
|
||||
* @return Whether that {@link Player} can unlock this {@link Research}
|
||||
*/
|
||||
public boolean canUnlock(@Nonnull Player p) {
|
||||
|
@ -7,7 +7,6 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.Material;
|
||||
@ -20,10 +19,7 @@ import org.bukkit.persistence.PersistentDataHolder;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
|
||||
/**
|
||||
@ -70,20 +66,17 @@ public class BlockDataService implements Keyed {
|
||||
Validate.notNull(b, "The block cannot be null!");
|
||||
Validate.notNull(value, "The value cannot be null!");
|
||||
|
||||
// Due to a bug on older versions, Persistent Data is nullable for non-snapshots
|
||||
boolean useSnapshot = SlimefunPlugin.getMinecraftVersion().isBefore(MinecraftVersion.MINECRAFT_1_16);
|
||||
|
||||
BlockStateSnapshotResult result = PaperLib.getBlockState(b, useSnapshot);
|
||||
BlockState state = result.getState();
|
||||
/**
|
||||
* Don't use PaperLib here, it seems to be quite buggy in block-placing scenarios
|
||||
* and it would be too tedious to check for individual build versions to circumvent this.
|
||||
*/
|
||||
BlockState state = b.getState();
|
||||
|
||||
if (state instanceof TileState) {
|
||||
try {
|
||||
PersistentDataContainer container = ((TileState) state).getPersistentDataContainer();
|
||||
container.set(namespacedKey, PersistentDataType.STRING, value);
|
||||
|
||||
if (result.isSnapshot()) {
|
||||
state.update();
|
||||
}
|
||||
state.update();
|
||||
} catch (Exception x) {
|
||||
Slimefun.getLogger().log(Level.SEVERE, "Please check if your Server Software is up to date!");
|
||||
|
||||
@ -100,21 +93,31 @@ public class BlockDataService implements Keyed {
|
||||
*
|
||||
* @param b
|
||||
* The {@link Block} to retrieve data from
|
||||
*
|
||||
* @return The stored value
|
||||
*/
|
||||
public Optional<String> getBlockData(@Nonnull Block b) {
|
||||
Validate.notNull(b, "The block cannot be null!");
|
||||
|
||||
BlockState state = PaperLib.getBlockState(b, false).getState();
|
||||
PersistentDataContainer container = getPersistentDataContainer(state);
|
||||
|
||||
if (state instanceof TileState) {
|
||||
PersistentDataContainer container = ((TileState) state).getPersistentDataContainer();
|
||||
if (container != null) {
|
||||
return Optional.ofNullable(container.get(namespacedKey, PersistentDataType.STRING));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PersistentDataContainer getPersistentDataContainer(@Nonnull BlockState state) {
|
||||
if (state instanceof TileState) {
|
||||
return ((TileState) state).getPersistentDataContainer();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks whether the given {@link Material} is a Tile Entity.
|
||||
* This is used to determine whether the {@link Block} produced by this {@link Material}
|
||||
|
@ -23,9 +23,22 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
*/
|
||||
public class CustomTextureService {
|
||||
|
||||
/**
|
||||
* The {@link Config} object in which the Server Owner can configure the item models.
|
||||
*/
|
||||
private final Config config;
|
||||
|
||||
/**
|
||||
* This nullable {@link StringBuffer} represents the "version" of the used item-models file.
|
||||
* This version is served with our resource pack.
|
||||
*/
|
||||
private String version = null;
|
||||
|
||||
/**
|
||||
* This boolean represents whether the file was modified anyway.
|
||||
* This is equivalent to at least one value being set to a number which
|
||||
* is not zero!
|
||||
*/
|
||||
private boolean modified = false;
|
||||
|
||||
/**
|
||||
@ -110,6 +123,7 @@ public class CustomTextureService {
|
||||
*/
|
||||
public int getModelData(@Nonnull String id) {
|
||||
Validate.notNull(id, "Cannot get the ModelData for 'null'");
|
||||
|
||||
return config.getInt(id);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ public class MetricsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* This will close the child classloader and mark all the resources held under this no longer
|
||||
* This will close the child {@link ClassLoader} and mark all the resources held under this no longer
|
||||
* in use, they will be cleaned up the next GC run.
|
||||
*/
|
||||
public void cleanUp() {
|
||||
|
@ -24,8 +24,20 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||
*/
|
||||
public class UpdaterService {
|
||||
|
||||
/**
|
||||
* Our {@link SlimefunPlugin} instance.
|
||||
*/
|
||||
private final SlimefunPlugin plugin;
|
||||
|
||||
/**
|
||||
* Our {@link Updater} implementation.
|
||||
*/
|
||||
private final Updater updater;
|
||||
|
||||
/**
|
||||
* The {@link SlimefunBranch} we are currently on.
|
||||
* If this is an official {@link SlimefunBranch}, auto updates will be enabled.
|
||||
*/
|
||||
private final SlimefunBranch branch;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ public class Contributor {
|
||||
private final ComputedOptional<String> headTexture = ComputedOptional.createNew();
|
||||
|
||||
private Optional<UUID> uuid = Optional.empty();
|
||||
private boolean locked = false;
|
||||
private boolean immutable = false;
|
||||
|
||||
/**
|
||||
* This creates a new {@link Contributor} with the given ingame name and GitHub profile.
|
||||
@ -76,7 +76,7 @@ public class Contributor {
|
||||
* specified role.
|
||||
*
|
||||
* @param role
|
||||
* The role
|
||||
* The role of this {@link Contributor}
|
||||
* @param commits
|
||||
* The amount of contributions made as that role
|
||||
*/
|
||||
@ -84,7 +84,7 @@ public class Contributor {
|
||||
Validate.notNull(role, "The role cannot be null!");
|
||||
Validate.isTrue(commits >= 0, "Contributions cannot be negative");
|
||||
|
||||
if (!locked || role.startsWith("translator,")) {
|
||||
if (!immutable || role.startsWith("translator,")) {
|
||||
contributions.put(role, commits);
|
||||
}
|
||||
}
|
||||
@ -120,6 +120,13 @@ public class Contributor {
|
||||
return profileLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a {@link List} of contributions for this {@link Contributor}.
|
||||
* Each entry consists of a {@link String} (for the role) and an {@link Integer}
|
||||
* (for the amount of commits).
|
||||
*
|
||||
* @return A {@link List} of contributions for this {@link Contributor}
|
||||
*/
|
||||
@Nonnull
|
||||
public List<Map.Entry<String, Integer>> getContributions() {
|
||||
List<Map.Entry<String, Integer>> list = new ArrayList<>(contributions.entrySet());
|
||||
@ -137,6 +144,8 @@ public class Contributor {
|
||||
* @return The amount of contributions this {@link Contributor} submitted as the given role
|
||||
*/
|
||||
public int getContributions(@Nonnull String role) {
|
||||
Validate.notNull(role, "The role cannot be null!");
|
||||
|
||||
return contributions.getOrDefault(role, 0);
|
||||
}
|
||||
|
||||
@ -214,16 +223,35 @@ public class Contributor {
|
||||
return contributions.values().stream().mapToInt(Integer::intValue).sum();
|
||||
}
|
||||
|
||||
public int index() {
|
||||
return -getTotalContributions();
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the final display name for this {@link Contributor}.
|
||||
* The display name is basically the GitHub username but if the Minecraft username differs,
|
||||
* it will be appended in brackets behind the GitHub username.
|
||||
*
|
||||
* @return The final display name of this {@link Contributor}.
|
||||
*/
|
||||
@Nonnull
|
||||
public String getDisplayName() {
|
||||
return ChatColor.GRAY + githubUsername + (!githubUsername.equals(minecraftUsername) ? ChatColor.DARK_GRAY + " (MC: " + minecraftUsername + ")" : "");
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
locked = true;
|
||||
/**
|
||||
* This returns the position on where to order this {@link Contributor}.
|
||||
* This is just a convenience method for a {@link Comparator}, it is equivalent to
|
||||
* {@link #getTotalContributions()} multiplied by minus one.
|
||||
*
|
||||
* @return The position of this {@link Contributor} in terms for positioning and ordering.
|
||||
*/
|
||||
public int getPosition() {
|
||||
return -getTotalContributions();
|
||||
}
|
||||
|
||||
/**
|
||||
* This marks this {@link Contributor} as immutable.
|
||||
* Immutable {@link Contributor Contributors} will no longer be assigned any contributions.
|
||||
* This is useful when you want to prevent some commits from counting twice.
|
||||
*/
|
||||
public void setImmutable() {
|
||||
immutable = true;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -37,6 +38,7 @@ public class GitHubService {
|
||||
private boolean logging = false;
|
||||
|
||||
private LocalDateTime lastUpdate = LocalDateTime.now();
|
||||
|
||||
private int openIssues = 0;
|
||||
private int pendingPullRequests = 0;
|
||||
private int publicForks = 0;
|
||||
@ -56,9 +58,18 @@ public class GitHubService {
|
||||
loadConnectors(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will start the {@link GitHubService} and run the asynchronous {@link GitHubTask}
|
||||
* every so often to update its data.
|
||||
*
|
||||
* @param plugin
|
||||
* Our instance of {@link SlimefunPlugin}
|
||||
*/
|
||||
public void start(@Nonnull SlimefunPlugin plugin) {
|
||||
long period = TimeUnit.HOURS.toMillis(1);
|
||||
GitHubTask task = new GitHubTask(this);
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, task, 80L, 60 * 60 * 20L);
|
||||
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, task, 80L, period);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,8 +226,16 @@ public class GitHubService {
|
||||
texturesCache.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the cached skin texture for a given username.
|
||||
*
|
||||
* @param username
|
||||
* The minecraft username
|
||||
*
|
||||
* @return The cached skin texture for that user (or null)
|
||||
*/
|
||||
@Nullable
|
||||
protected String getCachedTexture(@Nonnull String name) {
|
||||
return texturesCache.getString(name);
|
||||
protected String getCachedTexture(@Nonnull String username) {
|
||||
return texturesCache.getString(username);
|
||||
}
|
||||
}
|
||||
|
@ -39,17 +39,23 @@ class GitHubTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
gitHubService.getConnectors().forEach(GitHubConnector::download);
|
||||
connectAndCache();
|
||||
grabTextures();
|
||||
}
|
||||
|
||||
private void connectAndCache() {
|
||||
gitHubService.getConnectors().forEach(GitHubConnector::download);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will pull the skin textures for every {@link Contributor} and store
|
||||
* the {@link UUID} and received skin inside a local cache {@link File}.
|
||||
*/
|
||||
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<>();
|
||||
int requests = 0;
|
||||
|
||||
@ -73,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();
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ public class Translators {
|
||||
Contributor contributor = github.addContributor(minecraftName, "https://github.com/" + username, "translator," + lang.getLanguageId(), 0);
|
||||
|
||||
if (lock) {
|
||||
contributor.lock();
|
||||
contributor.setImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,14 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
|
||||
import me.mrCookieSlime.EmeraldEnchants.EnchantmentGuide;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
|
||||
/**
|
||||
* This is the EmeraldEnchants {@link Category}
|
||||
*
|
||||
* @deprecated Support for EmeraldEnchants is being faded out
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
class EmeraldEnchantsCategory extends FlexCategory {
|
||||
|
||||
|
@ -45,7 +45,7 @@ public enum PerformanceRating implements Predicate<Float> {
|
||||
@Override
|
||||
public boolean test(@Nullable Float value) {
|
||||
if (value == null) {
|
||||
// null will only test true for UNKNOWN
|
||||
// This way null will only test true for UNKNOWN
|
||||
return threshold < 0;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.services.profiler;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
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}.
|
||||
* It is a modification of {@link BlockPosition} to be as memory-efficient as possible.
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
this.position = new BlockPosition(l);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
ProfiledBlock(@Nonnull BlockPosition position, @Nonnull SlimefunItem item) {
|
||||
this.position = position;
|
||||
this.world = l.getWorld();
|
||||
this.position = getLocationAsLong((int) l.getX(), (int) l.getY(), (int) l.getZ());
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just a <strong>dummy</strong> constructor.
|
||||
* Please only use this for comparisons or lookups.
|
||||
*
|
||||
* @param b
|
||||
* A {@link Block}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
return item.getId();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public SlimefunAddon getAddon() {
|
||||
return item.getAddon();
|
||||
}
|
||||
@ -56,7 +144,8 @@ class ProfiledBlock {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
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;
|
||||
@ -64,7 +153,8 @@ class ProfiledBlock {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return position.hashCode();
|
||||
long hilo = world.getUID().getMostSignificantBits() ^ world.getUID().getLeastSignificantBits();
|
||||
return (int) (position ^ (position >> 32) ^ hilo ^ (hilo >> 32));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,11 +42,15 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
*/
|
||||
public class SlimefunProfiler {
|
||||
|
||||
// A minecraft server tick is 50ms and Slimefun ticks are stretched across
|
||||
// two ticks (sync and async blocks), so we use 100ms as a reference here
|
||||
/**
|
||||
* A minecraft server tick is 50ms and Slimefun ticks are stretched
|
||||
* across two ticks (sync and async blocks), so we use 100ms as a reference here
|
||||
*/
|
||||
private static final int MAX_TICK_DURATION = 100;
|
||||
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
private final SlimefunThreadFactory threadFactory = new SlimefunThreadFactory(5);
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(threadFactory.getThreadCount(), threadFactory);
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private final AtomicInteger queued = new AtomicInteger(0);
|
||||
|
||||
@ -139,8 +143,6 @@ public class SlimefunProfiler {
|
||||
return;
|
||||
}
|
||||
|
||||
// Since we got more than one Thread in our pool,
|
||||
// blocking this one is (hopefully) completely fine
|
||||
executor.execute(this::finishReport);
|
||||
}
|
||||
|
||||
@ -151,6 +153,10 @@ public class SlimefunProfiler {
|
||||
// Wait for all timing results to come in
|
||||
while (!running.get() && queued.get() > 0) {
|
||||
try {
|
||||
/**
|
||||
* Since we got more than one Thread in our pool,
|
||||
* blocking this one is (hopefully) completely fine
|
||||
*/
|
||||
Thread.sleep(1);
|
||||
iterations--;
|
||||
|
||||
@ -162,6 +168,7 @@ public class SlimefunProfiler {
|
||||
iterator.next().sendMessage("Your timings report has timed out, we were still waiting for " + queued.get() + " samples to be collected :/");
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@ -228,9 +235,10 @@ public class SlimefunProfiler {
|
||||
Map<String, Long> map = new HashMap<>();
|
||||
|
||||
for (Map.Entry<ProfiledBlock, Long> entry : timings.entrySet()) {
|
||||
String world = entry.getKey().getPosition().getWorld().getName();
|
||||
int x = entry.getKey().getPosition().getChunkX();
|
||||
int z = entry.getKey().getPosition().getChunkZ();
|
||||
ProfiledBlock block = entry.getKey();
|
||||
String world = block.getWorld().getName();
|
||||
int x = block.getChunkX();
|
||||
int z = block.getChunkZ();
|
||||
|
||||
map.merge(world + " (" + x + ',' + z + ')', entry.getValue(), Long::sum);
|
||||
}
|
||||
@ -243,9 +251,9 @@ public class SlimefunProfiler {
|
||||
int blocks = 0;
|
||||
|
||||
for (ProfiledBlock block : timings.keySet()) {
|
||||
String world = block.getPosition().getWorld().getName();
|
||||
int x = block.getPosition().getChunkX();
|
||||
int z = block.getPosition().getChunkZ();
|
||||
String world = block.getWorld().getName();
|
||||
int x = block.getChunkX();
|
||||
int z = block.getChunkZ();
|
||||
|
||||
if (chunk.equals(world + " (" + x + ',' + z + ')')) {
|
||||
blocks++;
|
||||
@ -284,6 +292,7 @@ public class SlimefunProfiler {
|
||||
protected float getPercentageOfTick() {
|
||||
float millis = totalElapsedTime / 1000000.0F;
|
||||
float fraction = (millis * 100.0F) / MAX_TICK_DURATION;
|
||||
|
||||
return Math.round((fraction * 100.0F) / 100.0F);
|
||||
}
|
||||
|
||||
@ -305,6 +314,7 @@ public class SlimefunProfiler {
|
||||
return PerformanceRating.UNKNOWN;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getTime() {
|
||||
return NumberUtils.getAsMillis(totalElapsedTime);
|
||||
}
|
||||
@ -324,6 +334,7 @@ public class SlimefunProfiler {
|
||||
*/
|
||||
public boolean hasTimings(@Nonnull Block b) {
|
||||
Validate.notNull("Cannot get timings for a null Block");
|
||||
|
||||
return timings.containsKey(new ProfiledBlock(b));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,49 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.services.profiler;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This is our {@link ThreadFactory} for the {@link SlimefunProfiler}.
|
||||
* It holds the amount of {@link Thread Threads} we dedicate towards our {@link SlimefunProfiler}
|
||||
* and provides a naming convention for our {@link Thread Threads}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see SlimefunProfiler
|
||||
*
|
||||
*/
|
||||
final class SlimefunThreadFactory implements ThreadFactory {
|
||||
|
||||
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) {
|
||||
this.threadCount = threadCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the amount of {@link Thread Threads} we dedicate towards
|
||||
* the {@link SlimefunProfiler}.
|
||||
*
|
||||
* @return The {@link Thread} count
|
||||
*/
|
||||
int getThreadCount() {
|
||||
return threadCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a new {@link Thread} for the {@link SlimefunProfiler}.
|
||||
*/
|
||||
@Override
|
||||
public Thread newThread(@Nonnull Runnable runnable) {
|
||||
return new Thread(runnable, "Slimefun Profiler");
|
||||
}
|
||||
|
||||
}
|
@ -18,7 +18,7 @@ import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.MachineTier;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.MachineType;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactivity;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.StormStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves.StormStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder;
|
||||
@ -403,7 +403,7 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack ELECTRIC_MOTOR = new SlimefunItemStack("ELECTRIC_MOTOR", HeadTexture.MOTOR, "&cElectric Motor");
|
||||
public static final SlimefunItemStack CARGO_MOTOR = new SlimefunItemStack("CARGO_MOTOR", HeadTexture.MOTOR, "&3Cargo Motor");
|
||||
public static final SlimefunItemStack SCROLL_OF_DIMENSIONAL_TELEPOSITION = new SlimefunItemStack("SCROLL_OF_DIMENSIONAL_TELEPOSITION", Material.PAPER, "&6Scroll of Dimensional Teleposition", "", "&cThis Scroll is capable of creating", "&ca temporary black Hole which pulls", "&cnearby Entities into itself and sends", "&cthem into another Dimension where", "&ceverything is turned around", "", "&fIn other words: Makes Entities turn by 180 Degrees");
|
||||
public static final SlimefunItemStack TOME_OF_KNOWLEDGE_SHARING = new SlimefunItemStack("TOME_OF_KNOWLEDGE_SHARING", Material.BOOK, "&6Tome of Knowledge Sharing", "&7Owner: &bNone", "", "&eRight Click&7 to bind this Tome to yourself", "", "", "&eRight Click&7 to obtain all Researches by", "&7the previously assigned Owner");
|
||||
public static final SlimefunItemStack TOME_OF_KNOWLEDGE_SHARING = new SlimefunItemStack("TOME_OF_KNOWLEDGE_SHARING", Material.ENCHANTED_BOOK, "&6Tome of Knowledge Sharing", "&7Owner: &bNone", "", "&eRight Click&7 to bind this Tome to yourself", "", "", "&eRight Click&7 to obtain all Researches by", "&7the previously assigned Owner");
|
||||
public static final SlimefunItemStack HARDENED_GLASS = new SlimefunItemStack("HARDENED_GLASS", Material.LIGHT_GRAY_STAINED_GLASS, "&7Hardened Glass", "", "&fWithstands Explosions");
|
||||
public static final SlimefunItemStack WITHER_PROOF_OBSIDIAN = new SlimefunItemStack("WITHER_PROOF_OBSIDIAN", Material.OBSIDIAN, "&5Wither-Proof Obsidian", "", "&fWithstands Explosions", "&fWithstands Wither Bosses");
|
||||
public static final SlimefunItemStack WITHER_PROOF_GLASS = new SlimefunItemStack("WITHER_PROOF_GLASS", Material.PURPLE_STAINED_GLASS, "&5Wither-Proof Glass", "", "&fWithstands Explosions", "&fWithstands Wither Bosses");
|
||||
|
@ -12,6 +12,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -75,9 +76,11 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksList
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GadgetsListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GrapplingHookListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.IronGolemListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemDropListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MobDropListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerProfileListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener;
|
||||
@ -85,7 +88,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBoots
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBowListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunGuideListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemConsumeListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemInteractListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
|
||||
@ -117,7 +120,6 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
|
||||
/**
|
||||
* This is the main class of Slimefun.
|
||||
* This is where all the magic starts, take a look around.
|
||||
* Feel like home.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*/
|
||||
@ -162,15 +164,36 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
private final BackpackListener backpackListener = new BackpackListener();
|
||||
private final SlimefunBowListener bowListener = new SlimefunBowListener();
|
||||
|
||||
/**
|
||||
* Our default constructor for {@link SlimefunPlugin}.
|
||||
*/
|
||||
public SlimefunPlugin() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor is invoked in Unit Test environments only.
|
||||
*
|
||||
* @param loader
|
||||
* Our {@link JavaPluginLoader}
|
||||
* @param description
|
||||
* A {@link PluginDescriptionFile}
|
||||
* @param dataFolder
|
||||
* The data folder
|
||||
* @param file
|
||||
* A {@link File} for this {@link Plugin}
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public SlimefunPlugin(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
|
||||
// This is only invoked during a Unit Test
|
||||
minecraftVersion = MinecraftVersion.UNIT_TEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the {@link Plugin} has been loaded and enabled on a {@link Server}.
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
@ -219,7 +242,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
networkSize = 1;
|
||||
}
|
||||
|
||||
networkManager = new NetworkManager(networkSize, config.getBoolean("networks.enable-visualizer"));
|
||||
networkManager = new NetworkManager(networkSize, config.getBoolean("networks.enable-visualizer"), config.getBoolean("networks.delete-excess-items"));
|
||||
|
||||
// Setting up bStats
|
||||
new Thread(metricsService::start, "Slimefun Metrics").start();
|
||||
@ -303,12 +326,83 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is our start method for a Unit Test environment.
|
||||
*/
|
||||
private void onUnitTestStart() {
|
||||
local = new LocalizationService(this, "", null);
|
||||
gpsNetwork = new GPSNetwork();
|
||||
networkManager = new NetworkManager(200, true);
|
||||
networkManager = new NetworkManager(200);
|
||||
command.register();
|
||||
registry.load(config);
|
||||
loadTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called when the {@link Plugin} gets disabled.
|
||||
* Most often it is called when the {@link Server} is shutting down or reloading.
|
||||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Slimefun never loaded successfully, so we don't even bother doing stuff here
|
||||
if (instance() == null || minecraftVersion == MinecraftVersion.UNIT_TEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel all tasks from this plugin immediately
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
|
||||
// Finishes all started movements/removals of block data
|
||||
ticker.halt();
|
||||
ticker.run();
|
||||
|
||||
// Save all Player Profiles that are still in memory
|
||||
PlayerProfile.iterator().forEachRemaining(profile -> {
|
||||
if (profile.isDirty()) {
|
||||
profile.save();
|
||||
}
|
||||
});
|
||||
|
||||
// Save all registered Worlds
|
||||
for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) {
|
||||
try {
|
||||
entry.getValue().saveAndRemove();
|
||||
} catch (Exception x) {
|
||||
getLogger().log(Level.SEVERE, x, () -> "An Error occurred while saving Slimefun-Blocks in World '" + entry.getKey() + "' for Slimefun " + getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
for (UniversalBlockMenu menu : registry.getUniversalInventories().values()) {
|
||||
menu.save();
|
||||
}
|
||||
|
||||
// Create a new backup zip
|
||||
backupService.run();
|
||||
|
||||
metricsService.cleanUp();
|
||||
|
||||
/**
|
||||
* Prevent Memory Leaks for reloads...
|
||||
* These static Maps should really be removed at some point...
|
||||
*/
|
||||
AContainer.processing = null;
|
||||
AContainer.progress = null;
|
||||
|
||||
AGenerator.processing = null;
|
||||
AGenerator.progress = null;
|
||||
|
||||
Reactor.processing = null;
|
||||
Reactor.progress = null;
|
||||
|
||||
instance = null;
|
||||
|
||||
/**
|
||||
* Close all inventories on the server to prevent item dupes
|
||||
* (Incase some idiot uses /reload)
|
||||
*/
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
p.closeInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -368,65 +462,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Slimefun never loaded successfully, so we don't even bother doing stuff here
|
||||
if (instance() == null || minecraftVersion == MinecraftVersion.UNIT_TEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel all tasks from this plugin immediately
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
|
||||
// Finishes all started movements/removals of block data
|
||||
ticker.halt();
|
||||
ticker.run();
|
||||
|
||||
// Save all Player Profiles that are still in memory
|
||||
PlayerProfile.iterator().forEachRemaining(profile -> {
|
||||
if (profile.isDirty()) {
|
||||
profile.save();
|
||||
}
|
||||
});
|
||||
|
||||
// Save all registered Worlds
|
||||
for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) {
|
||||
try {
|
||||
entry.getValue().saveAndRemove();
|
||||
} catch (Exception x) {
|
||||
getLogger().log(Level.SEVERE, x, () -> "An Error occurred while saving Slimefun-Blocks in World '" + entry.getKey() + "' for Slimefun " + getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
for (UniversalBlockMenu menu : registry.getUniversalInventories().values()) {
|
||||
menu.save();
|
||||
}
|
||||
|
||||
// Create a new backup zip
|
||||
backupService.run();
|
||||
|
||||
metricsService.cleanUp();
|
||||
|
||||
// Prevent Memory Leaks
|
||||
// These static Maps should be removed at some point...
|
||||
AContainer.processing = null;
|
||||
AContainer.progress = null;
|
||||
|
||||
AGenerator.processing = null;
|
||||
AGenerator.progress = null;
|
||||
|
||||
Reactor.processing = null;
|
||||
Reactor.progress = null;
|
||||
|
||||
instance = null;
|
||||
|
||||
// Close all inventories on the server to prevent item dupes
|
||||
// (Incase some idiot uses /reload)
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
p.closeInventory();
|
||||
}
|
||||
}
|
||||
|
||||
private void createDirectories() {
|
||||
String[] storageFolders = { "Players", "blocks", "stored-blocks", "stored-inventories", "stored-chunks", "universal-inventories", "waypoints", "block-backups" };
|
||||
String[] pluginFolders = { "scripts", "error-reports", "cache/github", "world-settings" };
|
||||
@ -450,7 +485,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
|
||||
private void registerListeners() {
|
||||
new SlimefunBootsListener(this);
|
||||
new SlimefunItemListener(this);
|
||||
new SlimefunItemInteractListener(this);
|
||||
new SlimefunItemConsumeListener(this);
|
||||
new BlockPhysicsListener(this);
|
||||
new CargoNodeListener(this);
|
||||
@ -460,6 +495,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
new BlockListener(this);
|
||||
new EnhancedFurnaceListener(this);
|
||||
new ItemPickupListener(this);
|
||||
new ItemDropListener(this);
|
||||
new DeathpointListener(this);
|
||||
new ExplosionsListener(this);
|
||||
new DebugFishListener(this);
|
||||
@ -477,6 +513,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
new GrindstoneListener(this);
|
||||
new CartographyTableListener(this);
|
||||
new HopperListener(this);
|
||||
new NetworkListener(this, networkManager);
|
||||
|
||||
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
|
||||
new BeeListener(this);
|
||||
@ -517,7 +554,10 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
private void loadTags() {
|
||||
for (SlimefunTag tag : SlimefunTag.valuesCache) {
|
||||
try {
|
||||
tag.reload();
|
||||
// Only reload "empty" (or unloaded) Tags
|
||||
if (tag.isEmpty()) {
|
||||
tag.reload();
|
||||
}
|
||||
} catch (TagMisconfigurationException e) {
|
||||
getLogger().log(Level.SEVERE, e, () -> "Failed to load Tag: " + tag.name());
|
||||
}
|
||||
|
@ -215,11 +215,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
|
||||
|
||||
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.setClickEvent(new ClickEvent(key, player ->
|
||||
SlimefunPlugin.runSync(() ->
|
||||
research.unlockFromGuide(this, player, profile, item, category, page)
|
||||
)
|
||||
));
|
||||
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> research.unlockFromGuide(this, player, profile, item, category, page))));
|
||||
|
||||
items.add(component);
|
||||
} else {
|
||||
|
@ -52,7 +52,7 @@ public class StomperBoots extends SlimefunItem {
|
||||
n.setVelocity(velocity);
|
||||
|
||||
// Check if it's not a Player or if PvP is enabled
|
||||
if (!(n instanceof Player) || (p.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, n.getLocation(), ProtectableAction.PVP))) {
|
||||
if (!(n instanceof Player) || (p.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, n.getLocation(), ProtectableAction.ATTACK_PLAYER))) {
|
||||
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, n, DamageCause.ENTITY_ATTACK, fallDamageEvent.getDamage() / 2);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
|
@ -79,21 +79,25 @@ public class BlockPlacer extends SlimefunItem {
|
||||
Material material = e.getItem().getType();
|
||||
|
||||
if (SlimefunTag.SHULKER_BOXES.isTagged(material)) {
|
||||
// Since vanilla Dispensers can already place Shulker boxes, we
|
||||
// simply fallback to the vanilla behaviour.
|
||||
/**
|
||||
* Since vanilla Dispensers can already place Shulker boxes,
|
||||
* we simply fallback to the vanilla behaviour.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
|
||||
if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) {
|
||||
// Some materials cannot be reliably placed, like beds, it would look
|
||||
// kinda wonky, so we just ignore these altogether.
|
||||
// The event has already been cancelled too, so they won't drop.
|
||||
/**
|
||||
* Some materials cannot be reliably placed, like beds,
|
||||
* it would look kinda wonky, so we just ignore these altogether.
|
||||
* The event has already been cancelled too, so they won't drop.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (facedBlock.isEmpty() && !isBlacklisted(material)) {
|
||||
if (facedBlock.isEmpty() && !isBlacklisted(material) && dispenser.getInventory().getViewers().isEmpty()) {
|
||||
SlimefunItem item = SlimefunItem.getByItem(e.getItem());
|
||||
|
||||
if (item != null) {
|
||||
@ -123,9 +127,11 @@ public class BlockPlacer extends SlimefunItem {
|
||||
String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner");
|
||||
|
||||
if (owner == null) {
|
||||
// If no owner was set, then we will fallback to the previous behaviour:
|
||||
// Allowing block placers to bypass protection, newly placed Block placers
|
||||
// will respect protection plugins.
|
||||
/**
|
||||
* If no owner was set, then we will fallback to the previous behaviour:
|
||||
* Allowing block placers to bypass protection, newly placed Block placers
|
||||
* will respect protection plugins.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class Composter extends SimpleSlimefunItem<BlockUseHandler> implements Re
|
||||
Player p = e.getPlayer();
|
||||
Block b = block.get();
|
||||
|
||||
if (p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES)) {
|
||||
if (p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK)) {
|
||||
ItemStack input = e.getItem();
|
||||
ItemStack output = getOutput(p, input);
|
||||
|
||||
|
@ -95,7 +95,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
|
||||
Player p = e.getPlayer();
|
||||
Block b = optional.get();
|
||||
|
||||
if (p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES)) {
|
||||
if (p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK)) {
|
||||
ItemStack input = e.getItem();
|
||||
Block block = b.getRelative(BlockFace.UP);
|
||||
|
||||
|
@ -65,7 +65,7 @@ abstract class AbstractCargoNode extends SlimefunItem {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.cargo.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.cargo.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public class ReactorAccessPort extends SlimefunItem {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +80,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,7 +183,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
|
||||
return;
|
||||
}
|
||||
|
||||
if (lifetime % 60 == 0 && getCharge(b.getLocation()) >= getEnergyConsumption()) {
|
||||
if (lifetime % 60 == 0 && getCharge(b.getLocation(), data) >= getEnergyConsumption()) {
|
||||
BlockMenu menu = BlockStorage.getInventory(b);
|
||||
|
||||
boolean hasBody = findResource(menu, getBody(), bodySlots);
|
||||
|
@ -86,7 +86,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,7 +53,7 @@ public class ElectricSmeltery extends AbstractVanillaBlockInventory {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,10 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
@ -13,12 +17,12 @@ import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
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.networks.energy.EnergyNetComponentType;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
||||
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.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
|
||||
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[] 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) {
|
||||
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) {
|
||||
preset.addItem(i, new CustomItem(Material.GRAY_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
|
||||
preset.addItem(i, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
|
||||
}
|
||||
|
||||
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) {
|
||||
preset.addItem(i, new CustomItem(Material.ORANGE_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
|
||||
preset.addItem(i, ChestMenuUtils.getOutputSlotTexture(), ChestMenuUtils.getEmptyClickHandler());
|
||||
}
|
||||
|
||||
for (int i : getOutputSlots()) {
|
||||
@ -114,14 +121,14 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
|
||||
return 512;
|
||||
}
|
||||
|
||||
protected void tick(Block b) {
|
||||
protected void tick(@Nonnull Block b) {
|
||||
Block fluid = b.getRelative(BlockFace.DOWN);
|
||||
|
||||
if (fluid.isLiquid() && getCharge(b.getLocation()) >= ENERGY_CONSUMPTION) {
|
||||
BlockMenu menu = BlockStorage.getInventory(b);
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
// 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
|
||||
// ourselves all of that computing...
|
||||
/**
|
||||
* 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 ourselves all of that computing...
|
||||
*/
|
||||
if (isSource(fluid)) {
|
||||
return fluid;
|
||||
}
|
||||
@ -162,10 +172,12 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ItemStack getFilledBucket(Block fluid) {
|
||||
@Nonnull
|
||||
private ItemStack getFilledBucket(@Nonnull Block fluid) {
|
||||
if (fluid.getType() == Material.LAVA) {
|
||||
return new ItemStack(Material.LAVA_BUCKET);
|
||||
} 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}.
|
||||
*/
|
||||
private boolean isSource(Block block) {
|
||||
private boolean isSource(@Nonnull Block block) {
|
||||
if (block.isLiquid()) {
|
||||
BlockData data = block.getBlockData();
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class HeatedPressureChamber extends AContainer {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +98,7 @@ public abstract class Reactor extends AbstractEnergyProvider {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,6 +45,6 @@ public class GEOScanner extends SimpleSlimefunItem<BlockUseHandler> {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean hasAccess(Player p, Location l) {
|
||||
return p.hasPermission("slimefun.gps.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, l, ProtectableAction.ACCESS_INVENTORIES));
|
||||
return p.hasPermission("slimefun.gps.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, l, ProtectableAction.INTERACT_BLOCK));
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class OilPump extends AContainer implements RecipeDisplayItem {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
if (!(p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES))) {
|
||||
if (!(p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -36,34 +36,47 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link ElevatorPlate} is a quick way of teleportation.
|
||||
* You can place multiple {@link ElevatorPlate ElevatorPlates} along the y axis
|
||||
* to teleport between them.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
|
||||
|
||||
/**
|
||||
* This is our key for storing the floor name.
|
||||
*/
|
||||
private static final String DATA_KEY = "floor";
|
||||
|
||||
/**
|
||||
* This is our {@link Set} of currently teleporting {@link Player Players}.
|
||||
* It is used to prevent them from triggering the {@link ElevatorPlate} they land on.
|
||||
*/
|
||||
private final Set<UUID> users = new HashSet<>();
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public ElevatorPlate(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
|
||||
super(category, item, recipeType, recipe, recipeOutput);
|
||||
|
||||
addItemHandler(onPlace());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private BlockPlaceHandler onPlace() {
|
||||
return new BlockPlaceHandler(false) {
|
||||
|
||||
@Override
|
||||
public void onPlayerPlace(BlockPlaceEvent e) {
|
||||
Block b = e.getBlock();
|
||||
BlockStorage.addBlockInfo(b, DATA_KEY, "&rFloor #0");
|
||||
BlockStorage.addBlockInfo(b, DATA_KEY, ChatColor.WHITE + "Floor #0");
|
||||
BlockStorage.addBlockInfo(b, "owner", e.getPlayer().getUniqueId().toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Set<UUID> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockUseHandler getItemHandler() {
|
||||
return e -> {
|
||||
@ -172,7 +185,7 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
|
||||
public void openEditor(Player p, Block b) {
|
||||
ChestMenu menu = new ChestMenu("Elevator Settings");
|
||||
|
||||
menu.addItem(4, new CustomItem(Material.NAME_TAG, "&7Floor Name &e(Click to edit)", "", "&r" + ChatColors.color(BlockStorage.getLocationInfo(b.getLocation(), DATA_KEY))));
|
||||
menu.addItem(4, new CustomItem(Material.NAME_TAG, "&7Floor Name &e(Click to edit)", "", ChatColor.WHITE + ChatColors.color(BlockStorage.getLocationInfo(b.getLocation(), DATA_KEY))));
|
||||
menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
|
||||
pl.closeInventory();
|
||||
pl.sendMessage("");
|
||||
|
@ -43,6 +43,6 @@ public class GPSControlPanel extends SimpleSlimefunItem<BlockUseHandler> {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean hasAccess(Player p, Location l) {
|
||||
return p.hasPermission("slimefun.gps.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, l, ProtectableAction.ACCESS_INVENTORIES));
|
||||
return p.hasPermission("slimefun.gps.bypass") || (SlimefunPlugin.getProtectionManager().hasPermission(p, l, ProtectableAction.INTERACT_BLOCK));
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public abstract class GPSTransmitter extends SimpleSlimefunItem<BlockTicker> imp
|
||||
|
||||
@Override
|
||||
public void tick(Block b, SlimefunItem item, Config data) {
|
||||
int charge = getCharge(b.getLocation());
|
||||
int charge = getCharge(b.getLocation(), data);
|
||||
UUID owner = UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"));
|
||||
|
||||
if (charge >= getEnergyConsumption()) {
|
||||
|
@ -1,10 +1,14 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.type.Hopper;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -22,15 +26,27 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link InfusedHopper} is a special kind of {@link Hopper} which teleports any
|
||||
* neaby {@link Item} to itself.
|
||||
* The radius can be configured in the config.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see InfusedMagnet
|
||||
*
|
||||
*/
|
||||
public class InfusedHopper extends SimpleSlimefunItem<BlockTicker> {
|
||||
|
||||
private final ItemSetting<Boolean> silent = new ItemSetting<>("silent", false);
|
||||
private final ItemSetting<Boolean> toggleable = new ItemSetting<>("toggleable-with-redstone", false);
|
||||
private final ItemSetting<Double> radius = new DoubleRangeSetting("radius", 0.1, 3.5, Double.MAX_VALUE);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public InfusedHopper(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemSetting(silent, radius);
|
||||
addItemSetting(silent, radius, toggleable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,17 +61,35 @@ public class InfusedHopper extends SimpleSlimefunItem<BlockTicker> {
|
||||
return;
|
||||
}
|
||||
|
||||
Location l = b.getLocation().add(0.5, 1.2, 0.5);
|
||||
boolean sound = false;
|
||||
double range = radius.getValue();
|
||||
// Check if this was enabled in the config
|
||||
if (toggleable.getValue()) {
|
||||
Hopper hopper = (Hopper) b.getBlockData();
|
||||
|
||||
/**
|
||||
* If the Hopper was disabled by a redstone signal,
|
||||
* we just don't do anything.
|
||||
*/
|
||||
if (!hopper.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Location l = b.getLocation().add(0.5, 1.2, 0.5);
|
||||
double range = radius.getValue();
|
||||
boolean playSound = false;
|
||||
|
||||
// Check for any nearby Items that can be picked up
|
||||
for (Entity item : b.getWorld().getNearbyEntities(l, range, range, range, n -> isValidItem(l, n))) {
|
||||
item.setVelocity(new Vector(0, 0.1, 0));
|
||||
item.teleport(l);
|
||||
sound = true;
|
||||
playSound = true;
|
||||
}
|
||||
|
||||
if (sound && !silent.getValue().booleanValue()) {
|
||||
/**
|
||||
* Play a sound if at least one item was teleported and
|
||||
* the "silent" setting is set to false.
|
||||
*/
|
||||
if (playSound && !silent.getValue().booleanValue()) {
|
||||
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.BLOCKS, 1F, 2F);
|
||||
}
|
||||
}
|
||||
@ -67,7 +101,7 @@ public class InfusedHopper extends SimpleSlimefunItem<BlockTicker> {
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isValidItem(Location l, Entity entity) {
|
||||
private boolean isValidItem(@Nonnull Location l, @Nonnull Entity entity) {
|
||||
if (entity instanceof Item && entity.isValid()) {
|
||||
Item item = (Item) entity;
|
||||
return !SlimefunUtils.hasNoPickupFlag(item) && item.getLocation().distanceSquared(l) > 0.25;
|
@ -1,6 +1,7 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@ -14,6 +15,7 @@ import org.bukkit.entity.ZombieVillager;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
|
||||
@ -40,6 +42,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
*/
|
||||
public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler> implements NotPlaceable {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public MagicalZombiePills(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
|
||||
super(category, item, recipeType, recipe, recipeOutput);
|
||||
|
||||
@ -50,6 +53,12 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
|
||||
public EntityInteractHandler getItemHandler() {
|
||||
return (e, item, offhand) -> {
|
||||
Entity entity = e.getRightClicked();
|
||||
|
||||
if (e.isCancelled() || !SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), entity.getLocation(), ProtectableAction.INTERACT_ENTITY)) {
|
||||
// They don't have permission to use it in this area
|
||||
return;
|
||||
}
|
||||
|
||||
Player p = e.getPlayer();
|
||||
|
||||
if (entity instanceof ZombieVillager) {
|
||||
|
@ -4,6 +4,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Soulbound;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes.SoulboundRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
@ -14,6 +14,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.Soulbound;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemDropHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.SoulboundItem;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@ -10,7 +10,9 @@ import org.bukkit.entity.Villager.Profession;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
@ -33,6 +35,11 @@ public class VillagerRune extends SimpleSlimefunItem<EntityInteractHandler> {
|
||||
@Override
|
||||
public EntityInteractHandler getItemHandler() {
|
||||
return (e, item, offhand) -> {
|
||||
if (e.isCancelled() || !SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), e.getRightClicked().getLocation(), ProtectableAction.INTERACT_ENTITY)) {
|
||||
// They don't have permission to use it in this area
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getRightClicked() instanceof Villager) {
|
||||
Villager v = (Villager) e.getRightClicked();
|
||||
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package holds any implementation of {@link me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem}
|
||||
* that is an ancient rune with functionality.
|
||||
*/
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes;
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -72,7 +72,7 @@ public class StormStaff extends SimpleSlimefunItem<ItemUseHandler> {
|
||||
Location loc = p.getTargetBlock(null, 30).getLocation();
|
||||
|
||||
if (loc.getWorld() != null && loc.getChunk().isLoaded()) {
|
||||
if (loc.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, loc, ProtectableAction.PVP)) {
|
||||
if (loc.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, loc, ProtectableAction.ATTACK_PLAYER)) {
|
||||
e.cancel();
|
||||
useItem(p, item, loc);
|
||||
} else {
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
@ -8,6 +8,8 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
@ -15,10 +17,20 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link WindStaff} is a powerful staff which launches the {@link Player} forward when right clicked.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class WindStaff extends SimpleSlimefunItem<ItemUseHandler> {
|
||||
|
||||
private final ItemSetting<Integer> multiplier = new IntRangeSetting("power", 1, 4, Integer.MAX_VALUE);
|
||||
|
||||
public WindStaff(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemSetting(multiplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -27,6 +39,7 @@ public class WindStaff extends SimpleSlimefunItem<ItemUseHandler> {
|
||||
Player p = e.getPlayer();
|
||||
|
||||
if (p.getFoodLevel() >= 2) {
|
||||
// The isItem() check is here to prevent the MultiTool from consuming hunger
|
||||
if (isItem(e.getItem()) && p.getGameMode() != GameMode.CREATIVE) {
|
||||
FoodLevelChangeEvent event = new FoodLevelChangeEvent(p, p.getFoodLevel() - 2);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
@ -36,7 +49,7 @@ public class WindStaff extends SimpleSlimefunItem<ItemUseHandler> {
|
||||
}
|
||||
}
|
||||
|
||||
p.setVelocity(p.getEyeLocation().getDirection().multiply(4));
|
||||
p.setVelocity(p.getEyeLocation().getDirection().multiply(multiplier.getValue()));
|
||||
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_TNT_PRIMED, 1, 1);
|
||||
p.getWorld().playEffect(p.getLocation(), Effect.SMOKE, 1);
|
||||
p.setFallDistance(0F);
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package holds any implementation of {@link me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem} that is
|
||||
* considered a "Magical Staff".
|
||||
*/
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves;
|
@ -57,6 +57,9 @@ public class MagicianTalisman extends Talisman {
|
||||
*
|
||||
* @param item
|
||||
* The {@link ItemStack} to find an {@link Enchantment} for
|
||||
* @param existingEnchantments
|
||||
* A {@link Set} containing the {@link Enchantment Enchantments} that currently exist on the
|
||||
* {@link ItemStack}
|
||||
*
|
||||
* @return An applicable {@link TalismanEnchantment} or null
|
||||
*/
|
||||
|
@ -21,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.PiglinBarterDrop;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.VillagerRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes.VillagerRune;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
|
@ -2,9 +2,13 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
@ -33,6 +37,7 @@ public class ExplosiveBow extends SlimefunBow {
|
||||
|
||||
private final ItemSetting<Integer> range = new IntRangeSetting("explosion-range", 1, 3, Integer.MAX_VALUE);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public ExplosiveBow(Category category, SlimefunItemStack item, ItemStack[] recipe) {
|
||||
super(category, item, recipe);
|
||||
|
||||
@ -44,8 +49,9 @@ public class ExplosiveBow extends SlimefunBow {
|
||||
return (e, target) -> {
|
||||
target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation(), 1);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1, 1);
|
||||
int radius = range.getValue();
|
||||
|
||||
Collection<Entity> entites = target.getWorld().getNearbyEntities(target.getLocation(), range.getValue(), range.getValue(), range.getValue(), entity -> entity instanceof LivingEntity && entity.isValid());
|
||||
Collection<Entity> entites = target.getWorld().getNearbyEntities(target.getLocation(), radius, radius, radius, this::canDamage);
|
||||
for (Entity nearby : entites) {
|
||||
LivingEntity entity = (LivingEntity) nearby;
|
||||
|
||||
@ -71,6 +77,10 @@ public class ExplosiveBow extends SlimefunBow {
|
||||
};
|
||||
}
|
||||
|
||||
private boolean canDamage(@Nonnull Entity n) {
|
||||
return n instanceof LivingEntity && !(n instanceof ArmorStand) && n.isValid();
|
||||
}
|
||||
|
||||
private double calculateDamage(double distanceSquared, double originalDamage) {
|
||||
if (distanceSquared <= 0.05) {
|
||||
return originalDamage;
|
||||
|
@ -2,6 +2,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Location;
|
||||
@ -42,6 +45,7 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
|
||||
private static final float DAMAGE = 6;
|
||||
private static final int RANGE = 10;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public SeismicAxe(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
}
|
||||
@ -96,7 +100,8 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
|
||||
}
|
||||
}
|
||||
|
||||
private Block findGround(Block b) {
|
||||
@Nonnull
|
||||
private Block findGround(@Nonnull Block b) {
|
||||
if (b.getType() == Material.AIR) {
|
||||
for (int y = 0; y < b.getY(); y++) {
|
||||
Block block = b.getRelative(0, -y, 0);
|
||||
|
@ -3,8 +3,11 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Skeleton;
|
||||
import org.bukkit.entity.WitherSkeleton;
|
||||
@ -21,6 +24,17 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link SwordOfBeheading} is a special kind of sword which allows you to obtain
|
||||
* {@link Zombie}, {@link Skeleton} and {@link Creeper} skulls when killing the respective {@link Monster}.
|
||||
* Additionally, you can also obtain the head of a {@link Player} by killing them too.
|
||||
* This sword also allows you to have a higher chance of getting the skull of a {@link WitherSkeleton} too.
|
||||
*
|
||||
* All chances are managed by an {@link ItemSetting} and can be configured.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
|
||||
|
||||
private final ItemSetting<Integer> chanceZombie = new IntRangeSetting("chance.ZOMBIE", 0, 40, 100);
|
||||
@ -29,6 +43,7 @@ public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
|
||||
private final ItemSetting<Integer> chanceCreeper = new IntRangeSetting("chance.CREEPER", 0, 40, 100);
|
||||
private final ItemSetting<Integer> chancePlayer = new IntRangeSetting("chance.PLAYER", 0, 70, 100);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public SwordOfBeheading(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
@ -40,29 +55,40 @@ public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
|
||||
return (e, entity, killer, item) -> {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
|
||||
if (e.getEntity() instanceof Zombie) {
|
||||
switch (e.getEntityType()) {
|
||||
case ZOMBIE:
|
||||
if (random.nextInt(100) < chanceZombie.getValue()) {
|
||||
e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD));
|
||||
}
|
||||
} else if (e.getEntity() instanceof WitherSkeleton) {
|
||||
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
|
||||
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
|
||||
}
|
||||
} else if (e.getEntity() instanceof Skeleton) {
|
||||
break;
|
||||
case SKELETON:
|
||||
if (random.nextInt(100) < chanceSkeleton.getValue()) {
|
||||
e.getDrops().add(new ItemStack(Material.SKELETON_SKULL));
|
||||
}
|
||||
} else if (e.getEntity() instanceof Creeper) {
|
||||
break;
|
||||
case CREEPER:
|
||||
if (random.nextInt(100) < chanceCreeper.getValue()) {
|
||||
e.getDrops().add(new ItemStack(Material.CREEPER_HEAD));
|
||||
}
|
||||
} else if (e.getEntity() instanceof Player && random.nextInt(100) < chancePlayer.getValue()) {
|
||||
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
|
||||
ItemMeta meta = skull.getItemMeta();
|
||||
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
|
||||
skull.setItemMeta(meta);
|
||||
break;
|
||||
case WITHER_SKELETON:
|
||||
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
|
||||
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
|
||||
}
|
||||
break;
|
||||
case PLAYER:
|
||||
if (random.nextInt(100) < chancePlayer.getValue()) {
|
||||
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
|
||||
|
||||
e.getDrops().add(skull);
|
||||
ItemMeta meta = skull.getItemMeta();
|
||||
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
|
||||
skull.setItemMeta(meta);
|
||||
|
||||
e.getDrops().add(skull);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
@ -28,6 +31,7 @@ public class VampireBlade extends SlimefunItem {
|
||||
private static final double HEALING_AMOUNT = 4.0;
|
||||
private final ItemSetting<Integer> chance = new IntRangeSetting("chance", 0, 45, 100);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public VampireBlade(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
@ -43,7 +47,7 @@ public class VampireBlade extends SlimefunItem {
|
||||
return chance.getValue();
|
||||
}
|
||||
|
||||
public void heal(Player p) {
|
||||
public void heal(@Nonnull Player p) {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 0.7F, 0.7F);
|
||||
double health = p.getHealth() + HEALING_AMOUNT;
|
||||
double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
||||
|
@ -128,7 +128,7 @@ public class AncientAltarListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SlimefunPlugin.getProtectionManager().hasPermission(p, pedestal, ProtectableAction.ACCESS_INVENTORIES)) {
|
||||
if (!SlimefunPlugin.getProtectionManager().hasPermission(p, pedestal, ProtectableAction.INTERACT_BLOCK)) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
|
||||
return;
|
||||
}
|
||||
@ -162,7 +162,7 @@ public class AncientAltarListener implements Listener {
|
||||
}
|
||||
|
||||
private void useAltar(@Nonnull Block altar, @Nonnull Player p) {
|
||||
if (!SlimefunPlugin.getProtectionManager().hasPermission(p, altar, ProtectableAction.ACCESS_INVENTORIES)) {
|
||||
if (!SlimefunPlugin.getProtectionManager().hasPermission(p, altar, ProtectableAction.INTERACT_BLOCK)) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
|
||||
return;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
@ -152,6 +153,9 @@ public class BlockListener implements Listener {
|
||||
if (!drops.isEmpty()) {
|
||||
e.getBlock().setType(Material.AIR);
|
||||
|
||||
// Notify plugins like CoreProtect
|
||||
SlimefunPlugin.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), ProtectableAction.BREAK_BLOCK);
|
||||
|
||||
if (e.isDropItems()) {
|
||||
for (ItemStack drop : drops) {
|
||||
if (drop != null && drop.getType() != Material.AIR) {
|
||||
|
@ -10,15 +10,17 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
|
||||
/**
|
||||
* The Listener class responsible for a {@link Player} interacting with an {@link Entity}.
|
||||
* The {@link Listener} responsible for a {@link Player} interacting with an {@link Entity}.
|
||||
*
|
||||
* @author Linox
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see EntityInteractHandler
|
||||
*
|
||||
@ -45,8 +47,17 @@ public class EntityInteractionListener implements Listener {
|
||||
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);
|
||||
|
||||
if (sfItem != null && Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) {
|
||||
sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
|
||||
if (sfItem != null) {
|
||||
if (Slimefun.hasUnlocked(e.getPlayer(), sfItem, true)) {
|
||||
sfItem.callItemHandler(EntityInteractHandler.class, handler -> handler.onInteract(e, itemStack, e.getHand() == EquipmentSlot.OFF_HAND));
|
||||
} else if (sfItem.getState() != ItemState.VANILLA_FALLBACK) {
|
||||
/**
|
||||
* If an Item is disabled, we don't want it to fallback to the vanilla behaviour
|
||||
* unless it is a Vanilla Item of course.
|
||||
* Related to Issue #2446
|
||||
*/
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,13 +4,22 @@ import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
|
||||
/**
|
||||
* This {@link Listener} makes sure that any {@link Firework} caused by a {@link Player}
|
||||
* unlocking a {@link Research} does not cause damage to be dealt.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class FireworksListener implements Listener {
|
||||
|
||||
public FireworksListener(@Nonnull SlimefunPlugin plugin) {
|
||||
@ -23,6 +32,12 @@ public class FireworksListener implements Listener {
|
||||
Firework firework = (Firework) e.getDamager();
|
||||
FireworkMeta meta = firework.getFireworkMeta();
|
||||
|
||||
/**
|
||||
* We could use Peristent Data for this in the future, but ItemMeta display names
|
||||
* work pretty reliably too and they don't cause any memory leaks like metadata.
|
||||
*
|
||||
* Entity display names do not work either as Firework cannot be named.
|
||||
*/
|
||||
if (meta.hasDisplayName() && meta.getDisplayName().equals(ChatColor.GREEN + "Slimefun Research")) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
/**
|
||||
* This {@link Listener} makes sure that an {@link IronGolem} cannot be healed with
|
||||
* a {@link SlimefunItem}.
|
||||
* This fixes Issue 1332.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
@ -42,6 +41,7 @@ public class IronGolemListener implements Listener {
|
||||
item = inv.getItemInOffHand();
|
||||
}
|
||||
|
||||
// Check if the Golem was clicked using an Iron Ingot
|
||||
if (item != null && item.getType() == Material.IRON_INGOT) {
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
|
||||
@ -49,8 +49,10 @@ public class IronGolemListener implements Listener {
|
||||
e.setCancelled(true);
|
||||
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.no-iron-golem-heal");
|
||||
|
||||
// This is just there to update the Inventory...
|
||||
// Somehow cancelling it isn't enough.
|
||||
/**
|
||||
* This is just there to update the Inventory...
|
||||
* Somehow cancelling it isn't enough.
|
||||
*/
|
||||
if (e.getHand() == EquipmentSlot.HAND) {
|
||||
inv.setItemInMainHand(item);
|
||||
} else if (e.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
@ -61,4 +63,11 @@ public class IronGolemListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// @EventHandler
|
||||
// public void onIronGolemSpawn(PLEASE_GIMME_AN_EVENT e) {
|
||||
// if (e.getBlock().getType() == Material.IRON_BLOCK) {
|
||||
// e.setCancelled(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemDropHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
|
||||
|
||||
/**
|
||||
* Listens to the {@link PlayerDropItemEvent} to call any {@link ItemDropHandler}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see ItemDropHandler
|
||||
*/
|
||||
public class ItemDropListener implements Listener {
|
||||
|
||||
public ItemDropListener(@Nonnull SlimefunPlugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDrop(PlayerDropItemEvent e) {
|
||||
for (ItemHandler handler : SlimefunItem.getPublicItemHandlers(ItemDropHandler.class)) {
|
||||
if (((ItemDropHandler) handler).onItemDrop(e, e.getPlayer(), e.getItemDrop())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,56 +7,78 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event.Result;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemDropHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
|
||||
|
||||
public class SlimefunItemListener implements Listener {
|
||||
/**
|
||||
* This {@link Listener} listens to the {@link PlayerInteractEvent}.
|
||||
* It is also responsible for calling our {@link PlayerRightClickEvent} and triggering any
|
||||
* {@link ItemUseHandler} or {@link BlockUseHandler} for the clicked {@link ItemStack} or {@link Block}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
* @author Liruxo
|
||||
*
|
||||
* @see PlayerRightClickEvent
|
||||
* @see ItemUseHandler
|
||||
* @see BlockUseHandler
|
||||
*
|
||||
*/
|
||||
public class SlimefunItemInteractListener implements Listener {
|
||||
|
||||
public SlimefunItemListener(@Nonnull SlimefunPlugin plugin) {
|
||||
public SlimefunItemInteractListener(@Nonnull SlimefunPlugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onRightClick(PlayerInteractEvent e) {
|
||||
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
// Exclude the Debug Fish here because it is handled in a seperate Listener
|
||||
if (SlimefunUtils.isItemSimilar(e.getItem(), SlimefunItems.DEBUG_FISH, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire our custom Event
|
||||
PlayerRightClickEvent event = new PlayerRightClickEvent(e);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
boolean itemUsed = e.getHand() == EquipmentSlot.OFF_HAND;
|
||||
|
||||
// Only handle the Item if it hasn't been denied
|
||||
if (event.useItem() != Result.DENY) {
|
||||
rightClickItem(e, event, itemUsed);
|
||||
}
|
||||
|
||||
if (!itemUsed && event.useBlock() != Result.DENY && !rightClickBlock(e, event)) {
|
||||
if (!itemUsed && event.useBlock() != Result.DENY && !rightClickBlock(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the original Event was not denied but the custom one was,
|
||||
* we also want to deny the original one.
|
||||
* This only applies for non-denied events because we do not want to
|
||||
* override any protective checks.
|
||||
*/
|
||||
|
||||
if (e.useInteractedBlock() != Result.DENY) {
|
||||
e.setUseInteractedBlock(event.useBlock());
|
||||
}
|
||||
@ -67,7 +89,6 @@ public class SlimefunItemListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean rightClickItem(PlayerInteractEvent e, PlayerRightClickEvent event, boolean defaultValue) {
|
||||
Optional<SlimefunItem> optional = event.getSlimefunItem();
|
||||
@ -84,12 +105,12 @@ public class SlimefunItemListener implements Listener {
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean rightClickBlock(PlayerInteractEvent e, PlayerRightClickEvent event) {
|
||||
private boolean rightClickBlock(PlayerRightClickEvent event) {
|
||||
Optional<SlimefunItem> optional = event.getSlimefunBlock();
|
||||
|
||||
if (optional.isPresent()) {
|
||||
if (!Slimefun.hasUnlocked(e.getPlayer(), optional.get(), true)) {
|
||||
e.setCancelled(true);
|
||||
if (!Slimefun.hasUnlocked(event.getPlayer(), optional.get(), true)) {
|
||||
event.getInteractEvent().setCancelled(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -97,10 +118,10 @@ public class SlimefunItemListener implements Listener {
|
||||
|
||||
if (!interactable) {
|
||||
String id = optional.get().getId();
|
||||
Player p = e.getPlayer();
|
||||
Player p = event.getPlayer();
|
||||
|
||||
if (BlockMenuPreset.isInventory(id)) {
|
||||
openInventory(p, id, e, event);
|
||||
openInventory(p, id, event.getInteractEvent().getClickedBlock(), event);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -110,22 +131,22 @@ public class SlimefunItemListener implements Listener {
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private void openInventory(Player p, String id, PlayerInteractEvent e, PlayerRightClickEvent event) {
|
||||
if (!p.isSneaking() || Material.AIR == event.getItem().getType()) {
|
||||
e.setCancelled(true);
|
||||
private void openInventory(Player p, String id, Block clickedBlock, PlayerRightClickEvent event) {
|
||||
if (!p.isSneaking() || event.getItem().getType() == Material.AIR) {
|
||||
event.getInteractEvent().setCancelled(true);
|
||||
|
||||
if (BlockStorage.hasUniversalInventory(id)) {
|
||||
UniversalBlockMenu menu = BlockStorage.getUniversalInventory(id);
|
||||
|
||||
if (menu.canOpen(e.getClickedBlock(), p)) {
|
||||
if (menu.canOpen(clickedBlock, p)) {
|
||||
menu.open(p);
|
||||
} else {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
|
||||
}
|
||||
} else if (BlockStorage.getStorage(e.getClickedBlock().getWorld()).hasInventory(e.getClickedBlock().getLocation())) {
|
||||
BlockMenu menu = BlockStorage.getInventory(e.getClickedBlock().getLocation());
|
||||
} else if (BlockStorage.getStorage(clickedBlock.getWorld()).hasInventory(clickedBlock.getLocation())) {
|
||||
BlockMenu menu = BlockStorage.getInventory(clickedBlock.getLocation());
|
||||
|
||||
if (menu.canOpen(e.getClickedBlock(), p)) {
|
||||
if (menu.canOpen(clickedBlock, p)) {
|
||||
menu.open(p);
|
||||
} else {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "inventory.no-access", true);
|
||||
@ -134,13 +155,4 @@ public class SlimefunItemListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDrop(PlayerDropItemEvent e) {
|
||||
for (ItemHandler handler : SlimefunItem.getPublicItemHandlers(ItemDropHandler.class)) {
|
||||
if (((ItemDropHandler) handler).onItemDrop(e, e.getPlayer(), e.getItemDrop())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -35,6 +35,7 @@ public class TeleporterListener implements Listener {
|
||||
}
|
||||
|
||||
String id = BlockStorage.checkID(e.getClickedBlock());
|
||||
|
||||
if (id == null) {
|
||||
return;
|
||||
}
|
||||
@ -55,7 +56,13 @@ public class TeleporterListener implements Listener {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
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) {
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
@ -21,6 +22,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
*
|
||||
* @author VoidAngel
|
||||
* @author SoSeDiK
|
||||
* @author CURVX
|
||||
*
|
||||
*/
|
||||
public class BrewingStandListener implements SlimefunCraftingListener {
|
||||
@ -52,4 +54,10 @@ public class BrewingStandListener implements SlimefunCraftingListener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void hopperOnBrew(InventoryMoveItemEvent e) {
|
||||
if (e.getDestination().getType() == InventoryType.BREWING && isUnallowed(e.getItem())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,8 @@ interface SlimefunCraftingListener extends Listener {
|
||||
} else {
|
||||
SlimefunItem sfItem1 = SlimefunItem.getByItem(item1);
|
||||
SlimefunItem sfItem2 = SlimefunItem.getByItem(item2);
|
||||
|
||||
if (isUnallowed(sfItem1) || isUnallowed(sfItem2)) {
|
||||
return true;
|
||||
}
|
||||
return isUnallowed(sfItem1) || isUnallowed(sfItem2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isUnallowed(@Nullable ItemStack item) {
|
||||
@ -32,7 +27,7 @@ interface SlimefunCraftingListener extends Listener {
|
||||
}
|
||||
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
return !(sfItem instanceof VanillaItem) && !sfItem.isDisabled();
|
||||
return isUnallowed(sfItem);
|
||||
}
|
||||
|
||||
default boolean isUnallowed(@Nullable SlimefunItem item) {
|
||||
|
@ -51,7 +51,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.Crucible;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.EnhancedFurnace;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.HardenedGlass;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.HologramProjector;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.InfusedHopper;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RainbowBlock;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RepairedSpawner;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock;
|
||||
@ -128,20 +127,21 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSTransmitte
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.PersonalActivationPlate;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.Teleporter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.TeleporterPylon;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.EnchantmentRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfernalBonemeal;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedHopper;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedMagnet;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.KnowledgeFlask;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.KnowledgeTome;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.MagicEyeOfEnder;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.MagicalZombiePills;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.SoulboundItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.SoulboundRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.StormStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.TelepositionScroll;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.VillagerRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.WaterStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.WindStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes.EnchantmentRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes.SoulboundRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.runes.VillagerRune;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves.StormStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves.WaterStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.staves.WindStaff;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.medical.Bandage;
|
||||
|
@ -7,12 +7,12 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
|
||||
abstract class PlayerTask implements Runnable {
|
||||
abstract class AbstractPlayerTask implements Runnable {
|
||||
|
||||
protected int id;
|
||||
protected Player p;
|
||||
|
||||
PlayerTask(@Nonnull Player p) {
|
||||
AbstractPlayerTask(@Nonnull Player 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.
|
||||
* It will also cancel this {@link PlayerTask} if it became invalid.
|
||||
* This method checks if this {@link AbstractPlayerTask} should be continued or cancelled.
|
||||
* 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() {
|
||||
if (!p.isOnline() || !p.isValid() || p.isDead() || !p.isSneaking()) {
|
@ -26,8 +26,10 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.SolarHelmet;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link ArmorTask} is responsible for handling {@link PotionEffect PotionEffects} for
|
||||
@ -167,8 +169,16 @@ public class ArmorTask implements Runnable {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (SlimefunItem radioactiveItem : SlimefunPlugin.getRegistry().getRadioactiveItems()) {
|
||||
if (radioactiveItem.isItem(item) && Slimefun.isEnabled(p, radioactiveItem, true)) {
|
||||
Set<SlimefunItem> radioactiveItems = SlimefunPlugin.getRegistry().getRadioactiveItems();
|
||||
ItemStack subject = item;
|
||||
|
||||
if (!(item instanceof SlimefunItemStack) && radioactiveItems.size() > 1) {
|
||||
// Performance optimization to reduce ItemMeta calls
|
||||
subject = new ItemStackWrapper(item);
|
||||
}
|
||||
|
||||
for (SlimefunItem radioactiveItem : radioactiveItems) {
|
||||
if (radioactiveItem.isItem(subject) && Slimefun.isEnabled(p, radioactiveItem, true)) {
|
||||
// If the item is enabled in the world, then make radioactivity do its job
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.radiation");
|
||||
|
||||
|
@ -0,0 +1,71 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.tasks;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
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;
|
||||
|
||||
/**
|
||||
* This task is run whenever a {@link Capacitor} needs to update their texture.
|
||||
* <strong>This must be executed on the main {@link Server} {@link Thread}!</strong>
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class CapacitorTextureUpdateTask implements Runnable {
|
||||
|
||||
/**
|
||||
* The {@link Location} of the {@link Capacitor}.
|
||||
*/
|
||||
private final Location l;
|
||||
|
||||
/**
|
||||
* The level of how "full" this {@link Capacitor} is.
|
||||
* From 0.0 to 1.0.
|
||||
*/
|
||||
private final double filledPercentage;
|
||||
|
||||
/**
|
||||
* This creates a new {@link CapacitorTextureUpdateTask} with the given parameters.
|
||||
*
|
||||
* @param l
|
||||
* The {@link Location} of the {@link Capacitor}
|
||||
* @param charge
|
||||
* The amount of charge in this {@link Capacitor}
|
||||
* @param capacity
|
||||
* The capacity of this {@link Capacitor}
|
||||
*/
|
||||
public CapacitorTextureUpdateTask(@Nonnull Location l, double charge, double capacity) {
|
||||
Validate.notNull(l, "The Location cannot be null");
|
||||
|
||||
this.l = l;
|
||||
this.filledPercentage = charge / capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Block b = l.getBlock();
|
||||
Material type = b.getType();
|
||||
|
||||
// Ensure that this Block is still a Player Head
|
||||
if (type == Material.PLAYER_HEAD || type == Material.PLAYER_WALL_HEAD) {
|
||||
if (filledPercentage <= 0.25) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());
|
||||
} else if (filledPercentage <= 0.5) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_50.getTexture());
|
||||
} else if (filledPercentage <= 0.75) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_75.getTexture());
|
||||
} else {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_100.getTexture());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -14,7 +14,7 @@ import org.bukkit.util.Vector;
|
||||
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
|
||||
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;
|
||||
|
||||
|
@ -11,7 +11,7 @@ import org.bukkit.util.Vector;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -13,7 +13,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.magical.InfusedMa
|
||||
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.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
@ -21,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
* @see InfusedMagnet
|
||||
*
|
||||
*/
|
||||
public class MagnetTask extends PlayerTask {
|
||||
public class MagnetTask extends AbstractPlayerTask {
|
||||
|
||||
private final double radius;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class ParachuteTask extends PlayerTask {
|
||||
public class ParachuteTask extends AbstractPlayerTask {
|
||||
|
||||
public ParachuteTask(@Nonnull Player p) {
|
||||
super(p);
|
||||
|
@ -9,7 +9,6 @@ import org.bukkit.World;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ButcherAndroidListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TeleporterListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
@ -69,10 +68,6 @@ public class SlimefunStartupTask implements Runnable {
|
||||
if (isEnabled("PROGRAMMABLE_ANDROID_BUTCHER", "PROGRAMMABLE_ANDROID_2_BUTCHER", "PROGRAMMABLE_ANDROID_3_BUTCHER")) {
|
||||
new ButcherAndroidListener(plugin);
|
||||
}
|
||||
|
||||
if (isEnabled("ENERGY_REGULATOR", "CARGO_MANAGER")) {
|
||||
new NetworkListener(plugin, SlimefunPlugin.getNetworkManager());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEnabled(String... itemIds) {
|
||||
@ -83,6 +78,7 @@ public class SlimefunStartupTask implements Runnable {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -146,8 +146,11 @@ public class TickerTask implements Runnable {
|
||||
if (item.getBlockTicker().isSynchronized()) {
|
||||
SlimefunPlugin.getProfiler().scheduleEntries(1);
|
||||
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(() -> {
|
||||
Block b = l.getBlock();
|
||||
tickBlock(l, b, item, data, System.nanoTime());
|
||||
|
@ -65,6 +65,7 @@ public final class ChatUtils {
|
||||
*
|
||||
* @return A human-friendly version of the given {@link String}
|
||||
*/
|
||||
@Nonnull
|
||||
public static String humanize(@Nonnull String string) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String[] segments = PatternUtils.UNDERSCORE.split(string.toLowerCase(Locale.ROOT));
|
||||
|
@ -159,6 +159,9 @@ public enum ColoredMaterial {
|
||||
|
||||
// @formatter:on
|
||||
|
||||
/**
|
||||
* This is our {@link List} of {@link Material Materials}, the backbone of this enum.
|
||||
*/
|
||||
private final List<Material> list;
|
||||
|
||||
/**
|
||||
@ -175,11 +178,25 @@ public enum ColoredMaterial {
|
||||
list = Collections.unmodifiableList(Arrays.asList(materials));
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns an ordered {@link List} of {@link Material Materials}
|
||||
* that are part o this {@link ColoredMaterial}.
|
||||
*
|
||||
* @return An ordered {@link List} of {@link Material Materials}
|
||||
*/
|
||||
@Nonnull
|
||||
public List<Material> asList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the {@link Material} at the given index.
|
||||
*
|
||||
* @param index
|
||||
* The index
|
||||
*
|
||||
* @return The {@link Material} at that index
|
||||
*/
|
||||
@Nonnull
|
||||
public Material get(int index) {
|
||||
Validate.isTrue(index >= 0 && index < 16, "The index must be between 0 and 15 (inclusive).");
|
||||
@ -187,6 +204,15 @@ public enum ColoredMaterial {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the {@link Material} with the given {@link DyeColor}.
|
||||
*
|
||||
* @param color
|
||||
* The {@link DyeColor}
|
||||
*
|
||||
* @return The {@link Material} with that {@link DyeColor}
|
||||
*/
|
||||
@Nonnull
|
||||
public Material get(@Nonnull DyeColor color) {
|
||||
Validate.notNull(color, "Color cannot be null!");
|
||||
|
||||
|
@ -119,18 +119,19 @@ public final class NumberUtils {
|
||||
* One hour later it will read {@code "1d 1h"}. For values smaller than an hour {@code "< 1h"}
|
||||
* will be returned instead.
|
||||
*
|
||||
* @param start
|
||||
* The starting {@link LocalDateTime}.
|
||||
* @param end
|
||||
* The ending {@link LocalDateTime}.
|
||||
* @param current
|
||||
* The current {@link LocalDateTime}.
|
||||
* @param priorDate
|
||||
* The {@link LocalDateTime} in the past.
|
||||
*
|
||||
* @return The elapsed time as a {@link String}
|
||||
*/
|
||||
@Nonnull
|
||||
public static String getElapsedTime(@Nonnull LocalDateTime start, @Nonnull LocalDateTime end) {
|
||||
Validate.notNull(start, "Provided start was null");
|
||||
Validate.notNull(end, "Provided end was null");
|
||||
long hours = Duration.between(start, end).toHours();
|
||||
public static String getElapsedTime(@Nonnull LocalDateTime current, @Nonnull LocalDateTime priorDate) {
|
||||
Validate.notNull(current, "Provided current date was null");
|
||||
Validate.notNull(priorDate, "Provided past date was null");
|
||||
|
||||
long hours = Duration.between(priorDate, current).toHours();
|
||||
|
||||
if (hours == 0) {
|
||||
return "< 1h";
|
||||
|
@ -14,7 +14,6 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -24,7 +23,6 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.ImmutableItemMeta;
|
||||
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
|
||||
import io.github.thebusybiscuit.cscorelib2.skull.SkullItem;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.api.exceptions.PrematureCodeException;
|
||||
@ -32,6 +30,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Soulbound;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.tasks.CapacitorTextureUpdateTask;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
|
||||
import me.mrCookieSlime.EmeraldEnchants.EmeraldEnchants;
|
||||
import me.mrCookieSlime.EmeraldEnchants.ItemEnchantment;
|
||||
@ -337,23 +336,7 @@ public final class SlimefunUtils {
|
||||
Validate.notNull(l, "Cannot update a texture for null");
|
||||
Validate.isTrue(capacity > 0, "Capacity must be greater than zero!");
|
||||
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
Block b = l.getBlock();
|
||||
|
||||
if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.PLAYER_WALL_HEAD) {
|
||||
double level = (double) charge / capacity;
|
||||
|
||||
if (level <= 0.25) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());
|
||||
} else if (level <= 0.5) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_50.getTexture());
|
||||
} else if (level <= 0.75) {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_75.getTexture());
|
||||
} else {
|
||||
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_100.getTexture());
|
||||
}
|
||||
}
|
||||
});
|
||||
SlimefunPlugin.runSync(new CapacitorTextureUpdateTask(l, charge, capacity));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,6 +42,10 @@ public final class ItemStackWrapper extends ItemStack {
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStackWrapper(@Nonnull Material material) {
|
||||
this(new ItemStack(material));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasItemMeta() {
|
||||
return hasItemMeta;
|
||||
|
@ -300,6 +300,18 @@ public enum SlimefunTag implements Tag<Material> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
if (!includedMaterials.isEmpty()) {
|
||||
/**
|
||||
* Without even needing to generate a Set we can safely
|
||||
* return false if there are directly included Materials
|
||||
*/
|
||||
return false;
|
||||
} else {
|
||||
return getValues().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a {@link Set} of {@link Tag Tags} which are children of this {@link SlimefunTag},
|
||||
* these can be other {@link SlimefunTag SlimefunTags} or regular {@link Tag Tags}.
|
||||
|
@ -252,6 +252,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
* identify all instances of the same {@link AContainer}.
|
||||
* This way we can add the recipes to all instances of the same machine.
|
||||
*
|
||||
* <strong>This method will be deprecated and replaced in the future</strong>
|
||||
*
|
||||
* @return The identifier of this machine
|
||||
*/
|
||||
@Nonnull
|
||||
@ -384,11 +386,13 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
Validate.notNull(l, "Can't attempt to take charge from a null location!");
|
||||
|
||||
if (isChargeable()) {
|
||||
if (getCharge(l) < getEnergyConsumption()) {
|
||||
int charge = getCharge(l);
|
||||
|
||||
if (charge < getEnergyConsumption()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
removeCharge(l, getEnergyConsumption());
|
||||
setCharge(l, charge - getEnergyConsumption());
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
|
@ -63,7 +63,7 @@ public abstract class AGenerator extends AbstractEnergyProvider {
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -152,7 +152,7 @@ public abstract class AGenerator extends AbstractEnergyProvider {
|
||||
ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(l).getTicks(), getProgressBar());
|
||||
|
||||
if (isChargeable()) {
|
||||
int charge = getCharge(l);
|
||||
int charge = getCharge(l, data);
|
||||
|
||||
if (getCapacity() - charge >= getEnergyProduction()) {
|
||||
progress.put(l, timeleft - 1);
|
||||
|
@ -47,6 +47,7 @@ public interface ItemHandler {
|
||||
*
|
||||
* @param item
|
||||
* The {@link SlimefunItem} to validate
|
||||
*
|
||||
* @return An {@link Optional} describing the result, it will contain an {@link IncompatibleItemHandlerException}
|
||||
* should there be an issue
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
|
||||
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||
@ -677,19 +676,20 @@ public class BlockStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public static SlimefunItem check(Block block) {
|
||||
return check(block.getLocation());
|
||||
@Nullable
|
||||
public static SlimefunItem check(@Nonnull Block b) {
|
||||
String id = checkID(b);
|
||||
return id == null ? null : SlimefunItem.getByID(id);
|
||||
}
|
||||
|
||||
public static SlimefunItem check(Location l) {
|
||||
if (!hasBlockInfo(l)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SlimefunItem.getByID(getLocationInfo(l, "id"));
|
||||
@Nullable
|
||||
public static SlimefunItem check(@Nonnull Location l) {
|
||||
String id = checkID(l);
|
||||
return id == null ? null : SlimefunItem.getByID(id);
|
||||
}
|
||||
|
||||
public static String checkID(Block b) {
|
||||
@Nullable
|
||||
public static String checkID(@Nonnull Block b) {
|
||||
if (SlimefunPlugin.getBlockDataService().isTileEntity(b.getType())) {
|
||||
Optional<String> blockData = SlimefunPlugin.getBlockDataService().getBlockData(b);
|
||||
|
||||
@ -714,18 +714,13 @@ public class BlockStorage {
|
||||
return getLocationInfo(l, "id");
|
||||
}
|
||||
|
||||
public static boolean check(Location l, String slimefunItem) {
|
||||
if (slimefunItem == null || !hasBlockInfo(l)) {
|
||||
public static boolean check(@Nonnull Location l, @Nullable String slimefunItem) {
|
||||
if (slimefunItem == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String id = getLocationInfo(l, "id");
|
||||
return id != null && id.equalsIgnoreCase(slimefunItem);
|
||||
} catch (Exception x) {
|
||||
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception occurred while checking " + new BlockPosition(l) + " for: \"" + slimefunItem + "\"");
|
||||
return false;
|
||||
}
|
||||
String id = checkID(l);
|
||||
return id != null && id.equals(slimefunItem);
|
||||
}
|
||||
|
||||
public static boolean isWorldRegistered(String name) {
|
||||
|
@ -91,12 +91,14 @@ public class DirtyChestMenu extends ChestMenu {
|
||||
}
|
||||
|
||||
public boolean fits(@Nonnull ItemStack item, int... slots) {
|
||||
if (getItemInSlot(slots[0]) == null) {
|
||||
// Very small optimization
|
||||
return true;
|
||||
} else {
|
||||
return InvUtils.fits(toInventory(), new ItemStackWrapper(item), slots);
|
||||
for (int slot : slots) {
|
||||
// A small optimization for empty slots
|
||||
if (getItemInSlot(slot) == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return InvUtils.fits(toInventory(), new ItemStackWrapper(item), slots);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -38,6 +38,7 @@ networks:
|
||||
max-size: 200
|
||||
cargo-ticker-delay: 0
|
||||
enable-visualizer: true
|
||||
delete-excess-items: false
|
||||
|
||||
items:
|
||||
talismans: true
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user