diff --git a/.github/workflows/discord-webhook.yml b/.github/workflows/discord-webhook.yml index f6c11887b..a4845bb6f 100644 --- a/.github/workflows/discord-webhook.yml +++ b/.github/workflows/discord-webhook.yml @@ -4,6 +4,7 @@ on: push: paths: - 'src/**' + - '!src/main/resources/languages/**' - 'pom.xml' jobs: @@ -15,11 +16,13 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@master + uses: actions/checkout@v2.3.3 + - name: Set up Java JDK 11 + uses: actions/setup-java@v1.4.3 with: - java-version: 1.8 + java-version: '11' + java-package: jdk + architecture: x64 - name: Run Discord Webhook uses: Slimefun/discord-webhook@master with: diff --git a/.github/workflows/url-checker.yml b/.github/workflows/url-checker.yml index e0e150008..523248f00 100644 --- a/.github/workflows/url-checker.yml +++ b/.github/workflows/url-checker.yml @@ -4,9 +4,6 @@ on: push: branches: - master - pull_request: - branches: - - master jobs: build: diff --git a/CHANGELOG.md b/CHANGELOG.md index d06dc74d9..e3f22799e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ **Table of contents** -- [Release Candidate 17 (TBD)](#release-candidate-17-tbd) +- [Release Candidate 18 (TBD)](#release-candidate-18-tbd) +- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020) - [Release Candidate 16 (07 Sep 2020)](#release-candidate-16-07-sep-2020) - [Release Candidate 15 (01 Aug 2020)](#release-candidate-15-01-aug-2020) - [Release Candidate 14 (12 Jul 2020)](#release-candidate-14-12-jul-2020) @@ -22,7 +23,16 @@ -## Release Candidate 17 (TBD) +## Release Candidate 18 (TBD) + +#### Additions + +#### Changes +* Removed 1.13 support + +#### Fixes + +## Release Candidate 17 (17 Oct 2020) #### Additions * Added /sf charge @@ -36,11 +46,20 @@ * (API) Added "NotConfigurable" attribute to disable configurability * Added Elytra Cap * Added Planks to Sticks recipe to the Table Saw +* Added "slimefun.gps.bypass" permission to open GPS devices anywhere +* (API) Added custom tags for developers +* The range of the Seeker Pickaxe is now configurable +* Added Energy Connector +* Blackstone can now be turned into lava using a Crucible +* Basalt can now be turned into lava using a Crucible +* Added "Tainted Sheep" (You can dye a Sheep using Strange Nether Goo) +* Added mcMMO support/integration #### Changes * Improved Auto-Updater (Multi-Threading and more) * General performance improvements * /sf cheat now shows seasonal categories all year through +* GPS devices now require chest-access in that area to be used #### Fixes * Fixed #2300 @@ -66,6 +85,24 @@ * Fixed #2391 * Fixed #2403 * Fixed #2405 +* Fixed #2412 +* Fixed #2238 +* Fixed #2439 +* Fixed #2420 +* Fixed #2422 +* Fixed #2433 +* Fixed #2455 +* Fixed #2450 +* Fixed Steel Thrusters being used to milk cows +* Fixed #2424 +* Fixed #2468 +* Fixed #2414 +* Fixed #2454 +* Fixed #2457 +* Fixed #2411 +* Fixed #2423 +* Fixed #2452 +* Fixed a dupe bug with mcMMO ## Release Candidate 16 (07 Sep 2020) https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#16 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9d1e9120..d80ac5dc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -94,3 +94,93 @@ Then you should be able build it via Maven using the goals `clean package`. If you have any further questions, then please join our [Discord Support Server](https://discord.gg/slimefun) and ask your questions in the `#programming-help` channel.
**Note that we will not accept any bug reports from custom-compiled versions of Slimefun**. + +## :black_nib: Code Style guidelines +The general gist when it comes to code style: **Try to be consistent!**.
+Try to stay inline with the code that surrounds you, having an entire package or even a single file that's filled with plenty of different and inconsistent code styles is just hard to read or maintain. That's why we wanna make sure everyone follows these principles. + +*Note that these are just guidelines, we may request changes on your pull request if we think there are changes necessary. +But we won't reject your Pull Request completely due to a few styling inconsistencies, we can always refactor code later. +But do try to follow our code style as best as you can.* + +#### 1. Imports +* Don't use wildcard (`*`) imports! +* Don't import unused classes! +* Don't use static imports! +* Always use imports, even in javadocs, don't write out the full location of a class. +#### 2. Annotations +* Methods and parameters should be annotated with `@Nullable` (`javax.annotation.Nullable`) or `@Nonnull`(`javax.annotation.Nonnull`)! +* Methods that override a method must be annotated with `@Override`! +* Interfaces with only one method should be annotated using `@FunctionalInterface`! +* If you deprecate a method, add an `@deprecated` section to the javadocs explaining why you did it. +#### 3. Documentation +* Every class and every public method should have a Javadocs section assigned to it. +* New packages should have a `package-info.java` file with documentation about the package. +* Classes should have an `@author` tag. +* If there are any other relevant classes related to yours, add them using the `@see` tag. +#### 4. Unit Tests +* Try to write Unit Tests where possible. +* Unit Test classes and methods should have no access modifier, not `public`, `protected` nor `private`. +* Each Test should have a plain text `@DisplayName` annotation! +#### 5. General best-practices +* Do not use `Collection#forEach(x -> ...)`, use a proper `for (...)` loop! +* Do not create new `Random` objects, use `ThreadLocalRandom.current()` instead! +* Always declare Maps or Collections using their base type! (e.g. `List list = new ArrayList<>();`) +* When doing String operations like `String#toUppercase()`, always specify `Locale.ROOT` as an argument! +* When reading or writing files, always specify the encoding using `StandardCharsets.UTF_8`! +* Do not declare multiple fields/variables on the same line! (e.g. Don't do this: `int x, y, z;`) +* Use a Logger, try to avoid `System.out.println(...)` and `Throwable#printStacktrace()`, use `Logger#log` instead! +* Do not use Exceptions to validate data, empty catch blocks are a very bad practice, use other means like a regular expression to validate data. +* If a parameter is annotated with `@Nonnull`, you should enforce this behaviour by doing `Validate.notNull(variable, "...");` and give a meaningful message about what went wrong +* Any `switch/case` should always have a `default:` case at the end. +* If you are working with a resource that must be closed, use a `try/with-resource`, this will automatically close the resource at the end. (e.g. `try (InputStream stream = ...) {`) +* Array designators should be placed behind the type, not the variable name. (e.g. `int[] myArray`) +* Enums must be compared using `==`, not with `.equals()`! +* Avoid direct string concatenation, use a `StringBuilder` instead! +* If you need both the key and the value from a Map, use `Map#entrySet()`! +#### 6. Naming conventions +* Classes should be in *PascalCase* (e.g. `MyAwesomeClass`) +* Enum constants should be in *SCREAMING_SNAKE_CASE* (e.g. `MY_ENUM_CONSTANT`) +* Constants (`static final` fields) should be in *SCREAMING_SNAKE_CASE* (e.g. `MY_CONSTANT_FIELD`) +* Variables, parameters and fields should be in *camelCase* (e.g. `myVariableOrField`) +* All methods should be in *camelCase* (e.g. `myMethod`) +* Packages must be all lowercase, consecutive words should generally be avoided. (e.g. `io.github.thebusybiscuit.slimefun4.core.something`) +#### 7. Style preferences +* Use **Spaces**, not Tabs! +* One class per file! Please don't put multiple classes into one file, this also applies to enums, make a seperate file for new classes or enums. +* Try to keep ternary operators to a minimum, only in return statements. (e.g. avoid doing this: `int y = x == null ? 1: 2`) +* Try to keep so-called "guard blocks" to a minimum. One guard block is fine but having multiple guard blocks before getting to the actual code... Well, you might wanna refactor your code there. Example: +```java +// guard block +if (something) { + return; +} + +// Actual code... +``` +* if/else statements should always include a bracket, please avoid one-line statements. (e.g. Avoid doing: `if (x == 0) return;`) +* We do not enforce any particular width or column limit, just try to prevent your lines from becoming too long. But please avoid line-wrapping. +* Annotations for methods or fields should never go on the same line, place them on the line above. +* Comments should never go on the same line as code! Always above or below. +* Make sure that empty lines are truly empty, they should not contain any whitespace characters. +* Empty blocks like constructors should not occupy more than one line. (e.g. `private MyClass() {}`) +* Modifiers for classes and fields must follow this order:
+`(public/protected/private) (abstract) (static) (final)` +* We recommend using horizontal whitespaces like this: + * In variable assignments: `int x = 123;` + * In a for-loop: `for (int i = 0; i < 10; i++) {` + * Before and after statement parenthesis: `if (x != null) {` + * Inbetween array initializers: `int[] array = { 1, 2, 3 };` + * After the double slash of a comment: `// This is a comment` +* Slimefun follows the **1TBS / OTBS** Bracket-Style standard (One true brace style): +```java +private void example(int x) { + if (x < 0) { + // x < 0 + } else if (x > 0) { + // x > 0 + } else { + // x == 0 + } +} +``` diff --git a/README.md b/README.md index 80f30248b..f531b510d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Here is a full summary of the differences between the two different versions of | | development (latest) | "stable" | | ------------------ | -------- | -------- | -| **Minecraft version(s)** | :video_game: **1.13.\* - 1.16.\*** | :video_game: **1.13.\* - 1.16.\*** | +| **Minecraft version(s)** | :video_game: **1.14.\* - 1.16.\*** | :video_game: **1.13.\* - 1.16.\*** | | **automatic updates** | :heavy_check_mark: | :heavy_check_mark: | | **frequent updates** | :heavy_check_mark: | :x: | | **latest content** | :heavy_check_mark: | :x: | diff --git a/pom.xml b/pom.xml index eba85470d..06d6812a0 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,10 @@ worldedit-repo https://maven.sk89q.com/repo/ + + codemc-repo + https://repo.codemc.org/repository/maven-public + placeholderapi-repo https://repo.extendedclip.com/content/repositories/placeholderapi/ @@ -262,6 +266,7 @@ * + tags/* languages/* @@ -310,7 +315,7 @@ com.github.seeseemelk MockBukkit-v1.16 - 0.10.2 + 0.13.0 test @@ -344,7 +349,7 @@ com.konghq unirest-java - 3.11.00 + 3.11.01 compile @@ -367,6 +372,32 @@ de.schlichtherle truezip + + net.java.truevfs + truevfs-profile-default_2.13 + + + + + com.gmail.nossr50.mcMMO + mcMMO + 2.1.149 + provided + + + + + org.jetbrains + annotations + + + com.sk89q.worldguard + worldguard-core + + + com.sk89q.worldguard + worldguard-legacy + diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java index 2abcada1d..7dbffa628 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java @@ -81,7 +81,7 @@ public class ErrorReport { } stream.println("Slimefun Data:"); - stream.println(" ID: " + item.getID()); + stream.println(" ID: " + item.getId()); stream.println(" Inventory: " + BlockStorage.getStorage(l.getWorld()).hasInventory(l)); stream.println(" Data: " + BlockStorage.getBlockInfoAsJson(l)); stream.println(); @@ -92,7 +92,7 @@ public class ErrorReport { public ErrorReport(T throwable, SlimefunItem item) { this(throwable, item.getAddon(), stream -> { stream.println("SlimefunItem:"); - stream.println(" ID: " + item.getID()); + stream.println(" ID: " + item.getId()); stream.println(" Plugin: " + (item.getAddon() == null ? "Unknown" : item.getAddon().getName())); stream.println(); }); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java index c4c8c0dd5..3f49247a9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/MinecraftVersion.java @@ -14,12 +14,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; */ public enum MinecraftVersion { - /** - * This constant represents Minecraft (Java Edition) Version 1.14 - * (The Update Aquatic) - */ - MINECRAFT_1_13("1.13.x"), - /** * This constant represents Minecraft (Java Edition) Version 1.14 * (The "Village & Pillage" Update) @@ -50,7 +44,7 @@ public enum MinecraftVersion { */ UNIT_TEST("Unit Test Environment"); - public static final MinecraftVersion[] values = values(); + public static final MinecraftVersion[] valuesCache = values(); private final String name; private final String prefix; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/exceptions/TagMisconfigurationException.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/exceptions/TagMisconfigurationException.java new file mode 100644 index 000000000..165f5c3be --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/exceptions/TagMisconfigurationException.java @@ -0,0 +1,48 @@ +package io.github.thebusybiscuit.slimefun4.api.exceptions; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.NamespacedKey; + +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; + +/** + * An {@link TagMisconfigurationException} is thrown whenever a {@link SlimefunTag} + * contains illegal, invalid or unknown values. + * + * @author TheBusyBiscuit + * + */ +public class TagMisconfigurationException extends Exception { + + private static final long serialVersionUID = 5412127960821774280L; + + /** + * This constructs a new {@link TagMisconfigurationException} for the given + * {@link SlimefunTag}'s {@link NamespacedKey} with the provided context. + * + * @param key + * The {@link NamespacedKey} of our {@link SlimefunTag} + * @param message + * The message to display + */ + @ParametersAreNonnullByDefault + public TagMisconfigurationException(NamespacedKey key, String message) { + super("Tag '" + key + "' has been misconfigured: " + message); + } + + /** + * This constructs a new {@link TagMisconfigurationException} for the given + * {@link SlimefunTag}'s {@link NamespacedKey} with the provided context. + * + * @param key + * The {@link NamespacedKey} of our {@link SlimefunTag} + * @param cause + * The {@link Throwable} which has caused this to happen + */ + @ParametersAreNonnullByDefault + public TagMisconfigurationException(NamespacedKey key, Throwable cause) { + super("Tag '" + key + "' has been misconfigured (" + cause.getMessage() + ')', cause); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java index b8fcbc218..81eb79474 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/geo/ResourceManager.java @@ -201,15 +201,19 @@ public class ResourceManager { menu.addItem(47, ChestMenuUtils.getPreviousButton(p, page + 1, pages)); menu.addMenuClickHandler(47, (pl, slot, item, action) -> { - if (page > 0) + if (page > 0) { scan(pl, block, page - 1); + } + return false; }); menu.addItem(51, ChestMenuUtils.getNextButton(p, page + 1, pages)); menu.addMenuClickHandler(51, (pl, slot, item, action) -> { - if (page + 1 < pages) + if (page + 1 < pages) { scan(pl, block, page + 1); + } + return false; }); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java index 1e7d7e311..649a0ea48 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/gps/GPSNetwork.java @@ -148,10 +148,12 @@ public class GPSNetwork { int index = 0; for (Location l : getTransmitters(p.getUniqueId())) { - if (index >= inventory.length) + if (index >= inventory.length) { break; + } SlimefunItem sfi = BlockStorage.check(l); + if (sfi instanceof GPSTransmitter) { int slot = inventory[index]; @@ -216,8 +218,10 @@ public class GPSNetwork { int index = 0; for (Waypoint waypoint : profile.getWaypoints()) { - if (index >= inventory.length) + if (index >= inventory.length) { break; + } + int slot = inventory[index]; Location l = waypoint.getLocation(); 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 e81bcf6a4..eb0ee827a 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 @@ -92,8 +92,9 @@ public final class TeleportationManager { @ParametersAreNonnullByDefault public int getTeleportationTime(int complexity, Location source, Location destination) { - if (complexity < 100) + if (complexity < 100) { return 100; + } int speed = 50_000 + complexity * complexity; return 1 + Math.min(4 * distanceSquared(source, destination) / speed, 40); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/HashedArmorpiece.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/HashedArmorpiece.java index 15b25a0bc..f1efceeb6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/HashedArmorpiece.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/HashedArmorpiece.java @@ -102,7 +102,7 @@ public final class HashedArmorpiece { @Override public String toString() { - return "HashedArmorpiece {hash=" + hash + ",item=" + item.map(SlimefunItem::getID).orElse("null") + '}'; + return "HashedArmorpiece {hash=" + hash + ",item=" + item.map(SlimefunItem::getId).orElse("null") + '}'; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSetting.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSetting.java index 7eedda655..e51ff0bcb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSetting.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/ItemSetting.java @@ -119,6 +119,17 @@ public class ItemSetting { return c.isInstance(defaultValue); } + /** + * This is an error message which should provide further context on what values + * are allowed. + * + * @return An error message which is displayed when this {@link ItemSetting} is misconfigured. + */ + @Nonnull + protected String getErrorMessage() { + return "Only '" + defaultValue.getClass().getSimpleName() + "' values are allowed!"; + } + /** * This method is called by a {@link SlimefunItem} which wants to load its {@link ItemSetting} * from the {@link Config} file. @@ -128,20 +139,33 @@ public class ItemSetting { */ @SuppressWarnings("unchecked") public void load(@Nonnull SlimefunItem item) { - SlimefunPlugin.getItemCfg().setDefaultValue(item.getID() + '.' + getKey(), getDefaultValue()); - Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getID() + '.' + getKey()); + SlimefunPlugin.getItemCfg().setDefaultValue(item.getId() + '.' + getKey(), getDefaultValue()); + Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getId() + '.' + getKey()); if (defaultValue.getClass().isInstance(configuredValue)) { - this.value = (T) configuredValue; + if (validateInput((T) configuredValue)) { + this.value = (T) configuredValue; + } 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() }); + Slimefun.getLogger().log(Level.WARNING, "{0} is not a valid input!", configuredValue); + Slimefun.getLogger().log(Level.WARNING, getErrorMessage()); + } } else { this.value = defaultValue; String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName(); Slimefun.getLogger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!"); Slimefun.getLogger().log(Level.WARNING, "Please only use settings that are valid."); - Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getID(), getKey() }); + Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() }); Slimefun.getLogger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found }); } } + @Override + public String toString() { + T currentValue = this.value != null ? this.value : defaultValue; + return getClass().getSimpleName() + " {" + getKey() + " = " + currentValue + " (default: " + getDefaultValue() + ")"; + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/DoubleRangeSetting.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/DoubleRangeSetting.java new file mode 100644 index 000000000..86b02ac05 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/DoubleRangeSetting.java @@ -0,0 +1,63 @@ +package io.github.thebusybiscuit.slimefun4.api.items.settings; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.apache.commons.lang.Validate; + +import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; + +/** + * This variation of {@link ItemSetting} allows you to define an {@link Double} range + * and enforces this range using the {@link #validateInput(Double)} method. + * + * @author TheBusyBiscuit + * + * @see ItemSetting + * @see IntRangeSetting + * + */ +public class DoubleRangeSetting extends ItemSetting { + + private final double min; + private final double max; + + @ParametersAreNonnullByDefault + public DoubleRangeSetting(String key, double min, double defaultValue, double max) { + super(key, defaultValue); + Validate.isTrue(defaultValue >= min && defaultValue <= max, "The default value is not in range."); + + this.min = min; + this.max = max; + } + + @Nonnull + @Override + protected String getErrorMessage() { + return "Only decimal numbers from " + min + '-' + max + "(inclusive) are allowed!"; + } + + @Override + public boolean validateInput(Double input) { + return super.validateInput(input) && input >= min && input <= max; + } + + /** + * This returns the minimum value of this {@link DoubleRangeSetting}. + * + * @return The minimum value + */ + public final double getMinimum() { + return min; + } + + /** + * This returns the maximum value of this {@link DoubleRangeSetting}. + * + * @return The maximum value + */ + public final double getMaximum() { + return max; + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/EnumSetting.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/EnumSetting.java new file mode 100644 index 000000000..d952286af --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/EnumSetting.java @@ -0,0 +1,72 @@ +package io.github.thebusybiscuit.slimefun4.api.items.settings; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; + +/** + * This variation of {@link ItemSetting} allows you to allow {@link Enum} constants to be + * used for {@link ItemSetting} validation. + * + * @author TheBusyBiscuit + * + * @see ItemSetting + * + */ +public class EnumSetting> extends ItemSetting { + + private final Class enumClass; + + @ParametersAreNonnullByDefault + public EnumSetting(String key, Class enumClass, T defaultValue) { + super(key, defaultValue.name()); + + this.enumClass = enumClass; + } + + @Nonnull + @Override + protected String getErrorMessage() { + String values = Arrays.stream(getAllowedValues()).map(Enum::name).collect(Collectors.joining(", ")); + return "The following values are valid: " + values; + } + + /** + * This returns an array of valid {@link Enum} values. + * This method may be overridden to further limit the allowed values. + * + * @return An array of allowed {@link Enum} constants + */ + public T[] getAllowedValues() { + return enumClass.getEnumConstants(); + } + + /** + * This will attempt to get the configured value as a constant of the desired {@link Enum}. + * + * @return The value as an {@link Enum} constant + */ + public T getAsEnumConstant() { + return Enum.valueOf(enumClass, getValue()); + } + + @Override + public boolean validateInput(String input) { + if (!super.validateInput(input)) { + return false; + } else { + for (Enum value : getAllowedValues()) { + if (value.name().equals(input)) { + return true; + } + } + + return false; + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/IntRangeSetting.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/IntRangeSetting.java new file mode 100644 index 000000000..f4b41ed38 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/IntRangeSetting.java @@ -0,0 +1,63 @@ +package io.github.thebusybiscuit.slimefun4.api.items.settings; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.apache.commons.lang.Validate; + +import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; + +/** + * This variation of {@link ItemSetting} allows you to define an {@link Integer} range + * and enforces this range using the {@link #validateInput(Integer)} method. + * + * @author TheBusyBiscuit + * + * @see ItemSetting + * @see DoubleRangeSetting + * + */ +public class IntRangeSetting extends ItemSetting { + + private final int min; + private final int max; + + @ParametersAreNonnullByDefault + public IntRangeSetting(String key, int min, int defaultValue, int max) { + super(key, defaultValue); + Validate.isTrue(defaultValue >= min && defaultValue <= max, "The default value is not in range."); + + this.min = min; + this.max = max; + } + + @Nonnull + @Override + protected String getErrorMessage() { + return "Only whole numbers from " + min + '-' + max + "(inclusive) are allowed!"; + } + + @Override + public boolean validateInput(Integer input) { + return super.validateInput(input) && input >= min && input <= max; + } + + /** + * This returns the minimum value of this {@link IntRangeSetting}. + * + * @return The minimum value + */ + public final int getMinimum() { + return min; + } + + /** + * This returns the maximum value of this {@link IntRangeSetting}. + * + * @return The maximum value + */ + public final int getMaximum() { + return max; + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/MaterialTagSetting.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/MaterialTagSetting.java new file mode 100644 index 000000000..b856d5614 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/MaterialTagSetting.java @@ -0,0 +1,83 @@ +package io.github.thebusybiscuit.slimefun4.api.items.settings; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.Material; +import org.bukkit.Tag; + +import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; + +/** + * This variation of {@link ItemSetting} allows you to define a default {@link Tag}. + * The {@link Tag} will be translated into a {@link String} {@link List} which the user + * can then configure as they wish. + * + * It also validates all inputs to be a valid {@link Material}. + * + * @author TheBusyBiscuit + * + * @see ItemSetting + * + */ +public class MaterialTagSetting extends ItemSetting> { + + private final Tag defaultTag; + + @ParametersAreNonnullByDefault + public MaterialTagSetting(String key, Tag defaultTag) { + super(key, getAsStringList(defaultTag)); + + this.defaultTag = defaultTag; + } + + /** + * This {@link Tag} holds the default values for this {@link MaterialTagSetting}. + * + * @return The default {@link Tag} + */ + @Nonnull + public Tag getDefaultTag() { + return defaultTag; + } + + @Nonnull + @Override + protected String getErrorMessage() { + return "This List can only contain Materials in the format of e.g. REDSTONE_BLOCK"; + } + + @Override + public boolean validateInput(List input) { + if (super.validateInput(input)) { + for (String value : input) { + Material material = Material.matchMaterial(value); + + // This value is not a valid material, the setting is not valid. + if (material == null) { + return false; + } + } + + return true; + } else { + return false; + } + } + + /** + * Internal method to turn a {@link Tag} into a {@link List} of {@link String Strings}. + * + * @param tag + * Our {@link Tag} + * @return The {@link String} {@link List} + */ + @Nonnull + private static List getAsStringList(@Nonnull Tag tag) { + return tag.getValues().stream().map(Material::name).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/package-info.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/package-info.java new file mode 100644 index 000000000..2f6bea34c --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/items/settings/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains various sub classes of {@link io.github.thebusybiscuit.slimefun4.api.items.ItemSetting}. + */ +package io.github.thebusybiscuit.slimefun4.api.items.settings; \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java index e0f2086f2..336a6bfbe 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/PlayerBackpack.java @@ -28,13 +28,14 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListe */ public class PlayerBackpack { + private static final String CONFIG_PREFIX = "backpacks."; + private final PlayerProfile profile; private final int id; private final Config cfg; private Inventory inventory; private int size; - private static final String CONFIG_PREFIX = "backpacks."; /** * This constructor loads an existing Backpack diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/StatusEffect.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/StatusEffect.java index c108221ce..12a364457 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/StatusEffect.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/player/StatusEffect.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; + import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import org.bukkit.Keyed; import org.bukkit.NamespacedKey; @@ -27,10 +29,11 @@ public class StatusEffect implements Keyed { private final NamespacedKey key; - public StatusEffect(NamespacedKey key) { + public StatusEffect(@Nonnull NamespacedKey key) { this.key = key; } + @Nonnull @Override public NamespacedKey getKey() { return key; @@ -48,7 +51,7 @@ public class StatusEffect implements Keyed { * @param unit * The {@link TimeUnit} for the given duration */ - public void add(Player p, int duration, TimeUnit unit) { + public void add(@Nonnull Player p, int duration, @Nonnull TimeUnit unit) { add(p, 1, duration, unit); } @@ -64,7 +67,7 @@ public class StatusEffect implements Keyed { * @param unit * The {@link TimeUnit} for the given duration */ - public void add(Player p, int level, int duration, TimeUnit unit) { + public void add(@Nonnull Player p, int level, int duration, @Nonnull TimeUnit unit) { PersistentDataAPI.setString(p, getKey(), level + ";" + System.currentTimeMillis() + unit.toMillis(duration)); } @@ -77,7 +80,7 @@ public class StatusEffect implements Keyed { * @param level * The level of this effect */ - public void addPermanent(Player p, int level) { + public void addPermanent(@Nonnull Player p, int level) { PersistentDataAPI.setString(p, getKey(), level + ";0"); } @@ -91,7 +94,7 @@ public class StatusEffect implements Keyed { * The {@link Player} to check for * @return Whether this {@link StatusEffect} is currently applied */ - public boolean isPresent(Player p) { + public boolean isPresent(@Nonnull Player p) { Optional optional = PersistentDataAPI.getOptionalString(p, getKey()); if (optional.isPresent()) { @@ -104,8 +107,9 @@ public class StatusEffect implements Keyed { clear(p); return false; } - } else + } else { return false; + } } /** @@ -116,15 +120,16 @@ public class StatusEffect implements Keyed { * The {@link Player} to check for * @return An {@link OptionalInt} that describes the result */ - public OptionalInt getLevel(Player p) { + @Nonnull + public OptionalInt getLevel(@Nonnull Player p) { Optional optional = PersistentDataAPI.getOptionalString(p, getKey()); if (optional.isPresent()) { String[] data = PatternUtils.SEMICOLON.split(optional.get()); return OptionalInt.of(Integer.parseInt(data[0])); - - } else + } else { return OptionalInt.empty(); + } } /** @@ -133,7 +138,7 @@ public class StatusEffect implements Keyed { * @param p * The {@link Player} to clear it from */ - public void clear(Player p) { + public void clear(@Nonnull Player p) { PersistentDataAPI.remove(p, getKey()); } 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 1b05dbcf1..538a1dc49 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/SlimefunRegistry.java @@ -11,6 +11,9 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nonnull; + +import org.apache.commons.lang.Validate; import org.bukkit.Server; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -19,14 +22,12 @@ import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.collections.KeyMap; import io.github.thebusybiscuit.cscorelib2.config.Config; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock; import io.github.thebusybiscuit.slimefun4.core.researching.Research; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide; import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide; @@ -47,7 +48,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu; * @author TheBusyBiscuit * */ -public class SlimefunRegistry { +public final class SlimefunRegistry { private final Map slimefunIds = new HashMap<>(); private final List slimefunItems = new ArrayList<>(); @@ -86,7 +87,9 @@ public class SlimefunRegistry { private final Map automatedCraftingChamberRecipes = new HashMap<>(); - public void load(Config cfg) { + public void load(@Nonnull Config cfg) { + Validate.notNull(cfg, "The Config cannot be null!"); + boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes"); layouts.put(SlimefunGuideLayout.CHEST, new ChestSlimefunGuide(showVanillaRecipes)); @@ -95,7 +98,7 @@ public class SlimefunRegistry { researchRanks.addAll(cfg.getStringList("research-ranks")); - backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility") || SlimefunPlugin.getMinecraftVersion().isBefore(MinecraftVersion.MINECRAFT_1_14); + backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility"); freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode"); researchFireworks = cfg.getBoolean("researches.enable-fireworks"); logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/EnergyNetComponent.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/EnergyNetComponent.java index 06123f1e3..6d2e1504d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/EnergyNetComponent.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/EnergyNetComponent.java @@ -66,6 +66,12 @@ public interface EnergyNetComponent extends ItemAttribute { */ default int getCharge(@Nonnull Location l) { Validate.notNull(l, "Location 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"); if (charge != null) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java index f19af55a5..b0e47b1a5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/RechargeableHelper.java @@ -13,7 +13,6 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import net.md_5.bungee.api.ChatColor; @@ -39,9 +38,7 @@ final class RechargeableHelper { BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP); float value = decimal.floatValue(); - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value); - } + meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value); List lore = meta.hasLore() ? meta.getLore() : new ArrayList<>(); for (int i = 0; i < lore.size(); i++) { @@ -59,13 +56,11 @@ final class RechargeableHelper { } static float getCharge(@Nonnull ItemMeta meta) { - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT); + Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT); - // If persistent data is available, we just return this value - if (value != null) { - return value; - } + // If persistent data is available, we just return this value + if (value != null) { + return value; } // If no persistent data exists, we will just fall back to the lore diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/SlimefunTabCompleter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/SlimefunTabCompleter.java index b061f475e..e22d222ec 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/SlimefunTabCompleter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/SlimefunTabCompleter.java @@ -99,7 +99,7 @@ class SlimefunTabCompleter implements TabCompleter { List list = new ArrayList<>(items.size()); for (SlimefunItem item : items) { - list.add(item.getID()); + list.add(item.getId()); } return list; 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 dacdb30e2..8bc1d7e2d 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 @@ -49,8 +49,9 @@ class ResearchCommand extends SubCommand { } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.not-online", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1])); } - } else + } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true); + } } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf research ")); } 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 11abe9817..1bb18b3e6 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 @@ -29,8 +29,9 @@ class StatsCommand extends SubCommand { } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.not-online", true, msg -> msg.replace("%player%", args[1])); } - } else + } else { SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true); + } } else if (sender instanceof Player) { PlayerProfile.get((Player) sender, profile -> profile.sendStats(sender)); } else { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java index 0fd23d500..94970ac43 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuide.java @@ -78,15 +78,20 @@ public final class SlimefunGuide { } public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideLayout layout, int selectedPage) { - if (category == null) + if (category == null) { return; + } + SlimefunPlugin.getRegistry().getGuideLayout(layout).openCategory(profile, category, selectedPage); } public static void openSearch(PlayerProfile profile, String input, boolean survival, boolean addToHistory) { SlimefunGuideImplementation layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST); - if (!survival) + + if (!survival) { layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEAT_SHEET); + } + layout.openSearch(profile, input, addToHistory); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideLayout.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideLayout.java index 278352c9d..562fe5981 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideLayout.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/SlimefunGuideLayout.java @@ -31,6 +31,6 @@ public enum SlimefunGuideLayout { */ CHEAT_SHEET; - public static final SlimefunGuideLayout[] values = values(); + public static final SlimefunGuideLayout[] valuesCache = values(); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideLayoutOption.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideLayoutOption.java index cf19b812d..38564d077 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideLayoutOption.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/guide/options/GuideLayoutOption.java @@ -98,7 +98,7 @@ class GuideLayoutOption implements SlimefunGuideOption { @Override public Optional getSelectedOption(Player p, ItemStack guide) { - for (SlimefunGuideLayout layout : SlimefunGuideLayout.values) { + for (SlimefunGuideLayout layout : SlimefunGuideLayout.valuesCache) { if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true, false)) { return Optional.of(layout); } 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 7c132d44f..1ed862a13 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 @@ -12,7 +12,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import io.github.thebusybiscuit.slimefun4.core.services.localization.Language; @@ -41,11 +40,8 @@ public final class SlimefunGuideSettings { static { options.add(new GuideLayoutOption()); - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - options.add(new FireworksOption()); - options.add(new PlayerLanguageOption()); - } + options.add(new FireworksOption()); + options.add(new PlayerLanguageOption()); } private SlimefunGuideSettings() {} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java index 5cd2867ea..4ba7ed63a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/handlers/RainbowTickHandler.java @@ -1,6 +1,9 @@ package io.github.thebusybiscuit.slimefun4.core.handlers; import java.util.Arrays; +import java.util.List; + +import javax.annotation.Nonnull; import org.apache.commons.lang.Validate; import org.bukkit.Material; @@ -10,7 +13,6 @@ import org.bukkit.block.data.BlockData; import org.bukkit.block.data.type.GlassPane; import io.github.thebusybiscuit.cscorelib2.collections.LoopIterator; -import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollection; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RainbowBlock; @@ -34,18 +36,22 @@ public class RainbowTickHandler extends BlockTicker { private final boolean glassPanes; private Material material; - public RainbowTickHandler(Material... materials) { + public RainbowTickHandler(@Nonnull List materials) { Validate.noNullElements(materials, "A RainbowTicker cannot have a Material that is null!"); - if (materials.length == 0) { + if (materials.isEmpty()) { throw new IllegalArgumentException("A RainbowTicker must have at least one Material associated with it!"); } glassPanes = containsGlassPanes(materials); - iterator = new LoopIterator<>(Arrays.asList(materials)); + iterator = new LoopIterator<>(materials); material = iterator.next(); } + public RainbowTickHandler(Material... materials) { + this(Arrays.asList(materials)); + } + /** * This method checks whether a given {@link Material} array contains any {@link Material} * that would result in a {@link GlassPane} {@link BlockData}. @@ -57,7 +63,7 @@ public class RainbowTickHandler extends BlockTicker { * * @return Whether the array contained any {@link GlassPane} materials */ - private boolean containsGlassPanes(Material[] materials) { + private boolean containsGlassPanes(@Nonnull List materials) { if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) { // BlockData is not available to us during Unit Tests :/ return false; @@ -75,10 +81,6 @@ public class RainbowTickHandler extends BlockTicker { return false; } - public RainbowTickHandler(MaterialCollection collection) { - this(collection.getAsArray()); - } - @Override public void tick(Block b, SlimefunItem item, Config data) { if (b.getType() == Material.AIR) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java index 83bb966b2..49b80dd9a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/multiblocks/MultiBlock.java @@ -41,10 +41,8 @@ public class MultiBlock { SUPPORTED_TAGS.add(Tag.LOGS); SUPPORTED_TAGS.add(Tag.WOODEN_TRAPDOORS); SUPPORTED_TAGS.add(Tag.WOODEN_SLABS); + SUPPORTED_TAGS.add(Tag.WOODEN_FENCES); - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - SUPPORTED_TAGS.add(Tag.WOODEN_FENCES); - } if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) { SUPPORTED_TAGS.add(Tag.FIRE); } @@ -119,7 +117,7 @@ public class MultiBlock { @Override public int hashCode() { - return Objects.hash(item.getID(), blocks, trigger, isSymmetric); + return Objects.hash(item.getId(), blocks, trigger, isSymmetric); } private boolean compareBlocks(Material a, @Nullable Material b) { @@ -161,6 +159,6 @@ public class MultiBlock { @Override public String toString() { - return "MultiBlock (" + item.getID() + ") {" + Arrays.toString(blocks) + "}"; + return "MultiBlock (" + item.getId() + ") {" + Arrays.toString(blocks) + "}"; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java index 81c8051c2..b7e5fabab 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/cargo/CargoUtils.java @@ -18,10 +18,10 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import io.papermc.lib.PaperLib; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.Slimefun.api.BlockStorage; @@ -54,6 +54,10 @@ final class CargoUtils { Material type = block.getType(); + if (SlimefunTag.SHULKER_BOXES.isTagged(type)) { + return true; + } + switch (type) { case CHEST: case TRAPPED_CHEST: @@ -62,28 +66,13 @@ final class CargoUtils { case DROPPER: case HOPPER: case BREWING_STAND: - case SHULKER_BOX: + case BARREL: + case BLAST_FURNACE: + case SMOKER: return true; default: - break; + return false; } - - if (type.name().endsWith("_SHULKER_BOX")) { - return true; - } - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - switch (type) { - case BARREL: - case BLAST_FURNACE: - case SMOKER: - return true; - default: - break; - } - } - - return false; } static int[] getInputSlotRange(@Nonnull Inventory inv, @Nullable ItemStack item) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java index c009dbab2..02eea2d4b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNet.java @@ -70,6 +70,7 @@ public class EnergyNet extends Network { return null; } else { switch (component.getEnergyComponentType()) { + case CONNECTOR: case CAPACITOR: return NetworkComponent.CONNECTOR; case CONSUMER: @@ -272,6 +273,20 @@ public class EnergyNet extends Network { return null; } + /** + * This attempts to get an {@link EnergyNet} from a given {@link Location}. + * If no suitable {@link EnergyNet} could be found, {@code null} will be returned. + * + * @param l + * The target {@link Location} + * + * @return The {@link EnergyNet} at that {@link Location}, or {@code null} + */ + @Nullable + public static EnergyNet getNetworkFromLocation(@Nonnull Location l) { + return SlimefunPlugin.getNetworkManager().getNetworkFromLocation(l, EnergyNet.class).orElse(null); + } + /** * This attempts to get an {@link EnergyNet} from a given {@link Location}. * If no suitable {@link EnergyNet} could be found, a new one will be created. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNetComponentType.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNetComponentType.java index fe62f19ad..ef05a8466 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNetComponentType.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/networks/energy/EnergyNetComponentType.java @@ -4,6 +4,7 @@ import org.bukkit.block.Block; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor; +import io.github.thebusybiscuit.slimefun4.implementation.items.electric.EnergyConnector; import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.Reactor; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; @@ -13,6 +14,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; * can have. * * @author TheBusyBiscuit + * @author Linox * * @see EnergyNetComponent * @see EnergyNet @@ -38,6 +40,12 @@ public enum EnergyNetComponentType { */ CONSUMER, + /** + * A Connector transmits energy through the network. + * Also see: {@link EnergyConnector} + */ + CONNECTOR, + /** * A fallback value to use when a {@link Block} cannot be classified as any of the * other options. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java index 9dd1449f8..c9c577681 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java @@ -11,9 +11,6 @@ import org.bukkit.block.TileState; import org.bukkit.persistence.PersistentDataHolder; import org.bukkit.plugin.Plugin; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - /** * The {@link BlockDataService} is similar to the {@link CustomItemDataService}, * it is responsible for storing NBT data inside a {@link TileState}. @@ -83,9 +80,8 @@ public class BlockDataService implements PersistentDataService, Keyed { * @return Whether the given {@link Material} is considered a Tile Entity */ public boolean isTileEntity(Material type) { - if (type == null || !SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - // We can only store data on Tile Entities in 1.14+ - // So we will just return false here in that case. + if (type == null || type.isAir()) { + // Cannot store data on air return false; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java index d5ce5225b..5587ad8b2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/CustomTextureService.java @@ -10,8 +10,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import io.github.thebusybiscuit.cscorelib2.config.Config; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; @@ -64,9 +62,9 @@ public class CustomTextureService { for (SlimefunItem item : items) { if (item != null) { - config.setDefaultValue(item.getID(), 0); + config.setDefaultValue(item.getId(), 0); - if (config.getInt(item.getID()) != 0) { + if (config.getInt(item.getId()) != 0) { modified = true; } } @@ -101,10 +99,7 @@ public class CustomTextureService { public void setTexture(@Nonnull ItemMeta im, @Nonnull String id) { int data = getModelData(id); - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - im.setCustomModelData(data == 0 ? null : data); - } + im.setCustomModelData(data == 0 ? null : data); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index 2da170c23..5835e9f86 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -48,12 +48,7 @@ public class MetricsService { private boolean hasDownloadedUpdate = false; static { - Unirest.config() - .concurrency(2, 1) - .setDefaultHeader("User-Agent", "MetricsModule Auto-Updater") - .setDefaultHeader("Accept", "application/vnd.github.v3+json") - .enableCookieManagement(false) - .cookieSpec("ignoreCookies"); + Unirest.config().concurrency(2, 1).setDefaultHeader("User-Agent", "MetricsModule Auto-Updater").setDefaultHeader("Accept", "application/vnd.github.v3+json").enableCookieManagement(false).cookieSpec("ignoreCookies"); } public MetricsService(@Nonnull SlimefunPlugin plugin) { @@ -221,7 +216,7 @@ public class MetricsService { return true; } } catch (UnirestException e) { - plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the builds page. Perhaps GitHub is down?"); + plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the builds page. Perhaps GitHub is down? Response: {0}", e.getMessage()); } catch (IOException e) { plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the new one. Please do this manually! Error: {0}", e.getMessage()); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java index 9c76ef6c7..8e11d9563 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PerWorldSettingsService.java @@ -85,7 +85,7 @@ public class PerWorldSettingsService { return false; } - return !items.contains(item.getID()); + return !items.contains(item.getId()); } /** @@ -105,9 +105,9 @@ public class PerWorldSettingsService { Set items = disabledItems.computeIfAbsent(world.getUID(), id -> loadWorldFromConfig(world)); if (enabled) { - items.remove(item.getID()); + items.remove(item.getId()); } else { - items.add(item.getID()); + items.add(item.getId()); } } @@ -178,7 +178,7 @@ public class PerWorldSettingsService { for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) { if (item != null) { String addon = item.getAddon().getName().toLowerCase(Locale.ROOT); - config.setValue(addon + '.' + item.getID(), !items.contains(item.getID())); + config.setValue(addon + '.' + item.getId(), !items.contains(item.getId())); } } @@ -222,7 +222,7 @@ public class PerWorldSettingsService { if (item != null) { String addon = item.getAddon().getName().toLowerCase(Locale.ROOT); config.setDefaultValue(addon + ".enabled", true); - config.setDefaultValue(addon + '.' + item.getID(), true); + config.setDefaultValue(addon + '.' + item.getId(), true); // Whether the entire addon has been disabled boolean isAddonDisabled = config.getBoolean(addon + ".enabled"); @@ -232,8 +232,8 @@ public class PerWorldSettingsService { blacklist.add(worldName); } - if (!isAddonDisabled || !config.getBoolean(addon + '.' + item.getID())) { - items.add(item.getID()); + if (!isAddonDisabled || !config.getBoolean(addon + '.' + item.getId())) { + items.add(item.getId()); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java index 63b2fbe62..920896ab2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PermissionsService.java @@ -41,12 +41,12 @@ public class PermissionsService { public void register(@Nonnull Iterable items, boolean save) { for (SlimefunItem item : items) { if (item != null) { - String path = item.getID() + ".permission"; + String path = item.getId() + ".permission"; config.setDefaultValue(path, "none"); - config.setDefaultValue(item.getID() + ".lore", new String[] { "&rYou do not have the permission", "&rto access this item." }); + config.setDefaultValue(item.getId() + ".lore", new String[] { "&rYou do not have the permission", "&rto access this item." }); - permissions.put(item.getID(), config.getString(path)); + permissions.put(item.getId(), config.getString(path)); } } @@ -72,7 +72,7 @@ public class PermissionsService { return true; } - String permission = permissions.get(item.getID()); + String permission = permissions.get(item.getId()); return permission == null || permission.equals("none") || p.hasPermission(permission); } @@ -89,7 +89,7 @@ public class PermissionsService { @Nonnull public Optional getPermission(@Nonnull SlimefunItem item) { Validate.notNull(item, "Cannot get permissions for null"); - String permission = permissions.get(item.getID()); + String permission = permissions.get(item.getId()); if (permission == null || permission.equals("none")) { return Optional.empty(); @@ -108,7 +108,7 @@ public class PermissionsService { */ public void setPermission(@Nonnull SlimefunItem item, @Nullable String permission) { Validate.notNull(item, "You cannot set the permission for null"); - permissions.put(item.getID(), permission != null ? permission : "none"); + permissions.put(item.getId(), permission != null ? permission : "none"); } /** @@ -124,7 +124,7 @@ public class PermissionsService { @Nonnull public List getLore(@Nonnull SlimefunItem item) { - List lore = config.getStringList(item.getID() + ".lore"); + List lore = config.getStringList(item.getId() + ".lore"); return lore == null ? Arrays.asList("LORE NOT FOUND") : lore; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java index 8a1035d74..b1792f546 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/PersistentDataService.java @@ -7,32 +7,29 @@ import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataHolder; import org.bukkit.persistence.PersistentDataType; +import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; /** * This interface is used to defer calls to Persistent Data and make sure they are only called * if the {@link MinecraftVersion} supports it. * * @author TheBusyBiscuit + * + * @deprecated This is redundant, we can use {@link PersistentDataAPI} instead. * */ +@Deprecated interface PersistentDataService { default void setString(Object obj, NamespacedKey key, String value) { - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && obj instanceof PersistentDataHolder) { - PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer(); - container.set(key, PersistentDataType.STRING, value); - } + PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer(); + container.set(key, PersistentDataType.STRING, value); } default Optional getString(Object obj, NamespacedKey key) { - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && obj instanceof PersistentDataHolder) { - PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer(); - return Optional.ofNullable(container.get(key, PersistentDataType.STRING)); - } - - return Optional.empty(); + PersistentDataContainer container = ((PersistentDataHolder) obj).getPersistentDataContainer(); + return Optional.ofNullable(container.get(key, PersistentDataType.STRING)); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java index baa099769..0f9e3e317 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java @@ -94,7 +94,7 @@ abstract class GitHubConnector { } } catch (UnirestException e) { if (github.isLoggingEnabled()) { - Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time."); + Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time.", e); } // It has the cached file, let's just read that then diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java index 5401465fb..932bf7060 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java @@ -88,7 +88,7 @@ class GitHubTask implements Runnable { } catch (IOException x) { // Too many requests Slimefun.getLogger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() }); - Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is down or started to rate-limit this connection, this is not an error message!"); + Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is temporarily down or started to rate-limit this connection, this is not an error message!"); // Retry after 5 minutes if it was rate-limiting if (x.getMessage().contains("429")) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java index 390f3a469..dc1bea4b1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SlimefunLocalization.java @@ -85,7 +85,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed protected abstract void addLanguage(@Nonnull String id, @Nonnull String texture); protected void loadEmbeddedLanguages() { - for (SupportedLanguage lang : SupportedLanguage.values) { + for (SupportedLanguage lang : SupportedLanguage.valuesCache) { if (lang.isReadyForRelease() || SlimefunPlugin.getUpdater().getBranch() != SlimefunBranch.STABLE) { addLanguage(lang.getLanguageId(), lang.getTexture()); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SupportedLanguage.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SupportedLanguage.java index 76287f772..a6381a059 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SupportedLanguage.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/SupportedLanguage.java @@ -58,7 +58,7 @@ enum SupportedLanguage { MACEDONIAN("mk", false, "a0e0b0b5d87a855466980a101a757bcdb5f77d9f7287889f3efa998ee0472fc0"), TAGALOG("tl", true, "9306c0c1ce6a9c61bb42a572c49e6d0ed20e0e6b3d122cc64c339cbf78e9e937"); - public static final SupportedLanguage[] values = values(); + public static final SupportedLanguage[] valuesCache = values(); private final String id; private final boolean releaseReady; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java index 80a235dbe..dd5f95a95 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/localization/Translators.java @@ -99,6 +99,9 @@ public class Translators { addTranslator("Dr4gonD", "DragonD", SupportedLanguage.DUTCH, true); addTranslator("svr333", SupportedLanguage.DUTCH, false); addTranslator("PabloMarcendo", SupportedLanguage.DUTCH, true); + addTranslator("milvantiou", SupportedLanguage.DUTCH, true); + addTranslator("Sven313D", SupportedLanguage.DUTCH, true); + addTranslator("TypischTeun", SupportedLanguage.DUTCH, true); // Translators - Danish addTranslator("Mini-kun", SupportedLanguage.DANISH, true); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java similarity index 75% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java index 3722fcfd6..212bb1f3f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagHook.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ClearLagIntegration.java @@ -11,11 +11,19 @@ import org.bukkit.event.Listener; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; +import me.minebuilders.clearlag.Clearlag; import me.minebuilders.clearlag.events.EntityRemoveEvent; -class ClearLagHook implements Listener { +/** + * This handles all integrations with {@link Clearlag}. + * We don't want it to clear our altar items. + * + * @author TheBusyBiscuit + * + */ +class ClearLagIntegration implements Listener { - ClearLagHook(@Nonnull SlimefunPlugin plugin) { + ClearLagIntegration(@Nonnull SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java index ecd2fd7b0..486c59af8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/EmeraldEnchantsCategory.java @@ -12,6 +12,7 @@ import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory; import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout; import me.mrCookieSlime.EmeraldEnchants.EnchantmentGuide; +@Deprecated class EmeraldEnchantsCategory extends FlexCategory { public EmeraldEnchantsCategory(@Nonnull NamespacedKey key) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java new file mode 100644 index 000000000..553627469 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/McMMOIntegration.java @@ -0,0 +1,60 @@ +package io.github.thebusybiscuit.slimefun4.core.services.plugins; + +import javax.annotation.Nonnull; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.events.skills.salvage.McMMOPlayerSalvageCheckEvent; + +import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem; +import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; + +/** + * This handles all integrations with {@link mcMMO}. + * + * @author TheBusyBiscuit + * + */ +class McMMOIntegration implements Listener { + + McMMOIntegration(@Nonnull SlimefunPlugin plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlacerPlace(BlockPlacerPlaceEvent e) { + // This registers blocks placed by the BlockPlacer as "player-placed" + mcMMO.getPlaceStore().setTrue(e.getBlock()); + } + + @EventHandler(ignoreCancelled = true) + public void onItemSalvage(McMMOPlayerSalvageCheckEvent e) { + // Prevent Slimefun items from being salvaged + if (!isSalvageable(e.getSalvageItem())) { + e.setCancelled(true); + SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "anvil.mcmmo-salvaging"); + } + } + + /** + * This method checks if an {@link ItemStack} can be salvaged or not. + * We basically don't want players to salvage any {@link SlimefunItem} unless + * it is a {@link VanillaItem}. + * + * @param item + * The {@link ItemStack} to check + * + * @return Whether this item can be safely salvaged + */ + private boolean isSalvageable(@Nonnull ItemStack item) { + SlimefunItem sfItem = SlimefunItem.getByItem(item); + return sfItem == null || sfItem instanceof VanillaItem; + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java similarity index 93% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java index 892729663..d49426458 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIHook.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/PlaceholderAPIIntegration.java @@ -13,14 +13,21 @@ import org.bukkit.entity.Player; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.researching.Research; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.expansion.PlaceholderExpansion; -class PlaceholderAPIHook extends PlaceholderExpansion { +/** + * This is our integration for {@link PlaceholderAPI}. + * + * @author TheBusyBiscuit + * + */ +class PlaceholderAPIIntegration extends PlaceholderExpansion { private final String version; private final String author; - public PlaceholderAPIHook(@Nonnull SlimefunPlugin plugin) { + public PlaceholderAPIIntegration(@Nonnull SlimefunPlugin plugin) { this.version = plugin.getDescription().getVersion(); this.author = plugin.getDescription().getAuthors().toString(); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java index 877aac6b1..4bf85071f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/ThirdPartyPluginService.java @@ -5,12 +5,16 @@ import java.util.function.Function; import java.util.logging.Level; import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; +import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import com.gmail.nossr50.events.fake.FakeBlockBreakEvent; + import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon; import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; @@ -31,25 +35,41 @@ public class ThirdPartyPluginService { private final SlimefunPlugin plugin; + private boolean initialized = false; private boolean isExoticGardenInstalled = false; private boolean isChestTerminalInstalled = false; private boolean isEmeraldEnchantsInstalled = false; - private boolean isCoreProtectInstalled = false; - private boolean isPlaceholderAPIInstalled = false; + private boolean isMcMMOInstalled = false; - // Overridden if ExoticGarden is loaded + /** + * This gets overridden if ExoticGarden is loaded + */ private Function> exoticGardenIntegration = b -> Optional.empty(); + /** + * This initializes the {@link ThirdPartyPluginService} + * + * @param plugin + * Our instance of {@link SlimefunPlugin} + */ public ThirdPartyPluginService(@Nonnull SlimefunPlugin plugin) { this.plugin = plugin; } + /** + * This method initializes all third party integrations. + */ public void start() { + if (initialized) { + throw new UnsupportedOperationException("Third Party Integrations have already been initialized!"); + } + + initialized = true; + if (isPluginInstalled("PlaceholderAPI")) { try { - PlaceholderAPIHook hook = new PlaceholderAPIHook(plugin); + PlaceholderAPIIntegration hook = new PlaceholderAPIIntegration(plugin); hook.register(); - isPlaceholderAPIInstalled = true; } catch (Exception | LinkageError x) { String version = plugin.getServer().getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion(); @@ -69,7 +89,7 @@ public class ThirdPartyPluginService { if (isPluginInstalled("WorldEdit")) { try { Class.forName("com.sk89q.worldedit.extent.Extent"); - new WorldEditHook(); + new WorldEditIntegration(); } catch (Exception | LinkageError x) { String version = plugin.getServer().getPluginManager().getPlugin("WorldEdit").getDescription().getVersion(); @@ -78,6 +98,21 @@ public class ThirdPartyPluginService { } } + // mcMMO Integration + if (isPluginInstalled("mcMMO")) { + try { + // This makes sure that the FakeEvent interface is present. + // Class.forName("com.gmail.nossr50.events.fake.FakeEvent"); + + new McMMOIntegration(plugin); + isMcMMOInstalled = true; + } catch (Exception | LinkageError x) { + String version = plugin.getServer().getPluginManager().getPlugin("mcMMO").getDescription().getVersion(); + Slimefun.getLogger().log(Level.WARNING, "Maybe consider updating mcMMO or Slimefun?"); + Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to hook into mcMMO v" + version); + } + } + /* * These Items are not marked as soft-dependencies and * therefore need to be loaded after the Server has finished @@ -85,7 +120,7 @@ public class ThirdPartyPluginService { */ plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { if (isPluginInstalled("ClearLag")) { - new ClearLagHook(plugin); + new ClearLagIntegration(plugin); } isChestTerminalInstalled = isPluginInstalled("ChestTerminal"); @@ -101,6 +136,7 @@ public class ThirdPartyPluginService { } } + @ParametersAreNonnullByDefault public void loadExoticGarden(Plugin plugin, Function> method) { if (plugin.getName().equals("ExoticGarden")) { isExoticGardenInstalled = true; @@ -120,16 +156,22 @@ public class ThirdPartyPluginService { return isEmeraldEnchantsInstalled; } - public boolean isCoreProtectInstalled() { - return isCoreProtectInstalled; - } - - public boolean isPlaceholderAPIInstalled() { - return isPlaceholderAPIInstalled; - } - public Optional harvestExoticGardenPlant(Block block) { return exoticGardenIntegration.apply(block); } + /** + * This checks if one of our third party integrations faked an {@link Event}. + * Faked {@link Event Events} should be ignored in our logic. + * + * @param event + * The {@link Event} to test + * + * @return Whether this is a fake event + */ + public boolean isEventFaked(@Nonnull Event event) { + // TODO: Change this to FakeEvent once the new mcMMO build was released + return isMcMMOInstalled && event instanceof FakeBlockBreakEvent; + } + } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java similarity index 86% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java index 3b134df92..38af34726 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditHook.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/plugins/WorldEditIntegration.java @@ -14,9 +14,16 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import me.mrCookieSlime.Slimefun.api.BlockStorage; -class WorldEditHook { +/** + * This handles all integrations with {@link WorldEdit}. + * If an are is cleared, we also wanna clear all Slimefun-related block data. + * + * @author TheBusyBiscuit + * + */ +class WorldEditIntegration { - WorldEditHook() { + WorldEditIntegration() { WorldEdit.getInstance().getEventBus().register(this); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/PerformanceRating.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/PerformanceRating.java index b03191c6c..b1417b523 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/PerformanceRating.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/PerformanceRating.java @@ -31,7 +31,7 @@ public enum PerformanceRating implements Predicate { HURTFUL(ChatColor.DARK_RED, 500), BAD(ChatColor.DARK_RED, Float.MAX_VALUE); - public static final PerformanceRating[] values = values(); + public static final PerformanceRating[] valuesCache = values(); private final ChatColor color; private final float threshold; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/ProfiledBlock.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/ProfiledBlock.java index c89707a9b..8a4e68d0d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/ProfiledBlock.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/ProfiledBlock.java @@ -46,7 +46,7 @@ class ProfiledBlock { } public String getId() { - return item.getID(); + return item.getId(); } public SlimefunAddon getAddon() { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java index d123c37c4..5a0d92d9a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/profiler/SlimefunProfiler.java @@ -296,7 +296,7 @@ public class SlimefunProfiler { public PerformanceRating getPerformance() { float percentage = getPercentageOfTick(); - for (PerformanceRating rating : PerformanceRating.values) { + for (PerformanceRating rating : PerformanceRating.valuesCache) { if (rating.test(percentage)) { return rating; } @@ -344,7 +344,7 @@ public class SlimefunProfiler { public String getTime(@Nonnull SlimefunItem item) { Validate.notNull("Cannot get timings for a null SlimefunItem"); - long time = getByItem().getOrDefault(item.getID(), 0L); + long time = getByItem().getOrDefault(item.getId(), 0L); return NumberUtils.getAsMillis(time); } 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 6c4cd245e..68c8b2d88 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunItems.java @@ -581,14 +581,14 @@ public final class SlimefunItems { public static final SlimefunItemStack ENHANCED_CRAFTING_TABLE = new SlimefunItemStack("ENHANCED_CRAFTING_TABLE", Material.CRAFTING_TABLE, "&eEnhanced Crafting Table", "", "&aA regular Crafting Table cannot", "&ahold this massive Amount of Power..."); public static final SlimefunItemStack GRIND_STONE = new SlimefunItemStack("GRIND_STONE", Material.DISPENSER, "&bGrind Stone", "", "&aGrinds items down into other items"); public static final SlimefunItemStack ARMOR_FORGE = new SlimefunItemStack("ARMOR_FORGE", Material.ANVIL, "&6Armor Forge", "", "&aGives you the ability to create powerful armor"); - public static final SlimefunItemStack MAKESHIFT_SMELTERY; + public static final SlimefunItemStack MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.BLAST_FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots"); public static final SlimefunItemStack SMELTERY = new SlimefunItemStack("SMELTERY", Material.FURNACE, "&6Smeltery", "", "&fA high-temperature furnace", "&fthat allows you to smelt dusts", "&finto ingots and create alloys."); public static final SlimefunItemStack ORE_CRUSHER = new SlimefunItemStack("ORE_CRUSHER", Material.DISPENSER, "&bOre Crusher", "", "&aCrushes ores to double them"); public static final SlimefunItemStack COMPRESSOR = new SlimefunItemStack("COMPRESSOR", Material.PISTON, "&bCompressor", "", "&aCompresses Items"); public static final SlimefunItemStack PRESSURE_CHAMBER = new SlimefunItemStack("PRESSURE_CHAMBER", Material.GLASS, "&bPressure Chamber", "", "&aCompresses Items even further"); public static final SlimefunItemStack MAGIC_WORKBENCH = new SlimefunItemStack("MAGIC_WORKBENCH", Material.CRAFTING_TABLE, "&6Magic Workbench", "", "&dInfuses Items with magical Energy"); public static final SlimefunItemStack ORE_WASHER = new SlimefunItemStack("ORE_WASHER", Material.CAULDRON, "&6Ore Washer", "", "&aWashes Sifted Ore to filter Ores", "&aand gives you small Stone Chunks"); - public static final SlimefunItemStack TABLE_SAW; + public static final SlimefunItemStack TABLE_SAW = new SlimefunItemStack("TABLE_SAW", Material.STONECUTTER, "&6Table Saw", "", "&aAllows you to get 8 planks from 1 Log", "&a(Works with all log types)"); public static final SlimefunItemStack JUICER = new SlimefunItemStack("JUICER", Material.GLASS_BOTTLE, "&aJuicer", "", "&aAllows you to create delicious Juice"); public static final SlimefunItemStack AUTOMATED_PANNING_MACHINE = new SlimefunItemStack("AUTOMATED_PANNING_MACHINE", Material.BOWL, "&eAutomated Panning Machine", "", "&fA MultiBlock Version of the Gold Pan", "&fand Nether Gold Pan combined in one machine."); @@ -676,22 +676,22 @@ public final class SlimefunItems { public static final SlimefunItemStack ELECTRIC_ORE_GRINDER = new SlimefunItemStack("ELECTRIC_ORE_GRINDER", Material.FURNACE, "&cElectric Ore Grinder", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12)); public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_2 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_2", Material.FURNACE, "&cElectric Ore Grinder &7(&eII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(4), LoreBuilder.powerPerSecond(30)); public static final SlimefunItemStack ELECTRIC_INGOT_PULVERIZER = new SlimefunItemStack("ELECTRIC_INGOT_PULVERIZER", Material.FURNACE, "&cElectric Ingot Pulverizer", "", "&fPulverizes Ingots into Dust", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(14)); - public static final SlimefunItemStack AUTO_DRIER; + public static final SlimefunItemStack AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10)); public static final SlimefunItemStack AUTO_ENCHANTER = new SlimefunItemStack("AUTO_ENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Enchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18)); public static final SlimefunItemStack AUTO_DISENCHANTER = new SlimefunItemStack("AUTO_DISENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Disenchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18)); public static final SlimefunItemStack AUTO_ANVIL = new SlimefunItemStack("AUTO_ANVIL", Material.IRON_BLOCK, "&7Auto Anvil", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &7Repair Factor: 10%", LoreBuilder.powerPerSecond(24)); public static final SlimefunItemStack AUTO_ANVIL_2 = new SlimefunItemStack("AUTO_ANVIL_2", Material.IRON_BLOCK, "&7Auto Anvil Mk.II", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Repair Factor: 25%", LoreBuilder.powerPerSecond(32)); - public static final SlimefunItemStack AUTO_BREWER; + public static final SlimefunItemStack AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.SMOKER, "&6Auto Brewer", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12)); public static final SlimefunItemStack BIO_REACTOR = new SlimefunItemStack("BIO_REACTOR", Material.LIME_TERRACOTTA, "&2Bio Reactor", "", LoreBuilder.machine(MachineTier.AVERAGE, MachineType.GENERATOR), LoreBuilder.powerBuffer(128), LoreBuilder.powerPerSecond(8)); public static final SlimefunItemStack MULTIMETER = new SlimefunItemStack("MULTIMETER", Material.CLOCK, "&eMultimeter", "", "&fMeasures the Amount of stored", "&fEnergy in a Block"); - public static final SlimefunItemStack SMALL_CAPACITOR = new SlimefunItemStack("SMALL_CAPACITOR", HeadTexture.CAPACITOR_25, "&aSmall Energy Capacitor", "", LoreBuilder.machine(MachineTier.BASIC, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7128 J Capacity"); - public static final SlimefunItemStack MEDIUM_CAPACITOR = new SlimefunItemStack("MEDIUM_CAPACITOR", HeadTexture.CAPACITOR_25, "&aMedium Energy Capacitor", "", LoreBuilder.machine(MachineTier.AVERAGE, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7512 J Capacity"); - public static final SlimefunItemStack BIG_CAPACITOR = new SlimefunItemStack("BIG_CAPACITOR", HeadTexture.CAPACITOR_25, "&aBig Energy Capacitor", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &71024 J Capacity"); - public static final SlimefunItemStack LARGE_CAPACITOR = new SlimefunItemStack("LARGE_CAPACITOR", HeadTexture.CAPACITOR_25, "&aLarge Energy Capacitor", "", LoreBuilder.machine(MachineTier.GOOD, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &78192 J Capacity"); - public static final SlimefunItemStack CARBONADO_EDGED_CAPACITOR = new SlimefunItemStack("CARBONADO_EDGED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aCarbonado Edged Energy Capacitor", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &765536 J Capacity"); - public static final SlimefunItemStack ENERGIZED_CAPACITOR = new SlimefunItemStack("ENERGIZED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aEnergized Energy Capacitor", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7524288 J Capacity"); + public static final SlimefunItemStack SMALL_CAPACITOR = new SlimefunItemStack("SMALL_CAPACITOR", HeadTexture.CAPACITOR_25, "&aSmall Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.BASIC, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7128 J Capacity"); + public static final SlimefunItemStack MEDIUM_CAPACITOR = new SlimefunItemStack("MEDIUM_CAPACITOR", HeadTexture.CAPACITOR_25, "&aMedium Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.AVERAGE, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7512 J Capacity"); + public static final SlimefunItemStack BIG_CAPACITOR = new SlimefunItemStack("BIG_CAPACITOR", HeadTexture.CAPACITOR_25, "&aBig Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &71024 J Capacity"); + public static final SlimefunItemStack LARGE_CAPACITOR = new SlimefunItemStack("LARGE_CAPACITOR", HeadTexture.CAPACITOR_25, "&aLarge Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.GOOD, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &78192 J Capacity"); + public static final SlimefunItemStack CARBONADO_EDGED_CAPACITOR = new SlimefunItemStack("CARBONADO_EDGED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aCarbonado Edged Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &765536 J Capacity"); + public static final SlimefunItemStack ENERGIZED_CAPACITOR = new SlimefunItemStack("ENERGIZED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aEnergized Energy Capacitor", LoreBuilder.range(6), "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7524288 J Capacity"); /* Robots */ public static final SlimefunItemStack PROGRAMMABLE_ANDROID = new SlimefunItemStack("PROGRAMMABLE_ANDROID", HeadTexture.PROGRAMMABLE_ANDROID, "&cProgrammable Android &7(Normal)", "", "&8\u21E8 &7Function: None", "&8\u21E8 &7Fuel Efficiency: 1.0x"); @@ -764,6 +764,7 @@ public final class SlimefunItems { public static final SlimefunItemStack BLISTERING_INGOT_3 = new SlimefunItemStack("BLISTERING_INGOT_3", Material.GOLD_INGOT, "&6Blistering Ingot", "", LoreBuilder.radioactive(Radioactivity.VERY_HIGH), LoreBuilder.HAZMAT_SUIT_REQUIRED); public static final SlimefunItemStack ENERGY_REGULATOR = new SlimefunItemStack("ENERGY_REGULATOR", HeadTexture.ENERGY_REGULATOR, "&6Energy Regulator", "", "&fCore Component of an Energy Network"); + public static final SlimefunItemStack ENERGY_CONNECTOR = new SlimefunItemStack("ENERGY_CONNECTOR", HeadTexture.ENERGY_CONNECTOR, "&eEnergy Connector", LoreBuilder.range(6), "", "&fPlace this between machines", "&fand generators to connect them", "&fto your regulator."); public static final SlimefunItemStack DEBUG_FISH = new SlimefunItemStack("DEBUG_FISH", Material.SALMON, "&3How much is the Fish?", "", "&eRight Click &fany Block to view it's BlockData", "&eLeft Click &fto break a Block", "&eShift + Left Click &fany Block to erase it's BlockData", "&eShift + Right Click &fto place a Placeholder Block"); public static final SlimefunItemStack NETHER_ICE = new SlimefunItemStack("NETHER_ICE", HeadTexture.NETHER_ICE, "&eNether Ice", "", LoreBuilder.radioactive(Radioactivity.MODERATE), LoreBuilder.HAZMAT_SUIT_REQUIRED); @@ -854,17 +855,5 @@ public final class SlimefunItems { static { INFUSED_ELYTRA.addUnsafeEnchantment(Enchantment.MENDING, 1); - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - TABLE_SAW = new SlimefunItemStack("TABLE_SAW", Material.STONECUTTER, "&6Table Saw", "", "&aAllows you to get 8 planks from 1 Log", "&a(Works with all log types)"); - MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.BLAST_FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots"); - AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10)); - AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.SMOKER, "&6Auto Brewer", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12)); - } else { - TABLE_SAW = null; - MAKESHIFT_SMELTERY = new SlimefunItemStack("MAKESHIFT_SMELTERY", Material.FURNACE, "&eMakeshift Smeltery", "", "&fImprovised version of the Smeltery", "&fthat only allows you to", "&fsmelt dusts into ingots"); - AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.FURNACE, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10)); - AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.BREWING_STAND, "&6Auto Brewer", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12)); - } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java index 517135ba1..23bfb15fb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java @@ -30,6 +30,7 @@ import io.github.thebusybiscuit.cscorelib2.protection.ProtectionManager; import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon; +import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException; import io.github.thebusybiscuit.slimefun4.api.gps.GPSNetwork; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.SlimefunRegistry; @@ -89,10 +90,15 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunItemL import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener; -import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.VillagerTradingListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.WitherListener; import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.AnvilListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.BrewingStandListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CartographyTableListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CauldronListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.CraftingTableListener; +import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.GrindstoneListener; import io.github.thebusybiscuit.slimefun4.implementation.resources.GEOResourcesSetup; import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup; import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup; @@ -100,6 +106,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.setup.SlimefunItemSetup import io.github.thebusybiscuit.slimefun4.implementation.tasks.ArmorTask; import io.github.thebusybiscuit.slimefun4.implementation.tasks.SlimefunStartupTask; import io.github.thebusybiscuit.slimefun4.implementation.tasks.TickerTask; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import io.papermc.lib.PaperLib; import me.mrCookieSlime.CSCoreLibPlugin.CSCoreLib; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer; @@ -175,10 +182,14 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { command.register(); registry.load(config); } else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) { + getLogger().log(Level.INFO, "CS-CoreLib was detected!"); long timestamp = System.nanoTime(); - PaperLib.suggestPaper(this); + if (PaperLib.isPaper()) { + getLogger().log(Level.INFO, "Paper was detected! Performance optimizations have been applied."); + } + // We wanna ensure that the Server uses a compatible version of Minecraft if (isVersionUnsupported()) { getServer().getPluginManager().disablePlugin(this); @@ -229,6 +240,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { getLogger().log(Level.INFO, "Loading GEO-Resources..."); GEOResourcesSetup.setup(); + getLogger().log(Level.INFO, "Loading Tags..."); + loadTags(); + getLogger().log(Level.INFO, "Loading items..."); loadItems(); @@ -267,7 +281,10 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes")); ticker.start(this); + + getLogger().log(Level.INFO, "Loading Third-Party plugin integrations..."); thirdPartySupportService.start(); + gitHubService.start(this); // Hooray! @@ -311,7 +328,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { String currentVersion = ReflectionUtils.getVersion(); if (currentVersion.startsWith("v")) { - for (MinecraftVersion version : MinecraftVersion.values) { + for (MinecraftVersion version : MinecraftVersion.valuesCache) { if (version.matches(currentVersion)) { minecraftVersion = version; return false; @@ -338,7 +355,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { private Collection getSupportedVersions() { List list = new ArrayList<>(); - for (MinecraftVersion version : MinecraftVersion.values) { + for (MinecraftVersion version : MinecraftVersion.valuesCache) { if (version != MinecraftVersion.UNKNOWN) { list.add(version.getName()); } @@ -442,7 +459,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { new DeathpointListener(this); new ExplosionsListener(this); new DebugFishListener(this); - new VanillaMachinesListener(this); new FireworksListener(this); new WitherListener(this); new IronGolemListener(this); @@ -450,6 +466,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { new MobDropListener(this); new VillagerTradingListener(this); new ElytraCrashListener(this); + new CraftingTableListener(this); + new AnvilListener(this); + new BrewingStandListener(this); + new CauldronListener(this); + new GrindstoneListener(this); + new CartographyTableListener(this); if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) { new BeeListener(this); @@ -491,6 +513,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { new PlayerProfileListener(this); } + private void loadTags() { + for (SlimefunTag tag : SlimefunTag.valuesCache) { + try { + tag.reload(); + } catch (TagMisconfigurationException e) { + getLogger().log(Level.SEVERE, e, () -> "Failed to load Tag: " + tag.name()); + } + } + } + private void loadItems() { try { SlimefunItemSetup.setup(this); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java index 0a26c0a7f..59b081e82 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/BookSlimefunGuide.java @@ -208,7 +208,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation { } private void addSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List items) { - NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getID().toLowerCase(Locale.ROOT)); + NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getId().toLowerCase(Locale.ROOT)); if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) { Research research = item.getResearch(); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java index 5ca33706b..cbab11d87 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/guide/ChestSlimefunGuide.java @@ -1,7 +1,5 @@ package io.github.thebusybiscuit.slimefun4.implementation.guide; -import javax.annotation.Nonnull; - import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; @@ -10,6 +8,8 @@ import java.util.Locale; import java.util.Optional; import java.util.logging.Level; +import javax.annotation.Nonnull; + import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Sound; @@ -26,7 +26,6 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatInput; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.recipes.MinecraftRecipe; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory; @@ -68,18 +67,12 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation { private final ItemStack item; private final int[] recipeSlots = { 3, 4, 5, 12, 13, 14, 21, 22, 23 }; - private final Sound sound; + private final Sound sound = Sound.ITEM_BOOK_PAGE_TURN; private final boolean showVanillaRecipes; public ChestSlimefunGuide(boolean vanillaRecipes) { showVanillaRecipes = vanillaRecipes; item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Chest GUI)"); - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - sound = Sound.ITEM_BOOK_PAGE_TURN; - } else { - sound = Sound.ENTITY_BAT_TAKEOFF; - } } @Override @@ -233,16 +226,22 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation { menu.addItem(46, ChestMenuUtils.getPreviousButton(p, page, pages)); menu.addMenuClickHandler(46, (pl, slot, item, action) -> { int next = page - 1; - if (next != page && next > 0) + + if (next != page && next > 0) { openCategory(profile, category, next); + } + return false; }); menu.addItem(52, ChestMenuUtils.getNextButton(p, page, pages)); menu.addMenuClickHandler(52, (pl, slot, item, action) -> { int next = page + 1; - if (next != page && next <= pages) + + if (next != page && next <= pages) { openCategory(profile, category, next); + } + return false; }); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java index 62a0d6318..80cc207cd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/altar/AncientPedestal.java @@ -2,6 +2,10 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.altar; import java.util.Optional; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; @@ -17,7 +21,9 @@ import org.bukkit.util.Vector; import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; +import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.listeners.AncientAltarListener; import io.github.thebusybiscuit.slimefun4.implementation.tasks.AncientAltarTask; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; @@ -39,14 +45,15 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; * @see AncientAltarTask * */ -public class AncientPedestal extends SlimefunItem { +public class AncientPedestal extends SimpleSlimefunItem { public static final String ITEM_PREFIX = ChatColors.color("&dALTAR &3Probe - &e"); + @ParametersAreNonnullByDefault public AncientPedestal(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) { super(category, item, recipeType, recipe, recipeOutput); - SlimefunItem.registerBlockHandler(getID(), (p, b, tool, reason) -> { + SlimefunItem.registerBlockHandler(getId(), (p, b, tool, reason) -> { Optional entity = getPlacedItem(b); if (entity.isPresent()) { @@ -63,7 +70,13 @@ public class AncientPedestal extends SlimefunItem { }); } - public Optional getPlacedItem(Block pedestal) { + @Override + public BlockDispenseHandler getItemHandler() { + return (e, d, block, machine) -> e.setCancelled(true); + } + + @Nonnull + public Optional getPlacedItem(@Nonnull Block pedestal) { Location l = pedestal.getLocation().add(0.5, 1.2, 0.5); for (Entity n : l.getWorld().getNearbyEntities(l, 0.5, 0.5, 0.5, this::testItem)) { @@ -75,7 +88,7 @@ public class AncientPedestal extends SlimefunItem { return Optional.empty(); } - private boolean testItem(Entity n) { + private boolean testItem(@Nullable Entity n) { if (n instanceof Item && n.isValid()) { Item item = (Item) n; ItemMeta meta = item.getItemStack().getItemMeta(); @@ -86,7 +99,8 @@ public class AncientPedestal extends SlimefunItem { } } - public ItemStack getOriginalItemStack(Item item) { + @Nonnull + public ItemStack getOriginalItemStack(@Nonnull Item item) { ItemStack stack = item.getItemStack().clone(); String customName = item.getCustomName(); @@ -108,7 +122,7 @@ public class AncientPedestal extends SlimefunItem { return stack; } - public void placeItem(Player p, Block b) { + public void placeItem(@Nonnull Player p, @Nonnull Block b) { ItemStack hand = p.getInventory().getItemInMainHand(); ItemStack displayItem = new CustomItem(hand, ITEM_PREFIX + System.nanoTime()); displayItem.setAmount(1); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidInterface.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidInterface.java new file mode 100644 index 000000000..2e745be60 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidInterface.java @@ -0,0 +1,34 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.androids; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.bukkit.inventory.ItemStack; + +import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler; +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; + +/** + * The {@link AndroidInterface} are inventories used to interact with a {@link ProgrammableAndroid}. + * There are two variants of interfaces, fuel and items. + * + * @author TheBusyBiscuit + * + * @see ProgrammableAndroid + * + */ +public class AndroidInterface extends SimpleSlimefunItem { + + @ParametersAreNonnullByDefault + public AndroidInterface(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { + super(category, item, recipeType, recipe); + } + + @Override + public BlockDispenseHandler getItemHandler() { + return (e, d, block, machine) -> e.setCancelled(true); + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java index 060bb6b81..e46721c84 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java @@ -10,8 +10,6 @@ import org.bukkit.block.data.Ageable; import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; @@ -57,10 +55,6 @@ public class FarmerAndroid extends ProgrammableAndroid { private ItemStack getDropFromCrop(Material crop) { Random random = ThreadLocalRandom.current(); - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && crop == Material.SWEET_BERRY_BUSH) { - return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1); - } - switch (crop) { case WHEAT: return new ItemStack(Material.WHEAT, random.nextInt(2) + 1); @@ -74,6 +68,8 @@ public class FarmerAndroid extends ProgrammableAndroid { return new ItemStack(Material.COCOA_BEANS, random.nextInt(3) + 1); case NETHER_WART: return new ItemStack(Material.NETHER_WART, random.nextInt(3) + 1); + case SWEET_BERRY_BUSH: + return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1); default: return null; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java index 085895521..de83525a7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FisherAndroid.java @@ -4,14 +4,12 @@ import java.util.concurrent.ThreadLocalRandom; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; import io.github.thebusybiscuit.cscorelib2.collections.RandomizedSet; -import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections; -import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; @@ -25,7 +23,7 @@ public class FisherAndroid extends ProgrammableAndroid { super(category, tier, item, recipeType, recipe); // Fish - for (Material fish : MaterialCollections.getAllFishItems()) { + for (Material fish : Tag.ITEMS_FISHES.getValues()) { fishingLoot.add(new ItemStack(fish), 25); } @@ -37,10 +35,7 @@ public class FisherAndroid extends ProgrammableAndroid { fishingLoot.add(new ItemStack(Material.STICK), 5); fishingLoot.add(new ItemStack(Material.ROTTEN_FLESH), 3); fishingLoot.add(new ItemStack(Material.LEATHER), 2); - - if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) { - fishingLoot.add(new ItemStack(Material.BAMBOO), 3); - } + fishingLoot.add(new ItemStack(Material.BAMBOO), 3); // "loot" fishingLoot.add(new ItemStack(Material.SADDLE), 1); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java index e80029472..4a2083b05 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java @@ -146,18 +146,18 @@ enum Instruction { }); private static final Map nameLookup = new HashMap<>(); - public static final Instruction[] values = values(); + public static final Instruction[] valuesCache = values(); + + static { + for (Instruction instruction : valuesCache) { + nameLookup.put(instruction.name(), instruction); + } + } private final ItemStack item; private final AndroidType type; private final AndroidAction method; - static { - for (Instruction instruction : values) { - nameLookup.put(instruction.name(), instruction); - } - } - @ParametersAreNonnullByDefault Instruction(AndroidType type, HeadTexture head, @Nullable AndroidAction method) { this.type = type; @@ -198,7 +198,7 @@ enum Instruction { * @return The {@link Instruction} or null if it does not exist. */ @Nullable - public static Instruction getFromCache(@Nonnull String value) { + public static Instruction getInstruction(@Nonnull String value) { Validate.notNull(value, "An Instruction cannot be null!"); return nameLookup.get(value); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index f082b68f5..4328e6c0e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -11,10 +11,10 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; -import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections; import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.api.events.AndroidMineEvent; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; @@ -40,7 +40,7 @@ public class MinerAndroid extends ProgrammableAndroid { protected void dig(Block b, BlockMenu menu, Block block) { Collection drops = block.getDrops(effectivePickaxe); - if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) { + if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) { @@ -71,7 +71,7 @@ public class MinerAndroid extends ProgrammableAndroid { protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) { Collection drops = block.getDrops(effectivePickaxe); - if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) { + if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) { 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 be15a49e3..b57b449e4 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 @@ -81,7 +81,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, texture = item.getSkullTexture().orElse(null); registerDefaultFuelTypes(); - new BlockMenuPreset(getID(), "Programmable Android") { + new BlockMenuPreset(getId(), "Programmable Android") { @Override public void init() { @@ -131,7 +131,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, } }; - registerBlockHandler(getID(), (p, b, stack, reason) -> { + registerBlockHandler(getId(), (p, b, stack, reason) -> { boolean allow = reason == UnregisterReason.PLAYER_BREAK && (BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(p.getUniqueId().toString()) || p.hasPermission("slimefun.android.bypass")); if (allow) { @@ -257,7 +257,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, return false; }); } else { - Instruction instruction = Instruction.getFromCache(script[i]); + Instruction instruction = Instruction.getInstruction(script[i]); if (instruction == null) { SlimefunPlugin.instance().getLogger().log(Level.WARNING, "Failed to parse Android instruction: {0}, maybe your server is out of date?", script[i]); @@ -493,7 +493,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, protected List getValidScriptInstructions() { List list = new ArrayList<>(); - for (Instruction part : Instruction.values) { + for (Instruction part : Instruction.valuesCache) { if (part == Instruction.START || part == Instruction.REPEAT) { continue; } @@ -646,7 +646,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, } BlockStorage.addBlockInfo(b, "fuel", String.valueOf(fuel - 1)); - Instruction instruction = Instruction.getFromCache(script[index]); + Instruction instruction = Instruction.getInstruction(script[index]); if (instruction == null) { SlimefunPlugin.instance().getLogger().log(Level.WARNING, "Failed to parse Android instruction: {0}, maybe your server is out of date?", script[index]); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java index 2b623dbc5..5d97975f7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Script.java @@ -9,6 +9,9 @@ import java.util.List; import java.util.UUID; import java.util.logging.Level; +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -22,6 +25,12 @@ import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; import me.mrCookieSlime.Slimefun.api.Slimefun; +/** + * A {@link Script} represents runnable code for a {@link ProgrammableAndroid}. + * + * @author TheBusyBiscuit + * + */ public final class Script { private final Config config; @@ -29,7 +38,13 @@ public final class Script { private final String author; private final String code; - private Script(Config config) { + /** + * This constructs a new {@link Script} from the given {@link Config}. + * + * @param config + * The {@link Config} + */ + private Script(@Nonnull Config config) { Validate.notNull(config); this.config = config; @@ -52,6 +67,7 @@ public final class Script { * * @return The name */ + @Nonnull public String getName() { return name; } @@ -62,6 +78,7 @@ public final class Script { * * @return The author of this {@link Script} */ + @Nonnull public String getAuthor() { return author; } @@ -73,6 +90,7 @@ public final class Script { * * @return The code for this {@link Script} */ + @Nonnull public String getSourceCode() { return code; } @@ -86,7 +104,7 @@ public final class Script { * * @return Whether the given {@link OfflinePlayer} is the author of this {@link Script}. */ - public boolean isAuthor(OfflinePlayer p) { + public boolean isAuthor(@Nonnull OfflinePlayer p) { return p.getUniqueId().equals(config.getUUID("author")); } @@ -99,7 +117,7 @@ public final class Script { * * @return Whether the given {@link Player} is able to rate this {@link Script} */ - public boolean canRate(Player p) { + public boolean canRate(@Nonnull Player p) { if (isAuthor(p)) { return false; } @@ -109,7 +127,8 @@ public final class Script { return !upvoters.contains(p.getUniqueId().toString()) && !downvoters.contains(p.getUniqueId().toString()); } - ItemStack getAsItemStack(ProgrammableAndroid android, Player p) { + @Nonnull + ItemStack getAsItemStack(@Nonnull ProgrammableAndroid android, @Nonnull Player p) { List lore = new LinkedList<>(); lore.add("&7by &r" + getAuthor()); lore.add(""); @@ -128,6 +147,7 @@ public final class Script { return new CustomItem(android.getItem(), "&b" + getName(), lore.toArray(new String[0])); } + @Nonnull private String getScriptRatingPercentage() { float percentage = getRating(); return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.RESET + "% "; @@ -181,7 +201,7 @@ public final class Script { config.save(); } - public void rate(Player p, boolean positive) { + public void rate(@Nonnull Player p, boolean positive) { config.reload(); String path = "rating." + (positive ? "positive" : "negative"); @@ -192,7 +212,8 @@ public final class Script { config.save(); } - public static List