diff --git a/.github/workflows/auto-approve.yml b/.github/workflows/auto-approve.yml
index 94ee3dbcf..3dd7a4b50 100644
--- a/.github/workflows/auto-approve.yml
+++ b/.github/workflows/auto-approve.yml
@@ -1,7 +1,6 @@
name: Auto approve
-on:
- pull_request
+on: pull_request
jobs:
auto-approve:
@@ -9,6 +8,9 @@ jobs:
name: Auto approve Pull Request
runs-on: ubuntu-latest
+ ## Only run this on the main repo
+ if: github.event.pull_request.head.repo.full_name == 'Slimefun/Slimefun4'
+
steps:
- name: Approve via actions
uses: hmarr/auto-approve-action@v2.1.0
diff --git a/.github/workflows/auto-squash.yml b/.github/workflows/auto-squash.yml
index ab14135d2..489d97b89 100644
--- a/.github/workflows/auto-squash.yml
+++ b/.github/workflows/auto-squash.yml
@@ -17,12 +17,17 @@ jobs:
name: Auto squash
runs-on: ubuntu-latest
+ ## Only run this on the main repo
+ if: github.event.pull_request.head.repo.full_name == 'Slimefun/Slimefun4'
+
steps:
- name: Auto squash
- uses: pascalgn/automerge-action@v0.13.1
+ uses: pascalgn/automerge-action@v0.14.1
env:
- GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- MERGE_METHOD: "squash"
+ GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
+ UPDATE_RETRIES: 0
+ MERGE_METHOD: squash
MERGE_FORKS: false
- MERGE_LABELS: "📄 Translations Update"
- MERGE_COMMIT_MESSAGE: "[CI skip] New locale updates from Crowdin"
+ MERGE_DELETE_BRANCH: true
+ MERGE_LABELS: '📄 Translations Update'
+ MERGE_COMMIT_MESSAGE: '[CI skip] New locale updates from Crowdin'
diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml
index ad787e29b..d76fa6610 100644
--- a/.github/workflows/discord-webhook.yml
+++ b/.github/workflows/discord-webhook.yml
@@ -12,13 +12,15 @@ jobs:
name: Discord Webhook
runs-on: ubuntu-latest
+
+ ## Only run this on the main repo
if: github.repository == 'Slimefun/Slimefun4'
steps:
- name: Checkout repository
uses: actions/checkout@v2.3.4
- name: Set up Java JDK 11
- uses: actions/setup-java@v2.0.0
+ uses: actions/setup-java@v2.1.0
with:
distribution: 'adopt'
java-version: '11'
diff --git a/.github/workflows/maven-compiler.yml b/.github/workflows/maven-compiler.yml
index 28d798574..f7937a839 100644
--- a/.github/workflows/maven-compiler.yml
+++ b/.github/workflows/maven-compiler.yml
@@ -24,7 +24,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up JDK 1.8
- uses: actions/setup-java@v2.0.0
+ uses: actions/setup-java@v2.1.0
with:
distribution: 'adopt'
java-version: '8'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d49150316..d7fdc738f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
# Table of contents
-- [Release Candidate 23 (TBD)](#release-candidate-23-tbd)
+- [Release Candidate 24 (TBD)](#release-candidate-24-tbd)
+- [Release Candidate 23 (19 May 2021)](#release-candidate-23-19-may-2021)
- [Release Candidate 22 (18 Apr 2021)](#release-candidate-22-18-apr-2021)
- [Release Candidate 21 (14 Mar 2021)](#release-candidate-21-14-mar-2021)
- [Release Candidate 20 (30 Jan 2021)](#release-candidate-20-30-jan-2021)
@@ -23,7 +24,21 @@
- [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019)
- [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019)
-## Release Candidate 23 (TBD)
+## Release Candidate 24 (TBD)
+
+#### Additions
+* The speed of the Ancient Altar can now be configured in the `Items.yml` file
+
+#### Changes
+
+#### Fixes
+* Fixed #3064
+* Fixed #2964
+* Fixed #2979
+* Fixed a permissions issue with `/sf charge`
+
+## Release Candidate 23 (19 May 2021)
+https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#23
#### Additions
* Added "Quartz Block -> 4 Quartz" recipe to Grind Stone
@@ -35,8 +50,12 @@
* Added "Ender Lump Tier 3 -> 4 Ender Lump Tier 2" recipe to Grind Stone
* Added Tier 2 Auto-Enchanter
* Added Tier 2 Auto-Disenchanter
+* (API) Added AsyncAutoEnchanterProcessEvent
* (API) Added Category#setTier() to modify a category's position in the guide
* Added the ability to disable auto (dis)enchanting with a lore - `use-ignored-lores` & `ignored-lores` in Items.yml
+* Added an option to turn off the "researching animation" in the `config.yml`
+* Added the option to turn off the "researching animation" within your Slimefun Guide
+* Added Portable Teleporter
#### Changes
* Renamed "Solar Panel" to "Photovoltaic Cell" to avoid confusions with solar generators
@@ -47,6 +66,7 @@
* (API) Removed deprecated "SlimefunBlockHandler"
* (API) Refactored "Machine Process" API
* Removed Automated Crafting Chamber
+* Memory and performance improvements for Cargo and Energy networks
#### Fixes
* Fixed #2987
@@ -58,9 +78,13 @@
* Fixed #2927
* Fixed #3007
* Fixed #3012
+* Fixed #3013
* Fixed #3027
* Fixed #2978
+* Fixed #3041
+* Fixed #3036
* Possibly fixed #2927
+* Fixed #3060
## Release Candidate 22 (18 Apr 2021)
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#22
diff --git a/pom.xml b/pom.xml
index 984234b44..88f38419d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -230,7 +230,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.2.0
+ 3.3.0
${project.basedir}
@@ -343,19 +343,19 @@
org.junit.jupiter
junit-jupiter
- 5.7.1
+ 5.7.2
test
org.mockito
mockito-core
- 3.9.0
+ 3.10.0
test
com.github.seeseemelk
MockBukkit-v1.16
- 0.34.2
+ 1.0.1
test
@@ -370,7 +370,7 @@
- com.github.TheBusyBiscuit
+ com.github.thebusybiscuit
CS-CoreLib2
0.31.0
compile
@@ -470,7 +470,7 @@
com.github.LoneDev6
itemsadder-api
- 2.3.3
+ 2.3.8
provided
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/AsyncAutoEnchanterProcessEvent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/AsyncAutoEnchanterProcessEvent.java
new file mode 100644
index 000000000..ca1958b5c
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/events/AsyncAutoEnchanterProcessEvent.java
@@ -0,0 +1,92 @@
+package io.github.thebusybiscuit.slimefun4.api.events;
+
+import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoEnchanter;
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.inventory.ItemStack;
+
+import javax.annotation.Nonnull;
+
+/**
+ * An {@link Event} that is called whenever an {@link AutoEnchanter} is
+ * enchanting an {@link ItemStack}.
+ *
+ * @author StarWishsama
+ */
+public class AsyncAutoEnchanterProcessEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private final ItemStack item;
+ private final ItemStack enchantedBook;
+ private final BlockMenu menu;
+
+ private boolean cancelled;
+
+ public AsyncAutoEnchanterProcessEvent(@Nonnull ItemStack item, @Nonnull ItemStack enchantedBook, @Nonnull BlockMenu menu) {
+ super(true);
+
+ Validate.notNull(item, "The item to enchant cannot be null!");
+ Validate.notNull(enchantedBook, "The enchanted book to enchant cannot be null!");
+ Validate.notNull(menu, "The menu of auto-enchanter cannot be null!");
+
+ this.item = item;
+ this.enchantedBook = enchantedBook;
+ this.menu = menu;
+ }
+
+ /**
+ * This returns the {@link ItemStack} that is being enchanted.
+ *
+ * @return The {@link ItemStack} that is being enchanted
+ */
+ @Nonnull
+ public ItemStack getItem() {
+ return item;
+ }
+
+ /**
+ * This returns the {@link ItemStack} that is being used enchanted book
+ *
+ * @return The {@link ItemStack} that is being used enchanted book
+ */
+ @Nonnull
+ public ItemStack getEnchantedBook() {
+ return enchantedBook;
+ }
+
+ /**
+ * This returns the {@link AutoEnchanter}'s {@link BlockMenu}
+ *
+ * @return The {@link BlockMenu} of {@link AutoEnchanter} that is enchanting item
+ */
+ @Nonnull
+ public BlockMenu getMenu() {
+ return menu;
+ }
+
+ @Nonnull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Nonnull
+ @Override
+ public HandlerList getHandlers() {
+ return getHandlerList();
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/TeleportationManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/TeleportationManager.java
index fa292e098..c918b34bb 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/TeleportationManager.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/TeleportationManager.java
@@ -51,12 +51,24 @@ public final class TeleportationManager {
*/
private final Set teleporterUsers = new HashSet<>();
+ /**
+ * Opens the GUI of the teleporter and calculates the network complexity of the {@link Player}
+ *
+ * @param p {@link Player} to be teleported
+ * @param ownerUUID {@link UUID} of the {@link Player} who owns the teleporter device
+ * @param b {@link Block} from where the {@link Player} is being teleported
+ */
@ParametersAreNonnullByDefault
- public void openTeleporterGUI(Player p, UUID uuid, Block b, int complexity) {
+ public void openTeleporterGUI(Player p, UUID ownerUUID, Block b) {
+ openTeleporterGUI(p, ownerUUID, b, SlimefunPlugin.getGPSNetwork().getNetworkComplexity(ownerUUID));
+ }
+
+ @ParametersAreNonnullByDefault
+ public void openTeleporterGUI(Player p, UUID ownerUUID, Block b, int complexity) {
if (teleporterUsers.add(p.getUniqueId())) {
p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1F, 1F);
- PlayerProfile.fromUUID(uuid, profile -> {
+ PlayerProfile.fromUUID(ownerUUID, profile -> {
ChestMenu menu = new ChestMenu("&3Teleporter");
menu.addMenuCloseHandler(pl -> teleporterUsers.remove(pl.getUniqueId()));
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java
index 015279689..cd9c81bec 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/Network.java
@@ -4,14 +4,18 @@ import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
+import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
+import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
+import org.bukkit.World;
+import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
import io.github.thebusybiscuit.slimefun4.core.networks.NetworkManager;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
@@ -20,6 +24,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListen
* An abstract Network class to manage networks in a stateful way
*
* @author meiamsome
+ * @author TheBusyBiscuit
*
* @see NetworkListener
* @see NetworkManager
@@ -37,8 +42,19 @@ public abstract class Network {
*/
protected Location regulator;
+ /**
+ * The {@link UUID} of the {@link World} this {@link Network} exists within.
+ */
+ private final UUID worldId;
+
+ /**
+ * This {@link Set} holds all {@link Network} positions that are part of this {@link Network}.
+ * The {@link World} should be equal for all positions, therefore we can save memory by simply
+ * storing {@link BlockPosition#getAsLong(int, int, int)}.
+ */
+ private final Set positions = new HashSet<>();
+
private final Queue nodeQueue = new ArrayDeque<>();
- protected final Set connectedLocations = new HashSet<>();
protected final Set regulatorNodes = new HashSet<>();
protected final Set connectorNodes = new HashSet<>();
protected final Set terminusNodes = new HashSet<>();
@@ -57,8 +73,9 @@ public abstract class Network {
this.manager = manager;
this.regulator = regulator;
+ this.worldId = regulator.getWorld().getUID();
- connectedLocations.add(regulator);
+ positions.add(BlockPosition.getAsLong(regulator));
nodeQueue.add(regulator.clone());
}
@@ -115,7 +132,10 @@ public abstract class Network {
* The {@link Location} to add
*/
protected void addLocationToNetwork(@Nonnull Location l) {
- if (connectedLocations.add(l.clone())) {
+ Validate.notNull(l, "You cannot add a Location to a Network which is null!");
+ Validate.isTrue(l.getWorld().getUID().equals(worldId), "Networks cannot exist in multiple worlds!");
+
+ if (positions.add(BlockPosition.getAsLong(l))) {
markDirty(l);
}
}
@@ -144,10 +164,14 @@ public abstract class Network {
* @return Whether the given {@link Location} is part of this {@link Network}
*/
public boolean connectsTo(@Nonnull Location l) {
- if (regulator.equals(l)) {
+ Validate.notNull(l, "The Location cannot be null.");
+
+ if (this.regulator.equals(l)) {
return true;
+ } else if (!l.getWorld().getUID().equals(this.worldId)) {
+ return false;
} else {
- return connectedLocations.contains(l);
+ return positions.contains(BlockPosition.getAsLong(l));
}
}
@@ -225,7 +249,8 @@ public abstract class Network {
*/
public void display() {
if (manager.isVisualizerEnabled()) {
- SlimefunPlugin.runSync(new NetworkVisualizer(this));
+ // TODO: Make Color configurable / network-dependent
+ SlimefunPlugin.runSync(new NetworkVisualizer(this, Color.BLUE));
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/NetworkVisualizer.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/NetworkVisualizer.java
index 7933c51ab..14ab69c85 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/NetworkVisualizer.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/network/NetworkVisualizer.java
@@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.api.network;
import javax.annotation.Nonnull;
+import org.apache.commons.lang.Validate;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
@@ -18,7 +19,7 @@ class NetworkVisualizer implements Runnable {
/**
* The {@link DustOptions} define the {@link Color} and size of our particles.
*/
- private final DustOptions options = new DustOptions(Color.BLUE, 3.5F);
+ private final DustOptions particleOptions;
/**
* This is our {@link Network} instance.
@@ -31,8 +32,12 @@ class NetworkVisualizer implements Runnable {
* @param network
* The {@link Network} to visualize
*/
- NetworkVisualizer(@Nonnull Network network) {
+ NetworkVisualizer(@Nonnull Network network, @Nonnull Color color) {
+ Validate.notNull(network, "The network should not be null.");
+ Validate.notNull(color, "The color cannot be null.");
+
this.network = network;
+ this.particleOptions = new DustOptions(color, 3F);
}
@Override
@@ -53,7 +58,7 @@ class NetworkVisualizer implements Runnable {
* The {@link Location} of our node
*/
private void spawnParticles(@Nonnull Location l) {
- l.getWorld().spawnParticle(Particle.REDSTONE, l.getX() + 0.5, l.getY() + 0.5, l.getZ() + 0.5, 1, 0, 0, 0, 1, options);
+ l.getWorld().spawnParticle(Particle.REDSTONE, l.getX() + 0.5, l.getY() + 0.5, l.getZ() + 0.5, 1, 0, 0, 0, 1, particleOptions);
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
index e6c146590..6658c3b69 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java
@@ -69,6 +69,7 @@ public final class SlimefunRegistry {
private boolean enableResearches;
private boolean freeCreativeResearches;
private boolean researchFireworks;
+ private boolean disableLearningAnimation;
private boolean logDuplicateBlockEntries;
private boolean talismanActionBarMessages;
@@ -109,6 +110,7 @@ public final class SlimefunRegistry {
backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility");
freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode");
researchFireworks = cfg.getBoolean("researches.enable-fireworks");
+ disableLearningAnimation = cfg.getBoolean("researches.disable-learning-animation");
logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries");
talismanActionBarMessages = cfg.getBoolean("talismans.use-actionbar");
}
@@ -238,6 +240,15 @@ public final class SlimefunRegistry {
return researchFireworks;
}
+ /**
+ * Returns whether the research learning animations is disabled
+ *
+ * @return Whether the research learning animations is disabled
+ */
+ public boolean isLearningAnimationDisabled() {
+ return disableLearningAnimation;
+ }
+
/**
* This method returns a {@link List} of every enabled {@link MultiBlock}.
*
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java
index cdc65a340..d1914e667 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/BackpackCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
@@ -11,10 +13,22 @@ import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.RestoredBackpack;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
+/**
+ * This command that allows for backpack retrieval in the event they are lost.
+ * The command accepts a name and id, if those match up it spawns a Medium Backpack
+ * with the correct lore set in the sender's inventory.
+ *
+ * @author Sfiguz7
+ *
+ * @see RestoredBackpack
+ *
+ */
class BackpackCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
BackpackCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "backpack", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ChargeCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ChargeCommand.java
index 8d3a64f09..c06d5fbd1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ChargeCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ChargeCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -19,6 +21,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
*/
class ChargeCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
ChargeCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "charge", false);
}
@@ -31,10 +34,11 @@ class ChargeCommand extends SubCommand {
@Override
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
- if (sender.hasPermission("slimefun.charge.command")) {
+ if (sender.hasPermission("slimefun.command.charge")) {
Player p = (Player) sender;
ItemStack item = p.getInventory().getItemInMainHand();
SlimefunItem slimefunItem = SlimefunItem.getByItem(item);
+
if (slimefunItem instanceof Rechargeable) {
Rechargeable rechargeableItem = (Rechargeable) slimefunItem;
rechargeableItem.setItemCharge(item, rechargeableItem.getMaxItemCharge(item));
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/CheatCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/CheatCommand.java
index 3a4e18aca..659023daa 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/CheatCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/CheatCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -10,6 +12,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class CheatCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
CheatCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "cheat", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/DebugFishCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/DebugFishCommand.java
index 1900a471d..619b6d2ec 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/DebugFishCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/DebugFishCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -10,6 +12,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class DebugFishCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
DebugFishCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "debug_fish", true);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GiveCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GiveCommand.java
index dc3e4f00d..f0efe22d0 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GiveCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GiveCommand.java
@@ -16,12 +16,15 @@ import java.util.Locale;
import java.util.Map;
import java.util.Optional;
+import javax.annotation.ParametersAreNonnullByDefault;
+
class GiveCommand extends SubCommand {
private static final String PLACEHOLDER_PLAYER = "%player%";
private static final String PLACEHOLDER_ITEM = "%item%";
private static final String PLACEHOLDER_AMOUNT = "%amount%";
+ @ParametersAreNonnullByDefault
GiveCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "give", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GuideCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GuideCommand.java
index c0f6a1949..94b49f630 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GuideCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/GuideCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -11,6 +13,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class GuideCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
GuideCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "guide", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/HelpCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/HelpCommand.java
index 43e43feb3..6ff08892f 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/HelpCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/HelpCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
@@ -8,6 +10,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class HelpCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
HelpCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "help", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/OpenGuideCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/OpenGuideCommand.java
index 8947d989f..7e4b88d7b 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/OpenGuideCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/OpenGuideCommand.java
@@ -13,6 +13,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class OpenGuideCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
OpenGuideCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "open_guide", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ResearchCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ResearchCommand.java
index 9c3d29889..59dbd7dd4 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ResearchCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/ResearchCommand.java
@@ -3,6 +3,9 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Optional;
import java.util.function.UnaryOperator;
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -18,6 +21,7 @@ class ResearchCommand extends SubCommand {
private static final String PLACEHOLDER_PLAYER = "%player%";
private static final String PLACEHOLDER_RESEARCH = "%research%";
+ @ParametersAreNonnullByDefault
ResearchCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "research", false);
}
@@ -57,6 +61,7 @@ class ResearchCommand extends SubCommand {
}
}
+ @ParametersAreNonnullByDefault
private void giveResearch(CommandSender sender, Player p, String input) {
Optional research = getResearchFromString(input);
@@ -70,6 +75,7 @@ class ResearchCommand extends SubCommand {
}
}
+ @ParametersAreNonnullByDefault
private void researchAll(CommandSender sender, PlayerProfile profile, Player p) {
for (Research res : SlimefunPlugin.getRegistry().getResearches()) {
if (!profile.hasUnlocked(res)) {
@@ -80,6 +86,7 @@ class ResearchCommand extends SubCommand {
}
}
+ @ParametersAreNonnullByDefault
private void reset(PlayerProfile profile, Player p) {
for (Research research : SlimefunPlugin.getRegistry().getResearches()) {
profile.setResearched(research, false);
@@ -88,7 +95,8 @@ class ResearchCommand extends SubCommand {
SlimefunPlugin.getLocalization().sendMessage(p, "commands.research.reset", true, msg -> msg.replace(PLACEHOLDER_PLAYER, p.getName()));
}
- private Optional getResearchFromString(String input) {
+ @Nonnull
+ private Optional getResearchFromString(@Nonnull String input) {
if (!input.contains(":")) {
return Optional.empty();
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SearchCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SearchCommand.java
index c52927221..56a4faaa1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SearchCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SearchCommand.java
@@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Arrays;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -14,6 +16,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class SearchCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
SearchCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "search", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SlimefunSubCommands.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SlimefunSubCommands.java
index 10378c3ff..488750f99 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SlimefunSubCommands.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/SlimefunSubCommands.java
@@ -4,6 +4,8 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
+import javax.annotation.Nonnull;
+
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@@ -20,7 +22,8 @@ public final class SlimefunSubCommands {
private SlimefunSubCommands() {}
- public static Collection getAllCommands(SlimefunCommand cmd) {
+ @Nonnull
+ public static Collection getAllCommands(@Nonnull SlimefunCommand cmd) {
SlimefunPlugin plugin = cmd.getPlugin();
List commands = new LinkedList<>();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/StatsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/StatsCommand.java
index 1bb18b3e6..a6e3651fb 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/StatsCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/StatsCommand.java
@@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Optional;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
@@ -14,6 +16,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class StatsCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
StatsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "stats", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TeleporterCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TeleporterCommand.java
index 2d7d56ba5..fbd31fe07 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TeleporterCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TeleporterCommand.java
@@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.BlockFace;
@@ -12,6 +14,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class TeleporterCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
TeleporterCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "teleporter", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TimingsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TimingsCommand.java
index 3673f48a6..849abbef4 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TimingsCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/TimingsCommand.java
@@ -24,6 +24,7 @@ class TimingsCommand extends SubCommand {
private static final String FLAG_PREFIX = "--";
private final Set flags = new HashSet<>(Arrays.asList("verbose"));
+ @ParametersAreNonnullByDefault
TimingsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "timings", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java
index 63d9f13e9..7c69fbaae 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java
@@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection;
import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -29,6 +30,7 @@ import net.md_5.bungee.api.chat.hover.content.Text;
*/
class VersionsCommand extends SubCommand {
+ @ParametersAreNonnullByDefault
VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "versions", false);
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideImplementation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideImplementation.java
index 873ce5105..8dceaa855 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideImplementation.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideImplementation.java
@@ -3,12 +3,14 @@ package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
+import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
@@ -18,7 +20,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This interface is used for the different implementations that add behaviour
* to the {@link SlimefunGuide}.
- *
+ *
* @author TheBusyBiscuit
*
* @see SlimefunGuideMode
@@ -30,7 +32,7 @@ public interface SlimefunGuideImplementation {
/**
* Every {@link SlimefunGuideImplementation} can be associated with a
* {@link SlimefunGuideMode}.
- *
+ *
* @return The mode this {@link SlimefunGuideImplementation} represents
*/
@Nonnull
@@ -40,22 +42,28 @@ public interface SlimefunGuideImplementation {
* Returns the {@link ItemStack} representation for this {@link SlimefunGuideImplementation}.
* In other words: The {@link ItemStack} you hold in your hand and that you use to
* open your {@link SlimefunGuide}
- *
+ *
* @return The {@link ItemStack} representation for this {@link SlimefunGuideImplementation}
*/
@Nonnull
ItemStack getItem();
+ @ParametersAreNonnullByDefault
void openMainMenu(PlayerProfile profile, int page);
+ @ParametersAreNonnullByDefault
void openCategory(PlayerProfile profile, Category category, int page);
+ @ParametersAreNonnullByDefault
void openSearch(PlayerProfile profile, String input, boolean addToHistory);
+ @ParametersAreNonnullByDefault
void displayItem(PlayerProfile profile, ItemStack item, int index, boolean addToHistory);
+ @ParametersAreNonnullByDefault
void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory);
+ @ParametersAreNonnullByDefault
default void unlockItem(Player p, SlimefunItem sfitem, Consumer callback) {
Research research = sfitem.getResearch();
@@ -63,7 +71,9 @@ public interface SlimefunGuideImplementation {
research.unlock(p, true, callback);
} else {
p.setLevel(p.getLevel() - research.getCost());
- research.unlock(p, false, callback);
+
+ boolean skipLearningAnimation = SlimefunPlugin.getRegistry().isLearningAnimationDisabled() || !SlimefunGuideSettings.hasLearningAnimationEnabled(p);
+ research.unlock(p, skipLearningAnimation, callback);
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/LearningAnimationOption.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/LearningAnimationOption.java
new file mode 100644
index 000000000..2b949d429
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/LearningAnimationOption.java
@@ -0,0 +1,74 @@
+package io.github.thebusybiscuit.slimefun4.core.guide.options;
+
+import java.util.List;
+import java.util.Optional;
+
+import javax.annotation.Nonnull;
+
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
+import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
+import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
+
+/**
+ * {@link LearningAnimationOption} represents a setting in the Slimefun guide book.
+ * It allows users to disable/enable the "learning animation",
+ * the information in chat when doing a Slimefun research.
+ *
+ * @author martinbrom
+ */
+class LearningAnimationOption implements SlimefunGuideOption {
+
+ @Nonnull
+ @Override
+ public SlimefunAddon getAddon() {
+ return SlimefunPlugin.instance();
+ }
+
+ @Nonnull
+ @Override
+ public NamespacedKey getKey() {
+ return new NamespacedKey(SlimefunPlugin.instance(), "research_learning_animation");
+ }
+
+ @Nonnull
+ @Override
+ public Optional getDisplayItem(@Nonnull Player p, @Nonnull ItemStack guide) {
+ if (SlimefunPlugin.getRegistry().isLearningAnimationDisabled()) {
+ return Optional.empty();
+ } else {
+ boolean enabled = getSelectedOption(p, guide).orElse(true);
+ String optionState = enabled ? "enabled" : "disabled";
+ List lore = SlimefunPlugin.getLocalization().getMessages(p, "guide.options.learning-animation." + optionState + ".text");
+ lore.add("");
+ lore.add("&7\u21E8 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.options.learning-animation." + optionState + ".click"));
+
+ ItemStack item = new CustomItem(enabled ? Material.MAP : Material.PAPER, lore);
+ return Optional.of(item);
+ }
+ }
+
+ @Override
+ public void onClick(@Nonnull Player p, @Nonnull ItemStack guide) {
+ setSelectedOption(p, guide, !getSelectedOption(p, guide).orElse(true));
+ SlimefunGuideSettings.openSettings(p, guide);
+ }
+
+ @Override
+ public Optional getSelectedOption(@Nonnull Player p, @Nonnull ItemStack guide) {
+ NamespacedKey key = getKey();
+ boolean value = !PersistentDataAPI.hasByte(p, key) || PersistentDataAPI.getByte(p, key) == (byte) 1;
+ return Optional.of(value);
+ }
+
+ @Override
+ public void setSelectedOption(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull Boolean value) {
+ PersistentDataAPI.setByte(p, getKey(), (byte) (value.booleanValue() ? 1 : 0));
+ }
+
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
index 6662fcb22..7c74f80a8 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/SlimefunGuideSettings.java
@@ -47,6 +47,7 @@ public final class SlimefunGuideSettings {
static {
options.add(new GuideModeOption());
options.add(new FireworksOption());
+ options.add(new LearningAnimationOption());
options.add(new PlayerLanguageOption());
}
@@ -238,15 +239,51 @@ public final class SlimefunGuideSettings {
* @return Whether this {@link Player} wants to see fireworks when unlocking a {@link Research}
*/
public static boolean hasFireworksEnabled(@Nonnull Player p) {
+ return getOptionValue(p, FireworksOption.class, true);
+ }
+
+ /**
+ * This method checks if the given {@link Player} has enabled the {@link LearningAnimationOption}
+ * in their {@link SlimefunGuide}.
+ * If they enabled this setting, they will see messages in chat about the progress of their {@link Research}.
+ *
+ * @param p
+ * The {@link Player}
+ *
+ * @return Whether this {@link Player} wants to info messages in chat when unlocking a {@link Research}
+ */
+ public static boolean hasLearningAnimationEnabled(@Nonnull Player p) {
+ return getOptionValue(p, LearningAnimationOption.class, true);
+ }
+
+ /**
+ * Helper method to get the value of a {@link SlimefunGuideOption} that the {@link Player}
+ * has set in their {@link SlimefunGuide}
+ *
+ * @param p
+ * The {@link Player}
+ * @param optionsClass
+ * Class of the {@link SlimefunGuideOption} to get the value of
+ * @param defaultValue
+ * Default value to return in case the option is not found at all or has no value set
+ * @param
+ * Type of the {@link SlimefunGuideOption}
+ * @param
+ * Type of the {@link SlimefunGuideOption} value
+ *
+ * @return The value of given {@link SlimefunGuideOption}
+ */
+ @Nonnull
+ private static , V> V getOptionValue(@Nonnull Player p, @Nonnull Class optionsClass, @Nonnull V defaultValue) {
for (SlimefunGuideOption> option : options) {
- if (option instanceof FireworksOption) {
- FireworksOption fireworks = (FireworksOption) option;
+ if (optionsClass.isInstance(option)) {
+ T o = optionsClass.cast(option);
ItemStack guide = SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE);
- return fireworks.getSelectedOption(p, guide).orElse(true);
+ return o.getSelectedOption(p, guide).orElse(defaultValue);
}
}
- return true;
+ return defaultValue;
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/NetworkManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/NetworkManager.java
index 66216750d..dd726af28 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/NetworkManager.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/NetworkManager.java
@@ -1,9 +1,11 @@
package io.github.thebusybiscuit.slimefun4.core.networks;
import java.util.ArrayList;
-import java.util.LinkedList;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -12,16 +14,21 @@ import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Server;
+import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
import io.github.thebusybiscuit.cscorelib2.config.Config;
+import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet;
+import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
+import me.mrCookieSlime.Slimefun.api.BlockStorage;
/**
* The {@link NetworkManager} is responsible for holding all instances of {@link Network}
* and providing some utility methods that would have probably been static otherwise.
*
* @author TheBusyBiscuit
+ * @author meiamsome
*
* @see Network
* @see NetworkListener
@@ -32,7 +39,16 @@ public class NetworkManager {
private final int maxNodes;
private final boolean enableVisualizer;
private final boolean deleteExcessItems;
- private final List networks = new LinkedList<>();
+
+ /**
+ * Fixes #3041
+ *
+ * We use a {@link CopyOnWriteArrayList} here to ensure thread-safety.
+ * This {@link List} is also much more frequently read than being written to.
+ * Therefore a {@link CopyOnWriteArrayList} should be perfect for this, even
+ * if insertions come at a slight cost.
+ */
+ private final List networks = new CopyOnWriteArrayList<>();
/**
* This creates a new {@link NetworkManager} with the given capacity.
@@ -93,12 +109,13 @@ public class NetworkManager {
/**
* This returns a {@link List} of every {@link Network} on the {@link Server}.
+ * The returned {@link List} is not modifiable.
*
* @return A {@link List} containing every {@link Network} on the {@link Server}
*/
@Nonnull
public List getNetworkList() {
- return networks;
+ return Collections.unmodifiableList(networks);
}
@Nonnull
@@ -169,11 +186,30 @@ public class NetworkManager {
public void updateAllNetworks(@Nonnull Location l) {
Validate.notNull(l, "The Location cannot be null");
- // No need to create a sublist and loop through it if there are no Networks
- if (!networks.isEmpty()) {
+ try {
+ /*
+ * No need to create a sublist and loop through it if
+ * there aren't even any networks on the server.
+ */
+ if (networks.isEmpty()) {
+ return;
+ }
+
+ /*
+ * Only a Slimefun block can be part of a Network.
+ * This check helps to speed up performance.
+ *
+ * (Skip for Unit Tests as they don't support block info yet)
+ */
+ if (!BlockStorage.hasBlockInfo(l) && SlimefunPlugin.getMinecraftVersion() != MinecraftVersion.UNIT_TEST) {
+ return;
+ }
+
for (Network network : getNetworksFromLocation(l, Network.class)) {
network.markDirty(l);
}
+ } catch (Exception x) {
+ SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception was thrown while causing a networks update @ " + new BlockPosition(l));
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
index 28d766fb4..7e5b166e1 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java
@@ -74,6 +74,7 @@ class ContributionsConnector extends GitHubConnector {
aliases.put("bverhoeven", "soczol");
aliases.put("ramdon-person", "ramdon_person");
aliases.put("NCBPFluffyBear", "FluffyBear_");
+ aliases.put("martinbrom", "OneTime97");
}
/**
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
index 051a427fe..129c285b2 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java
@@ -745,6 +745,7 @@ public final class SlimefunItems {
public static final SlimefunItemStack GPS_TELEPORTATION_MATRIX = new SlimefunItemStack("GPS_TELEPORTATION_MATRIX", Material.IRON_BLOCK, "&bGPS Teleporter Matrix", "", "&fThis is your Teleporter's Main Component", "&fThis Matrix allows Players to choose from all", "&fWaypoints made by the Player who has placed", "&fthis Device.");
public static final SlimefunItemStack GPS_ACTIVATION_DEVICE_SHARED = new SlimefunItemStack("GPS_ACTIVATION_DEVICE_SHARED", Material.STONE_PRESSURE_PLATE, "&fGPS Activation Device &3(Shared)", "", "&fPlace this onto a Teleportation Matrix", "&fand step onto this Plate to activate", "&fthe Teleportation Process");
public static final SlimefunItemStack GPS_ACTIVATION_DEVICE_PERSONAL = new SlimefunItemStack("GPS_ACTIVATION_DEVICE_PERSONAL", Material.STONE_PRESSURE_PLATE, "&fGPS Activation Device &a(Personal)", "", "&fPlace this onto a Teleportation Matrix", "&fand step onto this Plate to activate", "&fthe Teleportation Process", "", "&fThis Version only allows the Person who", "&fplaced this Device to use it");
+ public static final SlimefunItemStack PORTABLE_TELEPORTER = new SlimefunItemStack("PORTABLE_TELEPORTER", Material.COMPASS, "&bPortable Teleporter", "", "&fThis device allows you to teleport", "&fto your waypoints from anywhere", "", LoreBuilder.powerCharged(0, 50), "", "&eRight Click&7 to use");
public static final SlimefunItemStack ELEVATOR_PLATE = new SlimefunItemStack("ELEVATOR_PLATE", Material.STONE_PRESSURE_PLATE, "&bElevator Plate", "", "&fPlace an Elevator Plate on every floor", "&fand you will be able to teleport between them.", "", "&eRight Click this Block &7to name it");
public static final SlimefunItemStack INFUSED_HOPPER = new SlimefunItemStack("INFUSED_HOPPER", Material.HOPPER, "&5Infused Hopper", "", "&fAutomatically picks up nearby Items in a 7x7x7", "&fRadius when placed.");
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientAltar.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientAltar.java
index 232d2a215..9c1382e31 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientAltar.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientAltar.java
@@ -3,9 +3,14 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.altar;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.AncientAltarCraftEvent;
+import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
+import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.AncientAltarListener;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AncientAltarTask;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@@ -17,41 +22,47 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* The {@link AncientAltar} is a multiblock structure.
* The altar itself stands in the center, surrounded by {@link AncientPedestal Pedestals}, it is used
* to craft various magical items.
- *
+ *
* @author TheBusyBiscuit
- *
+ * @author martinbrom
+ *
* @see AncientAltarListener
* @see AncientAltarTask
* @see AncientAltarCraftEvent
* @see AncientPedestal
- *
*/
public class AncientAltar extends SlimefunItem {
- private final int speed;
+ /**
+ * This number represents a delay in ticks between two ritual steps.
+ * The whole ritual process consists of 36 steps, an item is consumed every 4 steps (8 times)
+ * and the output is spawned after the 36th step completes.
+ */
+ private static final int DEFAULT_STEP_DELAY = 8;
+
private final List recipes = new ArrayList<>();
- public AncientAltar(Category category, int speed, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
+ private final ItemSetting stepDelay = new IntRangeSetting(this, "step-delay", 0, DEFAULT_STEP_DELAY, Integer.MAX_VALUE);
+
+ @ParametersAreNonnullByDefault
+ public AncientAltar(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
- if (speed < 1) {
- throw new IllegalArgumentException("The speed must be at least 1.");
- }
-
- this.speed = speed;
+ addItemSetting(stepDelay);
}
/**
- * This returns the speed of this {@link AncientAltar}.
- * This number determines how much ticks happen inbetween a step in the ritual animation.
- * The default is 8 ticks.
- *
- * @return The speed of this {@link AncientAltar}
+ * This returns the delay of this {@link AncientAltar}.
+ * This number determines how many ticks happen in between a step in the ritual animation.
+ * The default is {@value #DEFAULT_STEP_DELAY} ticks.
+ *
+ * @return The delay between two ritual steps of this {@link AncientAltar}
*/
- public int getSpeed() {
- return speed;
+ public int getStepDelay() {
+ return stepDelay.getValue();
}
+ @Nonnull
public List getRecipes() {
return recipes;
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
index d8fda27ae..890113721 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java
@@ -684,7 +684,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
if ("false".equals(data.getString("paused"))) {
BlockMenu menu = BlockStorage.getInventory(b);
-
+
String fuelData = data.getString("fuel");
float fuel = fuelData == null ? 0 : Float.parseFloat(fuelData);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java
index eb5775bf1..eb7499f78 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java
@@ -67,15 +67,16 @@ public class WoodcutterAndroid extends ProgrammableAndroid {
private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) {
ItemStack drop = new ItemStack(log.getType());
- if (menu.fits(drop, getOutputSlots())) {
- menu.pushItem(drop, getOutputSlots());
- log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType());
+ // We try to push the log into the android's inventory, but nothing happens if it does not fit
+ menu.pushItem(drop, getOutputSlots());
- if (log.getY() == android.getRelative(face).getY()) {
- replant(log);
- } else {
- log.setType(Material.AIR);
- }
+ log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType());
+
+ // If the android just chopped the bottom log, we replant the appropriate sapling
+ if (log.getY() == android.getRelative(face).getY()) {
+ replant(log);
+ } else {
+ log.setType(Material.AIR);
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/AutoEnchanter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/AutoEnchanter.java
index 45cfb447f..274bf6337 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/AutoEnchanter.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/enchanting/AutoEnchanter.java
@@ -1,18 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.enchantments.Enchantment;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.EnchantmentStorageMeta;
-
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
+import io.github.thebusybiscuit.slimefun4.api.events.AsyncAutoEnchanterProcessEvent;
import io.github.thebusybiscuit.slimefun4.api.events.AutoEnchantEvent;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@@ -20,6 +9,16 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.EnchantmentStorageMeta;
+
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+import java.util.HashMap;
+import java.util.Map;
/**
* The {@link AutoEnchanter}, in contrast to the {@link AutoDisenchanter}, adds
@@ -65,10 +64,10 @@ public class AutoEnchanter extends AbstractEnchantmentMachine {
return null;
}
- ItemStack secondItem = menu.getItemInSlot(slot);
+ ItemStack enchantedBook = menu.getItemInSlot(slot);
- if (secondItem != null && secondItem.getType() == Material.ENCHANTED_BOOK) {
- return enchant(menu, item, secondItem);
+ if (enchantedBook != null && enchantedBook.getType() == Material.ENCHANTED_BOOK) {
+ return enchant(menu, item, enchantedBook);
}
}
@@ -78,6 +77,14 @@ public class AutoEnchanter extends AbstractEnchantmentMachine {
@Nullable
@ParametersAreNonnullByDefault
protected MachineRecipe enchant(BlockMenu menu, ItemStack target, ItemStack enchantedBook) {
+ // Call an event so other Plugins can modify it.
+ AsyncAutoEnchanterProcessEvent event = new AsyncAutoEnchanterProcessEvent(target, enchantedBook, menu);
+ Bukkit.getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return null;
+ }
+
EnchantmentStorageMeta meta = (EnchantmentStorageMeta) enchantedBook.getItemMeta();
Map enchantments = new HashMap<>();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/teleporter/PortableTeleporter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/teleporter/PortableTeleporter.java
new file mode 100644
index 000000000..8057f4c6b
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/teleporter/PortableTeleporter.java
@@ -0,0 +1,61 @@
+package io.github.thebusybiscuit.slimefun4.implementation.items.teleporter;
+
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import org.bukkit.block.BlockFace;
+import org.bukkit.entity.Player;
+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.attributes.Rechargeable;
+import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
+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;
+import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
+
+/**
+ * This item allows a {@link Player} to access and teleport to his waypoints
+ * from anywhere.
+ *
+ * @author martinbrom
+ *
+ * @see Teleporter
+ */
+public class PortableTeleporter extends SimpleSlimefunItem implements Rechargeable {
+
+ private static final int CAPACITY = 50;
+ private static final int DEFAULT_COST = 10;
+
+ private final ItemSetting cost = new IntRangeSetting(this, "teleportation-cost", 0, DEFAULT_COST, CAPACITY);
+
+ @ParametersAreNonnullByDefault
+ public PortableTeleporter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
+ super(category, item, recipeType, recipe);
+
+ addItemSetting(cost);
+ }
+
+ @Nonnull
+ @Override
+ public ItemUseHandler getItemHandler() {
+ return e -> {
+ ItemStack item = e.getItem();
+ e.cancel();
+
+ if (removeItemCharge(item, cost.getValue())) {
+ Player p = e.getPlayer();
+ SlimefunPlugin.getGPSNetwork().getTeleportationManager().openTeleporterGUI(
+ p, p.getUniqueId(), p.getLocation().getBlock().getRelative(BlockFace.DOWN));
+ }
+ };
+ }
+
+ @Override
+ public float getMaxItemCharge(ItemStack item) {
+ return CAPACITY;
+ }
+}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
index e3befeae2..3036f2484 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ExplosiveTool.java
@@ -156,7 +156,14 @@ public class ExplosiveTool extends SimpleSlimefunItem implements
*/
BlockBreakEvent dummyEvent = new BlockBreakEvent(b, e.getPlayer());
- if (!sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops)) && !dummyEvent.isCancelled()) {
+ /*
+ * Fixes #3036 and handling in general.
+ * Call the BlockBreakHandler if the block has one to allow for proper handling.
+ */
+ sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops));
+
+ // Make sure the event wasn't cancelled by the BlockBreakHandler.
+ if (!dummyEvent.isCancelled()) {
drops.addAll(sfItem.getDrops(p));
b.setType(Material.AIR);
BlockStorage.clearBlockInfo(b);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java
index c2cada5b9..0ad368509 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/GoldPan.java
@@ -94,7 +94,9 @@ public class GoldPan extends SimpleSlimefunItem implements Recip
randomizer.clear();
for (GoldPanDrop setting : drops) {
- randomizer.add(setting.getOutput(), setting.getValue());
+ if (setting.getValue() > 0) {
+ randomizer.add(setting.getOutput(), setting.getValue());
+ }
}
}
@@ -112,11 +114,13 @@ public class GoldPan extends SimpleSlimefunItem implements Recip
return item != null ? item : new ItemStack(Material.AIR);
}
+ @Nonnull
@Override
public String getLabelLocalPath() {
return "guide.tooltips.recipes.gold-pan";
}
+ @Nonnull
@Override
public ItemUseHandler getItemHandler() {
return e -> {
@@ -158,6 +162,7 @@ public class GoldPan extends SimpleSlimefunItem implements Recip
};
}
+ @Nonnull
@Override
public List getDisplayRecipes() {
List recipes = new LinkedList<>();
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/ExplosiveBow.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/ExplosiveBow.java
index e11429d39..10d9661d2 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/ExplosiveBow.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/ExplosiveBow.java
@@ -44,6 +44,7 @@ public class ExplosiveBow extends SlimefunBow {
addItemSetting(range);
}
+ @Nonnull
@Override
public BowShootHandler onShoot() {
return (e, target) -> {
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/IcyBow.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/IcyBow.java
index 78f176113..1c74652cd 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/IcyBow.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/weapons/IcyBow.java
@@ -1,10 +1,12 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
+import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@@ -16,8 +18,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link IcyBow} is a special kind of bow which slows down any
* {@link LivingEntity} it hits.
- *
+ *
* @author TheBusyBiscuit
+ * @author martinbrom
*
*/
public class IcyBow extends SlimefunBow {
@@ -27,9 +30,19 @@ public class IcyBow extends SlimefunBow {
super(category, item, recipe);
}
+ @Nonnull
@Override
public BowShootHandler onShoot() {
return (e, n) -> {
+ if (n instanceof Player) {
+ Player p = (Player) n;
+
+ // Fixes #3060 - Don't apply effects if the arrow was successfully blocked.
+ if (p.isBlocking() && e.getFinalDamage() <= 0) {
+ return;
+ }
+ }
+
n.getWorld().playEffect(n.getLocation(), Effect.STEP_SOUND, Material.ICE);
n.getWorld().playEffect(n.getEyeLocation(), Effect.STEP_SOUND, Material.ICE);
n.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * 2, 10));
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java
index d2dfd5534..81e683b8d 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/AncientAltarListener.java
@@ -225,7 +225,7 @@ public class AncientAltarListener implements Listener {
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_ILLUSIONER_PREPARE_MIRROR, 1, 1);
- AncientAltarTask task = new AncientAltarTask(this, b, altarItem.getSpeed(), result.get(), pedestals, consumed, p);
+ AncientAltarTask task = new AncientAltarTask(this, b, altarItem.getStepDelay(), result.get(), pedestals, consumed, p);
SlimefunPlugin.runSync(task, 10L);
} else {
altars.remove(b);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/NetworkListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/NetworkListener.java
index 98b55adfb..605fc2022 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/NetworkListener.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/NetworkListener.java
@@ -2,12 +2,14 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import javax.annotation.Nonnull;
+import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
+import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEvent;
import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.core.networks.NetworkManager;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@@ -16,6 +18,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
* This {@link Listener} is responsible for all updates to a {@link Network}.
*
* @author meiamsome
+ * @author TheBusyBiscuit
*
* @see Network
* @see NetworkManager
@@ -23,6 +26,9 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
*/
public class NetworkListener implements Listener {
+ /**
+ * Our {@link NetworkManager} instance.
+ */
private final NetworkManager manager;
public NetworkListener(@Nonnull SlimefunPlugin plugin, @Nonnull NetworkManager manager) {
@@ -39,4 +45,12 @@ public class NetworkListener implements Listener {
public void onBlockPlace(BlockPlaceEvent e) {
manager.updateAllNetworks(e.getBlock().getLocation());
}
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onExplosiveToolUse(ExplosiveToolBreakBlocksEvent e) {
+ // Fixes #3013 - Also update networks when using an explosive tool
+ for (Block b : e.getAdditionalBlocks()) {
+ manager.updateAllNetworks(b.getLocation());
+ }
+ }
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TeleporterListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TeleporterListener.java
index a22a795be..daec58682 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TeleporterListener.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/TeleporterListener.java
@@ -59,7 +59,7 @@ public class TeleporterListener implements Listener {
if (teleporter instanceof Teleporter && checkForPylons(b.getRelative(BlockFace.DOWN))) {
Block block = b.getRelative(BlockFace.DOWN);
UUID owner = UUID.fromString(BlockStorage.getLocationInfo(block.getLocation(), "owner"));
- SlimefunPlugin.getGPSNetwork().getTeleportationManager().openTeleporterGUI(p, owner, block, SlimefunPlugin.getGPSNetwork().getNetworkComplexity(owner));
+ SlimefunPlugin.getGPSNetwork().getTeleportationManager().openTeleporterGUI(p, owner, block);
}
}
}
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java
index 8c8015aee..dbe200ead 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/ResearchSetup.java
@@ -287,6 +287,7 @@ public final class ResearchSetup {
register("improved_generators", 275, "Improved Generators", 24, SlimefunItems.COAL_GENERATOR_2, SlimefunItems.LAVA_GENERATOR_2);
register("ingredients_and_cheese", 276, "Slimefun Cuisine", 5, SlimefunItems.SALT, SlimefunItems.WHEAT_FLOUR, SlimefunItems.HEAVY_CREAM, SlimefunItems.CHEESE, SlimefunItems.BUTTER);
register("medium_tier_auto_enchanting", 277, "Fast Automatic Enchanting and Disenchanting", 48, SlimefunItems.AUTO_ENCHANTER_2, SlimefunItems.AUTO_DISENCHANTER_2);
+ register("portable_teleporter", 278, "Teleportation from Anywhere", 42, SlimefunItems.PORTABLE_TELEPORTER);
}
@ParametersAreNonnullByDefault
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
index 44fc8316e..a47fa8df0 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java
@@ -182,6 +182,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner
import io.github.thebusybiscuit.slimefun4.implementation.items.seasonal.ChristmasPresent;
import io.github.thebusybiscuit.slimefun4.implementation.items.seasonal.EasterEgg;
import io.github.thebusybiscuit.slimefun4.implementation.items.teleporter.PersonalActivationPlate;
+import io.github.thebusybiscuit.slimefun4.implementation.items.teleporter.PortableTeleporter;
import io.github.thebusybiscuit.slimefun4.implementation.items.teleporter.SharedActivationPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.teleporter.Teleporter;
import io.github.thebusybiscuit.slimefun4.implementation.items.teleporter.TeleporterPylon;
@@ -1492,7 +1493,7 @@ public final class SlimefunItemSetup {
new SlimefunItemStack(SlimefunItems.ANCIENT_PEDESTAL, 4))
.register(plugin);
- new AncientAltar(categories.magicalGadgets, 8, SlimefunItems.ANCIENT_ALTAR, RecipeType.MAGIC_WORKBENCH,
+ new AncientAltar(categories.magicalGadgets, SlimefunItems.ANCIENT_ALTAR, RecipeType.MAGIC_WORKBENCH,
new ItemStack[] {null, new ItemStack(Material.ENCHANTING_TABLE), null, SlimefunItems.MAGIC_LUMP_3, SlimefunItems.GOLD_8K, SlimefunItems.MAGIC_LUMP_3, new ItemStack(Material.OBSIDIAN), SlimefunItems.GOLD_8K, new ItemStack(Material.OBSIDIAN)})
.register(plugin);
@@ -2221,6 +2222,10 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.GPS_TELEPORTER_PYLON, SlimefunItems.REINFORCED_ALLOY_INGOT, SlimefunItems.GPS_TELEPORTER_PYLON, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.GPS_CONTROL_PANEL, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.GPS_TELEPORTER_PYLON, SlimefunItems.REINFORCED_ALLOY_INGOT, SlimefunItems.GPS_TELEPORTER_PYLON})
.register(plugin);
+ new PortableTeleporter(categories.gps, SlimefunItems.PORTABLE_TELEPORTER, RecipeType.ENHANCED_CRAFTING_TABLE,
+ new ItemStack[] {SlimefunItems.ELECTRO_MAGNET, SlimefunItems.GPS_TRANSMITTER_3, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.REINFORCED_PLATE, SlimefunItems.GPS_TELEPORTATION_MATRIX, SlimefunItems.REINFORCED_PLATE, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.MEDIUM_CAPACITOR, SlimefunItems.BLISTERING_INGOT_3})
+ .register(plugin);
+
new SharedActivationPlate(categories.gps, SlimefunItems.GPS_ACTIVATION_DEVICE_SHARED, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, new ItemStack(Material.STONE_PRESSURE_PLATE), null, new ItemStack(Material.REDSTONE), SlimefunItems.GPS_TRANSMITTER, new ItemStack(Material.REDSTONE), SlimefunItems.BILLON_INGOT, SlimefunItems.BILLON_INGOT, SlimefunItems.BILLON_INGOT})
.register(plugin);
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/AncientAltarTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/AncientAltarTask.java
index 3cb89b6da..ca53ab578 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/AncientAltarTask.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/AncientAltarTask.java
@@ -46,7 +46,7 @@ public class AncientAltarTask implements Runnable {
private final AncientPedestal pedestalItem = (AncientPedestal) SlimefunItems.ANCIENT_PEDESTAL.getItem();
private final Block altar;
- private final int speed;
+ private final int stepDelay;
private final Location dropLocation;
private final ItemStack output;
private final List pedestals;
@@ -60,10 +60,10 @@ public class AncientAltarTask implements Runnable {
private final Player player;
@ParametersAreNonnullByDefault
- public AncientAltarTask(AncientAltarListener listener, Block altar, int speed, ItemStack output, List pedestals, List items, Player player) {
+ public AncientAltarTask(AncientAltarListener listener, Block altar, int stepDelay, ItemStack output, List pedestals, List items, Player player) {
this.listener = listener;
this.dropLocation = altar.getLocation().add(0.5, 1.3, 0.5);
- this.speed = speed;
+ this.stepDelay = stepDelay;
this.altar = altar;
this.output = output;
this.pedestals = pedestals;
@@ -102,7 +102,7 @@ public class AncientAltarTask implements Runnable {
}
this.stage += 1;
- SlimefunPlugin.runSync(this, speed);
+ SlimefunPlugin.runSync(this, stepDelay);
}
private boolean checkLockedItems() {
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java
index 5c75ac863..59694e842 100644
--- a/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java
+++ b/src/main/java/me/mrCookieSlime/Slimefun/api/BlockStorage.java
@@ -59,6 +59,8 @@ public class BlockStorage {
private final Map blocksCache = new ConcurrentHashMap<>();
private static int chunkChanges = 0;
+ private static boolean chunksLoaded = false;
+ private static boolean universalInventoriesLoaded = false;
private int changes = 0;
private AtomicBoolean isMarkedForRemoval = new AtomicBoolean(false);
@@ -214,6 +216,12 @@ public class BlockStorage {
}
private void loadChunks() {
+ if (chunksLoaded) {
+ return;
+ }
+
+ chunksLoaded = true;
+
File chunks = new File(PATH_CHUNKS + "chunks.sfc");
if (chunks.exists()) {
@@ -237,6 +245,12 @@ public class BlockStorage {
if (file.getName().startsWith(world.getName()) && file.getName().endsWith(".sfi")) {
try {
Location l = deserializeLocation(file.getName().replace(".sfi", ""));
+
+ // We only want to only load this world's menus
+ if (world != l.getWorld()) {
+ continue;
+ }
+
io.github.thebusybiscuit.cscorelib2.config.Config cfg = new io.github.thebusybiscuit.cscorelib2.config.Config(file);
BlockMenuPreset preset = BlockMenuPreset.getPreset(cfg.getString("preset"));
@@ -253,6 +267,12 @@ public class BlockStorage {
}
}
+ if (universalInventoriesLoaded) {
+ return;
+ }
+
+ universalInventoriesLoaded = true;
+
for (File file : new File("data-storage/Slimefun/universal-inventories").listFiles()) {
if (file.getName().endsWith(".sfi")) {
try {
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java b/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java
deleted file mode 100644
index 936a7096a..000000000
--- a/src/main/java/me/mrCookieSlime/Slimefun/api/Slimefun.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package me.mrCookieSlime.Slimefun.api;
-
-import org.bukkit.entity.Player;
-
-import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
-import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
-
-/**
- * Provides a few static convenience methods.
- *
- * @deprecated This class is slowly getting stripped away in favour of a more object-oriented approach.
- *
- * @author TheBusyBiscuit
- * @author Walshy
- * @author Poslovitch
- */
-@Deprecated
-public final class Slimefun {
-
- private Slimefun() {}
-
- /**
- * Checks if this player has the permission to use this item.
- *
- * @param p
- * the player to check, not null
- * @param item
- * the item to check, null returns true
- * @param message
- * whether a message should be sent to the player or not
- *
- * @deprecated This method will soon be removed.
- *
- * @return true
if the item is not null and if the player has the permission to use it,
- * false
otherwise.
- */
- @Deprecated
- public static boolean hasPermission(Player p, SlimefunItem item, boolean message) {
- if (item == null) {
- return true;
- } else if (SlimefunPlugin.getPermissionsService().hasPermission(p, item)) {
- return true;
- } else {
- if (message) {
- SlimefunPlugin.getLocalization().sendMessage(p, "messages.no-permission", true);
- }
-
- return false;
- }
- }
-
- /**
- * Checks if this item is enabled in the world this player is in.
- *
- * @param p
- * the player to get the world he is in, not null
- * @param sfItem
- * the item to check, not null
- * @param message
- * whether a message should be sent to the player or not
- *
- * @deprecated Please use {@link SlimefunItem#isDisabledIn(org.bukkit.World)} instead.
- *
- * @return true
if the item is enabled in the world the player is in,
- * false
otherwise.
- */
- @Deprecated
- public static boolean isEnabled(Player p, SlimefunItem sfItem, boolean message) {
- if (sfItem.isDisabled()) {
- if (message) {
- SlimefunPlugin.getLocalization().sendMessage(p, "messages.disabled-item", true);
- }
-
- return false;
- } else if (!SlimefunPlugin.getWorldSettingsService().isEnabled(p.getWorld(), sfItem)) {
- if (message) {
- SlimefunPlugin.getLocalization().sendMessage(p, "messages.disabled-in-world", true);
- }
-
- return false;
- }
- return true;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java
index 3c5412f66..9307b0cab 100644
--- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java
+++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java
@@ -86,6 +86,17 @@ public class DirtyChestMenu extends ChestMenu {
return InvUtils.fits(toInventory(), new ItemStackWrapper(item), slots);
}
+ /**
+ * Adds given {@link ItemStack} to any of the given inventory slots.
+ * Items will be added to the inventory slots based on their order in the function argument.
+ * Items will be added either to any empty inventory slots or any partially filled slots, in which case
+ * as many items as can fit will be added to that specific spot.
+ *
+ * @param item {@link ItemStack} to be added to the inventory
+ * @param slots Numbers of slots to add the {@link ItemStack} to
+ * @return {@link ItemStack} with any items that did not fit into the inventory
+ * or null when everything had fit
+ */
@Nullable
public ItemStack pushItem(ItemStack item, int... slots) {
if (item == null || item.getType() == Material.AIR) {
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index a0f9cd53a..a0240c6d4 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -26,6 +26,7 @@ guide:
researches:
free-in-creative-mode: true
enable-fireworks: true
+ disable-learning-animation: false
URID:
info-delay: 3000
diff --git a/src/main/resources/languages/de/messages.yml b/src/main/resources/languages/de/messages.yml
index dc9381eab..e1d95a960 100644
--- a/src/main/resources/languages/de/messages.yml
+++ b/src/main/resources/languages/de/messages.yml
@@ -75,6 +75,24 @@ guide:
translations:
name: '&aFehlt etwas?'
lore: 'Klicke um eine Übersetzung hinzuzufügen'
+ options:
+ learning-animation:
+ enabled:
+ text:
+ - '&bLern-Animation: &aAn'
+ - ''
+ - '&7Du kannst nun entscheiden, ob'
+ - '&7du eine Animation beim Freischalten von'
+ - '&7Items sehen wirst.'
+ click: '&eKlicke um die Lern-Animation zu deaktivieren'
+ disabled:
+ text:
+ - '&bLern-Animation: &4Aus'
+ - ''
+ - '&7Du kannst nun entscheiden, ob'
+ - '&7du eine Animation beim Freischalten von'
+ - '&7Items sehen wirst.'
+ click: '&eKlicke um die Lern-Animation zu aktivieren'
title:
main: 'Slimefun-Handbuch'
settings: 'Einstellungen & Infos'
@@ -139,6 +157,11 @@ messages:
- ''
- '&eLeft Click &7to temporarily disable the recipe'
- '&eRight Click &7to remove this recipe'
+ disabled:
+ - '&cDieses Rezept ist momentan deaktiviert'
+ - ''
+ - '&eLeft Click &7to re-enable this recipe'
+ - '&eRight Click &7to remove this recipe'
talisman:
anvil: '&a&oDein Talisman hat dein Werkzeug vor dem Zerfall gerettet'
miner: '&a&oDein Talisman hat soeben die Drops verdoppelt'
@@ -197,6 +220,8 @@ messages:
- '&7Always look on the bright side of life!'
- '&7Ist das jetzt ein Keks, Cookie oder ein Biscuit?'
- '&7Jetzt auch zuckerfrei!'
+ pickaxe-of-the-seeker:
+ no-ores: '&cEs konnten keine Erze in deiner Nähe gefunden werden!'
machines:
pattern-not-found: '&eEs tut mir leid, aber ich konnte kein passendes Rezept finden.'
unknown-material: '&eEs tut mir leid, aber ich erkenne das Item in meinem Werfer nicht, probier ein anderes Item aus.'
diff --git a/src/main/resources/languages/en/messages.yml b/src/main/resources/languages/en/messages.yml
index ae6bbac0e..39ffbc636 100644
--- a/src/main/resources/languages/en/messages.yml
+++ b/src/main/resources/languages/en/messages.yml
@@ -91,6 +91,25 @@ guide:
name: '&aIs something missing?'
lore: 'Click to add your own translation'
+ options:
+ learning-animation:
+ enabled:
+ text:
+ - '&bLearning Animation: &aYes'
+ - ''
+ - '&7You can now toggle whether you'
+ - '&7will see information about your pondering in chat'
+ - '&7upon researching an item.'
+ click: '&eClick to disable your learning animation'
+ disabled:
+ text:
+ - '&bLearning Animation: &4No'
+ - ''
+ - '&7You can now toggle whether you'
+ - '&7will see information about your pondering in chat'
+ - '&7upon researching an item.'
+ click: '&eClick to enable your learning animation'
+
title:
main: 'Slimefun Guide'
settings: 'Settings & Info'
diff --git a/src/main/resources/languages/en/researches.yml b/src/main/resources/languages/en/researches.yml
index 123388cd6..12964f3ca 100644
--- a/src/main/resources/languages/en/researches.yml
+++ b/src/main/resources/languages/en/researches.yml
@@ -255,3 +255,4 @@ slimefun:
improved_generators: Improved Generators
ingredients_and_cheese: Slimefun Cuisine
medium_tier_auto_enchanting: Fast Automatic Enchanting and Disenchanting
+ portable_teleporter: Teleportation from Anywhere
diff --git a/src/main/resources/languages/lv/messages.yml b/src/main/resources/languages/lv/messages.yml
index ab2848c44..2595400e5 100644
--- a/src/main/resources/languages/lv/messages.yml
+++ b/src/main/resources/languages/lv/messages.yml
@@ -35,7 +35,7 @@ guide:
languages: 'Izvēlies savu vēlamo valodu,'
credits: 'Slimefun4 Ieguldītāji'
credits:
- commit: "Ieguldījums"
+ commit: 'Ieguldījums'
commits: 'Ieguldījumi'
profile-link: 'Spied, lai apmeklētu GitHub profilu'
roles: