1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 03:35:51 +00:00
refactoring/holograms

Conflicts:
	src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/HologramProjector.java
This commit is contained in:
TheBusyBiscuit 2021-01-13 14:29:18 +01:00
commit 029bc2ae78
129 changed files with 3231 additions and 2504 deletions

6
.github/CODEOWNERS vendored
View File

@ -5,3 +5,9 @@
/.github/ @Slimefun/slimefun4-maintainers
pom.xml @Slimefun/slimefun4-maintainers
CONTRIBUTING.md @Slimefun/slimefun4-maintainers
# Changes to the Issue templates need to be checked by the triage team
/.github/ISSUE_TEMPLATE/ @Slimefun/bug-testers
# This file is handled by TheBusyBiscuit (admins have overwrite access anyway)
/.github/CODEOWNERS @TheBusyBiscuit

View File

@ -2,7 +2,7 @@
name: Bug Report
about: Report a Bug or an Issue with Slimefun 4.
title: ''
labels: '🐞 Bug Report'
labels: "\U0001F3AF Needs testing, \U0001F41E Bug Report"
assignees: ''
---

View File

@ -6,6 +6,8 @@ on:
- 'src/**'
- '!src/main/resources/languages/**'
- 'pom.xml'
tags-ignore:
- 'RC.*'
jobs:
report:

View File

@ -2,7 +2,7 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of contents**
- [Release Candidate 19 (TBD)](#release-candidate-19-tbd)
- [Release Candidate 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021)
- [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020)
- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020)
- [Release Candidate 16 (07 Sep 2020)](#release-candidate-16-07-sep-2020)
@ -24,14 +24,28 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Release Candidate 19 (TBD)
## Release Candidate 20 (TBD)
#### Additions
#### Changes
#### Fixes
* Fixed elevator floor order
## Release Candidate 19 (11 Jan 2021)
#### Additions
* Added Bee Armor (1.15+ only)
* (API) Added AndroidFarmEvent
#### Changes
* Performance optimizations for Cargo networks
* Removed an old version of bStats
* CraftBukkit is officially no longer supported, Slimefun will now be disabled on old builds of CraftBukkit
* Removed the deprecated ItemManipulationAPI for BlockMenus
* Removed the "Written Book" variant of the Slimefun Guide
* The Elevator has an Inventory menu now
#### Fixes
* Fixed a couple of compatibility issues with ItemsAdder
@ -41,6 +55,8 @@
* Fixed #2647
* Fixed #2664
* Fixed #2655
* Fixed /sf timings --verbose not working correctly
* Fixed #2675
## Release Candidate 18 (03 Dec 2020)

36
pom.xml
View File

@ -9,10 +9,11 @@
<!-- Our default version will be UNOFFICIAL, this will prevent auto updates -->
<!-- from overriding our local test file -->
<version>4.8-UNOFFICIAL</version>
<version>4.9-UNOFFICIAL</version>
<inceptionYear>2013</inceptionYear>
<packaging>jar</packaging>
<!-- Project Info -->
<description>Slimefun is a Spigot/Paper plugin that simulates a modpack-like atmosphere by adding over 500 new items and recipes to your Minecraft Server.</description>
<url>https://github.com/Slimefun/Slimefun4</url>
@ -33,11 +34,13 @@
<sonar.coverage.jacoco.xmlReportPaths>target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>
<!-- Bug Tracker -->
<issueManagement>
<system>GitHub Issues</system>
<url>https://github.com/Slimefun/Slimefun4/issues</url>
</issueManagement>
<!-- License -->
<licenses>
<license>
<name>GNU General Public License v3.0</name>
@ -46,6 +49,7 @@
</license>
</licenses>
<!-- The repositories which host our dependencies -->
<repositories>
<repository>
<id>spigot-repo</id>
@ -77,11 +81,13 @@
</repository>
</repositories>
<!-- Build settings -->
<build>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<defaultGoal>clean package</defaultGoal>
<!-- The name of the final jar -->
<finalName>${project.name} v${project.version}</finalName>
<plugins>
@ -104,6 +110,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
@ -119,6 +126,11 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<junitArtifactName>org.junit.jupiter:junit-jupiter</junitArtifactName>
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
<!-- Sonarcloud Scanner -->
@ -137,6 +149,7 @@
<executions>
<execution>
<id>prepare</id>
<goals>
<goal>prepare-agent</goal>
</goals>
@ -145,6 +158,7 @@
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
@ -159,8 +173,7 @@
<version>3.2.4</version>
<configuration>
<!-- Shade dependencies into the output jar -->
<!-- Relocate these to avoid clashes and conflicts -->
<relocations>
<relocation>
<pattern>io.github.thebusybiscuit.cscorelib2</pattern>
@ -328,7 +341,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.6.28</version>
<version>3.7.0</version>
<scope>test</scope>
</dependency>
@ -336,7 +349,7 @@
<dependency>
<groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.27.4</version>
<version>0.29.1</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -348,7 +361,7 @@
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.11.09</version>
<version>3.11.10</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@ -362,7 +375,7 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.0</version>
<version>7.2.1</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -380,7 +393,7 @@
<dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.1.164</version>
<version>2.1.171</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -397,6 +410,13 @@
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-legacy</artifactId>
</exclusion>
<exclusion>
<!-- We do not want to use the wrong TextComponents by -->
<!-- accident. If we use adventure, then we will add -->
<!-- it ourselves. -->
<groupId>net.kyori</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@ -35,6 +35,9 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
* an {@link ErrorReport} instead.
* Error reports get saved in the plugin folder.
*
* @param <T>
* The type of {@link Throwable} which has spawned this {@link ErrorReport}
*
* @author TheBusyBiscuit
*
*/
@ -222,6 +225,16 @@ public class ErrorReport<T extends Throwable> {
return newFile;
}
/**
* This helper method wraps the given {@link Runnable} into a try-catch block.
* When an {@link Exception} occurs, a new {@link ErrorReport} will be generated using
* the provided {@link Function}.
*
* @param function
* The {@link Function} to generate a new {@link ErrorReport}
* @param runnable
* The code to execute
*/
public static void tryCatch(@Nonnull Function<Exception, ErrorReport<Exception>> function, @Nonnull Runnable runnable) {
try {
runnable.run();

View File

@ -6,6 +6,7 @@ import org.apache.commons.lang.Validate;
import org.bukkit.Server;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
/**
* This enum holds all versions of Minecraft that we currently support.
@ -21,19 +22,19 @@ public enum MinecraftVersion {
* This constant represents Minecraft (Java Edition) Version 1.14
* (The "Village &amp; Pillage" Update)
*/
MINECRAFT_1_14("1.14.x"),
MINECRAFT_1_14(14, "1.14.x"),
/**
* This constant represents Minecraft (Java Edition) Version 1.15
* (The "Buzzy Bees" Update)
*/
MINECRAFT_1_15("1.15.x"),
MINECRAFT_1_15(15, "1.15.x"),
/**
* This constant represents Minecraft (Java Edition) Version 1.16
* (The "Nether Update")
*/
MINECRAFT_1_16("1.16.x"),
MINECRAFT_1_16(16, "1.16.x"),
/**
* This constant represents an exceptional state in which we were unable
@ -51,18 +52,22 @@ public enum MinecraftVersion {
private final String name;
private final boolean virtual;
private final String prefix;
private final int majorVersion;
/**
* This constructs a new {@link MinecraftVersion} with the given name.
* This constructor forces the {@link MinecraftVersion} to be real.
* It must be a real version of Minecraft.
*
* @param majorVersion
* The major version of minecraft as an {@link Integer}
* @param name
* The display name of this {@link MinecraftVersion}
*/
MinecraftVersion(@Nonnull String name) {
this(name, false);
MinecraftVersion(int majorVersion, @Nonnull String name) {
this.name = name;
this.majorVersion = majorVersion;
this.virtual = false;
}
/**
@ -77,8 +82,8 @@ public enum MinecraftVersion {
*/
MinecraftVersion(@Nonnull String name, boolean virtual) {
this.name = name;
this.majorVersion = 0;
this.virtual = virtual;
this.prefix = name().replace("MINECRAFT_", "v") + '_';
}
/**
@ -105,18 +110,21 @@ public enum MinecraftVersion {
}
/**
* This method checks whether the given version matches with this
* This tests if the given minecraft version number matches with this
* {@link MinecraftVersion}.
* <p>
* You can obtain the version number by doing {@link PaperLib#getMinecraftVersion()}.
* It is equivalent to the "major" version
* <p>
* Example: {@literal "1.13"} returns {@literal 13}
*
* @param version
* The version to compare
* @param minecraftVersion
* The {@link Integer} version to match
*
* @return Whether the version matches with this one
* @return Whether this {@link MinecraftVersion} matches the specified version id
*/
public boolean matches(@Nonnull String version) {
Validate.notNull(version, "The input version must not be null!");
return version.startsWith(prefix);
public boolean isMinecraftVersion(int minecraftVersion) {
return !isVirtual() && this.majorVersion == minecraftVersion;
}
/**

View File

@ -1,21 +1,15 @@
package io.github.thebusybiscuit.slimefun4.api;
import java.util.Collection;
import java.util.Locale;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
@ -106,16 +100,4 @@ public interface SlimefunAddon {
return description.getDepend().contains(dependency) || description.getSoftDepend().contains(dependency);
}
/**
* This returns a {@link Collection} holding every {@link Category} that can be directly
* linked to this {@link SlimefunAddon} based on its {@link NamespacedKey}.
*
* @return A {@link Collection} of every {@link Category} from this addon
*/
@Nonnull
default Collection<Category> getCategories() {
String namespace = getJavaPlugin().getName().toLowerCase(Locale.ROOT);
return SlimefunPlugin.getRegistry().getCategories().stream().filter(cat -> cat.getKey().getNamespace().equals(namespace)).collect(Collectors.toList());
}
}

View File

@ -34,10 +34,10 @@ public class AncientAltarCraftEvent extends PlayerEvent implements Cancellable {
private boolean cancelled;
/**
* @param block
* The altar {@link Block}
* @param output
* The {@link ItemStack} that would be dropped by the ritual
* @param block
* The altar {@link Block}
* @param player
* The {@link Player} that started the ritual.
*/

View File

@ -0,0 +1,122 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.block.Block;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AndroidInstance;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.FarmerAndroid;
/**
* This {@link Event} is fired before a {@link FarmerAndroid} harvests a {@link Block}.
* If this {@link Event} is cancelled, the {@link Block} will not be harvested.
* <p>
* The {@link Event} will still be fired for non-harvestable blocks.
*
* @author TheBusyBiscuit
*
*/
public class AndroidFarmEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Block block;
private final AndroidInstance android;
private final boolean isAdvanced;
private ItemStack drop;
private boolean cancelled;
/**
* @param block
* The harvested {@link Block}
* @param android
* The {@link AndroidInstance} that triggered this {@link Event}
* @param isAdvanced
* Whether this is an advanced farming action
* @param drop
* The item to be dropped or null
*/
public AndroidFarmEvent(@Nonnull Block block, @Nonnull AndroidInstance android, boolean isAdvanced, @Nullable ItemStack drop) {
this.block = block;
this.android = android;
this.isAdvanced = isAdvanced;
this.drop = drop;
}
/**
* This method returns the mined {@link Block}
*
* @return the mined {@link Block}
*/
@Nonnull
public Block getBlock() {
return block;
}
/**
* This returns the harvested item or null.
*
* @return The harvested item or null
*/
@Nullable
public ItemStack getDrop() {
return drop;
}
/**
* Whether this was invoked via an advanced farming action
*
* @return Whether it is advanced
*/
public boolean isAdvanced() {
return isAdvanced;
}
/**
* This will set the {@link ItemStack} result.
*
* @param drop
* The result or null
*/
public void setDrop(@Nullable ItemStack drop) {
this.drop = drop;
}
/**
* This method returns the {@link AndroidInstance} who
* triggered this {@link Event}
*
* @return the involved {@link AndroidInstance}
*/
@Nonnull
public AndroidInstance getAndroid() {
return android;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@Nonnull
public static HandlerList getHandlerList() {
return handlers;
}
@Nonnull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -3,16 +3,16 @@ package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.apache.commons.lang.Validate;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is called whenever a {@link Player} clicks to unlock a {@link Research}.
@ -21,8 +21,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefu
*
* @author uiytt
*
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SurvivalSlimefunGuide
*
*/
public class PlayerPreResearchEvent extends Event implements Cancellable {

View File

@ -16,7 +16,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.data.ComputedOptional;
import io.github.thebusybiscuit.cscorelib2.data.TriStateOptional;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -46,8 +46,8 @@ public class PlayerRightClickEvent extends PlayerEvent {
private final EquipmentSlot hand;
private final BlockFace face;
private ComputedOptional<SlimefunItem> slimefunItem = ComputedOptional.createNew();
private ComputedOptional<SlimefunItem> slimefunBlock = ComputedOptional.createNew();
private TriStateOptional<SlimefunItem> slimefunItem = TriStateOptional.createNew();
private TriStateOptional<SlimefunItem> slimefunBlock = TriStateOptional.createNew();
private Result itemResult;
private Result blockResult;
@ -127,7 +127,7 @@ public class PlayerRightClickEvent extends PlayerEvent {
if (itemStack.isPresent()) {
slimefunItem.compute(SlimefunItem.getByItem(itemStack.get()));
} else {
slimefunItem = ComputedOptional.empty();
slimefunItem = TriStateOptional.empty();
}
}
@ -140,7 +140,7 @@ public class PlayerRightClickEvent extends PlayerEvent {
if (clickedBlock.isPresent()) {
slimefunBlock.compute(BlockStorage.check(clickedBlock.get()));
} else {
slimefunBlock = ComputedOptional.empty();
slimefunBlock = TriStateOptional.empty();
}
}

View File

@ -9,14 +9,14 @@ import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
/**
* This {@link Event} is called whenever a {@link Player} tries to open the Slimefun Guide book.
*
* @author Linox
*
* @see SlimefunGuideLayout
* @see SlimefunGuideMode
*/
public class SlimefunGuideOpenEvent extends Event implements Cancellable {
@ -24,10 +24,10 @@ public class SlimefunGuideOpenEvent extends Event implements Cancellable {
private final Player player;
private final ItemStack guide;
private SlimefunGuideLayout layout;
private SlimefunGuideMode layout;
private boolean cancelled;
public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideLayout layout) {
public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideMode layout) {
Validate.notNull(p, "The Player cannot be null");
Validate.notNull(guide, "Guide cannot be null");
Validate.notNull(layout, "Layout cannot be null");
@ -59,23 +59,23 @@ public class SlimefunGuideOpenEvent extends Event implements Cancellable {
}
/**
* This returns the {@link SlimefunGuideLayout} of the Slimefun Guide
* This returns the {@link SlimefunGuideMode} of the Slimefun Guide
* that {@link Player} tries to open.
*
* @return The {@link SlimefunGuideLayout}
* @return The {@link SlimefunGuideMode}
*/
@Nonnull
public SlimefunGuideLayout getGuideLayout() {
public SlimefunGuideMode getGuideLayout() {
return layout;
}
/**
* Changes the {@link SlimefunGuideLayout} that was tried to be opened with.
* Changes the {@link SlimefunGuideMode} that was tried to be opened with.
*
* @param layout
* The new {@link SlimefunGuideLayout}
* The new {@link SlimefunGuideMode}
*/
public void setGuideLayout(@Nonnull SlimefunGuideLayout layout) {
public void setGuideLayout(@Nonnull SlimefunGuideMode layout) {
Validate.notNull(layout, "You must specify a layout that is not-null!");
this.layout = layout;
}

View File

@ -23,7 +23,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.events.WaypointCreateEvent;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager;
@ -34,6 +33,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSTransmitte
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.Teleporter;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -157,7 +157,7 @@ public class GPSNetwork {
if (sfi instanceof GPSTransmitter) {
int slot = inventory[index];
menu.addItem(slot, new CustomItem(SlimefunItems.GPS_TRANSMITTER, "&bGPS Transmitter", "&8\u21E8 &7World: &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "", "&8\u21E8 &7Signal Strength: &f" + ((GPSTransmitter) sfi).getMultiplier(l.getBlockY()), "&8\u21E8 &7Ping: &f" + DoubleHandler.fixDouble(1000D / l.getY()) + "ms"));
menu.addItem(slot, new CustomItem(SlimefunItems.GPS_TRANSMITTER, "&bGPS Transmitter", "&8\u21E8 &7World: &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "", "&8\u21E8 &7Signal Strength: &f" + ((GPSTransmitter) sfi).getMultiplier(l.getBlockY()), "&8\u21E8 &7Ping: &f" + NumberUtils.roundDecimalNumber(1000D / l.getY()) + "ms"));
menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler());
index++;

View File

@ -20,11 +20,11 @@ import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -64,7 +64,7 @@ public final class TeleportationManager {
int slot = teleporterInventory[index];
Location l = waypoint.getLocation();
double time = DoubleHandler.fixDouble(0.5 * getTeleportationTime(complexity, source, l));
double time = NumberUtils.reparseDouble(0.5 * getTeleportationTime(complexity, source, l));
String[] lore = { "", "&8\u21E8 &7" + SlimefunPlugin.getLocalization().getResourceString(p, "tooltips.world") + ": &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "&8\u21E8 &7" + SlimefunPlugin.getLocalization().getMessage(p, "machines.TELEPORTER.gui.time") + ": &f" + time + "s", "", "&8\u21E8 &c" + SlimefunPlugin.getLocalization().getMessage(p, "machines.TELEPORTER.gui.tooltip") };

View File

@ -10,7 +10,6 @@ import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This class represents a Setting for a {@link SlimefunItem} that can be modified via
@ -152,19 +151,19 @@ public class ItemSetting<T> {
if (validateInput(newValue)) {
this.value = newValue;
} else {
Slimefun.getLogger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
Slimefun.getLogger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
Slimefun.getLogger().log(Level.WARNING, getErrorMessage());
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
SlimefunPlugin.logger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
SlimefunPlugin.logger().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, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
SlimefunPlugin.logger().log(Level.WARNING, "Please only use settings that are valid.");
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
SlimefunPlugin.logger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
}
}

View File

@ -12,6 +12,9 @@ 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.
*
* @param <T>
* The {@link Enum} type
*
* @author TheBusyBiscuit
*
* @see ItemSetting
@ -41,6 +44,7 @@ public class EnumSetting<T extends Enum<T>> extends ItemSetting<String> {
*
* @return An array of allowed {@link Enum} constants
*/
@Nonnull
public T[] getAllowedValues() {
return enumClass.getEnumConstants();
}
@ -50,6 +54,7 @@ public class EnumSetting<T extends Enum<T>> extends ItemSetting<String> {
*
* @return The value as an {@link Enum} constant
*/
@Nonnull
public T getAsEnumConstant() {
return Enum.valueOf(enumClass, getValue());
}

View File

@ -43,7 +43,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* A class that can store a Player's {@link Research} progress for caching purposes.
@ -96,7 +95,7 @@ public final class PlayerProfile {
waypoints.add(new Waypoint(this, key, loc, waypointName));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
}
}
}

View File

@ -14,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -25,12 +26,12 @@ import io.github.thebusybiscuit.cscorelib2.config.Config;
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.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -71,12 +72,16 @@ public final class SlimefunRegistry {
private final Set<SlimefunItem> radioactive = new HashSet<>();
private final Set<ItemStack> barterDrops = new HashSet<>();
private NamespacedKey soulboundKey;
private NamespacedKey itemChargeKey;
private NamespacedKey guideKey;
private final KeyMap<GEOResource> geoResources = new KeyMap<>();
private final Map<UUID, PlayerProfile> profiles = new ConcurrentHashMap<>();
private final Map<String, BlockStorage> worlds = new ConcurrentHashMap<>();
private final Map<String, BlockInfoConfig> chunks = new HashMap<>();
private final Map<SlimefunGuideLayout, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideLayout.class);
private final Map<SlimefunGuideMode, SlimefunGuideImplementation> guides = new EnumMap<>(SlimefunGuideMode.class);
private final Map<EntityType, Set<ItemStack>> mobDrops = new EnumMap<>(EntityType.class);
private final Map<String, BlockMenuPreset> blockMenuPresets = new HashMap<>();
@ -84,14 +89,17 @@ public final class SlimefunRegistry {
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
private final Map<String, SlimefunBlockHandler> blockHandlers = new HashMap<>();
public void load(@Nonnull Config cfg) {
public void load(@Nonnull SlimefunPlugin plugin, @Nonnull Config cfg) {
Validate.notNull(plugin, "The Plugin cannot be null!");
Validate.notNull(cfg, "The Config cannot be null!");
boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes");
soulboundKey = new NamespacedKey(plugin, "soulbound");
itemChargeKey = new NamespacedKey(plugin, "item_charge");
guideKey = new NamespacedKey(plugin, "slimefun_guide_mode");
layouts.put(SlimefunGuideLayout.CHEST, new ChestSlimefunGuide(showVanillaRecipes));
layouts.put(SlimefunGuideLayout.CHEAT_SHEET, new CheatSheetSlimefunGuide());
layouts.put(SlimefunGuideLayout.BOOK, new BookSlimefunGuide());
boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes");
guides.put(SlimefunGuideMode.SURVIVAL_MODE, new SurvivalSlimefunGuide(showVanillaRecipes));
guides.put(SlimefunGuideMode.CHEAT_MODE, new CheatSheetSlimefunGuide());
researchRanks.addAll(cfg.getStringList("research-ranks"));
@ -132,6 +140,7 @@ public final class SlimefunRegistry {
automaticallyLoadItems = mode;
}
@Nonnull
public List<Category> getCategories() {
return categories;
}
@ -141,6 +150,7 @@ public final class SlimefunRegistry {
*
* @return A {@link List} containing every {@link SlimefunItem}
*/
@Nonnull
public List<SlimefunItem> getAllSlimefunItems() {
return slimefunItems;
}
@ -150,18 +160,22 @@ public final class SlimefunRegistry {
*
* @return A {@link List} containing every enabled {@link SlimefunItem}
*/
@Nonnull
public List<SlimefunItem> getEnabledSlimefunItems() {
return enabledItems;
}
@Nonnull
public List<Research> getResearches() {
return researches;
}
@Nonnull
public Set<UUID> getCurrentlyResearchingPlayers() {
return researchingPlayers;
}
@Nonnull
public List<String> getResearchRanks() {
return researchRanks;
}
@ -186,12 +200,31 @@ public final class SlimefunRegistry {
return researchFireworks;
}
@Nonnull
public List<MultiBlock> getMultiBlocks() {
return multiblocks;
}
public SlimefunGuideImplementation getGuideLayout(SlimefunGuideLayout layout) {
return layouts.get(layout);
/**
* This returns the corresponding {@link SlimefunGuideImplementation} for a certain
* {@link SlimefunGuideMode}.
*
* @param mode
* The {@link SlimefunGuideMode}
*
* @return The corresponding {@link SlimefunGuideImplementation}
*/
@Nonnull
public SlimefunGuideImplementation getSlimefunGuide(@Nonnull SlimefunGuideMode mode) {
Validate.notNull(mode, "The Guide mode cannot be null");
SlimefunGuideImplementation guide = guides.get(mode);
if (guide == null) {
throw new IllegalStateException("Slimefun Guide '" + mode + "' has no registered implementation.");
}
return guide;
}
/**
@ -200,6 +233,7 @@ public final class SlimefunRegistry {
*
* @return The {@link Map} of custom mob drops
*/
@Nonnull
public Map<EntityType, Set<ItemStack>> getMobDrops() {
return mobDrops;
}
@ -210,50 +244,62 @@ public final class SlimefunRegistry {
*
* @return A {@link Set} of bartering drops
*/
@Nonnull
public Set<ItemStack> getBarteringDrops() {
return barterDrops;
}
@Nonnull
public Set<SlimefunItem> getRadioactiveItems() {
return radioactive;
}
@Nonnull
public Set<String> getTickerBlocks() {
return tickers;
}
@Nonnull
public Map<String, SlimefunItem> getSlimefunItemIds() {
return slimefunIds;
}
@Nonnull
public Map<String, BlockMenuPreset> getMenuPresets() {
return blockMenuPresets;
}
@Nonnull
public Map<String, UniversalBlockMenu> getUniversalInventories() {
return universalInventories;
}
@Nonnull
public Map<UUID, PlayerProfile> getPlayerProfiles() {
return profiles;
}
@Nonnull
public Map<Class<? extends ItemHandler>, Set<ItemHandler>> getPublicItemHandlers() {
return globalItemHandlers;
}
@Nonnull
public Map<String, SlimefunBlockHandler> getBlockHandlers() {
return blockHandlers;
}
@Nonnull
public Map<String, BlockStorage> getWorlds() {
return worlds;
}
@Nonnull
public Map<String, BlockInfoConfig> getChunks() {
return chunks;
}
@Nonnull
public KeyMap<GEOResource> getGEOResources() {
return geoResources;
}
@ -262,4 +308,19 @@ public final class SlimefunRegistry {
return logDuplicateBlockEntries;
}
@Nonnull
public NamespacedKey getSoulboundDataKey() {
return soulboundKey;
}
@Nonnull
public NamespacedKey getItemChargeDataKey() {
return itemChargeKey;
}
@Nonnull
public NamespacedKey getGuideDataKey() {
return guideKey;
}
}

View File

@ -28,7 +28,6 @@ import net.md_5.bungee.api.ChatColor;
*/
final class RechargeableHelper {
private static final NamespacedKey CHARGE_KEY = new NamespacedKey(SlimefunPlugin.instance(), "item_charge");
private static final String LORE_PREFIX = ChatColors.color("&8\u21E8 &e\u26A1 &7");
private static final Pattern REGEX = Pattern.compile(ChatColors.color("(&c&o)?" + LORE_PREFIX) + "[0-9.]+ / [0-9.]+ J");
@ -38,7 +37,8 @@ final class RechargeableHelper {
BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP);
float value = decimal.floatValue();
meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value);
NamespacedKey key = SlimefunPlugin.getRegistry().getItemChargeDataKey();
meta.getPersistentDataContainer().set(key, PersistentDataType.FLOAT, value);
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < lore.size(); i++) {
@ -56,7 +56,8 @@ final class RechargeableHelper {
}
static float getCharge(@Nonnull ItemMeta meta) {
Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT);
NamespacedKey key = SlimefunPlugin.getRegistry().getItemChargeDataKey();
Float value = meta.getPersistentDataContainer().get(key, PersistentDataType.FLOAT);
// If persistent data is available, we just return this value
if (value != null) {

View File

@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -45,12 +45,12 @@ public abstract class FlexCategory extends Category {
* @param profile
* The {@link PlayerProfile} of the {@link Player}
* @param layout
* The {@link SlimefunGuideLayout} in which this {@link FlexCategory} is viewed
* The {@link SlimefunGuideMode} in which this {@link FlexCategory} is viewed
*
* @return Whether to display this {@link FlexCategory}
*/
@ParametersAreNonnullByDefault
public abstract boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideLayout layout);
public abstract boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideMode layout);
/**
* This method is called when a {@link Player} opens this {@link FlexCategory}.
@ -62,13 +62,13 @@ public abstract class FlexCategory extends Category {
* @param profile
* The corresponding {@link PlayerProfile} for that {@link Player}
* @param layout
* The current {@link SlimefunGuideLayout}
* The current {@link SlimefunGuideMode}
*/
public abstract void open(Player p, PlayerProfile profile, SlimefunGuideLayout layout);
public abstract void open(Player p, PlayerProfile profile, SlimefunGuideMode layout);
@Override
public final boolean isHidden(@Nonnull Player p) {
/**
/*
* We can stop this method right here.
* We provide a custom method with more parameters for this.
* See isVisible(...)

View File

@ -14,6 +14,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -76,8 +77,8 @@ public class LockedCategory extends Category {
}
@Override
public void register() {
super.register();
public void register(@Nonnull SlimefunAddon addon) {
super.register(addon);
List<NamespacedKey> namespacedKeys = new ArrayList<>();
@ -94,7 +95,7 @@ public class LockedCategory extends Category {
}
for (NamespacedKey key : namespacedKeys) {
Slimefun.getLogger().log(Level.INFO, "Parent \"{0}\" for Category \"{1}\" was not found, probably just disabled.", new Object[] { key, getKey() });
SlimefunPlugin.logger().log(Level.INFO, "Parent \"{0}\" for Category \"{1}\" was not found, probably just disabled.", new Object[] { key, getKey() });
}
}
@ -148,12 +149,13 @@ public class LockedCategory extends Category {
* The {@link Player} to check
* @param profile
* The {@link PlayerProfile} that belongs to the given {@link Player}
*
* @return Whether the {@link Player} has fully completed all parent categories, otherwise false
*/
public boolean hasUnlocked(@Nonnull Player p, @Nonnull PlayerProfile profile) {
for (Category category : parents) {
for (SlimefunItem item : category.getItems()) {
/**
/*
* Should probably be replaced with Slimefun.hasUnlocked(...)
* However this will result in better performance because we don't
* request the PlayerProfile everytime

View File

@ -6,7 +6,7 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class GuideCommand extends SubCommand {
@ -19,7 +19,7 @@ class GuideCommand extends SubCommand {
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.guide")) {
SlimefunGuideLayout design = SlimefunGuide.getDefaultLayout();
SlimefunGuideMode design = SlimefunGuide.getDefaultMode();
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(design).clone());
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -1,12 +1,14 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class OpenGuideCommand extends SubCommand {
@ -16,11 +18,11 @@ class OpenGuideCommand extends SubCommand {
}
@Override
@ParametersAreNonnullByDefault
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.open_guide")) {
boolean book = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book");
SlimefunGuide.openGuide((Player) sender, book ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST);
SlimefunGuide.openGuide((Player) sender, SlimefunGuideMode.SURVIVAL_MODE);
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}

View File

@ -9,6 +9,7 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class SearchCommand extends SubCommand {
@ -23,7 +24,7 @@ class SearchCommand extends SubCommand {
if (sender.hasPermission("slimefun.command.search")) {
if (args.length > 1) {
String query = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
PlayerProfile.get((Player) sender, profile -> SlimefunGuide.openSearch(profile, query, true, true));
PlayerProfile.get((Player) sender, profile -> SlimefunGuide.openSearch(profile, query, SlimefunGuideMode.SURVIVAL_MODE, true));
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf search <SearchTerm>"));
}

View File

@ -1,26 +1,97 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.PerformanceInspector;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors.ConsolePerformanceInspector;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors.PlayerPerformanceInspector;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class TimingsCommand extends SubCommand {
private static final String FLAG_PREFIX = "--";
private final Set<String> flags = new HashSet<>(Arrays.asList("verbose"));
TimingsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "timings", false);
}
@Override
protected String getDescription() {
return "commands.timings.description";
}
@Override
public void onExecute(CommandSender sender, String[] args) {
if (sender.hasPermission("slimefun.command.timings") || sender instanceof ConsoleCommandSender) {
sender.sendMessage("Please wait a second... The results are coming in!");
SlimefunPlugin.getProfiler().requestSummary(sender);
if (hasInvalidFlags(sender, args)) {
return;
}
boolean verbose = hasFlag(args, "verbose");
if (verbose && sender instanceof Player) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.verbose-player", true);
return;
}
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.please-wait", true);
PerformanceInspector inspector = inspectorOf(sender, verbose);
SlimefunPlugin.getProfiler().requestSummary(inspector);
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
}
@ParametersAreNonnullByDefault
private boolean hasInvalidFlags(CommandSender sender, String[] args) {
boolean hasInvalidFlags = false;
// We start at 1 because args[0] will be "timings".
for (int i = 1; i < args.length; i++) {
String argument = args[i].toLowerCase(Locale.ROOT);
if (argument.startsWith(FLAG_PREFIX) && !flags.contains(argument.substring(2))) {
hasInvalidFlags = true;
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.unknown-flag", true, msg -> msg.replace("%flag%", argument));
}
}
return hasInvalidFlags;
}
@ParametersAreNonnullByDefault
private boolean hasFlag(String[] args, String flag) {
// We start at 1 because args[0] will be "timings".
for (int i = 1; i < args.length; i++) {
if (args[i].equalsIgnoreCase(FLAG_PREFIX + flag)) {
return true;
}
}
return false;
}
@Nonnull
private PerformanceInspector inspectorOf(@Nonnull CommandSender sender, boolean verbose) {
if (sender instanceof Player) {
return new PlayerPerformanceInspector((Player) sender);
} else {
return new ConsolePerformanceInspector(sender, verbose);
}
}
}

View File

@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@ -9,7 +10,6 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -22,14 +22,14 @@ class VersionsCommand extends SubCommand {
}
@Override
public void onExecute(CommandSender sender, String[] args) {
public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (sender.hasPermission("slimefun.command.versions") || sender instanceof ConsoleCommandSender) {
// After all these years... Spigot still displays as "CraftBukkit"
// so we will just fix this inconsistency for them :)
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + ReflectionUtils.getVersion()));
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion()));
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));

View File

@ -3,15 +3,19 @@ package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -22,36 +26,35 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
* @author TheBusyBiscuit
*
* @see SlimefunGuideImplementation
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SurvivalSlimefunGuide
*
*/
public final class SlimefunGuide {
private SlimefunGuide() {}
public static ItemStack getItem(@Nonnull SlimefunGuideLayout design) {
return SlimefunPlugin.getRegistry().getGuideLayout(design).getItem();
@Nonnull
public static ItemStack getItem(@Nonnull SlimefunGuideMode design) {
return SlimefunPlugin.getRegistry().getSlimefunGuide(design).getItem();
}
public static void openCheatMenu(Player p) {
openMainMenuAsync(p, SlimefunGuideLayout.CHEAT_SHEET, 1);
public static void openCheatMenu(@Nonnull Player p) {
openMainMenuAsync(p, SlimefunGuideMode.CHEAT_MODE, 1);
}
public static void openGuide(Player p, ItemStack guide) {
if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.CHEST), true)) {
openGuide(p, SlimefunGuideLayout.CHEST);
} else if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.BOOK), true)) {
openGuide(p, SlimefunGuideLayout.BOOK);
} else if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.CHEAT_SHEET), true)) {
openGuide(p, SlimefunGuideLayout.CHEAT_SHEET);
public static void openGuide(@Nonnull Player p, @Nullable ItemStack guide) {
if (getItem(SlimefunGuideMode.CHEAT_MODE).equals(guide)) {
openGuide(p, SlimefunGuideMode.CHEAT_MODE);
} else {
// When using /sf cheat or /sf open_guide, ItemStack is null.
openGuide(p, SlimefunGuideLayout.CHEST);
/*
* When using /sf cheat or /sf open_guide the ItemStack is null anyway,
* so we don't even need to check here at this point.
*/
openGuide(p, SlimefunGuideMode.SURVIVAL_MODE);
}
}
public static void openGuide(Player p, SlimefunGuideLayout layout) {
public static void openGuide(@Nonnull Player p, @Nonnull SlimefunGuideMode mode) {
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
@ -60,58 +63,72 @@ public final class SlimefunGuide {
if (optional.isPresent()) {
PlayerProfile profile = optional.get();
SlimefunGuideImplementation guide = SlimefunPlugin.getRegistry().getGuideLayout(layout);
SlimefunGuideImplementation guide = SlimefunPlugin.getRegistry().getSlimefunGuide(mode);
profile.getGuideHistory().openLastEntry(guide);
} else {
openMainMenuAsync(p, layout, 1);
openMainMenuAsync(p, mode, 1);
}
}
private static void openMainMenuAsync(Player player, SlimefunGuideLayout layout, int selectedPage) {
if (!PlayerProfile.get(player, profile -> SlimefunPlugin.runSync(() -> openMainMenu(profile, layout, selectedPage)))) {
@ParametersAreNonnullByDefault
private static void openMainMenuAsync(Player player, SlimefunGuideMode mode, int selectedPage) {
if (!PlayerProfile.get(player, profile -> SlimefunPlugin.runSync(() -> openMainMenu(profile, mode, selectedPage)))) {
SlimefunPlugin.getLocalization().sendMessage(player, "messages.opening-guide");
}
}
public static void openMainMenu(PlayerProfile profile, SlimefunGuideLayout layout, int selectedPage) {
SlimefunPlugin.getRegistry().getGuideLayout(layout).openMainMenu(profile, selectedPage);
@ParametersAreNonnullByDefault
public static void openMainMenu(PlayerProfile profile, SlimefunGuideMode mode, int selectedPage) {
SlimefunPlugin.getRegistry().getSlimefunGuide(mode).openMainMenu(profile, selectedPage);
}
public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideLayout layout, int selectedPage) {
if (category == null) {
return;
@ParametersAreNonnullByDefault
public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideMode mode, int selectedPage) {
SlimefunPlugin.getRegistry().getSlimefunGuide(mode).openCategory(profile, category, selectedPage);
}
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) {
layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEAT_SHEET);
}
layout.openSearch(profile, input, addToHistory);
@ParametersAreNonnullByDefault
public static void openSearch(PlayerProfile profile, String input, SlimefunGuideMode mode, boolean addToHistory) {
SlimefunGuideImplementation guide = SlimefunPlugin.getRegistry().getSlimefunGuide(mode);
guide.openSearch(profile, input, addToHistory);
}
@ParametersAreNonnullByDefault
public static void displayItem(PlayerProfile profile, ItemStack item, boolean addToHistory) {
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST).displayItem(profile, item, 0, addToHistory);
SlimefunPlugin.getRegistry().getSlimefunGuide(SlimefunGuideMode.SURVIVAL_MODE).displayItem(profile, item, 0, addToHistory);
}
@ParametersAreNonnullByDefault
public static void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST).displayItem(profile, item, addToHistory);
SlimefunPlugin.getRegistry().getSlimefunGuide(SlimefunGuideMode.SURVIVAL_MODE).displayItem(profile, item, addToHistory);
}
public static boolean isGuideItem(ItemStack item) {
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEST), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.BOOK), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEAT_SHEET), true);
}
public static SlimefunGuideLayout getDefaultLayout() {
if (SlimefunPlugin.getCfg().getBoolean("guide.default-view-book")) {
return SlimefunGuideLayout.BOOK;
/**
* This method checks if a given {@link ItemStack} is a {@link SlimefunGuide}.
*
* @param item
* The {@link ItemStack} to check
*
* @return Whether this {@link ItemStack} represents a {@link SlimefunGuide}
*/
public static boolean isGuideItem(@Nullable ItemStack item) {
if (item == null || item.getType() != Material.ENCHANTED_BOOK) {
return false;
} else if (item instanceof SlimefunGuideItem) {
return true;
} else {
return SlimefunGuideLayout.CHEST;
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideMode.SURVIVAL_MODE), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideMode.CHEAT_MODE), true);
}
}
/**
* Get the default mode for the Slimefun guide.
* Currently this is only {@link SlimefunGuideMode#SURVIVAL_MODE}.
*
* @return The default {@link SlimefunGuideMode}.
*/
@Nonnull
public static SlimefunGuideMode getDefaultMode() {
return SlimefunGuideMode.SURVIVAL_MODE;
}
}

View File

@ -11,8 +11,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
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.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -22,21 +21,20 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
*
* @author TheBusyBiscuit
*
* @see SlimefunGuideLayout
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SlimefunGuideMode
* @see SurvivalSlimefunGuide
*
*/
public interface SlimefunGuideImplementation {
/**
* Every {@link SlimefunGuideImplementation} can be associated with a
* {@link SlimefunGuideLayout}.
* {@link SlimefunGuideMode}.
*
* @return The layout this {@link SlimefunGuideImplementation} represents
* @return The mode this {@link SlimefunGuideImplementation} represents
*/
@Nonnull
SlimefunGuideLayout getLayout();
SlimefunGuideMode getMode();
/**
* Returns the {@link ItemStack} representation for this {@link SlimefunGuideImplementation}.
@ -48,14 +46,6 @@ public interface SlimefunGuideImplementation {
@Nonnull
ItemStack getItem();
/**
* This method returns whether this {@link SlimefunGuideImplementation} is meant
* for Survival Mode.
*
* @return Whether this is a survival mode implementation
*/
boolean isSurvivalMode();
void openMainMenu(PlayerProfile profile, int page);
void openCategory(PlayerProfile profile, Category category, int page);

View File

@ -13,24 +13,17 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
* @see SlimefunGuideImplementation
*
*/
public enum SlimefunGuideLayout {
/**
* This design is a book representation of the {@link SlimefunGuide}
*/
BOOK,
public enum SlimefunGuideMode {
/**
* This design is the standard layout, it uses a {@link ChestMenu}
*/
CHEST,
SURVIVAL_MODE,
/**
* This is an admin-only design which creates a {@link SlimefunGuide} that allows
* you to spawn in any {@link SlimefunItem}
*/
CHEAT_SHEET;
public static final SlimefunGuideLayout[] valuesCache = values();
CHEAT_MODE;
}

View File

@ -4,6 +4,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@ -13,35 +16,41 @@ import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
class GuideModeOption implements SlimefunGuideOption<SlimefunGuideMode> {
@Nonnull
@Override
public SlimefunAddon getAddon() {
return SlimefunPlugin.instance();
}
@Nonnull
@Override
public NamespacedKey getKey() {
return new NamespacedKey(SlimefunPlugin.instance(), "guide_layout");
}
@Nonnull
@Override
public Optional<ItemStack> getDisplayItem(Player p, ItemStack guide) {
Optional<SlimefunGuideLayout> current = getSelectedOption(p, guide);
if (!p.hasPermission("slimefun.cheat.items")) {
// Only Players with the appropriate permission can access the cheat sheet
return Optional.empty();
}
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) {
SlimefunGuideLayout layout = current.get();
SlimefunGuideMode layout = current.get();
ItemStack item = new ItemStack(Material.AIR);
if (layout == SlimefunGuideLayout.CHEST) {
if (layout == SlimefunGuideMode.SURVIVAL_MODE) {
item.setType(Material.CHEST);
} else if (layout == SlimefunGuideLayout.BOOK) {
item.setType(Material.BOOK);
} else {
item.setType(Material.COMMAND_BLOCK);
}
@ -50,12 +59,9 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Design: " + ChatColor.YELLOW + ChatUtils.humanize(layout.name()));
List<String> lore = new ArrayList<>();
lore.add("");
lore.add((layout == SlimefunGuideLayout.CHEST ? ChatColor.GREEN : ChatColor.GRAY) + "Chest");
lore.add((layout == SlimefunGuideLayout.BOOK ? ChatColor.GREEN : ChatColor.GRAY) + "Book");
lore.add((layout == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Chest");
if (p.hasPermission("slimefun.cheat.items")) {
lore.add((layout == SlimefunGuideLayout.CHEAT_SHEET ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
}
lore.add((layout == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
lore.add("");
lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change your layout");
@ -69,46 +75,43 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
}
@Override
public void onClick(Player p, ItemStack guide) {
Optional<SlimefunGuideLayout> current = getSelectedOption(p, guide);
public void onClick(@Nonnull Player p, @Nonnull ItemStack guide) {
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) {
SlimefunGuideLayout next = getNextLayout(p, current.get());
SlimefunGuideMode next = getNextMode(p, current.get());
setSelectedOption(p, guide, next);
}
SlimefunGuideSettings.openSettings(p, guide);
}
private SlimefunGuideLayout getNextLayout(Player p, SlimefunGuideLayout layout) {
@Nonnull
private SlimefunGuideMode getNextMode(@Nonnull Player p, @Nonnull SlimefunGuideMode mode) {
if (p.hasPermission("slimefun.cheat.items")) {
if (layout == SlimefunGuideLayout.CHEST) {
return SlimefunGuideLayout.BOOK;
}
if (layout == SlimefunGuideLayout.BOOK) {
return SlimefunGuideLayout.CHEAT_SHEET;
}
return SlimefunGuideLayout.CHEST;
if (mode == SlimefunGuideMode.SURVIVAL_MODE) {
return SlimefunGuideMode.CHEAT_MODE;
} else {
return layout == SlimefunGuideLayout.CHEST ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST;
return SlimefunGuideMode.SURVIVAL_MODE;
}
} else {
return SlimefunGuideMode.SURVIVAL_MODE;
}
}
@Nonnull
@Override
public Optional<SlimefunGuideMode> getSelectedOption(@Nonnull Player p, @Nonnull ItemStack guide) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(SlimefunGuideMode.CHEAT_MODE), true, false)) {
return Optional.of(SlimefunGuideMode.CHEAT_MODE);
} else {
return Optional.of(SlimefunGuideMode.SURVIVAL_MODE);
}
}
@Override
public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.valuesCache) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true, false)) {
return Optional.of(layout);
}
}
return Optional.empty();
}
@Override
public void setSelectedOption(Player p, ItemStack guide, SlimefunGuideLayout value) {
@ParametersAreNonnullByDefault
public void setSelectedOption(Player p, ItemStack guide, SlimefunGuideMode value) {
guide.setItemMeta(SlimefunGuide.getItem(value).getItemMeta());
}

View File

@ -13,7 +13,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
@ -39,7 +39,7 @@ public final class SlimefunGuideSettings {
private static final List<SlimefunGuideOption<?>> options = new ArrayList<>();
static {
options.add(new GuideLayoutOption());
options.add(new GuideModeOption());
options.add(new FireworksOption());
options.add(new PlayerLanguageOption());
}
@ -65,7 +65,7 @@ public final class SlimefunGuideSettings {
}
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) {
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideLayout.CHEST), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
SlimefunGuide.openGuide(pl, guide);
return false;
});
@ -141,7 +141,7 @@ public final class SlimefunGuideSettings {
for (SlimefunGuideOption<?> option : options) {
if (option instanceof FireworksOption) {
FireworksOption fireworks = (FireworksOption) option;
return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideLayout.CHEST)).orElse(true);
return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE)).orElse(true);
}
}

View File

@ -12,7 +12,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -32,16 +31,14 @@ import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
@ -368,7 +365,7 @@ abstract class AbstractItemNetwork extends Network {
ItemMeta im = stack.getItemMeta();
List<String> lore = new ArrayList<>();
lore.add("");
lore.add(ChatColors.color("&7Stored Items: &f" + DoubleHandler.getFancyDouble(item.getInt())));
lore.add(ChatColors.color("&7Stored Items: &f" + NumberUtils.getCompactDouble(item.getInt())));
if (stack.getMaxStackSize() > 1) {
int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt();
@ -426,12 +423,7 @@ abstract class AbstractItemNetwork extends Network {
}
} else if (BlockStorage.hasInventory(target)) {
BlockMenu blockMenu = BlockStorage.getInventory(target);
if (blockMenu.getPreset().getID().startsWith("BARREL_")) {
gatherItemsFromBarrel(l, blockMenu, items);
} else {
handleWithdraw(blockMenu, items, l);
}
} else if (CargoUtils.hasInventory(target)) {
BlockState state = PaperLib.getBlockState(target, false).getState();
@ -445,41 +437,6 @@ abstract class AbstractItemNetwork extends Network {
}
}
@ParametersAreNonnullByDefault
private void gatherItemsFromBarrel(Location l, BlockMenu blockMenu, List<ItemStackAndInteger> items) {
try {
Config cfg = BlockStorage.getLocationInfo(blockMenu.getLocation());
String data = cfg.getString("storedItems");
if (data == null) {
return;
}
int stored = Integer.parseInt(data);
for (int slot : blockMenu.getPreset().getSlotsAccessedByItemTransport((DirtyChestMenu) blockMenu, ItemTransportFlow.WITHDRAW, null)) {
ItemStack stack = blockMenu.getItemInSlot(slot);
if (stack != null && CargoUtils.matchesFilter(this, l.getBlock(), stack)) {
boolean add = true;
for (ItemStackAndInteger item : items) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true, false)) {
add = false;
item.add(stack.getAmount() + stored);
}
}
if (add) {
items.add(new ItemStackAndInteger(stack, stack.getAmount() + stored));
}
}
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception occurred while trying to read data from a Barrel", x);
}
}
@ParametersAreNonnullByDefault
private void handleWithdraw(DirtyChestMenu menu, List<ItemStackAndInteger> items, Location l) {
for (int slot : menu.getPreset().getSlotsAccessedByItemTransport(menu, ItemTransportFlow.WITHDRAW, null)) {

View File

@ -20,7 +20,6 @@ import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link CargoNet} is a type of {@link Network} which deals with {@link ItemStack} transportation.
@ -250,7 +249,7 @@ public class CargoNet extends AbstractItemNetwork {
String str = BlockStorage.getLocationInfo(node).getString("frequency");
return str == null ? 0 : Integer.parseInt(str);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while parsing a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + "," + node.getBlockY() + "," + +node.getBlockZ() + ")");
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while parsing a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + "," + node.getBlockY() + "," + +node.getBlockZ() + ")");
return 0;
}
}

View File

@ -22,9 +22,20 @@ import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
/**
* This is a helper class for the {@link CargoNet} which provides
* a free static utility methods to let the {@link CargoNet} interact with
* an {@link Inventory} or {@link BlockMenu}.
*
* @author TheBusyBiscuit
* @author Walshy
* @author DNx5
*
*/
final class CargoUtils {
/**
@ -32,6 +43,10 @@ final class CargoUtils {
*/
private static final int[] FILTER_SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
/**
* This is a utility class and should not be instantiated.
* Therefore we just hide the public constructor.
*/
private CargoUtils() {}
/**
@ -51,10 +66,6 @@ final class CargoUtils {
Material type = block.getType();
if (SlimefunTag.SHULKER_BOXES.isTagged(type)) {
return true;
}
switch (type) {
case CHEST:
case TRAPPED_CHEST:
@ -68,10 +79,11 @@ final class CargoUtils {
case SMOKER:
return true;
default:
return false;
return SlimefunTag.SHULKER_BOXES.isTagged(type);
}
}
@Nonnull
static int[] getInputSlotRange(@Nonnull Inventory inv, @Nullable ItemStack item) {
if (inv instanceof FurnaceInventory) {
if (item != null && item.getType().isFuel()) {
@ -101,7 +113,8 @@ final class CargoUtils {
}
}
static int[] getOutputSlotRange(Inventory inv) {
@Nonnull
static int[] getOutputSlotRange(@Nonnull Inventory inv) {
if (inv instanceof FurnaceInventory) {
// Slot 2-3
return new int[] { 2, 3 };
@ -114,6 +127,7 @@ final class CargoUtils {
}
}
@Nullable
static ItemStack withdraw(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target, ItemStack template) {
DirtyChestMenu menu = getChestMenu(target);
@ -145,7 +159,7 @@ final class CargoUtils {
if (SlimefunUtils.isItemSimilar(is, wrapper, true) && matchesFilter(network, node, is)) {
if (is.getAmount() > template.getAmount()) {
is.setAmount(is.getAmount() - template.getAmount());
menu.replaceExistingItem(slot, is.clone());
menu.replaceExistingItem(slot, is);
return template;
} else {
menu.replaceExistingItem(slot, null);
@ -157,6 +171,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStack withdrawFromVanillaInventory(AbstractItemNetwork network, Block node, ItemStack template, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getOutputSlotRange(inv);
@ -184,6 +199,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStackAndInteger withdraw(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target) {
DirtyChestMenu menu = getChestMenu(target);
@ -215,6 +231,7 @@ final class CargoUtils {
return null;
}
@Nullable
private static ItemStackAndInteger withdrawFromVanillaInventory(AbstractItemNetwork network, Block node, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getOutputSlotRange(inv);
@ -233,6 +250,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStack insert(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target, ItemStack stack) {
if (!matchesFilter(network, node, stack)) {
return stack;
@ -273,7 +291,7 @@ final class CargoUtils {
int maxStackSize = itemInSlot.getType().getMaxStackSize();
int currentAmount = itemInSlot.getAmount();
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false) && currentAmount < maxStackSize) {
if (currentAmount < maxStackSize && SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
int amount = currentAmount + stack.getAmount();
itemInSlot.setAmount(Math.min(amount, maxStackSize));
@ -291,6 +309,7 @@ final class CargoUtils {
return stack;
}
@Nullable
private static ItemStack insertIntoVanillaInventory(ItemStack stack, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getInputSlotRange(inv, stack);
@ -309,7 +328,7 @@ final class CargoUtils {
} else {
int maxStackSize = itemInSlot.getType().getMaxStackSize();
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false) && itemInSlot.getAmount() < maxStackSize) {
if (itemInSlot.getAmount() < maxStackSize && SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
int amount = itemInSlot.getAmount() + stack.getAmount();
if (amount > maxStackSize) {
@ -327,13 +346,14 @@ final class CargoUtils {
return stack;
}
@Nullable
static DirtyChestMenu getChestMenu(@Nonnull Block block) {
if (BlockStorage.hasInventory(block)) {
return BlockStorage.getInventory(block);
}
} else {
return BlockStorage.getUniversalInventory(block);
}
}
static boolean matchesFilter(@Nonnull AbstractItemNetwork network, @Nonnull Block node, @Nullable ItemStack item) {
if (item == null || item.getType() == Material.AIR) {
@ -365,20 +385,12 @@ final class CargoUtils {
}
private static boolean isPotion(@Nullable ItemStack item) {
return item != null && (item.getType() == Material.POTION || item.getType() == Material.SPLASH_POTION || item.getType() == Material.LINGERING_POTION);
if (item != null) {
Material type = item.getType();
return type == Material.POTION || type == Material.SPLASH_POTION || type == Material.LINGERING_POTION;
} else {
return false;
}
/**
* Get the whitelist/blacklist slots in a Cargo Input Node. If you wish to access the items
* in the cargo (without hardcoding the slots in case of change) then you can use this method.
*
* @deprecated Renamed to {@link #getFilteringSlots()}
*
* @return The slot indexes for the whitelist/blacklist section.
*/
@Deprecated
public static int[] getWhitelistBlacklistSlots() {
return FILTER_SLOTS;
}
/**
@ -387,6 +399,7 @@ final class CargoUtils {
*
* @return The slots where the {@link ItemFilter} section for a cargo node sits
*/
@Nonnull
public static int[] getFilteringSlots() {
return FILTER_SLOTS;
}

View File

@ -15,7 +15,6 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service is responsible for automatically saving {@link Player} and {@link Block}
@ -66,7 +65,7 @@ public class AutoSavingService {
}
if (players > 0) {
Slimefun.getLogger().log(Level.INFO, "Auto-saved all player data for {0} player(s)!", players);
SlimefunPlugin.logger().log(Level.INFO, "Auto-saved all player data for {0} player(s)!", players);
}
}
@ -89,7 +88,7 @@ public class AutoSavingService {
}
if (!worlds.isEmpty()) {
Slimefun.getLogger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
SlimefunPlugin.logger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
for (BlockStorage storage : worlds) {
storage.save();

View File

@ -20,7 +20,6 @@ import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service creates a Backup of your Slimefun world data on every server shutdown.
@ -43,7 +42,7 @@ public class BackupService implements Runnable {
try {
purgeBackups(backups);
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Could not delete an old backup", e);
SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e);
}
}
@ -56,12 +55,12 @@ public class BackupService implements Runnable {
createBackup(output);
}
Slimefun.getLogger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
} else {
Slimefun.getLogger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
}
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
}
}
}

View File

@ -19,8 +19,8 @@ import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link BlockDataService} is similar to the {@link CustomItemDataService},
@ -78,12 +78,12 @@ public class BlockDataService implements Keyed {
container.set(namespacedKey, PersistentDataType.STRING, value);
state.update();
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "Please check if your Server Software is up to date!");
SlimefunPlugin.logger().log(Level.SEVERE, "Please check if your Server Software is up to date!");
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
Slimefun.getLogger().log(Level.SEVERE, () -> serverSoftware + " | " + Bukkit.getVersion() + " | " + Bukkit.getBukkitVersion());
SlimefunPlugin.logger().log(Level.SEVERE, () -> serverSoftware + " | " + Bukkit.getVersion() + " | " + Bukkit.getBukkitVersion());
Slimefun.getLogger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Block", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Block", x);
}
}
}

View File

@ -30,6 +30,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class CustomItemDataService implements Keyed {
/**
* This is the {@link NamespacedKey} used to store/read data.
*/
private final NamespacedKey namespacedKey;
/**

View File

@ -23,11 +23,10 @@ import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.core.services.localization.SlimefunLocalization;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
/**
* As the name suggests, this Service is responsible for Localization.
@ -78,7 +77,7 @@ public class LocalizationService extends SlimefunLocalization {
plugin.getLogger().log(Level.WARNING, "Could not recognize the given language: \"{0}\"", serverDefaultLanguage);
}
Slimefun.getLogger().log(Level.INFO, "Available languages: {0}", String.join(", ", languages.keySet()));
SlimefunPlugin.logger().log(Level.INFO, "Available languages: {0}", String.join(", ", languages.keySet()));
save();
} else {
translationsEnabled = false;
@ -178,7 +177,7 @@ public class LocalizationService extends SlimefunLocalization {
defaultLanguage.setCategoriesFile(streamConfigFile("categories_" + language + ".yml", null));
defaultLanguage.setRecipeTypesFile(streamConfigFile("recipes_" + language + ".yml", null));
Slimefun.getLogger().log(Level.INFO, "Loaded language \"{0}\"", language);
SlimefunPlugin.logger().log(Level.INFO, "Loaded language \"{0}\"", language);
getConfig().setValue(LANGUAGE_PATH, language);
// Loading in the defaults from our resources folder
@ -188,7 +187,7 @@ public class LocalizationService extends SlimefunLocalization {
FileConfiguration config = YamlConfiguration.loadConfiguration(reader);
getConfig().getConfiguration().setDefaults(config);
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to load language file: \"" + path + "\"");
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to load language file: \"" + path + "\"");
}
save();
@ -245,13 +244,15 @@ public class LocalizationService extends SlimefunLocalization {
}
}
return Math.min(DoubleHandler.fixDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
return Math.min(NumberUtils.reparseDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
}
@Nonnull
private Set<String> getTotalKeys(@Nonnull Language lang) {
return getKeys(lang.getFiles());
}
@Nonnull
private Set<String> getKeys(FileConfiguration... files) {
Set<String> keys = new HashSet<>();
@ -278,7 +279,7 @@ public class LocalizationService extends SlimefunLocalization {
return config;
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to load language file into memory: \"" + path + "\"");
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to load language file into memory: \"" + path + "\"");
return null;
}
}

View File

@ -20,14 +20,14 @@ import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.recipes.MinecraftRecipe;
import io.github.thebusybiscuit.cscorelib2.recipes.RecipeSnapshot;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
/**
* This Service is responsible for accessing a {@link RecipeSnapshot}.
* This snapshot contains a compiled list of all recipes that could be found on the
* Server at the time the Service was loaded.
*
* This Service is primarily used by the {@link ChestSlimefunGuide}.
* This Service is primarily used by the {@link SurvivalSlimefunGuide}.
*
* @author TheBusyBiscuit
*

View File

@ -9,10 +9,10 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class ContributionsConnector extends GitHubConnector {
@ -84,7 +84,7 @@ class ContributionsConnector extends GitHubConnector {
if (response.isArray()) {
computeContributors(response.getArray());
} else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
SlimefunPlugin.logger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}

View File

@ -15,7 +15,7 @@ import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import io.github.thebusybiscuit.cscorelib2.data.ComputedOptional;
import io.github.thebusybiscuit.cscorelib2.data.TriStateOptional;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
@ -35,7 +35,7 @@ public class Contributor {
private final String profileLink;
private final ConcurrentMap<String, Integer> contributions = new ConcurrentHashMap<>();
private final ComputedOptional<String> headTexture = ComputedOptional.createNew();
private final TriStateOptional<String> headTexture = TriStateOptional.createNew();
private Optional<UUID> uuid = Optional.empty();
private boolean immutable = false;
@ -181,10 +181,10 @@ public class Contributor {
public String getTexture() {
if (!headTexture.isComputed() || !headTexture.isPresent()) {
GitHubService github = SlimefunPlugin.getGitHubService();
if (github != null) {
String cached = github.getCachedTexture(githubUsername);
return cached != null ? cached : HeadTexture.UNKNOWN.getTexture();
if (cached != null) {
return cached;
} else {
return HeadTexture.UNKNOWN.getTexture();
}

View File

@ -14,12 +14,12 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import kong.unirest.json.JSONException;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link GitHubConnector} is used to connect to the GitHub API service.
@ -100,7 +100,7 @@ abstract class GitHubConnector {
file = new File("plugins/Slimefun/cache/github/" + getFileName() + ".json");
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.INFO, "Retrieving {0}.json from GitHub...", getFileName());
SlimefunPlugin.logger().log(Level.INFO, "Retrieving {0}.json from GitHub...", getFileName());
}
try {
@ -116,7 +116,7 @@ abstract class GitHubConnector {
writeCacheFile(response.getBody());
} else {
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { url, response.getStatus(), response.getBody() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { url, response.getStatus(), response.getBody() });
}
// It has the cached file, let's just read that then
@ -130,7 +130,7 @@ abstract class GitHubConnector {
}
} catch (UnirestException e) {
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time.", e);
SlimefunPlugin.logger().log(Level.WARNING, "Could not connect to GitHub in time.", e);
}
// It has the cached file, let's just read that then
@ -153,7 +153,7 @@ abstract class GitHubConnector {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
return new JsonNode(reader.readLine());
} catch (IOException | JSONException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] { file.getName(), e.getClass().getSimpleName(), e.getMessage() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] { file.getName(), e.getClass().getSimpleName(), e.getMessage() });
return null;
}
}
@ -162,7 +162,7 @@ abstract class GitHubConnector {
try (FileOutputStream output = new FileOutputStream(file)) {
output.write(node.toString().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] { e.getClass().getSimpleName(), e.getMessage() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] { e.getClass().getSimpleName(), e.getMessage() });
}
}
}

View File

@ -7,10 +7,10 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class GitHubIssuesConnector extends GitHubConnector {
@ -42,7 +42,7 @@ class GitHubIssuesConnector extends GitHubConnector {
callback.accept(issues, pullRequests);
} else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
SlimefunPlugin.logger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}

View File

@ -14,9 +14,8 @@ import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount.TooManyRequestsException;
import io.github.thebusybiscuit.cscorelib2.players.TooManyRequestsException;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link GitHubTask} represents a {@link Runnable} that is run every X minutes.
@ -101,8 +100,8 @@ class GitHubTask implements Runnable {
contributor.setTexture(null);
} 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 temporarily down or started to rate-limit this connection, this is not an error message!");
SlimefunPlugin.logger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() });
SlimefunPlugin.logger().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")) {
@ -111,7 +110,7 @@ class GitHubTask implements Runnable {
return -1;
} catch (TooManyRequestsException x) {
Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
SlimefunPlugin.logger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance(), this::grabTextures, 4 * 60 * 20L);
return -1;

View File

@ -36,6 +36,8 @@ public class Translators {
addTranslator("ishi-sama", SupportedLanguage.FRENCH, true);
addTranslator("amarcais53", SupportedLanguage.FRENCH, true);
addTranslator("NinoFutur", SupportedLanguage.FRENCH, true);
addTranslator("TheRetix", SupportedLanguage.FRENCH, true);
addTranslator("Aeris1One", SupportedLanguage.FRENCH, true);
// Translators - Italian
addTranslator("xXDOTTORXx", SupportedLanguage.ITALIAN, true);
@ -50,6 +52,8 @@ public class Translators {
// Translators - Hungarian
addTranslator("andris155", SupportedLanguage.HUNGARIAN, true);
addTranslator("KingDeadZ", SupportedLanguage.HUNGARIAN, true);
addTranslator("poma123", SupportedLanguage.HUNGARIAN, false);
// Translators - Vietnamese
addTranslator("HSGamer", SupportedLanguage.VIETNAMESE, false);
@ -164,6 +168,7 @@ public class Translators {
// Translators - Bulgarian
addTranslator("DNBGlol", SupportedLanguage.BULGARIAN, true);
addTranslator("Pukejoy", SupportedLanguage.BULGARIAN, true);
// Translators - Tagalog
addTranslator("sccooottttie", SupportedLanguage.TAGALOG, true);
@ -177,8 +182,10 @@ public class Translators {
addTranslator("Sakanas", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("krazybeat", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("FaolanMalcadh", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("G4stavoM1ster", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Gusstavo", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Day-OS", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("ooicram", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Sxigames", SupportedLanguage.PORTUGUESE_BRAZIL, true);
}
@ParametersAreNonnullByDefault

View File

@ -1,60 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.plugins;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nonnull;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.integrations.IntegrationsManager;
/**
* This Service holds all interactions and hooks with third-party {@link Plugin Plugins}
* that are not necessarily a dependency or a {@link SlimefunAddon}.
*
* Integration with these plugins happens inside Slimefun itself.
*
* @author TheBusyBiscuit
*
* @deprecated Renamed to {@link IntegrationsManager}
*
* @see SlimefunPlugin
*
*/
@Deprecated
public class ThirdPartyPluginService extends IntegrationsManager {
/**
* This gets overridden if ExoticGarden is loaded
*/
private Function<Block, Optional<ItemStack>> exoticGardenIntegration = b -> Optional.empty();
/**
* This initializes the {@link ThirdPartyPluginService}
*
* @param plugin
* Our instance of {@link SlimefunPlugin}
*/
public ThirdPartyPluginService(@Nonnull SlimefunPlugin plugin) {
super(plugin);
}
@Deprecated
public void loadExoticGarden(Plugin plugin, Function<Block, Optional<ItemStack>> method) {
// TODO: Move this method to IntegrationsManager and think of a better way to handle this
if (plugin.getName().equals("ExoticGarden")) {
exoticGardenIntegration = method;
}
}
@Deprecated
public Optional<ItemStack> harvestExoticGardenPlant(Block block) {
return exoticGardenIntegration.apply(block);
}
}

View File

@ -1,4 +0,0 @@
/**
* This package contains all hooks to external plugins
*/
package io.github.thebusybiscuit.slimefun4.core.services.plugins;

View File

@ -0,0 +1,41 @@
package io.github.thebusybiscuit.slimefun4.core.services.profiler;
import javax.annotation.Nonnull;
import org.bukkit.Server;
/**
* This interface is used to identify someone as a {@link PerformanceInspector}.
* A {@link PerformanceInspector} can query the {@link SlimefunProfiler} and get the
* results send to them as a {@link PerformanceSummary}.
*
* @author TheBusyBiscuit
*
*/
public interface PerformanceInspector {
/**
* This returns whether this {@link PerformanceInspector} is still valid.
* An inspector will become invalid if they leave the {@link Server}.
*
* @return Whether this inspector is still valid
*/
boolean isValid();
/**
* This will send a text message to the {@link PerformanceInspector}.
*
* @param msg
* The message to send
*/
void sendMessage(@Nonnull String msg);
/**
* This determines whether the {@link PerformanceInspector} will get the full view
* or a trimmed version which only shows the most urgent samples.
*
* @return Whether to send the full {@link PerformanceSummary} or a trimmed version
*/
boolean isVerbose();
}

View File

@ -11,10 +11,8 @@ import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors.PlayerPerformanceInspector;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import net.md_5.bungee.api.ChatColor;
@ -54,7 +52,7 @@ class PerformanceSummary {
items = profiler.getByItem();
}
public void send(@Nonnull CommandSender sender) {
public void send(@Nonnull PerformanceInspector sender) {
sender.sendMessage("");
sender.sendMessage(ChatColor.GREEN + "===== Slimefun Lag Profiler =====");
sender.sendMessage(ChatColor.GOLD + "Total time: " + ChatColor.YELLOW + NumberUtils.getAsMillis(totalElapsedTime));
@ -91,17 +89,17 @@ class PerformanceSummary {
}
@ParametersAreNonnullByDefault
private void summarizeTimings(int count, String name, CommandSender sender, Map<String, Long> map, Function<Map.Entry<String, Long>, String> formatter) {
private void summarizeTimings(int count, String name, PerformanceInspector inspector, Map<String, Long> map, Function<Map.Entry<String, Long>, String> formatter) {
Stream<Map.Entry<String, Long>> stream = map.entrySet().stream();
List<Entry<String, Long>> results = stream.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toList());
String prefix = count + " " + name + (count != 1 ? 's' : "");
if (sender instanceof Player) {
if (inspector instanceof PlayerPerformanceInspector) {
TextComponent component = summarizeAsTextComponent(count, prefix, results, formatter);
sender.spigot().sendMessage(component);
((PlayerPerformanceInspector) inspector).sendMessage(component);
} else {
String text = summarizeAsString(count, prefix, results, formatter);
sender.sendMessage(text);
String text = summarizeAsString(inspector, count, prefix, results, formatter);
inspector.sendMessage(text);
}
}
@ -143,7 +141,7 @@ class PerformanceSummary {
@Nonnull
@ParametersAreNonnullByDefault
private String summarizeAsString(int count, String prefix, List<Entry<String, Long>> results, Function<Entry<String, Long>, String> formatter) {
private String summarizeAsString(PerformanceInspector inspector, int count, String prefix, List<Entry<String, Long>> results, Function<Entry<String, Long>, String> formatter) {
int shownEntries = 0;
int hiddenEntries = 0;
@ -154,7 +152,7 @@ class PerformanceSummary {
builder.append(ChatColor.YELLOW);
for (Map.Entry<String, Long> entry : results) {
if (shownEntries < MAX_ITEMS && (shownEntries < MIN_ITEMS || entry.getValue() > VISIBILITY_THRESHOLD)) {
if (inspector.isVerbose() || (shownEntries < MAX_ITEMS && (shownEntries < MIN_ITEMS || entry.getValue() > VISIBILITY_THRESHOLD))) {
builder.append("\n ");
builder.append(ChatColor.stripColor(formatter.apply(entry)));
shownEntries++;

View File

@ -19,7 +19,6 @@ import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitScheduler;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
@ -27,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.TickerTask;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link SlimefunProfiler} works closely to the {@link TickerTask} and is
@ -69,7 +67,7 @@ public class SlimefunProfiler {
private long totalElapsedTime;
private final Map<ProfiledBlock, Long> timings = new ConcurrentHashMap<>();
private final Queue<CommandSender> requests = new ConcurrentLinkedQueue<>();
private final Queue<PerformanceInspector> requests = new ConcurrentLinkedQueue<>();
/**
* This method terminates the {@link SlimefunProfiler}.
@ -183,7 +181,7 @@ public class SlimefunProfiler {
// If we waited for too long, then we should just abort
if (iterations <= 0) {
Iterator<CommandSender> iterator = requests.iterator();
Iterator<PerformanceInspector> iterator = requests.iterator();
while (iterator.hasNext()) {
iterator.next().sendMessage("Your timings report has timed out, we were still waiting for " + queued.get() + " samples to be collected :/");
@ -193,7 +191,7 @@ public class SlimefunProfiler {
return;
}
} catch (InterruptedException e) {
Slimefun.getLogger().log(Level.SEVERE, "A Profiler Thread was interrupted", e);
SlimefunPlugin.logger().log(Level.SEVERE, "A Profiler Thread was interrupted", e);
Thread.currentThread().interrupt();
}
}
@ -207,7 +205,7 @@ public class SlimefunProfiler {
if (!requests.isEmpty()) {
PerformanceSummary summary = new PerformanceSummary(this, totalElapsedTime, timings.size());
Iterator<CommandSender> iterator = requests.iterator();
Iterator<PerformanceInspector> iterator = requests.iterator();
while (iterator.hasNext()) {
summary.send(iterator.next());
@ -217,16 +215,16 @@ public class SlimefunProfiler {
}
/**
* This method requests a summary for the given {@link CommandSender}.
* This method requests a summary for the given {@link PerformanceInspector}.
* The summary will be sent upon the next available moment in time.
*
* @param sender
* The {@link CommandSender} who shall receive this summary.
* @param inspector
* The {@link PerformanceInspector} who shall receive this summary.
*/
public void requestSummary(@Nonnull CommandSender sender) {
Validate.notNull(sender, "Cannot request a summary for null");
public void requestSummary(@Nonnull PerformanceInspector inspector) {
Validate.notNull(inspector, "Cannot request a summary for null");
requests.add(sender);
requests.add(inspector);
}
@Nonnull

View File

@ -0,0 +1,62 @@
package io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.PerformanceInspector;
/**
* This implementation of {@link PerformanceInspector} refers to a {@link CommandSender}
* which is preferabbly a {@link ConsoleCommandSender}.
* But it can theoretically be used for any type of {@link CommandSender} as it uses uncolored texts.
*
* @author TheBusyBiscuit
*
*/
public class ConsolePerformanceInspector implements PerformanceInspector {
/**
* Our reference to the actual underlying {@link CommandSender}.
*/
private final CommandSender console;
/**
* Whether a summary will be verbose or trimmed of.
*/
private final boolean verbose;
/**
* This creates a new {@link ConsolePerformanceInspector} for the given {@link CommandSender}.
*
* @param console
* The {@link CommandSender}, preferabbly a {@link ConsoleCommandSender}
* @param verbose
* Whether the summary will be verbose or not
*/
public ConsolePerformanceInspector(@Nonnull CommandSender console, boolean verbose) {
Validate.notNull(console, "CommandSender cannot be null");
this.console = console;
this.verbose = verbose;
}
@Override
public boolean isValid() {
// The console is always "online".
return true;
}
@Override
public boolean isVerbose() {
return verbose;
}
@Override
public void sendMessage(@Nonnull String msg) {
console.sendMessage(msg);
}
}

View File

@ -0,0 +1,74 @@
package io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.PerformanceInspector;
import net.md_5.bungee.api.chat.TextComponent;
/**
* This implementation of {@link PerformanceInspector} refers to a {@link Player}.
* It also supports {@link TextComponent TextComponents} for rich text messages.
*
* @author TheBusyBiscuit
*
*/
public class PlayerPerformanceInspector implements PerformanceInspector {
/**
* Our reference to the {@link UUID} of the {@link Player}.
*/
private final UUID uuid;
/**
* This creates a new {@link PlayerPerformanceInspector} for the given {@link Player}.
*
* @param player
* The {@link Player}
*/
public PlayerPerformanceInspector(@Nonnull Player player) {
Validate.notNull(player, "Player cannot be null");
this.uuid = player.getUniqueId();
}
@Nullable
private Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
@Override
public boolean isValid() {
Player player = getPlayer();
return player != null && player.isOnline();
}
@Override
public boolean isVerbose() {
return false;
}
@Override
public void sendMessage(@Nonnull String msg) {
Player player = getPlayer();
if (player != null) {
player.sendMessage(msg);
}
}
public void sendMessage(@Nonnull TextComponent component) {
Player player = getPlayer();
if (player != null) {
player.spigot().sendMessage(component);
}
}
}

View File

@ -0,0 +1,5 @@
/**
* This package holds the different implementations of
* {@link io.github.thebusybiscuit.slimefun4.core.services.profiler.PerformanceInspector}.
*/
package io.github.thebusybiscuit.slimefun4.core.services.profiler.inspectors;

View File

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@ -20,6 +21,7 @@ import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.Recipe;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
@ -27,9 +29,7 @@ import org.bukkit.plugin.java.JavaPluginLoader;
import org.bukkit.scheduler.BukkitTask;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
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;
@ -50,7 +50,6 @@ import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService;
import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
@ -113,6 +112,7 @@ 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.integrations.IntegrationsManager;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
@ -148,14 +148,14 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private final BackupService backupService = new BackupService();
private final PermissionsService permissionsService = new PermissionsService(this);
private final PerWorldSettingsService worldSettingsService = new PerWorldSettingsService(this);
private final ThirdPartyPluginService thirdPartySupportService = new ThirdPartyPluginService(this);
private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this);
private final SlimefunProfiler profiler = new SlimefunProfiler();
private LocalizationService local;
private final IntegrationsManager integrations = new IntegrationsManager(this);
private final SlimefunProfiler profiler = new SlimefunProfiler();
private LocalizationService local;
private GPSNetwork gpsNetwork;
private NetworkManager networkManager;
private ProtectionManager protections;
// Important config files for Slimefun
private final Config config = new Config(this);
@ -199,23 +199,63 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*/
@Override
public void onEnable() {
instance = this;
if (minecraftVersion == MinecraftVersion.UNIT_TEST) {
// We handle Unit Tests seperately.
setInstance(this);
onUnitTestStart();
} else if (isVersionUnsupported()) {
// We wanna ensure that the Server uses a compatible version of Minecraft.
setInstance(this);
getLogger().log(Level.WARNING, "Slimefun was not installed properly! Disabling...");
getServer().getPluginManager().disablePlugin(this);
} else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
// The Environment and dependencies have been validated.
setInstance(this);
getLogger().log(Level.INFO, "CS-CoreLib was detected!");
onPluginStart();
} else {
// Terminate our Plugin instance
setInstance(null);
// CS-CoreLib has not been installed!
getLogger().log(Level.INFO, "#################### - INFO - ####################");
getLogger().log(Level.INFO, " ");
getLogger().log(Level.INFO, "Slimefun could not be loaded (yet).");
getLogger().log(Level.INFO, "It appears that you have not installed CS-CoreLib.");
getLogger().log(Level.INFO, "Please download and install CS-CoreLib manually:");
getLogger().log(Level.INFO, "https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
// Send a message upon doing /slimefun
getCommand("slimefun").setExecutor((sender, cmd, label, args) -> {
sender.sendMessage("You have forgotten to install CS-CoreLib! Slimefun is disabled.");
sender.sendMessage("https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
return true;
});
}
}
/**
* This is our start method for a Unit Test environment.
*/
private void onUnitTestStart() {
local = new LocalizationService(this, "", null);
gpsNetwork = new GPSNetwork();
networkManager = new NetworkManager(200);
command.register();
registry.load(this, config);
loadTags();
}
/**
* This is our start method for a correct Slimefun installation.
*/
private void onPluginStart() {
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);
return;
} else {
PaperLib.suggestPaper(this);
}
// Disabling backwards-compatibility for fresh Slimefun installs
@ -229,7 +269,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Creating all necessary Folders
getLogger().log(Level.INFO, "Creating directories...");
createDirectories();
registry.load(config);
registry.load(this, config);
// Set up localization
getLogger().log(Level.INFO, "Loading language files...");
@ -279,7 +319,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Initiating various Stuff and all items with a slight delay (0ms after the Server finished loading)
runSync(new SlimefunStartupTask(this, () -> {
protections = new ProtectionManager(getServer());
textureService.register(registry.getAllSlimefunItems(), true);
permissionsService.register(registry.getAllSlimefunItems(), true);
@ -292,8 +331,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}), 0);
// Setting up the command /sf and all subcommands
// Setting up our commands
try {
command.register();
} catch (Exception | LinkageError x) {
getLogger().log(Level.SEVERE, "An Exception occurred while registering the /slimefun command", x);
}
// Armor Update Task
if (config.getBoolean("options.enable-armor-effects")) {
@ -301,44 +344,27 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(radioactiveFire), 0L, config.getInt("options.armor-update-interval") * 20L);
}
// Starting our tasks
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
ticker.start(this);
// Loading integrations
getLogger().log(Level.INFO, "Loading Third-Party plugin integrations...");
thirdPartySupportService.start();
integrations.start();
gitHubService.start(this);
// Hooray!
getLogger().log(Level.INFO, "Slimefun has finished loading in {0}", getStartupTime(timestamp));
} else {
instance = null;
getLogger().log(Level.INFO, "#################### - INFO - ####################");
getLogger().log(Level.INFO, " ");
getLogger().log(Level.INFO, "Slimefun could not be loaded (yet).");
getLogger().log(Level.INFO, "It appears that you have not installed CS-CoreLib.");
getLogger().log(Level.INFO, "Please download and install CS-CoreLib manually:");
getLogger().log(Level.INFO, "https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
getCommand("slimefun").setExecutor((sender, cmd, label, args) -> {
sender.sendMessage("You have forgotten to install CS-CoreLib! Slimefun is disabled.");
sender.sendMessage("https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
return true;
});
}
}
/**
* This is our start method for a Unit Test environment.
*/
private void onUnitTestStart() {
local = new LocalizationService(this, "", null);
gpsNetwork = new GPSNetwork();
networkManager = new NetworkManager(200);
command.register();
registry.load(config);
loadTags();
@Override
public JavaPlugin getJavaPlugin() {
return this;
}
@Override
public String getBugTrackerURL() {
return "https://github.com/Slimefun/Slimefun4/issues";
}
/**
@ -378,6 +404,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
// Save all "universal" inventories (ender chests for example)
for (UniversalBlockMenu menu : registry.getUniversalInventories().values()) {
menu.save();
}
@ -388,20 +415,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Close and unload any resources from our Metrics Service
metricsService.cleanUp();
/**
* Prevent Memory Leaks for reloads...
* These static Maps should really be removed at some point...
*/
AContainer.processing = null;
AContainer.progress = null;
// Terminate our Plugin instance
setInstance(null);
AGenerator.processing = null;
AGenerator.progress = null;
Reactor.processing = null;
Reactor.progress = null;
instance = null;
// Clean up any static fields
cleanUp();
/**
* Close all inventories on the server to prevent item dupes
@ -412,17 +430,55 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This is a private internal method to set the de-facto instance of {@link SlimefunPlugin}.
* Having this as a seperate method ensures the seperation between static and non-static fields.
* It also makes sonarcloud happy :)
* Only ever use it during {@link #onEnable()} or {@link #onDisable()}.
*
* @param pluginInstance
* Our instance of {@link SlimefunPlugin} or null
*/
private static void setInstance(@Nullable SlimefunPlugin pluginInstance) {
instance = pluginInstance;
}
/**
* This returns the time it took to load Slimefun (given a starting point).
*
* @param timestamp
* The time at which we started to load Slimefun.
*
* @return The total time it took to load Slimefun (in ms or s)
*/
@Nonnull
private String getStartupTime(long timestamp) {
long ms = (System.nanoTime() - timestamp) / 1000000;
if (ms > 1000) {
return DoubleHandler.fixDouble(ms / 1000.0) + "s";
return NumberUtils.roundDecimalNumber(ms / 1000.0) + "s";
} else {
return DoubleHandler.fixDouble(ms) + "ms";
return NumberUtils.roundDecimalNumber(ms) + "ms";
}
}
/**
* Cleaning up our static fields prevents memory leaks from a reload.
*
* @deprecated These static Maps should really be removed at some point...
*/
@Deprecated
private static void cleanUp() {
AContainer.processing = null;
AContainer.progress = null;
AGenerator.processing = null;
AGenerator.progress = null;
Reactor.processing = null;
Reactor.progress = null;
}
/**
* This method checks for the {@link MinecraftVersion} of the {@link Server}.
* If the version is unsupported, a warning will be printed to the console.
@ -430,12 +486,29 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
* @return Whether the {@link MinecraftVersion} is unsupported
*/
private boolean isVersionUnsupported() {
String currentVersion = ReflectionUtils.getVersion();
try {
// First check if they still use the unsupported CraftBukkit software.
if (!PaperLib.isSpigot() && Bukkit.getName().equals("CraftBukkit")) {
getLogger().log(Level.SEVERE, "###############################################");
getLogger().log(Level.SEVERE, "### Slimefun was not installed correctly!");
getLogger().log(Level.SEVERE, "### CraftBukkit is no longer supported!");
getLogger().log(Level.SEVERE, "###");
getLogger().log(Level.SEVERE, "### Slimefun requires you to use Spigot, Paper or");
getLogger().log(Level.SEVERE, "### any supported fork of Spigot or Paper.");
getLogger().log(Level.SEVERE, "### (We recommend Paper)");
getLogger().log(Level.SEVERE, "###############################################");
if (currentVersion.startsWith("v")) {
for (MinecraftVersion version : MinecraftVersion.valuesCache) {
if (version.matches(currentVersion)) {
minecraftVersion = version;
return true;
}
// Now check the actual Version of Minecraft
int version = PaperLib.getMinecraftVersion();
if (version > 0) {
// Check all supported versions of Minecraft
for (MinecraftVersion supportedVersion : MinecraftVersion.valuesCache) {
if (supportedVersion.isMinecraftVersion(version)) {
minecraftVersion = supportedVersion;
return false;
}
}
@ -445,17 +518,42 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getLogger().log(Level.SEVERE, "### Slimefun was not installed correctly!");
getLogger().log(Level.SEVERE, "### You are using the wrong version of Minecraft!");
getLogger().log(Level.SEVERE, "###");
getLogger().log(Level.SEVERE, "### You are using Minecraft {0}", currentVersion);
getLogger().log(Level.SEVERE, "### You are using Minecraft 1.{0}.x", version);
getLogger().log(Level.SEVERE, "### but Slimefun {0} requires you to be using", getDescription().getVersion());
getLogger().log(Level.SEVERE, "### Minecraft {0}", String.join(" / ", getSupportedVersions()));
getLogger().log(Level.SEVERE, "#############################################");
return true;
}
} else {
getLogger().log(Level.WARNING, "We could not determine the version of Minecraft you were using? ({0})", Bukkit.getVersion());
getLogger().log(Level.WARNING, "We could not determine the version of Minecraft you were using ({0})", currentVersion);
/*
* If we are unsure about it, we will assume "supported".
* They could be using a non-Bukkit based Software which still
* might support Bukkit-based plugins.
* Use at your own risk in this case.
*/
return false;
}
} catch (Exception | LinkageError x) {
getLogger().log(Level.SEVERE, x, () -> "Error: Could not determine Environment or version of Minecraft for Slimefun v" + getDescription().getVersion());
// We assume "unsupported" if something went wrong.
return true;
}
}
/**
* This private method gives us a {@link Collection} of every {@link MinecraftVersion}
* that Slimefun is compatible with (as a {@link String} representation).
* <p>
* Example:
*
* <pre>
* { 1.14.x, 1.15.x, 1.16.x }
* </pre>
*
* @return A {@link Collection} of all compatible minecraft versions as strings
*/
@Nonnull
private Collection<String> getSupportedVersions() {
List<String> list = new ArrayList<>();
@ -469,6 +567,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return list;
}
/**
* This method creates all necessary directories (and sub directories) for Slimefun.
*/
private void createDirectories() {
String[] storageFolders = { "Players", "blocks", "stored-blocks", "stored-inventories", "stored-chunks", "universal-inventories", "waypoints", "block-backups" };
String[] pluginFolders = { "scripts", "error-reports", "cache/github", "world-settings" };
@ -564,6 +665,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new PlayerProfileListener(this);
}
/**
* This (re)loads every {@link SlimefunTag}.
*/
private void loadTags() {
for (SlimefunTag tag : SlimefunTag.valuesCache) {
try {
@ -577,6 +681,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This loads all of our items.
*/
private void loadItems() {
try {
SlimefunItemSetup.setup(this);
@ -585,6 +692,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This loads our researches.
*/
private void loadResearches() {
try {
ResearchSetup.setupResearches();
@ -593,6 +703,19 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This private static method allows us to throw a proper {@link Exception}
* whenever someone tries to access a static method while the instance is null.
* This happens when the method is invoked before {@link #onEnable()} or after {@link #onDisable()}.
* <p>
* Use it whenever a null check is needed to avoid a non-descriptive {@link NullPointerException}.
*/
private static void validateInstance() {
if (instance == null) {
throw new IllegalStateException("Cannot invoke static method, Slimefun instance is null.");
}
}
/**
* This returns the global instance of {@link SlimefunPlugin}.
* This may return null if the {@link Plugin} was disabled.
@ -604,24 +727,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance;
}
public static Config getCfg() {
return instance.config;
}
public static Config getResearchCfg() {
return instance.researches;
}
public static Config getItemCfg() {
return instance.items;
}
public static GPSNetwork getGPSNetwork() {
return instance.gpsNetwork;
}
public static TickerTask getTickerTask() {
return instance.ticker;
/**
* This returns the {@link Logger} instance that Slimefun uses.
* <p>
* <strong>Any {@link SlimefunAddon} should use their own {@link Logger} instance!</strong>
*
* @return Our {@link Logger} instance
*/
@Nonnull
public static Logger logger() {
validateInstance();
return instance.getLogger();
}
/**
@ -629,59 +745,96 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The currently installed version of Slimefun
*/
@Nonnull
public static String getVersion() {
validateInstance();
return instance.getDescription().getVersion();
}
@Nonnull
public static Config getCfg() {
validateInstance();
return instance.config;
}
@Nonnull
public static Config getResearchCfg() {
validateInstance();
return instance.researches;
}
@Nonnull
public static Config getItemCfg() {
validateInstance();
return instance.items;
}
@Nonnull
public static GPSNetwork getGPSNetwork() {
validateInstance();
return instance.gpsNetwork;
}
@Nonnull
public static TickerTask getTickerTask() {
validateInstance();
return instance.ticker;
}
/**
* This returns the {@link LocalizationService} of Slimefun.
*
* @return The {@link LocalizationService} of Slimefun
*/
@Nonnull
public static LocalizationService getLocalization() {
validateInstance();
return instance.local;
}
public static ProtectionManager getProtectionManager() {
return instance.protections;
}
/**
* This method returns out {@link MinecraftRecipeService} for Slimefun.
* This service is responsible for finding/identifying {@link Recipe Recipes}
* from vanilla Minecraft.
*
* @return Slimefun's {@link MinecraftRecipeService} instance
*/
@Nonnull
public static MinecraftRecipeService getMinecraftRecipeService() {
validateInstance();
return instance.recipeService;
}
@Nonnull
public static CustomItemDataService getItemDataService() {
validateInstance();
return instance.itemDataService;
}
@Nonnull
public static CustomTextureService getItemTextureService() {
validateInstance();
return instance.textureService;
}
@Nonnull
public static PermissionsService getPermissionsService() {
validateInstance();
return instance.permissionsService;
}
@Nonnull
public static BlockDataService getBlockDataService() {
validateInstance();
return instance.blockDataService;
}
@Nonnull
public static PerWorldSettingsService getWorldSettingsService() {
validateInstance();
return instance.worldSettingsService;
}
/**
* This method has been renamed.
*
* @deprecated Please use {@link #getIntegrations()} instead.
*
* @return the {@link ThirdPartyPluginService}
*/
@Deprecated
public static ThirdPartyPluginService getThirdPartySupportService() {
return instance.thirdPartySupportService;
}
/**
* This returns our instance of {@link IntegrationsManager}.
* This is responsible for managing any integrations with third party {@link Plugin plugins}.
@ -690,7 +843,19 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*/
@Nonnull
public static IntegrationsManager getIntegrations() {
return instance.thirdPartySupportService;
validateInstance();
return instance.integrations;
}
/**
* This returns out instance of the {@link ProtectionManager}.
* This bridge is used to hook into any third-party protection {@link Plugin}.
*
* @return Our instanceof of the {@link ProtectionManager}
*/
@Nonnull
public static ProtectionManager getProtectionManager() {
return getIntegrations().getProtectionManager();
}
/**
@ -699,7 +864,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The {@link UpdaterService} for Slimefun
*/
@Nonnull
public static UpdaterService getUpdater() {
validateInstance();
return instance.updaterService;
}
@ -709,7 +876,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The {@link MetricsService} for Slimefun
*/
@Nonnull
public static MetricsService getMetricsService() {
validateInstance();
return instance.metricsService;
}
@ -719,30 +888,105 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The {@link GitHubService} for Slimefun
*/
@Nonnull
public static GitHubService getGitHubService() {
validateInstance();
return instance.gitHubService;
}
public static SlimefunRegistry getRegistry() {
return instance.registry;
}
/**
* This returns our {@link NetworkManager} which is responsible
* for handling the Cargo and Energy networks.
*
* @return Our {@link NetworkManager} instance
*/
@Nonnull
public static NetworkManager getNetworkManager() {
validateInstance();
return instance.networkManager;
}
@Nonnull
public static SlimefunRegistry getRegistry() {
validateInstance();
return instance.registry;
}
@Nonnull
public static GrapplingHookListener getGrapplingHookListener() {
validateInstance();
return instance.grapplingHookListener;
}
@Nonnull
public static BackpackListener getBackpackListener() {
validateInstance();
return instance.backpackListener;
}
@Nonnull
public static SlimefunBowListener getBowListener() {
validateInstance();
return instance.bowListener;
}
/**
* The {@link Command} that was added by Slimefun.
*
* @return Slimefun's command
*/
@Nonnull
public static SlimefunCommand getCommand() {
validateInstance();
return instance.command;
}
/**
* This returns our instance of the {@link SlimefunProfiler}, a tool that is used
* to analyse performance and lag.
*
* @return The {@link SlimefunProfiler}
*/
@Nonnull
public static SlimefunProfiler getProfiler() {
validateInstance();
return instance.profiler;
}
/**
* This returns the currently installed version of Minecraft.
*
* @return The current version of Minecraft
*/
@Nonnull
public static MinecraftVersion getMinecraftVersion() {
validateInstance();
return instance.minecraftVersion;
}
/**
* This method returns whether this version of Slimefun was newly installed.
* It will return true if this {@link Server} uses Slimefun for the very first time.
*
* @return Whether this is a new installation of Slimefun
*/
public static boolean isNewlyInstalled() {
validateInstance();
return instance.isNewlyInstalled;
}
@Nonnull
public static String getCSCoreLibVersion() {
validateInstance();
Plugin cscorelib = instance.getServer().getPluginManager().getPlugin("CS-CoreLib");
if (cscorelib == null) {
throw new IllegalStateException("CS-CoreLib is not installed.");
} else {
return cscorelib.getDescription().getVersion();
}
}
/**
* This method returns a {@link Set} of every {@link Plugin} that lists Slimefun
* as a required or optional dependency.
@ -753,66 +997,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*/
@Nonnull
public static Set<Plugin> getInstalledAddons() {
return Arrays.stream(instance.getServer().getPluginManager().getPlugins()).filter(plugin -> plugin.getDescription().getDepend().contains(instance.getName()) || plugin.getDescription().getSoftDepend().contains(instance.getName())).collect(Collectors.toSet());
}
validateInstance();
/**
* The {@link Command} that was added by Slimefun.
*
* @return Slimefun's command
*/
public static SlimefunCommand getCommand() {
return instance.command;
}
String pluginName = instance.getName();
/**
* This returns our instance of the {@link SlimefunProfiler}, a tool that is used
* to analyse performance and lag.
*
* @return The {@link SlimefunProfiler}
*/
public static SlimefunProfiler getProfiler() {
return instance.profiler;
}
/**
* This returns the currently installed version of Minecraft.
*
* @return The current version of Minecraft
*/
public static MinecraftVersion getMinecraftVersion() {
return instance.minecraftVersion;
}
/**
* This method returns whether this version of Slimefun was newly installed.
* It will return true if this {@link Server} uses Slimefun for the very first time.
*
* @return Whether this is a new installation of Slimefun
*/
public static boolean isNewlyInstalled() {
return instance.isNewlyInstalled;
}
@Nonnull
public static String getCSCoreLibVersion() {
Plugin cscorelib = instance.getServer().getPluginManager().getPlugin("CS-CoreLib");
if (cscorelib == null) {
throw new IllegalStateException("CS-CoreLib is not installed.");
} else {
return cscorelib.getDescription().getVersion();
}
}
@Override
public JavaPlugin getJavaPlugin() {
return this;
}
@Override
public String getBugTrackerURL() {
return "https://github.com/Slimefun/Slimefun4/issues";
// @formatter:off
return Arrays.stream(instance.getServer().getPluginManager().getPlugins())
.filter(plugin -> {
PluginDescriptionFile description = plugin.getDescription();
return description.getDepend().contains(pluginName) || description.getSoftDepend().contains(pluginName);
}).collect(Collectors.toSet());
// @formatter:on
}
/**

View File

@ -1,253 +0,0 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.chat.json.ChatComponent;
import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link BookSlimefunGuide} is a {@link SlimefunGuideImplementation} which
* uses a {@link CustomBookInterface} to display the contents of the {@link SlimefunGuide}.
* {@link Player Players} have the option to choose this Written Book layout over the
* standard {@link Inventory} variant.
*
* @author TheBusyBiscuit
*
* @see SlimefunGuide
* @see SlimefunGuideImplementation
* @see ChestSlimefunGuide
* @see CheatSheetSlimefunGuide
*
*/
public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance(), "search");
private final ItemStack item;
public BookSlimefunGuide() {
item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Book GUI)");
}
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.BOOK;
}
@Override
public boolean isSurvivalMode() {
return true;
}
@Override
public ItemStack getItem() {
return item;
}
private void openBook(Player p, PlayerProfile profile, List<ChatComponent> lines, boolean backButton) {
CustomBookInterface book = new CustomBookInterface(SlimefunPlugin.instance());
book.setTitle(SlimefunPlugin.getLocalization().getMessage(p, "guide.title.main"));
for (int i = 0; i < lines.size(); i = i + 10) {
ChatComponent page = new ChatComponent("");
ChatComponent header = new ChatComponent(ChatColors.color("&b&l- " + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.main") + " -\n\n"));
header.setHoverEvent(new HoverEvent(ChestMenuUtils.getSearchButton(p)));
header.setClickEvent(new ClickEvent(guideSearch, player -> SlimefunPlugin.runSync(() -> {
SlimefunPlugin.getLocalization().sendMessage(player, "guide.search.message");
ChatInput.waitForPlayer(SlimefunPlugin.instance(), player, msg -> SlimefunGuide.openSearch(profile, msg, true, true));
}, 1)));
page.append(header);
for (int j = i; j < lines.size() && j < i + 10; j++) {
page.append(lines.get(j));
}
page.append(new ChatComponent("\n"));
if (backButton) {
ChatComponent button = new ChatComponent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"));
button.setHoverEvent(new HoverEvent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", ChatColor.GRAY + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")));
button.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance(), "slimefun_guide"), pl -> openMainMenu(profile, 1)));
page.append(button);
}
book.addPage(page);
}
book.open(p);
}
@Override
public void openMainMenu(PlayerProfile profile, int page) {
Player p = profile.getPlayer();
if (p == null) {
return;
}
List<ChatComponent> lines = new LinkedList<>();
int tier = 0;
for (Category category : SlimefunPlugin.getRegistry().getCategories()) {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getLayout()))) {
if (tier < category.getTier()) {
tier = category.getTier();
if (tier > 1) {
for (int i = 0; i < 10 && lines.size() % 10 != 0; i++) {
lines.add(new ChatComponent("\n"));
}
}
lines.add(new ChatComponent(ChatColor.DARK_GRAY + "\u21E8" + ChatColor.DARK_BLUE + " Tier " + tier + "\n"));
}
addCategory(p, profile, category, lines);
}
}
openBook(p, profile, lines, false);
}
private void addCategory(Player p, PlayerProfile profile, Category category, List<ChatComponent> lines) {
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
} else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
}
@Override
public void openCategory(PlayerProfile profile, Category category, int page) {
Player p = profile.getPlayer();
if (p == null) {
return;
}
if (category instanceof FlexCategory) {
((FlexCategory) category).open(p, profile, getLayout());
} else if (category.getItems().size() < 250) {
profile.getGuideHistory().add(category, page);
List<ChatComponent> items = new LinkedList<>();
for (SlimefunItem slimefunItem : category.getItems()) {
if (Slimefun.hasPermission(p, slimefunItem, false)) {
if (Slimefun.isEnabled(p, slimefunItem, false)) {
addSlimefunItem(category, page, p, profile, slimefunItem, items);
}
} else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(slimefunItem.getItem())) + "\n");
List<String> lore = new ArrayList<>();
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(slimefunItem.getItem())));
lore.add("");
for (String line : SlimefunPlugin.getPermissionsService().getLore(slimefunItem)) {
lore.add(ChatColors.color(line));
}
component.setHoverEvent(new HoverEvent(lore));
items.add(component);
}
}
openBook(p, profile, items, true);
} else {
p.sendMessage(ChatColor.RED + "That Category is too big to open :/");
}
}
private void addSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getId().toLowerCase(Locale.ROOT));
if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
Research research = item.getResearch();
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n");
component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)"));
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> research.unlockFromGuide(this, player, profile, item, category, page))));
items.add(component);
} else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, item.getItemName()) + "\n");
List<String> lore = new ArrayList<>();
lore.add(item.getItemName());
if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
lore.addAll(item.getItem().getItemMeta().getLore());
}
component.setHoverEvent(new HoverEvent(lore));
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> displayItem(profile, item, true))));
items.add(component);
}
}
@Override
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
// We need to write a book implementation for this at some point
SlimefunGuide.openSearch(profile, input, true, addToHistory);
}
@Override
public void displayItem(PlayerProfile profile, ItemStack item, int index, boolean addToHistory) {
SlimefunGuide.displayItem(profile, item, addToHistory);
}
@Override
public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
SlimefunGuide.displayItem(profile, item, addToHistory);
}
}

View File

@ -12,7 +12,7 @@ import org.bukkit.inventory.Recipe;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
@ -21,13 +21,13 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This is an admin-variant of the {@link ChestSlimefunGuide} which allows a {@link Player}
* This is an admin-variant of the {@link SurvivalSlimefunGuide} which allows a {@link Player}
* to spawn in a {@link SlimefunItem} via click rather than showing their {@link Recipe}.
*
* @author TheBusyBiscuit
*
*/
public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
public class CheatSheetSlimefunGuide extends SurvivalSlimefunGuide {
private final ItemStack item;
@ -37,11 +37,6 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
item = new SlimefunGuideItem(this, "&cSlimefun Guide &4(Cheat Sheet)");
}
@Override
public boolean isSurvivalMode() {
return false;
}
/**
* Returns a {@link List} of visible {@link Category} instances that the {@link SlimefunGuide} would display.
*
@ -65,11 +60,13 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
return categories;
}
@Nonnull
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.CHEAT_SHEET;
public SlimefunGuideMode getMode() {
return SlimefunGuideMode.CHEAT_MODE;
}
@Nonnull
@Override
public ItemStack getItem() {
return item;

View File

@ -21,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
* A {@link RecipeChoiceTask} is an asynchronously repeating task that cycles
* through the different variants of {@link Material} that a {@link MaterialChoice} or {@link Tag} can represent.
*
* It is used in the {@link ChestSlimefunGuide} for any {@link ItemStack} from Minecraft
* It is used in the {@link SurvivalSlimefunGuide} for any {@link ItemStack} from Minecraft
* that accepts more than one {@link Material} in its {@link Recipe}.
*
* @author TheBusyBiscuit

View File

@ -27,6 +27,7 @@ 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.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
@ -34,7 +35,7 @@ import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
@ -51,18 +52,17 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link ChestSlimefunGuide} is the standard version of our {@link SlimefunGuide}.
* The {@link SurvivalSlimefunGuide} is the standard version of our {@link SlimefunGuide}.
* It uses an {@link Inventory} to display {@link SlimefunGuide} contents.
*
* @author TheBusyBiscuit
*
* @see SlimefunGuide
* @see SlimefunGuideImplementation
* @see BookSlimefunGuide
* @see CheatSheetSlimefunGuide
*
*/
public class ChestSlimefunGuide implements SlimefunGuideImplementation {
public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36;
private static final Sound sound = Sound.ITEM_BOOK_PAGE_TURN;
@ -71,14 +71,14 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private final ItemStack item;
private final boolean showVanillaRecipes;
public ChestSlimefunGuide(boolean showVanillaRecipes) {
public SurvivalSlimefunGuide(boolean showVanillaRecipes) {
this.showVanillaRecipes = showVanillaRecipes;
item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Chest GUI)");
}
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.CHEST;
public SlimefunGuideMode getMode() {
return SlimefunGuideMode.SURVIVAL_MODE;
}
@Override
@ -86,9 +86,8 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
return item;
}
@Override
public boolean isSurvivalMode() {
return true;
protected final boolean isSurvivalMode() {
return getMode() != SlimefunGuideMode.CHEAT_MODE;
}
/**
@ -105,9 +104,19 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
List<Category> categories = new LinkedList<>();
for (Category category : SlimefunPlugin.getRegistry().getCategories()) {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getLayout()))) {
try {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getMode()))) {
categories.add(category);
}
} catch (Exception | LinkageError x) {
SlimefunAddon addon = category.getAddon();
if (addon != null) {
addon.getLogger().log(Level.SEVERE, x, () -> "Could not display Category: " + category);
} else {
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "Could not display Category: " + category);
}
}
}
return categories;
@ -204,7 +213,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
}
if (category instanceof FlexCategory) {
((FlexCategory) category).open(p, profile, getLayout());
((FlexCategory) category).open(p, profile, getMode());
return;
}
@ -561,7 +570,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
pl.closeInventory();
SlimefunPlugin.getLocalization().sendMessage(pl, "guide.search.message");
ChatInput.waitForPlayer(SlimefunPlugin.instance(), pl, msg -> SlimefunGuide.openSearch(profile, msg, isSurvivalMode(), isSurvivalMode()));
ChatInput.waitForPlayer(SlimefunPlugin.instance(), pl, msg -> SlimefunGuide.openSearch(profile, msg, getMode(), isSurvivalMode()));
return false;
});
@ -698,7 +707,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private void printErrorMessage(Player p, Throwable x) {
p.sendMessage(ChatColor.DARK_RED + "An internal server error has occurred. Please inform an admin, check the console for further info.");
Slimefun.getLogger().log(Level.SEVERE, "An error has occurred while trying to open a SlimefunItem in the guide!", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An error has occurred while trying to open a SlimefunItem in the guide!", x);
}
}

View File

@ -1,55 +0,0 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
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;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
* The {@link AdvancedFarmerAndroid} is an extension of the {@link FarmerAndroid}.
* It also allows the {@link Player} to harvest plants from the addon ExoticGarden.
*
* @author John000708
* @author TheBusyBiscuit
*
* @see FarmerAndroid
*
*/
public class AdvancedFarmerAndroid extends FarmerAndroid {
@ParametersAreNonnullByDefault
public AdvancedFarmerAndroid(Category category, int tier, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, tier, item, recipeType, recipe);
}
@Override
public AndroidType getAndroidType() {
return AndroidType.ADVANCED_FARMER;
}
@Override
protected void exoticFarm(BlockMenu menu, Block block) {
farm(menu, block);
if (SlimefunPlugin.getIntegrations().isExoticGardenInstalled()) {
Optional<ItemStack> result = SlimefunPlugin.getThirdPartySupportService().harvestExoticGardenPlant(block);
if (result.isPresent()) {
ItemStack drop = result.get();
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
}
}
}
}

View File

@ -29,7 +29,7 @@ public enum AndroidType {
FARMER,
/**
* The {@link AdvancedFarmerAndroid} is an extension of the {@link FarmerAndroid},
* The Advanced Farmer is an extension of the {@link FarmerAndroid},
* it can also harvest plants from ExoticGarden.
*/
ADVANCED_FARMER,

View File

@ -3,6 +3,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -10,6 +13,7 @@ import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.AndroidFarmEvent;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -17,37 +21,41 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public class FarmerAndroid extends ProgrammableAndroid {
@ParametersAreNonnullByDefault
public FarmerAndroid(Category category, int tier, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, tier, item, recipeType, recipe);
}
@Override
public AndroidType getAndroidType() {
return AndroidType.FARMER;
}
private boolean isFullGrown(Block block) {
BlockData data = block.getBlockData();
if (!(data instanceof Ageable)) {
return false;
}
Ageable ageable = (Ageable) data;
return ageable.getAge() >= ageable.getMaximumAge();
return getTier() == 1 ? AndroidType.FARMER : AndroidType.ADVANCED_FARMER;
}
@Override
protected void farm(BlockMenu menu, Block block) {
if (isFullGrown(block)) {
ItemStack drop = getDropFromCrop(block.getType());
protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) {
Material blockType = block.getType();
BlockData data = block.getBlockData();
ItemStack drop = null;
if (drop != null && menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
Ageable ageable = (Ageable) block.getBlockData();
ageable.setAge(0);
block.setBlockData(ageable);
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
if (data instanceof Ageable && ((Ageable) data).getAge() >= ((Ageable) data).getMaximumAge()) {
drop = getDropFromCrop(blockType);
}
AndroidInstance instance = new AndroidInstance(this, b);
AndroidFarmEvent event = new AndroidFarmEvent(block, instance, isAdvanced, drop);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
drop = event.getDrop();
if (drop != null && menu.pushItem(drop, getOutputSlots()) == null) {
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, blockType);
if (data instanceof Ageable) {
((Ageable) data).setAge(0);
block.setBlockData(data);
}
}
}
}

View File

@ -1,11 +1,12 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
@ -191,7 +192,7 @@ public enum Instruction {
*/
FARM_FORWARD(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.farm(inv, target);
android.farm(b, inv, target, false);
}),
/**
@ -200,7 +201,7 @@ public enum Instruction {
*/
FARM_DOWN(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.farm(inv, target);
android.farm(b, inv, target, false);
}),
/**
@ -211,7 +212,7 @@ public enum Instruction {
*/
FARM_EXOTIC_FORWARD(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.exoticFarm(inv, target);
android.farm(b, inv, target, true);
}),
/**
@ -222,7 +223,7 @@ public enum Instruction {
*/
FARM_EXOTIC_DOWN(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.exoticFarm(inv, target);
android.farm(b, inv, target, true);
}),
/**

View File

@ -58,7 +58,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -425,7 +424,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
openScriptEditor(player, b);
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception was thrown when a User tried to download a Script!", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception was thrown when a User tried to download a Script!", x);
}
return false;
@ -844,6 +843,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
}
}
@ParametersAreNonnullByDefault
protected void move(Block b, BlockFace face, Block block) {
if (block.getY() > 0 && block.getY() < block.getWorld().getMaxHeight() && block.isEmpty()) {
BlockData blockData = Material.PLAYER_HEAD.createBlockData(data -> {
@ -881,11 +881,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
throw new UnsupportedOperationException("Non-woodcutter Android tried to chop a Tree!");
}
protected void farm(BlockMenu menu, Block block) {
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
}
protected void exoticFarm(BlockMenu menu, Block block) {
protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) {
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
}

View File

@ -21,9 +21,9 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
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}.
@ -244,7 +244,7 @@ public final class Script {
scripts.add(new Script(config));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception occurred while trying to load Android Script '" + file.getName() + "'");
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception occurred while trying to load Android Script '" + file.getName() + "'");
}
}
}

View File

@ -105,7 +105,6 @@ public class StomperBoots extends SlimefunItem {
* @return If the entity can move.
*/
protected boolean canPush(@Nonnull Player player, @Nonnull LivingEntity entity) {
return entity.isValid() && !entity.getUniqueId().equals(player.getUniqueId())
&& entity.isCollidable() && entity.hasGravity();
return entity.isValid() && !entity.getUniqueId().equals(player.getUniqueId()) && entity.isCollidable() && entity.hasGravity();
}
}

View File

@ -11,13 +11,13 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -90,9 +90,9 @@ public class HologramProjector extends SlimefunItem implements HologramOwner {
return false;
});
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + NumberUtils.roundDecimalNumber(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
double offset = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + (action.isRightClicked() ? -0.1F : 0.1F));
double offset = NumberUtils.reparseDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + (action.isRightClicked() ? -0.1F : 0.1F));
ArmorStand hologram = getArmorStand(projector, true);
Location l = new Location(projector.getWorld(), projector.getX() + 0.5, projector.getY() + offset, projector.getZ() + 0.5);
hologram.teleport(l);

View File

@ -14,7 +14,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
@ -114,7 +113,7 @@ public abstract class AbstractEnergyProvider extends SlimefunItem implements Inv
List<String> lore = new ArrayList<>();
lore.add(ChatColors.color("&8\u21E8 &7Lasts " + NumberUtils.getTimeLeft(fuel.getTicks() / 2)));
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + getEnergyProduction() * 2) + " J/s");
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + DoubleHandler.getFancyDouble((double) fuel.getTicks() * getEnergyProduction()) + " J in total"));
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + NumberUtils.getCompactDouble((double) fuel.getTicks() * getEnergyProduction()) + " J in total"));
im.setLore(lore);
item.setItemMeta(im);
list.add(item);

View File

@ -52,8 +52,7 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
} while (index != i && !modes.get(index).isEnabled());
return index;
}

View File

@ -11,7 +11,6 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
@ -20,6 +19,7 @@ import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponen
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -166,7 +166,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
menu.replaceExistingItem(31, new CustomItem(Material.PISTON, "&7Offset: &3" + offset + " Block(s)", "", "&fLeft Click: &7+0.1", "&fRight Click: &7-0.1"));
menu.addMenuClickHandler(31, (p, slot, item, action) -> {
double offsetv = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET)) + (action.isRightClicked() ? -0.1F : 0.1F));
double offsetv = NumberUtils.reparseDouble(Double.valueOf(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET)) + (action.isRightClicked() ? -0.1F : 0.1F));
BlockStorage.addBlockInfo(b, KEY_OFFSET, String.valueOf(offsetv));
updateBlockInventory(menu, b);
return false;

View File

@ -0,0 +1,93 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
/**
* This represents an {@link ElevatorFloor} to which a {@link Player}
* can travel to using an {@link ElevatorPlate}.
*
* @author TheBusyBiscuit
*
*/
class ElevatorFloor {
/**
* The name of this floor.
*/
private final String name;
/**
* The floor number.
*/
private final int number;
/**
* The {@link Location} of this floor.
*/
private final Location location;
/**
* This constructs a new {@link ElevatorFloor} with the given name
* and the {@link Location} of the provided {@link Block}.
*
* @param name
* The name of this {@link ElevatorFloor}
* @param block
* The {@link Block} of this floor
*/
public ElevatorFloor(@Nonnull String name, int number, @Nonnull Block block) {
Validate.notNull(name, "An ElevatorFloor must have a name");
Validate.notNull(block, "An ElevatorFloor must have a block");
this.name = name;
this.number = number;
this.location = block.getLocation();
}
/**
* This returns the name of this {@link ElevatorFloor}.
*
* @return The name of this floor
*/
@Nonnull
public String getName() {
return name;
}
/**
* This returns the {@link Location} of this {@link ElevatorFloor}.
*
* @return The {@link Location} of this floor
*/
@Nonnull
public Location getLocation() {
return location;
}
/**
* This returns the "altitude" of this floor.
* This is equivalent to the Y level of {@link #getLocation()}.
*
* @return The altitude of this floor
*/
public int getAltitude() {
return location.getBlockY();
}
/**
* This returns the number of this floor.
* The lowest floor will have the number 0 and it
* increments from there.
*
* @return The number of this floor.
*/
public int getNumber() {
return number;
}
}

View File

@ -1,4 +1,4 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.gps;
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;
import java.util.HashSet;
import java.util.LinkedList;
@ -12,22 +12,19 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.json.ChatComponent;
import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -42,7 +39,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* to teleport between them.
*
* @author TheBusyBiscuit
*
* @author Walshy
*/
public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
@ -51,6 +48,11 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
*/
private static final String DATA_KEY = "floor";
/**
* This is the size of our {@link Inventory}.
*/
private static final int GUI_SIZE = 27;
/**
* This is our {@link Set} of currently teleporting {@link Player Players}.
* It is used to prevent them from triggering the {@link ElevatorPlate} they land on.
@ -77,6 +79,7 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
};
}
@Nonnull
@Override
public BlockUseHandler getItemHandler() {
return e -> {
@ -89,19 +92,24 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
}
@Nonnull
public List<Block> getFloors(@Nonnull Block b) {
List<Block> floors = new LinkedList<>();
public List<ElevatorFloor> getFloors(@Nonnull Block b) {
LinkedList<ElevatorFloor> floors = new LinkedList<>();
int index = 0;
for (int y = b.getWorld().getMaxHeight(); y > 0; y--) {
for (int y = 0; y < b.getWorld().getMaxHeight(); y++) {
if (y == b.getY()) {
floors.add(b);
String name = ChatColors.color(BlockStorage.getLocationInfo(b.getLocation(), DATA_KEY));
floors.addFirst(new ElevatorFloor(name, index, b));
index++;
continue;
}
Block block = b.getWorld().getBlockAt(b.getX(), y, b.getZ());
if (block.getType() == getItem().getType() && BlockStorage.check(block, getId())) {
floors.add(block);
String name = ChatColors.color(BlockStorage.getLocationInfo(block.getLocation(), DATA_KEY));
floors.addFirst(new ElevatorFloor(name, index, block));
index++;
}
}
@ -114,54 +122,69 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
return;
}
List<Block> floors = getFloors(b);
List<ElevatorFloor> floors = getFloors(b);
if (floors.size() < 2) {
SlimefunPlugin.getLocalization().sendMessage(p, "machines.ELEVATOR.no-destinations", true);
} else {
openFloorSelector(b, floors, p);
openFloorSelector(b, floors, p, 1);
}
}
@ParametersAreNonnullByDefault
private void openFloorSelector(Block b, List<Block> floors, Player p) {
CustomBookInterface book = new CustomBookInterface(SlimefunPlugin.instance());
ChatComponent page = null;
private void openFloorSelector(Block b, List<ElevatorFloor> floors, Player p, int page) {
ChestMenu menu = new ChestMenu(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.pick-a-floor"));
menu.setEmptySlotsClickable(false);
for (int i = 0; i < floors.size(); i++) {
if (i % 10 == 0) {
if (page != null) {
book.addPage(page);
}
int index = GUI_SIZE * (page - 1);
page = new ChatComponent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.pick-a-floor")) + "\n");
}
for (int i = 0; i < Math.min(GUI_SIZE, floors.size() - index); i++) {
ElevatorFloor floor = floors.get(index + i);
Block block = floors.get(i);
String floor = ChatColors.color(BlockStorage.getLocationInfo(block.getLocation(), DATA_KEY));
ChatComponent line;
if (block.getY() == b.getY()) {
line = new ChatComponent("\n" + ChatColor.GRAY + "> " + (floors.size() - i) + ". " + ChatColor.BLACK + floor);
line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.current-floor")), "", ChatColor.WHITE + floor, ""));
// @formatter:off
if (floor.getAltitude() == b.getY()) {
menu.addItem(i, new CustomItem(
Material.COMPASS,
ChatColor.GRAY.toString() + floor.getNumber() + ". " + ChatColor.BLACK + floor.getName(),
SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.current-floor") + ' ' + ChatColor.WHITE + floor.getName()
), ChestMenuUtils.getEmptyClickHandler());
} else {
line = new ChatComponent("\n" + ChatColor.GRAY + (floors.size() - i) + ". " + ChatColor.BLACK + floor);
line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.click-to-teleport")), "", ChatColor.WHITE + floor, ""));
line.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance(), DATA_KEY + i), player -> teleport(player, floor, block)));
menu.addItem(i, new CustomItem(
Material.PAPER,
ChatColor.GRAY.toString() + floor.getNumber() + ". " + ChatColor.BLACK + floor.getName(),
SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.click-to-teleport") + ' ' + ChatColor.WHITE + floor.getName()
), (player, slot, itemStack, clickAction) -> {
teleport(player, floor);
return false;
});
}
// @formatter:on
}
page.append(line);
int pages = 1 + (floors.size() / GUI_SIZE);
// 0 index so size is the first slot of the last row.
for (int i = GUI_SIZE; i < GUI_SIZE + 9; i++) {
if (i == GUI_SIZE + 2 && pages > 1 && page != 1) {
menu.addItem(i, ChestMenuUtils.getPreviousButton(p, page, pages), (player, i1, itemStack, clickAction) -> {
openFloorSelector(b, floors, p, page - 1);
return false;
});
} else if (i == GUI_SIZE + 6 && pages > 1 && page != pages) {
menu.addItem(i, ChestMenuUtils.getNextButton(p, page, pages), (player, i1, itemStack, clickAction) -> {
openFloorSelector(b, floors, p, page + 1);
return false;
});
} else {
menu.addItem(i, ChestMenuUtils.getBackground(), (player, i1, itemStack, clickAction) -> false);
}
}
if (page != null) {
book.addPage(page);
}
book.open(p);
menu.open(p);
}
@ParametersAreNonnullByDefault
private void teleport(Player player, String floorName, Block target) {
private void teleport(Player player, ElevatorFloor floor) {
SlimefunPlugin.runSync(() -> {
users.add(player.getUniqueId());
@ -171,11 +194,12 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
yaw = -180 + (yaw - 180);
}
Location destination = new Location(player.getWorld(), target.getX() + 0.5, target.getY() + 0.4, target.getZ() + 0.5, yaw, player.getEyeLocation().getPitch());
Location loc = floor.getLocation();
Location destination = new Location(player.getWorld(), loc.getX() + 0.5, loc.getY() + 0.4, loc.getZ() + 0.5, yaw, player.getEyeLocation().getPitch());
PaperLib.teleportAsync(player, destination).thenAccept(teleported -> {
if (teleported.booleanValue()) {
player.sendTitle(ChatColor.WHITE + ChatColors.color(floorName), null, 20, 60, 20);
player.sendTitle(ChatColor.WHITE + ChatColors.color(floor.getName()), null, 20, 60, 20);
}
});
});

View File

@ -0,0 +1,5 @@
/**
* This package holds the {@link io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate} and any
* related classes to making the elevator work.
*/
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;

View File

@ -17,8 +17,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -42,7 +42,7 @@ public class MagicianTalisman extends Talisman {
enchantments.add(new TalismanEnchantment(enchantment, i));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "The following Exception occurred while trying to register the following Enchantment: " + enchantment);
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "The following Exception occurred while trying to register the following Enchantment: " + enchantment);
}
}

View File

@ -27,7 +27,6 @@ import io.github.thebusybiscuit.cscorelib2.scheduling.TaskQueue;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This represents a running instance of an {@link IndustrialMiner}.
@ -198,7 +197,7 @@ class ActiveMiner implements Runnable {
nextColumn();
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "An Error occurred while running an Industrial Miner at " + new BlockPosition(chest));
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "An Error occurred while running an Industrial Miner at " + new BlockPosition(chest));
stop();
}
});
@ -350,7 +349,7 @@ class ActiveMiner implements Runnable {
stop("machines.INDUSTRIAL_MINER.destroyed");
}
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "An Error occurred while moving a Piston for an Industrial Miner at " + new BlockPosition(block));
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "An Error occurred while moving a Piston for an Industrial Miner at " + new BlockPosition(block));
stop();
}
}

View File

@ -67,12 +67,13 @@ public class BlockListener implements Listener {
SlimefunItem sfItem = BlockStorage.check(block);
if (sfItem != null) {
/* Temp fix for #2636
for (ItemStack item : sfItem.getDrops()) {
if (item != null && !item.getType().isAir()) {
block.getWorld().dropItemNaturally(block.getLocation(), item);
}
}
/*
* Temp fix for #2636
* for (ItemStack item : sfItem.getDrops()) {
* if (item != null && !item.getType().isAir()) {
* block.getWorld().dropItemNaturally(block.getLocation(), item);
* }
* }
*/
BlockStorage.clearBlockInfo(block);
}

View File

@ -29,7 +29,6 @@ import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for handling our debugging tool, the debug fish.
@ -99,7 +98,7 @@ public class DebugFishListener implements Listener {
try {
sendInfo(p, b);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception occurred while using a Debug-Fish", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception occurred while using a Debug-Fish", x);
}
}
}

View File

@ -12,10 +12,10 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunGuideOpenEvent;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunGuideOpenEvent;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@ -38,7 +38,7 @@ public class SlimefunGuideListener implements Listener {
return;
}
SlimefunGuideLayout type = SlimefunGuide.getDefaultLayout();
SlimefunGuideMode type = SlimefunGuide.getDefaultMode();
p.getInventory().addItem(SlimefunGuide.getItem(type).clone());
}
}
@ -47,31 +47,27 @@ public class SlimefunGuideListener implements Listener {
public void onInteract(PlayerRightClickEvent e) {
Player p = e.getPlayer();
if (tryOpenGuide(p, e, SlimefunGuideLayout.BOOK) == Result.ALLOW) {
if (tryOpenGuide(p, e, SlimefunGuideMode.SURVIVAL_MODE) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
openGuide(p, e, SlimefunGuideLayout.BOOK);
openGuide(p, e, SlimefunGuideMode.SURVIVAL_MODE);
}
} else if (tryOpenGuide(p, e, SlimefunGuideLayout.CHEST) == Result.ALLOW) {
} else if (tryOpenGuide(p, e, SlimefunGuideMode.CHEAT_MODE) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
openGuide(p, e, SlimefunGuideLayout.CHEST);
}
} else if (tryOpenGuide(p, e, SlimefunGuideLayout.CHEAT_SHEET) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
// We rather just run the command here,
// all necessary permission checks will be handled there.
/*
* We rather just run the command here, all
* necessary permission checks will be handled there.
*/
p.chat("/sf cheat");
}
}
}
@ParametersAreNonnullByDefault
private void openGuide(Player p, PlayerRightClickEvent e, SlimefunGuideLayout layout) {
private void openGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layout) {
SlimefunGuideOpenEvent event = new SlimefunGuideOpenEvent(p, e.getItem(), layout);
Bukkit.getPluginManager().callEvent(event);
@ -83,7 +79,7 @@ public class SlimefunGuideListener implements Listener {
@Nonnull
@ParametersAreNonnullByDefault
private Result tryOpenGuide(Player p, PlayerRightClickEvent e, SlimefunGuideLayout layout) {
private Result tryOpenGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layout) {
ItemStack item = e.getItem();
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true, false)) {

View File

@ -15,7 +15,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.Teleporter;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;

View File

@ -11,7 +11,6 @@ import org.bukkit.event.world.WorldUnloadEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public class WorldListener implements Listener {
@ -32,7 +31,7 @@ public class WorldListener implements Listener {
if (storage != null) {
storage.saveAndRemove();
} else {
Slimefun.getLogger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName());
SlimefunPlugin.logger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName());
}
}

View File

@ -35,14 +35,13 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Smelt
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public final class PostSetup {
private PostSetup() {}
public static void setupWiki() {
Slimefun.getLogger().log(Level.INFO, "Loading Wiki pages...");
SlimefunPlugin.logger().log(Level.INFO, "Loading Wiki pages...");
JsonParser parser = new JsonParser();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(SlimefunPlugin.class.getResourceAsStream("/wiki.json"), StandardCharsets.UTF_8))) {
@ -57,7 +56,7 @@ public final class PostSetup {
}
}
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, "Failed to load wiki.json file", e);
SlimefunPlugin.logger().log(Level.SEVERE, "Failed to load wiki.json file", e);
}
}
@ -68,7 +67,7 @@ public final class PostSetup {
SlimefunItem item = iterator.next();
if (item == null) {
Slimefun.getLogger().log(Level.WARNING, "Removed bugged Item ('NULL?')");
SlimefunPlugin.logger().log(Level.WARNING, "Removed bugged Item ('NULL?')");
iterator.remove();
} else {
try {

View File

@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.RadioactiveItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AdvancedFarmerAndroid;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AndroidInterface;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.ButcherAndroid;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.FarmerAndroid;
@ -110,6 +109,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.XPCollector;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NetherStarReactor;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NuclearReactor;
import io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.BirthdayCake;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.DietCookie;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.FortuneCookie;
@ -122,7 +122,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOScanner;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.OilPump;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.PortableGEOScanner;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSControlPanel;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSMarkerTool;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSTransmitter;
@ -1895,7 +1894,7 @@ public final class SlimefunItemSetup {
new ItemStack[] {null, SlimefunItems.GPS_TRANSMITTER, null, new ItemStack(Material.DIAMOND_SWORD), SlimefunItems.PROGRAMMABLE_ANDROID_2, new ItemStack(Material.DIAMOND_SWORD), null, SlimefunItems.ELECTRIC_MOTOR, null})
.register(plugin);
new AdvancedFarmerAndroid(categories.androids, 2, SlimefunItems.PROGRAMMABLE_ANDROID_2_FARMER, RecipeType.ENHANCED_CRAFTING_TABLE,
new FarmerAndroid(categories.androids, 2, SlimefunItems.PROGRAMMABLE_ANDROID_2_FARMER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, SlimefunItems.GPS_TRANSMITTER, null, new ItemStack(Material.DIAMOND_HOE), SlimefunItems.PROGRAMMABLE_ANDROID_2, new ItemStack(Material.DIAMOND_HOE), null, SlimefunItems.ELECTRIC_MOTOR, null})
.register(plugin);

View File

@ -10,8 +10,8 @@ import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.JetBoots;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
public class JetBootsTask extends AbstractPlayerTask {
@ -30,7 +30,7 @@ public class JetBootsTask extends AbstractPlayerTask {
return;
}
double accuracy = DoubleHandler.fixDouble(boots.getSpeed() - 0.7);
double accuracy = NumberUtils.reparseDouble(boots.getSpeed() - 0.7);
if (boots.removeItemCharge(p.getInventory().getBoots(), COST)) {
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_TNT_PRIMED, (float) 0.25, 1);

View File

@ -12,7 +12,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.TeleporterLis
import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Task initializes all items, some listeners and various other stuff.
@ -54,7 +53,7 @@ public class SlimefunStartupTask implements Runnable {
try {
new BlockStorage(world);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while trying to load World \"" + world.getName() + "\" for Slimefun v" + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while trying to load World \"" + world.getName() + "\" for Slimefun v" + SlimefunPlugin.getVersion());
}
}

View File

@ -27,7 +27,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker},
@ -132,7 +131,7 @@ public class TickerTask implements Runnable {
reset();
SlimefunPlugin.getProfiler().stop();
} catch (Exception | LinkageError x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
reset();
}
}
@ -147,7 +146,7 @@ public class TickerTask implements Runnable {
}
}
} catch (ArrayIndexOutOfBoundsException | NumberFormatException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk);
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk);
}
}
@ -204,10 +203,10 @@ public class TickerTask implements Runnable {
new ErrorReport<>(x, l, item);
bugs.put(position, errors);
} else if (errors == 4) {
Slimefun.getLogger().log(Level.SEVERE, "X: {0} Y: {1} Z: {2} ({3})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), item.getId() });
Slimefun.getLogger().log(Level.SEVERE, "has thrown 4 error messages in the last 4 Ticks, the Block has been terminated.");
Slimefun.getLogger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
Slimefun.getLogger().log(Level.SEVERE, " ");
SlimefunPlugin.logger().log(Level.SEVERE, "X: {0} Y: {1} Z: {2} ({3})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), item.getId() });
SlimefunPlugin.logger().log(Level.SEVERE, "has thrown 4 error messages in the last 4 Ticks, the Block has been terminated.");
SlimefunPlugin.logger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
SlimefunPlugin.logger().log(Level.SEVERE, " ");
bugs.remove(position);
BlockStorage.deleteLocationInfoUnsafely(l, true);

View File

@ -14,9 +14,9 @@ import org.bukkit.plugin.Plugin;
import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
import dev.lone.itemsadder.api.ItemsAdder;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectionManager;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service holds all interactions and hooks with third-party {@link Plugin Plugins}
@ -36,6 +36,11 @@ public class IntegrationsManager {
*/
protected final SlimefunPlugin plugin;
/**
* Our {@link ProtectionManager} instance.
*/
private ProtectionManager protectionManager;
/**
* This boolean determines whether {@link #start()} was run.
*/
@ -50,7 +55,6 @@ public class IntegrationsManager {
// Addon support
private boolean isChestTerminalInstalled = false;
private boolean isExoticGardenInstalled = false;
/**
* This initializes the {@link IntegrationsManager}
@ -127,13 +131,27 @@ public class IntegrationsManager {
* This method is called when the {@link Server} has finished loading all its {@link Plugin Plugins}.
*/
private void onServerStart() {
isChestTerminalInstalled = isAddonInstalled("ChestTerminal");
isExoticGardenInstalled = isAddonInstalled("ExoticGarden");
try {
// Load Protection plugin integrations
protectionManager = new ProtectionManager(plugin.getServer());
} catch (Exception | LinkageError x) {
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load Protection plugin integrations for Slimefun v" + SlimefunPlugin.getVersion());
}
isChestTerminalInstalled = isAddonInstalled("ChestTerminal");
}
/**
* This method checks if the given addon is installed.
*
* @param addon
* The name of the addon
*
* @return Whether that addon is installed on the {@link Server}
*/
private boolean isAddonInstalled(@Nonnull String addon) {
if (plugin.getServer().getPluginManager().isPluginEnabled(addon)) {
Slimefun.getLogger().log(Level.INFO, "Hooked into Slimefun Addon: {0}", addon);
SlimefunPlugin.logger().log(Level.INFO, "Hooked into Slimefun Addon: {0}", addon);
return true;
} else {
return false;
@ -154,18 +172,29 @@ public class IntegrationsManager {
if (integration != null && integration.isEnabled()) {
String version = integration.getDescription().getVersion();
Slimefun.getLogger().log(Level.INFO, "Hooked into Plugin: {0} v{1}", new Object[] { pluginName, version });
SlimefunPlugin.logger().log(Level.INFO, "Hooked into Plugin: {0} v{1}", new Object[] { pluginName, version });
try {
// Run our callback
consumer.accept(integration);
} catch (Exception | LinkageError x) {
Slimefun.getLogger().log(Level.WARNING, "Maybe consider updating {0} or Slimefun?", pluginName);
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to hook into " + pluginName + " v" + version);
SlimefunPlugin.logger().log(Level.WARNING, "Maybe consider updating {0} or Slimefun?", pluginName);
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to hook into " + pluginName + " v" + version);
}
}
}
/**
* This returns out instance of the {@link ProtectionManager}.
* This bridge is used to hook into any third-party protection {@link Plugin}.
*
* @return Our instanceof of the {@link ProtectionManager}
*/
@Nonnull
public ProtectionManager getProtectionManager() {
return protectionManager;
}
/**
* This checks if one of our third party integrations faked an {@link Event}.
* Faked {@link Event Events} should be ignored in our logic.
@ -218,8 +247,4 @@ public class IntegrationsManager {
return isChestTerminalInstalled;
}
public boolean isExoticGardenInstalled() {
return isExoticGardenInstalled;
}
}

View File

@ -114,8 +114,6 @@ public enum HeadTexture {
PIGLIN_HEAD("2882af1294a74023e6919a31d1a027310f2e142afb4667d230d155e7f21dbb41"),
NECROTIC_SKULL("7953b6c68448e7e6b6bf8fb273d7203acd8e1be19e81481ead51f45de59a8");
public static final HeadTexture[] valuesCache = values();
private final String texture;
private final UUID uuid;

View File

@ -223,10 +223,15 @@ public final class NumberUtils {
}
}
@Nonnull
public static String roundDecimalNumber(double number) {
return DECIMAL_FORMAT.format(number);
}
public static double reparseDouble(double number) {
return Double.valueOf(roundDecimalNumber(number));
}
public static long getLong(@Nullable Long value, long defaultValue) {
return value == null ? defaultValue : value;
}

View File

@ -47,8 +47,6 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public final class SlimefunUtils {
private static final String NO_PICKUP_METADATA = "no_pickup";
private static final NamespacedKey SOULBOUND_KEY = new NamespacedKey(SlimefunPlugin.instance(), "soulbound");
private static final String SOULBOUND_LORE = ChatColor.GRAY + "Soulbound";
private SlimefunUtils() {}
@ -110,8 +108,9 @@ public final class SlimefunUtils {
private static boolean hasSoulboundFlag(@Nullable ItemMeta meta) {
if (meta != null) {
PersistentDataContainer container = meta.getPersistentDataContainer();
NamespacedKey key = SlimefunPlugin.getRegistry().getSoulboundDataKey();
if (container.has(SOULBOUND_KEY, PersistentDataType.BYTE)) {
if (container.has(key, PersistentDataType.BYTE)) {
return true;
}
}
@ -142,13 +141,14 @@ public final class SlimefunUtils {
ItemMeta meta = item.getItemMeta();
PersistentDataContainer container = meta.getPersistentDataContainer();
NamespacedKey key = SlimefunPlugin.getRegistry().getSoulboundDataKey();
if (makeSoulbound && !isSoulbound) {
container.set(SOULBOUND_KEY, PersistentDataType.BYTE, (byte) 1);
container.set(key, PersistentDataType.BYTE, (byte) 1);
}
if (!makeSoulbound && isSoulbound) {
container.remove(SOULBOUND_KEY);
container.remove(key);
}
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();

View File

@ -1,6 +1,6 @@
package io.github.thebusybiscuit.slimefun4.utils.itemstack;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
@ -10,10 +10,11 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
/**
* This is just a helper {@link ItemStack} class for the {@link SlimefunGuide} {@link ItemStack}.
@ -32,12 +33,15 @@ public class SlimefunGuideItem extends ItemStack {
ItemMeta meta = getItemMeta();
meta.setDisplayName(ChatColors.color(name));
List<String> lore = new LinkedList<>();
lore.add(implementation instanceof CheatSheetSlimefunGuide ? ChatColors.color("&4&lOnly openable by Admins") : "");
List<String> lore = new ArrayList<>();
SlimefunGuideMode type = implementation.getMode();
lore.add(type == SlimefunGuideMode.CHEAT_MODE ? ChatColors.color("&4&lOnly openable by Admins") : "");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
PersistentDataAPI.setString(meta, SlimefunPlugin.getRegistry().getGuideDataKey(), type.name());
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
setItemMeta(meta);

View File

@ -7,6 +7,7 @@ import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
@ -19,6 +20,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.SeasonalCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
@ -37,6 +39,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/
public class Category implements Keyed {
private SlimefunAddon addon;
protected final List<SlimefunItem> items = new ArrayList<>();
protected final NamespacedKey key;
protected final ItemStack item;
@ -94,12 +98,29 @@ public class Category implements Keyed {
* Registers this category.
* <p>
* By default, a category is automatically registered when a {@link SlimefunItem} was added to it.
*
* @param addon
* The {@link SlimefunAddon} that wants to register this {@link Category}
*/
public void register() {
public void register(@Nonnull SlimefunAddon addon) {
Validate.notNull(addon, "The Addon cannot be null");
this.addon = addon;
SlimefunPlugin.getRegistry().getCategories().add(this);
Collections.sort(SlimefunPlugin.getRegistry().getCategories(), Comparator.comparingInt(Category::getTier));
}
/**
* This returns the {@link SlimefunAddon} which has registered this {@link Category}.
* Or null if it has not been registered yet.
*
* @return The {@link SlimefunAddon} or null if unregistered
*/
@Nullable
public final SlimefunAddon getAddon() {
return addon;
}
/**
* Adds the given {@link SlimefunItem} to this {@link Category}.
*
@ -247,7 +268,7 @@ public class Category implements Keyed {
/**
* This method returns whether this {@link Category} has been registered yet.
* More specifically: Whether {@link #register()} was called or not.
* More specifically: Whether {@link #register(SlimefunAddon)} was called or not.
*
* @return Whether this {@link Category} has been registered
*/

View File

@ -12,6 +12,7 @@ import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
@ -130,6 +131,7 @@ public class SlimefunItem implements Placeable {
* @param recipe
* An Array representing the recipe of this {@link SlimefunItem}
*/
@ParametersAreNonnullByDefault
public SlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
this(category, item, recipeType, recipe, null);
}
@ -148,6 +150,7 @@ public class SlimefunItem implements Placeable {
* @param recipeOutput
* The result of crafting this item
*/
@ParametersAreNonnullByDefault
public SlimefunItem(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
Validate.notNull(category, "'category' is not allowed to be null!");
Validate.notNull(item, "'item' is not allowed to be null!");
@ -162,6 +165,7 @@ public class SlimefunItem implements Placeable {
}
// Previously deprecated constructor, now only for internal purposes
@ParametersAreNonnullByDefault
protected SlimefunItem(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
Validate.notNull(category, "'category' is not allowed to be null!");
Validate.notNull(item, "'item' is not allowed to be null!");
@ -371,7 +375,7 @@ public class SlimefunItem implements Placeable {
* @return The {@link SlimefunAddon} that registered this {@link SlimefunItem}
*/
@Nonnull
public SlimefunAddon getAddon() {
public final SlimefunAddon getAddon() {
if (addon == null) {
throw new UnregisteredItemException(this);
}
@ -476,12 +480,22 @@ public class SlimefunItem implements Placeable {
private final void onEnable() {
// Register the Category too if it hasn't been registered yet
if (!category.isRegistered()) {
category.register();
category.register(addon);
}
// Send out deprecation warnings for any classes or interfaces
checkForDeprecations(getClass());
// Check for an illegal stack size
if (itemStackTemplate.getAmount() != 1) {
// @formatter:off
warn("This item has an illegal stack size: " + itemStackTemplate.getAmount()
+ "An Item size of 1 is recommended. Please inform the autho of " + addon.getName()
+ " to fix this. Crafting Results with amounts of higher should be handled"
+ " via the recipeOutput parameter!");
// @formatter:on
}
// Add it to the list of enabled items
SlimefunPlugin.getRegistry().getEnabledSlimefunItems().add(this);
@ -501,13 +515,17 @@ public class SlimefunItem implements Placeable {
if (exception.isPresent()) {
throw exception.get();
} else {
// Make developers or at least Server admins aware that
// an Item is using a deprecated ItemHandler
/*
* Make developers or at least Server admins aware that an Item
* is using a deprecated ItemHandler
*/
checkForDeprecations(handler.getClass());
}
// If this ItemHandler is "public" (not bound to this SlimefunItem),
// we add it to the list of public Item handlers
/*
* If this ItemHandler is "public" (not bound to this SlimefunItem),
* we add it to the list of public Item handlers
*/
if (!handler.isPrivate()) {
Set<ItemHandler> handlerset = getPublicItemHandlers(handler.getIdentifier());
handlerset.add(handler);
@ -563,15 +581,19 @@ public class SlimefunItem implements Placeable {
*/
private void checkForDeprecations(@Nullable Class<?> c) {
if (SlimefunPlugin.getUpdater().getBranch() == SlimefunBranch.DEVELOPMENT) {
// This method is currently way too spammy with all the restructuring going on...
// Since DEV builds are anyway under "development", things may be relocated.
// So we fire these only for stable versions, since devs should update then, so
// it's the perfect moment to tell them to act.
/*
* This method is currently way too spammy with all the restructuring going on...
* Since DEV builds are anyway under "development", things may be relocated.
* So we fire these only for stable versions, since devs should update then, so
* it's the perfect moment to tell them to act.
*/
return;
}
// We do not wanna throw an Exception here since this could also mean that
// we have reached the end of the Class hierarchy
/*
* We do not wanna throw an Exception here since this could also mean that.
* We have reached the end of the Class hierarchy
*/
if (c != null) {
// Check if this Class is deprecated
if (c.isAnnotationPresent(Deprecated.class)) {

View File

@ -32,8 +32,8 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -97,7 +97,7 @@ public class BlockStorage {
return new Location(w, Integer.parseInt(components[1]), Integer.parseInt(components[2]), Integer.parseInt(components[3]));
}
} catch (NumberFormatException x) {
Slimefun.getLogger().log(Level.WARNING, "Could not parse Number", x);
SlimefunPlugin.logger().log(Level.WARNING, "Could not parse Number", x);
}
return null;
}
@ -114,8 +114,8 @@ public class BlockStorage {
return;
}
Slimefun.getLogger().log(Level.INFO, "Loading Blocks for World \"{0}\"", w.getName());
Slimefun.getLogger().log(Level.INFO, "This may take a long time...");
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks for World \"{0}\"", w.getName());
SlimefunPlugin.logger().log(Level.INFO, "This may take a long time...");
File dir = new File(PATH_BLOCKS + w.getName());
@ -142,13 +142,13 @@ public class BlockStorage {
try {
for (File file : directory.listFiles()) {
if (file.getName().equals("null.sfb")) {
Slimefun.getLogger().log(Level.WARNING, "File with corrupted blocks detected!");
Slimefun.getLogger().log(Level.WARNING, "Slimefun will simply skip this File, you should look inside though!");
Slimefun.getLogger().log(Level.WARNING, file.getPath());
SlimefunPlugin.logger().log(Level.WARNING, "File with corrupted blocks detected!");
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun will simply skip this File, you should look inside though!");
SlimefunPlugin.logger().log(Level.WARNING, file.getPath());
} else if (file.getName().endsWith(".sfb")) {
if (timestamp + delay < System.currentTimeMillis()) {
int progress = Math.round((((done * 100.0F) / total) * 100.0F) / 100.0F);
Slimefun.getLogger().log(Level.INFO, "Loading Blocks... {0}% done (\"{1}\")", new Object[] { progress, world.getName() });
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks... {0}% done (\"{1}\")", new Object[] { progress, world.getName() });
timestamp = System.currentTimeMillis();
}
@ -164,11 +164,11 @@ public class BlockStorage {
}
} finally {
long time = (System.currentTimeMillis() - start);
Slimefun.getLogger().log(Level.INFO, "Loading Blocks... 100% (FINISHED - {0}ms)", time);
Slimefun.getLogger().log(Level.INFO, "Loaded a total of {0} Blocks for World \"{1}\"", new Object[] { totalBlocks, world.getName() });
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks... 100% (FINISHED - {0}ms)", time);
SlimefunPlugin.logger().log(Level.INFO, "Loaded a total of {0} Blocks for World \"{1}\"", new Object[] { totalBlocks, world.getName() });
if (totalBlocks > 0) {
Slimefun.getLogger().log(Level.INFO, "Avg: {0}ms/Block", DoubleHandler.fixDouble((double) time / (double) totalBlocks, 3));
SlimefunPlugin.logger().log(Level.INFO, "Avg: {0}ms/Block", NumberUtils.roundDecimalNumber((double) time / (double) totalBlocks));
}
}
}
@ -193,7 +193,7 @@ public class BlockStorage {
* error to the console (if enabled).
*/
if (SlimefunPlugin.getRegistry().logDuplicateBlockEntries()) {
Slimefun.getLogger().log(Level.INFO, "Ignoring duplicate block @ {0}, {1}, {2} ({3} -> {4})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), blockInfo.getString("id"), storage.get(l).getString("id") });
SlimefunPlugin.logger().log(Level.INFO, "Ignoring duplicate block @ {0}, {1}, {2} ({3} -> {4})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), blockInfo.getString("id"), storage.get(l).getString("id") });
}
return;
@ -206,7 +206,7 @@ public class BlockStorage {
}
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to load " + file.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load " + file.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
}
}
@ -223,7 +223,7 @@ public class BlockStorage {
SlimefunPlugin.getRegistry().getChunks().put(key, data);
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to load " + chunks.getName() + " in World " + world.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load " + chunks.getName() + " in World " + world.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
}
}
}
@ -245,7 +245,7 @@ public class BlockStorage {
inventories.put(l, new BlockMenu(preset, l, cfg));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while loading this Block Inventory: " + file.getName());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while loading this Block Inventory: " + file.getName());
}
}
}
@ -260,7 +260,7 @@ public class BlockStorage {
SlimefunPlugin.getRegistry().getUniversalInventories().put(preset.getID(), new UniversalBlockMenu(preset, cfg));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while loading this universal Inventory: " + file.getName());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while loading this universal Inventory: " + file.getName());
}
}
}
@ -291,7 +291,7 @@ public class BlockStorage {
return;
}
Slimefun.getLogger().log(Level.INFO, "Saving block data for world \"{0}\" ({1} change(s) queued)", new Object[] { world.getName(), changes });
SlimefunPlugin.logger().log(Level.INFO, "Saving block data for world \"{0}\" ({1} change(s) queued)", new Object[] { world.getName(), changes });
Map<String, Config> cache = new HashMap<>(blocksCache);
for (Map.Entry<String, Config> entry : cache.entrySet()) {
@ -305,7 +305,7 @@ public class BlockStorage {
try {
Files.delete(file.toPath());
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
}
}
} else {
@ -315,7 +315,7 @@ public class BlockStorage {
try {
Files.move(tmpFile.toPath(), cfg.getFile().toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while copying a temporary File for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while copying a temporary File for Slimefun " + SlimefunPlugin.getVersion());
}
}
}
@ -431,7 +431,7 @@ public class BlockStorage {
try {
return new BlockInfoConfig(parseJSON(json));
} catch (Exception x) {
Logger logger = Slimefun.getLogger();
Logger logger = SlimefunPlugin.logger();
logger.log(Level.WARNING, x.getClass().getName());
logger.log(Level.WARNING, "Failed to parse BlockInfo for Block @ {0}, {1}, {2}", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ() });
logger.log(Level.WARNING, json);
@ -457,7 +457,7 @@ public class BlockStorage {
writer.endObject();
return string.toString();
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, "An error occurred while serializing BlockInfo", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An error occurred while serializing BlockInfo", x);
return null;
}
}
@ -508,7 +508,7 @@ public class BlockStorage {
BlockStorage storage = getStorage(l.getWorld());
if (storage == null) {
Slimefun.getLogger().warning("Could not set Block info for non-registered World '" + l.getWorld().getName() + "'. Is some plugin trying to store data in a fake world?");
SlimefunPlugin.logger().warning("Could not set Block info for non-registered World '" + l.getWorld().getName() + "'. Is some plugin trying to store data in a fake world?");
return;
}
@ -817,7 +817,7 @@ public class BlockStorage {
return cfg;
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to parse ChunkInfo for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to parse ChunkInfo for Slimefun " + SlimefunPlugin.getVersion());
return emptyBlockData;
}
}

View File

@ -1,9 +1,6 @@
package me.mrCookieSlime.Slimefun.api;
import java.util.Optional;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -25,11 +22,6 @@ public final class Slimefun {
private Slimefun() {}
@Nonnull
public static Logger getLogger() {
return SlimefunPlugin.instance().getLogger();
}
/**
* Checks if this player can use this item.
*

View File

@ -10,8 +10,9 @@ import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
// This class will be deprecated, relocated and rewritten in a future version.
public class BlockMenu extends DirtyChestMenu {
private Location location;
@ -117,7 +118,7 @@ public class BlockMenu extends DirtyChestMenu {
try {
Files.delete(file.toPath());
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
}
}
}

View File

@ -20,6 +20,7 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
// This class will be deprecated, relocated and rewritten in a future version.
public abstract class BlockMenuPreset extends ChestMenu {
private final Set<Integer> occupiedSlots = new HashSet<>();
@ -32,8 +33,6 @@ public abstract class BlockMenuPreset extends ChestMenu {
private final boolean universal;
private boolean locked;
private ItemManipulationEvent event;
public BlockMenuPreset(@Nonnull String id, @Nonnull String title) {
this(id, title, false);
}
@ -75,19 +74,6 @@ public abstract class BlockMenuPreset extends ChestMenu {
public abstract int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow);
/**
* This method is deprecated.
*
* @deprecated Override {@link #onItemStackChange(DirtyChestMenu, int, ItemStack, ItemStack)} instead
*
* @param event
* The event
*/
@Deprecated
public void registerEvent(ItemManipulationEvent event) {
this.event = event;
}
/**
* This method is called whenever an {@link ItemStack} changes.
* You can override this as necessary if you need to listen to these events
@ -259,7 +245,6 @@ public abstract class BlockMenuPreset extends ChestMenu {
menu.addMenuOpeningHandler(getMenuOpeningHandler());
menu.addMenuCloseHandler(getMenuCloseHandler());
menu.registerEvent(event);
}
public void newInstance(@Nonnull BlockMenu menu, @Nonnull Location l) {

View File

@ -18,10 +18,10 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
// This class will be deprecated, relocated and rewritten in a future version.
public class DirtyChestMenu extends ChestMenu {
protected final BlockMenuPreset preset;
protected ItemManipulationEvent event;
protected int changes = 1;
public DirtyChestMenu(@Nonnull BlockMenuPreset preset) {
@ -61,35 +61,20 @@ public class DirtyChestMenu extends ChestMenu {
return preset.canOpen(b, p);
}
@Override
public void open(Player... players) {
super.open(players);
// The Inventory will likely be modified soon
markDirty();
}
public void close() {
for (HumanEntity human : new ArrayList<>(toInventory().getViewers())) {
human.closeInventory();
}
}
/**
* This method has been deprecated.
*
* @deprecated The {@link ItemManipulationEvent} has been deprecated.
*
* @param event
* deprecated class
*/
@Deprecated
public void registerEvent(ItemManipulationEvent event) {
this.event = event;
}
@Override
public ChestMenu addMenuOpeningHandler(MenuOpeningHandler handler) {
if (handler instanceof MenuSavingHandler) {
MenuOpeningHandler openingHandler = ((MenuSavingHandler) handler).getOpeningHandler();
return super.addMenuOpeningHandler(new MenuSavingHandler(this, openingHandler));
} else {
return super.addMenuOpeningHandler(new MenuSavingHandler(this, handler));
}
}
public boolean fits(@Nonnull ItemStack item, int... slots) {
for (int slot : slots) {
// A small optimization for empty slots
@ -161,11 +146,6 @@ public class DirtyChestMenu extends ChestMenu {
public void replaceExistingItem(int slot, ItemStack item, boolean event) {
if (event) {
ItemStack previous = getItemInSlot(slot);
if (this.event != null) {
item = this.event.onEvent(slot, previous, item);
}
item = preset.onItemStackChange(this, slot, previous, item);
}

View File

@ -1,17 +0,0 @@
package me.mrCookieSlime.Slimefun.api.inventory;
import org.bukkit.inventory.ItemStack;
/**
* @deprecated Please use {@link BlockMenuPreset#onItemStackChange(DirtyChestMenu, int, ItemStack, ItemStack)} instead.
*
* @author TheBusyBiscuit
*
*/
@Deprecated
@FunctionalInterface
public interface ItemManipulationEvent {
ItemStack onEvent(int slot, ItemStack previous, ItemStack next);
}

View File

@ -1,30 +0,0 @@
package me.mrCookieSlime.Slimefun.api.inventory;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.entity.Player;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.MenuOpeningHandler;
public class MenuSavingHandler implements MenuOpeningHandler {
private final DirtyChestMenu menu;
private final MenuOpeningHandler handler;
@ParametersAreNonnullByDefault
public MenuSavingHandler(DirtyChestMenu menu, MenuOpeningHandler handler) {
this.menu = menu;
this.handler = handler;
}
@Override
public void onOpen(Player p) {
handler.onOpen(p);
menu.markDirty();
}
public MenuOpeningHandler getOpeningHandler() {
return handler;
}
}

Some files were not shown because too many files have changed in this diff Show More