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

Merge branch 'master' into performance/cobblestone

This commit is contained in:
TheBusyBiscuit 2020-09-29 20:59:10 +02:00 committed by GitHub
commit 775275c661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 1269 additions and 560 deletions

7
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,7 @@
# Modifications to the source code should be handled by the review team
*.java @Slimefun/code-reviewers
# Modifications to sensitive files should be reviewed by maintainers
/.github/ @Slimefun/slimefun4-maintainers
pom.xml @Slimefun/slimefun4-maintainers
CONTRIBUTING.md @Slimefun/slimefun4-maintainers

View File

@ -19,7 +19,7 @@ We generally expect users to engage in the Issues section by reporting bugs or c
Pull Requests are very much welcome and encouraged! They keep the project alive, so if you see an Issue and know how to fix it, feel free to create a Pull Request!
Issues that are considered "good first issues", indicated by the [good first issue](https://github.com/Slimefun/Slimefun4/labels/good%20first%20issue) label, are generally expected to be beginner-friendly.
And even if you shouldn't know where to start or how to proceed, our [Discord Server](https://github.com/Slimefun/Slimefun4#discord) and its community will be there for you!
And even if you shouldn't know where to start or how to proceed, our [Discord Server](https://discord.gg/slimefun) and its community will be there for you!
When commenting, please keep in mind that this software is offered for **free**. Don't expect to receive lightning-fast replies 24 hours a day.
Everyone here works on this project in their free time and usually has work, school, university or family to take care of, so we appreciate patience and understanding.
@ -59,7 +59,7 @@ https://github.com/orgs/Slimefun/people
## :wrench: Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders (labelled on Discord as "Admins" or "Moderators") responsible for enforcement on our [Discord Server](https://github.com/Slimefun/Slimefun4#discord).
reported to the community leaders (labelled on Discord as "Admins" or "Moderators") responsible for enforcement on our [Discord Server](discord.gg/slimefun).
If you want your issue to be handled discreetly, message `TheBusyBiscuit#2610` or `Walshy#9709` privately on Discord and state your concerns.
All complaints will be reviewed and investigated promptly and fairly.

View File

@ -7,5 +7,5 @@ contact_links:
url: https://github.com/Slimefun/Slimefun4/wiki/How-to-report-bugs
about: Guidelines on how to make good Bug reports
- name: Discord Server (for Questions and Suggestions)
url: https://discord.gg/fsD4Bkh
url: https://discord.gg/slimefun
about: Please ask and answer questions here.

View File

@ -48,7 +48,7 @@ If you need help on how to get started, maybe try looking into the following res
* [Working with forks](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks)
* [Creating a Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork)
* Slimefun
* [Contributing to Slimefun](https://github.com/Slimefun/Slimefun4/blob/master/.github/CONTRIBUTING.md)
* [Contributing to Slimefun](https://github.com/Slimefun/Slimefun4/blob/master/CONTRIBUTING.md)
* [Code of Conduct](https://github.com/Slimefun/Slimefun4/blob/master/.github/CODE_OF_CONDUCT.md)
<hr>

View File

@ -23,4 +23,4 @@ jobs:
print_all: False
retry_count: 2
## These URLs will always be correct, even if their services may be offline right now
white_listed_patterns: http://textures.minecraft.net/texture/,https://pastebin.com/,https://www.spigotmc.org/threads/spigot-bungeecord-1-16-1.447405/#post-3852349
white_listed_patterns: http://textures.minecraft.net/texture/,https://pastebin.com/,https://www.spigotmc.org/threads/spigot-bungeecord-1-16-1.447405/#post-3852349,https://gitlocalize.com/repo/3841

View File

@ -26,9 +26,13 @@
#### Additions
* Added /sf charge
* Added Energized Energy Capacitor
* Added various new fuel types to the Coal Generator
* Added a config option for Grappling Hooks to not be consumed on use
#### Changes
* Improved Auto-Updater (Multi-Threading and more)
* General performance improvements
* Performance Improvements and Optimizations for Cobblestone/Stone/Basalt generators and mining androids
* Androids operating on a Cobblestone/Stone/Basalt generator now work faster
@ -38,6 +42,13 @@
* Fixed colors of Cheat Sheet Slimefun Guide
* Fixed Cheat Sheet Slimefun Guide being unable to open the settings menu via shift + right click
* Fixed #2320
* Fixed some issues with ChestTerminal
* Fixed #2325
* Fixed Climbing Pick having no animation in creative mode
* Fixed #2322
* Fixed some cargo incompatibilities with overflowing inventories
* Fixed #2353
* Fixed #2359
## Release Candidate 16 (07 Sep 2020)
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#16

View File

@ -15,22 +15,6 @@ If you encounter an issue which has already been reported, please don't open a n
It would be awesome though if you could post a comment on the existing issue which explains how you were able to reproduce this yourself.
The more context and information we get, the easier we can fix it.
## :toolbox: How to compile Slimefun4
Slimefun is written in Java and uses [Maven](https://maven.apache.org/) for compilation.<br>
To compile Slimefun yourself, follow these steps:
1. Clone the project via git<br>
`$ git clone https://github.com/Slimefun/Slimefun4/`
2. Compile the project using Maven<br>
`$ mvn clean package`
3. Extract the compiled `Slimefun-v4.X-UNOFFICIAL.jar` from your `/target/` directory.
If you are already using an IDE, make sure to import the project via git and set it up as a *Maven project*.
Then you should be able build it via Maven using the goals `clean package`.
If you have any further questions, then please join our [Discord Support Server](#discord) and ask your questions in the `#programming-help` channel.<br>
**Note that we will not accept any bug reports from custom-compiled versions of Slimefun**.
## :hammer_and_wrench: 2. Pull Requests: Bug Fixes
Bugs that have been reported need to be fixed of course.<br>
Any open Issue on our [Issues Tracker](https://github.com/Slimefun/Slimefun4/issues) is waiting to be fixed.
@ -42,7 +26,7 @@ You can also comment on the existing Issue, proposing your idea or communicating
## :wrench: 3. Pull Requests: Additions/Changes
Slimefun is an Open-Source project and anyone is allowed to make changes or add content to this plugin!
Please visit our [Discord Server](https://github.com/Slimefun/Slimefun4#discord) and share your ideas first, we hate to reject changes because the community disagrees.<br>
Please visit our [Discord Server](https://discord.gg/slimefun) and share your ideas first, we hate to reject changes because the community disagrees.<br>
So communicating your intended changes before-hand will ensure that you don't put too much work into something that might get rejected.
We also have a suggestions section in our Discord Server too. Suggestions can be placed in the `#suggestions` channel and community members can vote on a suggestion.
@ -74,11 +58,11 @@ You can find a tutorial on how to contribute to our wiki right here:<br>
https://github.com/Slimefun/Slimefun4/wiki/Expanding-the-Wiki
## :star: 6. Pull Requests: Code Quality
Slimefun uses [sonarcloud.io](https://sonarcloud.io/dashboard?id=TheBusyBiscuit_Slimefun4) to monitor Code Quality.
Slimefun uses [sonarcloud.io](https://sonarcloud.io/dashboard?id=Slimefun_Slimefun4) to monitor Code Quality.
We always welcome quality improvements to the code and the "Code Smells" section on [sonarcloud.io](https://sonarcloud.io/dashboard?id=TheBusyBiscuit_Slimefun4) is a great place to start.
We always welcome quality improvements to the code and the "Code Smells" section on [sonarcloud.io](https://sonarcloud.io/dashboard?id=Slimefun_Slimefun4) is a great place to start.
But please keep in mind that some design patterns may not be changed too abruptly if an addon depends on them.
To prevent any accidents from happening, please contact us on our [Discord Server](https://github.com/Slimefun/Slimefun4#discord) before-hand and state your intended changes.
To prevent any accidents from happening, please contact us on our [Discord Server](https://discord.gg/slimefun) before-hand and state your intended changes.
#### Documentation
Code documentation is also a great way to improve the maintainability of the project.
@ -94,3 +78,19 @@ More or better Unit Tests are always good to have, so feel free to submit a Test
We are using [Junit 5 - Jupiter](https://github.com/junit-team/junit5/) and [MockBukkit](https://github.com/seeseemelk/MockBukkit) as our testing environment.<br>
Every new Unit Test should have a `@DisplayName` annotation with a plain text description on what the Unit Test tests.
## :toolbox: How to compile Slimefun4
Slimefun is written in Java and uses [Maven](https://maven.apache.org/) for compilation.<br>
To compile Slimefun yourself, follow these steps:
1. Clone the project via git<br>
`$ git clone https://github.com/Slimefun/Slimefun4/`
2. Compile the project using Maven<br>
`$ mvn clean package`
3. Extract the compiled `Slimefun-v4.X-UNOFFICIAL.jar` from your `/target/` directory.
If you are already using an IDE, make sure to import the project via git and set it up as a *Maven project*.
Then you should be able build it via Maven using the goals `clean package`.
If you have any further questions, then please join our [Discord Support Server](https://discord.gg/slimefun) and ask your questions in the `#programming-help` channel.<br>
**Note that we will not accept any bug reports from custom-compiled versions of Slimefun**.

View File

@ -19,7 +19,7 @@ Check out our [Addons](https://github.com/Slimefun/Slimefun4/wiki/Addons), you m
* **[Bug Tracker](https://github.com/Slimefun/Slimefun4/issues)**
* **[Wiki](https://github.com/Slimefun/Slimefun4/wiki)**
* **[FAQ](https://github.com/Slimefun/Slimefun4/wiki/FAQ)**
* **[How to contribute](https://github.com/Slimefun/Slimefun4/blob/master/.github/CONTRIBUTING.md)**
* **[How to contribute](https://github.com/Slimefun/Slimefun4/blob/master/CONTRIBUTING.md)**
## Download Slimefun 4
(See also: [How to install Slimefun](https://github.com/Slimefun/Slimefun4/wiki/Installing-Slimefun))
@ -76,10 +76,9 @@ Due to the sheer size of this discord server, we need to enforce some [important
Not following these rules can lead to a kick or even a ban from the server.
<p align="center">
<a href="https://discord.gg/fsD4Bkh">
<img src="https://img.shields.io/discord/565557184348422174?color=7289DA&label=Discord&style=for-the-badge" alt="Discord Invite"/>
</a><br>
(Click the badge to join)
<a href="https://discord.gg/slimefun">
<img src="https://discordapp.com/api/guilds/565557184348422174/widget.png?style=banner3" alt="Discord Invite"/>
</a>
</p>
## Wiki
@ -106,7 +105,7 @@ Slimefun 4 is an Open-Source project and licensed under
Over 150+ people have already contributed to this amazing project. You guys are awesome.<br>
Please consider helping us maintain this project too, your engagement keeps the project alive <3.
You can find more info on how to contribute to this project in our [CONTRIBUTING.md](https://github.com/Slimefun/Slimefun4/blob/master/.github/CONTRIBUTING.md).
You can find more info on how to contribute to this project in our [CONTRIBUTING.md](https://github.com/Slimefun/Slimefun4/blob/master/CONTRIBUTING.md).
## Disclaimers
Slimefun4 uses various systems that collect usage information or download automatic updates as well as the latest information about the project.

12
pom.xml
View File

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.thebusybiscuit</groupId>
<groupId>com.github.slimefun</groupId>
<artifactId>Slimefun</artifactId>
<!-- Our default version will be UNOFFICIAL, this will prevent auto updates -->
@ -26,8 +26,8 @@
<spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
<!-- Default settings for sonarcloud.io -->
<sonar.projectKey>TheBusyBiscuit_Slimefun4</sonar.projectKey>
<sonar.organization>thebusybiscuit-github</sonar.organization>
<sonar.projectKey>Slimefun_Slimefun4</sonar.projectKey>
<sonar.organization>slimefun</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.log.level>DEBUG</sonar.log.level>
<sonar.exclusions>src/main/java/me/mrCookieSlime/Slimefun/bstats/bukkit/Metrics.java</sonar.exclusions>
@ -128,7 +128,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<version>0.8.6</version>
<executions>
<execution>
@ -323,7 +323,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.10</version>
<version>3.5.13</version>
<scope>test</scope>
</dependency>
@ -343,7 +343,7 @@
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.10.00</version>
<version>3.11.00</version>
<scope>compile</scope>
<exclusions>
<exclusion>

View File

@ -8,6 +8,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
@ -26,7 +27,6 @@ import io.papermc.lib.PaperLib;
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;
/**
* This class represents an {@link ErrorReport}.
@ -41,7 +41,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class ErrorReport<T extends Throwable> {
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm", Locale.ROOT);
private static int count;
private static final AtomicInteger count = new AtomicInteger(0);
private SlimefunAddon addon;
private T throwable;
@ -52,7 +52,7 @@ public class ErrorReport<T extends Throwable> {
this.throwable = throwable;
this.addon = addon;
Slimefun.runSync(() -> print(printer));
SlimefunPlugin.runSync(() -> print(printer));
}
@ParametersAreNonnullByDefault
@ -124,12 +124,12 @@ public class ErrorReport<T extends Throwable> {
* @return The amount of {@link ErrorReport ErrorReports} created.
*/
public static int count() {
return count;
return count.get();
}
private void print(@Nonnull Consumer<PrintStream> printer) {
this.file = getNewFile();
count++;
count.incrementAndGet();
try (PrintStream stream = new PrintStream(file, StandardCharsets.UTF_8.name())) {
stream.println();

View File

@ -0,0 +1,65 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is fired whenever an {@link AGenerator} has completed its process.
*
* @author poma123
*
*/
public class AsyncGeneratorProcessCompleteEvent extends AsyncMachineProcessCompleteEvent {
private static final HandlerList handlers = new HandlerList();
private final AGenerator generator;
private final MachineFuel machineFuel;
@ParametersAreNonnullByDefault
public AsyncGeneratorProcessCompleteEvent(Location l, AGenerator generator, MachineFuel machineFuel) {
super(l, null, null);
this.generator = generator;
this.machineFuel = machineFuel;
}
/**
* The {@link SlimefunItem} instance of the generator.
*
* @return The {@link SlimefunItem} instance of the generator
*/
@Nonnull
public AGenerator getGenerator() {
return generator;
}
/**
* This returns the used {@link MachineFuel} in the process.
*
* @return The {@link MachineFuel} of the process
*/
@Nonnull
public MachineFuel getMachineFuel() {
return machineFuel;
}
@Nonnull
public static HandlerList getHandlerList() {
return handlers;
}
@Nonnull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -1,14 +1,15 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.Nullable;
import org.bukkit.block.Block;
import org.bukkit.Location;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is fired whenever an {@link AContainer} has completed its process.
@ -20,33 +21,44 @@ public class AsyncMachineProcessCompleteEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final Block block;
private final Location location;
private final AContainer container;
private final MachineRecipe machineRecipe;
@ParametersAreNonnullByDefault
public AsyncMachineProcessCompleteEvent(Block block, MachineRecipe machineRecipe) {
public AsyncMachineProcessCompleteEvent(@Nonnull Location l, @Nullable AContainer container, @Nullable MachineRecipe machineRecipe) {
super(true);
this.block = block;
this.location = l;
this.container = container;
this.machineRecipe = machineRecipe;
}
/**
* This method returns the {@link Block} of the machine.
* This returns the {@link Location} of the machine.
*
* @return the {@link Block} of the machine
* @return The {@link Location} of the machine
*/
@Nonnull
public Block getMachine() {
return block;
public Location getLocation() {
return location;
}
/**
* The {@link SlimefunItem} instance of the machine.
*
* @return The {@link SlimefunItem} instance of the machine
*/
@Nullable
public AContainer getMachine() {
return container;
}
/**
* This returns the used {@link MachineRecipe} in the process.
*
* @return the {@link MachineRecipe} of the process.
* @return The {@link MachineRecipe} of the process
*/
@Nonnull
@Nullable
public MachineRecipe getMachineRecipe() {
return machineRecipe;
}

View File

@ -0,0 +1,65 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.Reactor;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is fired whenever a {@link Reactor} has completed its process.
*
* @author poma123
*
*/
public class AsyncReactorProcessCompleteEvent extends AsyncMachineProcessCompleteEvent {
private static final HandlerList handlers = new HandlerList();
private final Reactor reactor;
private final MachineFuel machineFuel;
@ParametersAreNonnullByDefault
public AsyncReactorProcessCompleteEvent(Location l, Reactor reactor, MachineFuel machineFuel) {
super(l, null, null);
this.reactor = reactor;
this.machineFuel = machineFuel;
}
/**
* The {@link SlimefunItem} instance of the reactor.
*
* @return The {@link SlimefunItem} instance of the reactor
*/
@Nonnull
public Reactor getReactor() {
return reactor;
}
/**
* This returns the used {@link MachineFuel} in the process.
*
* @return The {@link MachineFuel} of the process
*/
@Nonnull
public MachineFuel getMachineFuel() {
return machineFuel;
}
@Nonnull
public static HandlerList getHandlerList() {
return handlers;
}
@Nonnull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -37,7 +37,6 @@ import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link GPSNetwork} is a manager class for all {@link GPSTransmitter Transmitters} and waypoints.
@ -288,7 +287,7 @@ public class GPSNetwork {
return;
}
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
WaypointCreateEvent event = new WaypointCreateEvent(p, name, l);
Bukkit.getPluginManager().callEvent(event);

View File

@ -27,7 +27,6 @@ import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public final class TeleportationManager {
@ -79,7 +78,7 @@ public final class TeleportationManager {
index++;
}
Slimefun.runSync(() -> menu.open(p));
SlimefunPlugin.runSync(() -> menu.open(p));
});
}
@ -137,7 +136,7 @@ public final class TeleportationManager {
source.getWorld().spawnParticle(Particle.PORTAL, source, progress * 2, 0.2F, 0.8F, 0.2F);
source.getWorld().playSound(source, Sound.BLOCK_BEACON_AMBIENT, 1F, 0.6F);
Slimefun.runSync(() -> updateProgress(uuid, speed, progress + speed, source, destination, resistance), 10L);
SlimefunPlugin.runSync(() -> updateProgress(uuid, speed, progress + speed, source, destination, resistance), 10L);
}
}
else {
@ -149,7 +148,7 @@ public final class TeleportationManager {
private void onTeleport(Player p, Location destination, boolean success, boolean resistance) {
// This needs to run on the main Thread so we force it, as the
// async teleportation might happen on a separate Thread.
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (success) {
// Apply Resistance Effect, if enabled
if (resistance) {

View File

@ -16,8 +16,8 @@ import org.bukkit.Particle;
import org.bukkit.Particle.DustOptions;
import io.github.thebusybiscuit.slimefun4.core.networks.NetworkManager;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* An abstract Network class to manage networks in a stateful way
@ -217,7 +217,7 @@ public abstract class Network {
* every {@link Location} that this {@link Network} is connected to.
*/
public void display() {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
DustOptions options = new DustOptions(Color.BLUE, 3F);
for (Location l : connectedLocations) {

View File

@ -10,9 +10,9 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.SlimefunBackpack;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListener;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This class represents the instance of a {@link SlimefunBackpack} that is ready to
@ -123,7 +123,7 @@ public class PlayerBackpack {
* The players who this Backpack will be shown to
*/
public void open(Player... players) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
for (Player p : players) {
p.openInventory(inventory);
}

View File

@ -404,6 +404,8 @@ public final class PlayerProfile {
* @return Whether the {@link PlayerProfile} was already loaded
*/
public static boolean request(@Nonnull OfflinePlayer p) {
Validate.notNull(p, "Cannot request a Profile for null");
if (!SlimefunPlugin.getRegistry().getPlayerProfiles().containsKey(p.getUniqueId())) {
// Should probably prevent multiple requests for the same profile in the future
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {

View File

@ -11,7 +11,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -70,7 +69,6 @@ public class SlimefunRegistry {
private final Set<String> tickers = new HashSet<>();
private final Set<SlimefunItem> radioactive = new HashSet<>();
private final Set<String> activeChunks = ConcurrentHashMap.newKeySet();
private final Set<ItemStack> barterDrops = new HashSet<>();
private final KeyMap<GEOResource> geoResources = new KeyMap<>();
@ -86,8 +84,6 @@ public class SlimefunRegistry {
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
private final Map<String, SlimefunBlockHandler> blockHandlers = new HashMap<>();
private final Map<String, Set<Location>> activeTickers = new ConcurrentHashMap<>();
private final Map<String, ItemStack> automatedCraftingChamberRecipes = new HashMap<>();
public void load(Config cfg) {
@ -226,10 +222,6 @@ public class SlimefunRegistry {
return tickers;
}
public Set<String> getActiveChunks() {
return activeChunks;
}
public Map<String, SlimefunItem> getSlimefunItemIds() {
return slimefunIds;
}
@ -262,10 +254,6 @@ public class SlimefunRegistry {
return chunks;
}
public Map<String, Set<Location>> getActiveTickers() {
return activeTickers;
}
public KeyMap<GEOResource> getGEOResources() {
return geoResources;
}

View File

@ -28,6 +28,7 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
public interface EnergyNetProvider extends EnergyNetComponent {
@Override
@Nonnull
default EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.GENERATOR;
}

View File

@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.core.attributes;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -18,9 +20,11 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
*/
public interface Placeable {
@Nonnull
Collection<ItemStack> getDrops();
Collection<ItemStack> getDrops(Player p);
@Nonnull
Collection<ItemStack> getDrops(@Nonnull Player p);
/**
* This method determines how to treat this {@link Block} when it is broken.

View File

@ -1,5 +1,8 @@
package io.github.thebusybiscuit.slimefun4.core.attributes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
@ -29,6 +32,7 @@ public interface ProtectiveArmor extends ItemAttribute {
*
* @return The {@link ProtectionType}s.
*/
@Nonnull
ProtectionType[] getProtectionTypes();
/**
@ -44,5 +48,6 @@ public interface ProtectiveArmor extends ItemAttribute {
*
* @return The set {@link NamespacedKey}, <code>null</code> if none is found.
*/
@Nullable
NamespacedKey getArmorSetId();
}

View File

@ -12,7 +12,6 @@ import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class BackpackCommand extends SubCommand {
@ -27,43 +26,48 @@ class BackpackCommand extends SubCommand {
@Override
public void onExecute(CommandSender sender, String[] args) {
if (!(sender instanceof Player) || !sender.hasPermission("slimefun.command.backpack")) {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
return;
}
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.backpack")) {
if (args.length != 3) {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf backpack <Player> <ID>"));
return;
}
if (args.length != 3) {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf backpack <Player> <ID>"));
return;
}
if (!PatternUtils.NUMERIC.matcher(args[2]).matches()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.invalid-id");
return;
}
if (!PatternUtils.NUMERIC.matcher(args[2]).matches()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.invalid-id");
return;
}
@SuppressWarnings("deprecation")
OfflinePlayer backpackOwner = Bukkit.getOfflinePlayer(args[1]);
@SuppressWarnings("deprecation")
OfflinePlayer backpackOwner = Bukkit.getOfflinePlayer(args[1]);
if (!(backpackOwner instanceof Player) && !backpackOwner.hasPlayedBefore()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.player-never-joined");
return;
}
if (!(backpackOwner instanceof Player) && !backpackOwner.hasPlayedBefore()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.player-never-joined");
return;
}
int id = Integer.parseInt(args[2]);
int id = Integer.parseInt(args[2]);
PlayerProfile.get(backpackOwner, profile -> {
if (!profile.getBackpack(id).isPresent()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.backpack-does-not-exist");
return;
}
PlayerProfile.get(backpackOwner, profile -> {
if (!profile.getBackpack(id).isPresent()) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.backpack-does-not-exist");
return;
SlimefunPlugin.runSync(() -> {
ItemStack item = SlimefunItems.RESTORED_BACKPACK.clone();
SlimefunPlugin.getBackpackListener().setBackpackId(backpackOwner, item, 2, id);
((Player) sender).getInventory().addItem(item);
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.restored-backpack-given");
});
});
}
Slimefun.runSync(() -> {
ItemStack item = SlimefunItems.RESTORED_BACKPACK.clone();
SlimefunPlugin.getBackpackListener().setBackpackId(backpackOwner, item, 2, id);
((Player) sender).getInventory().addItem(item);
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.backpack.restored-backpack-given");
});
});
else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
}
else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.only-players", true);
}
}
}

View File

@ -14,7 +14,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuid
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This is a static utility class that provides convenient access to the methods
@ -73,7 +72,7 @@ public final class SlimefunGuide {
}
private static void openMainMenuAsync(Player player, SlimefunGuideLayout layout, int selectedPage) {
if (!PlayerProfile.get(player, profile -> Slimefun.runSync(() -> openMainMenu(profile, layout, selectedPage)))) {
if (!PlayerProfile.get(player, profile -> SlimefunPlugin.runSync(() -> openMainMenu(profile, layout, selectedPage)))) {
SlimefunPlugin.getLocalization().sendMessage(player, "messages.opening-guide");
}
}

View File

@ -180,7 +180,7 @@ public class CargoNet extends ChestTerminalNetwork {
SlimefunPlugin.getProfiler().scheduleEntries((terminals.isEmpty() ? 1 : 2) + inputs.size());
CargoNetworkTask runnable = new CargoNetworkTask(this, inputs, outputs, chestTerminalInputs, chestTerminalOutputs);
Slimefun.runSync(runnable);
SlimefunPlugin.runSync(runnable);
}
}

View File

@ -108,11 +108,18 @@ class CargoNetworkTask implements Runnable {
Inventory inv = inventories.get(inputTarget.getLocation());
if (inv != null) {
// Check if the original slot hasn't been occupied in the meantime
if (inv.getItem(previousSlot) == null) {
inv.setItem(previousSlot, stack);
}
else {
inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), stack);
// Try to add the item into another available slot then
ItemStack rest = inv.addItem(stack).get(0);
if (rest != null) {
// If the item still couldn't be inserted, simply drop it on the ground
inputTarget.getWorld().dropItem(inputTarget.getLocation().add(0, 1, 0), rest);
}
}
}
else {

View File

@ -15,6 +15,8 @@ import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.Material;
@ -296,7 +298,8 @@ abstract class ChestTerminalNetwork extends Network {
try {
for (Location l : terminals) {
BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
String data = BlockStorage.getLocationInfo(l, "page");
int page = data == null ? 1 : Integer.parseInt(data);
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1;
@ -325,13 +328,14 @@ abstract class ChestTerminalNetwork extends Network {
return System.nanoTime() - timestamp;
}
}
@Override
public void markDirty(@Nonnull Location l) {
connectorCache.remove(l);
super.markDirty(l);
}
@ParametersAreNonnullByDefault
private void updateTerminal(Location l, BlockMenu terminal, int slot, int index, List<ItemStackAndInteger> items) {
if (items.size() > index) {
ItemStackAndInteger item = items.get(index);
@ -390,6 +394,7 @@ abstract class ChestTerminalNetwork extends Network {
return items;
}
@ParametersAreNonnullByDefault
private void findAllItems(List<ItemStackAndInteger> items, Location l, Block target) {
UniversalBlockMenu menu = BlockStorage.getUniversalInventory(target);
@ -422,6 +427,7 @@ abstract class ChestTerminalNetwork extends Network {
}
}
@ParametersAreNonnullByDefault
private void gatherItemsFromBarrel(Location l, BlockMenu blockMenu, List<ItemStackAndInteger> items) {
try {
Config cfg = BlockStorage.getLocationInfo(blockMenu.getLocation());
@ -457,13 +463,15 @@ abstract class ChestTerminalNetwork extends Network {
}
}
@ParametersAreNonnullByDefault
private void handleWithdraw(DirtyChestMenu menu, List<ItemStackAndInteger> items, Location l) {
for (int slot : menu.getPreset().getSlotsAccessedByItemTransport(menu, ItemTransportFlow.WITHDRAW, null)) {
filter(menu.getItemInSlot(slot), items, l);
}
}
private void filter(ItemStack stack, List<ItemStackAndInteger> items, Location node) {
@ParametersAreNonnullByDefault
private void filter(@Nullable ItemStack stack, List<ItemStackAndInteger> items, Location node) {
if (stack != null && CargoUtils.matchesFilter(node.getBlock(), stack)) {
boolean add = true;

View File

@ -27,7 +27,6 @@ import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
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;
/**
* The {@link EnergyNet} is an implementation of {@link Network} that deals with
@ -229,7 +228,7 @@ public class EnergyNet extends Network {
explodedBlocks.add(loc);
BlockStorage.clearBlockInfo(loc);
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
loc.getBlock().setType(Material.LAVA);
loc.getWorld().createExplosion(loc, 0F, false);
});

View File

@ -26,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup;
import io.github.thebusybiscuit.slimefun4.utils.FireworkUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* Represents a research, which is bound to one
@ -230,7 +229,7 @@ public class Research implements Keyed {
*/
public void unlock(@Nonnull Player p, boolean instant, @Nonnull Consumer<Player> callback) {
if (!instant) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1F);
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)).replace("%progress%", "0%"));
}, 10L);
@ -238,7 +237,7 @@ public class Research implements Keyed {
PlayerProfile.get(p, profile -> {
if (!profile.hasUnlocked(this)) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ResearchUnlockEvent event = new ResearchUnlockEvent(p, this);
Bukkit.getPluginManager().callEvent(event);
@ -250,7 +249,7 @@ public class Research implements Keyed {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.start", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)));
playResearchAnimation(p);
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
finishResearch(p, profile, callback);
SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().remove(p.getUniqueId());
}, (RESEARCH_PROGRESS.length + 1) * 20L);
@ -275,7 +274,7 @@ public class Research implements Keyed {
for (int i = 1; i < RESEARCH_PROGRESS.length + 1; i++) {
int j = i;
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1F);
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)).replace("%progress%", RESEARCH_PROGRESS[j - 1] + "%"));
}, i * 20L);

View File

@ -22,7 +22,6 @@ import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Class represents a Metrics Service that sends data to https://bstats.org/
@ -102,7 +101,7 @@ public class MetricsService {
String version = metricsClass.getPackage().getImplementationVersion();
// This is required to be sync due to bStats.
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
try {
start.invoke(null);
plugin.getLogger().info("Metrics build #" + version + " started.");

View File

@ -1,8 +1,6 @@
package io.github.thebusybiscuit.slimefun4.core.services;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -12,8 +10,10 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Server;
import org.bukkit.World;
@ -38,7 +38,7 @@ public class PerWorldSettingsService {
private final Map<SlimefunAddon, Set<String>> disabledAddons = new HashMap<>();
private final Set<UUID> disabledWorlds = new HashSet<>();
public PerWorldSettingsService(SlimefunPlugin plugin) {
public PerWorldSettingsService(@Nonnull SlimefunPlugin plugin) {
this.plugin = plugin;
}
@ -48,14 +48,7 @@ public class PerWorldSettingsService {
* @param worlds
* An {@link Iterable} of {@link World Worlds} to load
*/
public void load(Iterable<World> worlds) {
try {
migrate();
}
catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "An error occurred while migrating old world settings", e);
}
public void load(@Nonnull Iterable<World> worlds) {
for (World world : worlds) {
load(world);
}
@ -67,41 +60,11 @@ public class PerWorldSettingsService {
* @param world
* The {@link World} to load
*/
public void load(World world) {
public void load(@Nonnull World world) {
Validate.notNull(world, "Cannot load a world that is null");
disabledItems.putIfAbsent(world.getUID(), loadWorldFromConfig(world));
}
/**
* Temporary migration method for the old system
*
* @throws IOException
* This will be thrown if we failed to delete the old {@link File}
*/
private void migrate() throws IOException {
Config oldConfig = new Config(plugin, "whitelist.yml");
if (oldConfig.getFile().exists()) {
for (String world : oldConfig.getKeys()) {
Config newConfig = new Config(plugin, "world-settings/" + world + ".yml");
newConfig.setDefaultValue("enabled", oldConfig.getBoolean(world + ".enabled"));
for (String id : oldConfig.getKeys(world + ".enabled-items")) {
SlimefunItem item = SlimefunItem.getByID(id);
if (item != null) {
String addon = item.getAddon().getName().toLowerCase(Locale.ROOT);
newConfig.setDefaultValue(addon + ".enabled", true);
newConfig.setDefaultValue(addon + '.' + id, oldConfig.getBoolean(world + ".enabled-items." + id));
}
}
newConfig.save();
}
Files.delete(oldConfig.getFile().toPath());
}
}
/**
* This method checks whether the given {@link SlimefunItem} is enabled in the given {@link World}.
*
@ -112,7 +75,10 @@ public class PerWorldSettingsService {
*
* @return Whether the given {@link SlimefunItem} is enabled in that {@link World}
*/
public boolean isEnabled(World world, SlimefunItem item) {
public boolean isEnabled(@Nonnull World world, @Nonnull SlimefunItem item) {
Validate.notNull(world, "The world cannot be null");
Validate.notNull(item, "The SlimefunItem cannot be null");
Set<String> items = disabledItems.computeIfAbsent(world.getUID(), id -> loadWorldFromConfig(world));
if (disabledWorlds.contains(world.getUID())) {
@ -132,7 +98,10 @@ public class PerWorldSettingsService {
* @param enabled
* Whether the given {@link SlimefunItem} should be enabled in that world
*/
public void setEnabled(World world, SlimefunItem item, boolean enabled) {
public void setEnabled(@Nonnull World world, @Nonnull SlimefunItem item, boolean enabled) {
Validate.notNull(world, "The world cannot be null");
Validate.notNull(item, "The SlimefunItem cannot be null");
Set<String> items = disabledItems.computeIfAbsent(world.getUID(), id -> loadWorldFromConfig(world));
if (enabled) {
@ -151,7 +120,8 @@ public class PerWorldSettingsService {
* @param enabled
* Whether this {@link World} should be enabled or not
*/
public void setEnabled(World world, boolean enabled) {
public void setEnabled(@Nonnull World world, boolean enabled) {
Validate.notNull(world, "null is not a valid World");
load(world);
if (enabled) {
@ -170,7 +140,8 @@ public class PerWorldSettingsService {
*
* @return Whether this {@link World} is enabled
*/
public boolean isWorldEnabled(World world) {
public boolean isWorldEnabled(@Nonnull World world) {
Validate.notNull(world, "null is not a valid World");
load(world);
return !disabledWorlds.contains(world.getUID());
@ -186,7 +157,9 @@ public class PerWorldSettingsService {
*
* @return Whether this addon is enabled in that {@link World}
*/
public boolean isAddonEnabled(World world, SlimefunAddon addon) {
public boolean isAddonEnabled(@Nonnull World world, @Nonnull SlimefunAddon addon) {
Validate.notNull(world, "World cannot be null");
Validate.notNull(addon, "Addon cannot be null");
return isWorldEnabled(world) && disabledAddons.getOrDefault(addon, Collections.emptySet()).contains(world.getName());
}
@ -198,7 +171,8 @@ public class PerWorldSettingsService {
* @param world
* The {@link World} to save
*/
public void save(World world) {
public void save(@Nonnull World world) {
Validate.notNull(world, "Cannot save a World that does not exist");
Set<String> items = disabledItems.computeIfAbsent(world.getUID(), id -> loadWorldFromConfig(world));
Config config = getConfig(world);
@ -213,7 +187,10 @@ public class PerWorldSettingsService {
config.save();
}
private Set<String> loadWorldFromConfig(World world) {
@Nonnull
private Set<String> loadWorldFromConfig(@Nonnull World world) {
Validate.notNull(world, "Cannot load a World that does not exist");
String name = world.getName();
Optional<Set<String>> optional = disabledItems.get(world.getUID());
@ -231,6 +208,7 @@ public class PerWorldSettingsService {
if (config.getBoolean("enabled")) {
loadItemsFromWorldConfig(name, config, items);
// We don't actually wanna write to disk during a Unit test
if (SlimefunPlugin.getMinecraftVersion() != MinecraftVersion.UNIT_TEST) {
config.save();
}
@ -243,13 +221,14 @@ public class PerWorldSettingsService {
}
}
private void loadItemsFromWorldConfig(String worldName, Config config, Set<String> items) {
private void loadItemsFromWorldConfig(@Nonnull String worldName, @Nonnull Config config, @Nonnull Set<String> items) {
for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
if (item != null) {
String addon = item.getAddon().getName().toLowerCase(Locale.ROOT);
config.setDefaultValue(addon + ".enabled", true);
config.setDefaultValue(addon + '.' + item.getID(), true);
// Whether the entire addon has been disabled
boolean isAddonDisabled = config.getBoolean(addon + ".enabled");
if (isAddonDisabled) {
@ -264,7 +243,17 @@ public class PerWorldSettingsService {
}
}
private Config getConfig(World world) {
/**
* This method returns the relevant {@link Config} for the given {@link World}
*
* @param world
* Our {@link World}
*
* @return The corresponding {@link Config}
*/
@Nonnull
private Config getConfig(@Nonnull World world) {
Validate.notNull(world, "World cannot be null");
return new Config(plugin, "world-settings/" + world.getName() + ".yml");
}

View File

@ -0,0 +1,22 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
import java.time.LocalDateTime;
import javax.annotation.Nonnull;
@FunctionalInterface
interface ActivityCallback {
/**
* This method is called when the {@link GitHubActivityConnector} finished loading.
*
* @param forks
* The amount of forks
* @param stars
* The amount of stars
* @param date
* The {@link LocalDateTime} of the last activity
*/
void accept(int forks, int stars, @Nonnull LocalDateTime date);
}

View File

@ -61,14 +61,14 @@ class ContributionsConnector extends GitHubConnector {
}
@Override
public void onSuccess(JsonNode element) {
public void onSuccess(@Nonnull JsonNode response) {
finished = true;
if (element.isArray()) {
computeContributors(element.getArray());
if (response.isArray()) {
computeContributors(response.getArray());
}
else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", element);
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}
@ -96,7 +96,8 @@ class ContributionsConnector extends GitHubConnector {
String profile = object.getString("html_url");
if (!blacklist.contains(name)) {
github.addContributor(aliases.getOrDefault(name, name), profile, role, commits);
String username = aliases.getOrDefault(name, name);
github.addContributor(username, profile, role, commits);
}
}
}

View File

@ -40,15 +40,29 @@ public class Contributor {
private Optional<UUID> uuid = Optional.empty();
private boolean locked = false;
public Contributor(@Nonnull String username, @Nonnull String profile) {
Validate.notNull(username, "Username must never be null!");
/**
* This creates a new {@link Contributor} with the given ingame name and GitHub profile.
*
* @param minecraftName
* The ingame name in Minecraft for this {@link Contributor}
* @param profile
* A link to their GitHub profile
*/
public Contributor(@Nonnull String minecraftName, @Nonnull String profile) {
Validate.notNull(minecraftName, "Username must never be null!");
Validate.notNull(profile, "The profile cannot be null!");
githubUsername = profile.substring(profile.lastIndexOf('/') + 1);
minecraftUsername = username;
minecraftUsername = minecraftName;
profileLink = profile;
}
/**
* This creates a new {@link Contributor} with the given username.
*
* @param username
* The username of this {@link Contributor}
*/
public Contributor(@Nonnull String username) {
Validate.notNull(username, "Username must never be null!");
@ -57,8 +71,18 @@ public class Contributor {
profileLink = null;
}
public void setContribution(@Nonnull String role, int commits) {
/**
* This sets the amount of contributions of this {@link Contributor} for the
* specified role.
*
* @param role
* The role
* @param commits
* The amount of contributions made as that role
*/
public void setContributions(@Nonnull String role, int commits) {
Validate.notNull(role, "The role cannot be null!");
Validate.isTrue(commits >= 0, "Contributions cannot be negative");
if (!locked || role.startsWith("translator,")) {
contributions.put(role, commits);
@ -66,9 +90,9 @@ public class Contributor {
}
/**
* Returns the name of this contributor.
* Returns the name of this {@link Contributor}.
*
* @return the name of this contributor
* @return the name of this {@link Contributor}
*/
@Nonnull
public String getName() {
@ -76,10 +100,10 @@ public class Contributor {
}
/**
* Returns the MC name of the contributor.
* This may be the same as {@link #getName()}.
* Returns the Minecraft username of the {@link Contributor}.
* This can be the same as {@link #getName()}.
*
* @return The MC username of this contributor.
* @return The Minecraft username of this {@link Contributor}.
*/
@Nonnull
public String getMinecraftName() {
@ -109,6 +133,7 @@ public class Contributor {
*
* @param role
* The role for which to count the contributions.
*
* @return The amount of contributions this {@link Contributor} submitted as the given role
*/
public int getContributions(@Nonnull String role) {
@ -137,7 +162,7 @@ public class Contributor {
}
/**
* Returns this Creator's head texture.
* Returns this contributor's head texture.
* If no texture could be found, or it hasn't been pulled yet,
* then it will return a placeholder texture.
*
@ -171,10 +196,22 @@ public class Contributor {
return headTexture.isComputed();
}
/**
* This sets the skin texture of this {@link Contributor} or clears it.
*
* @param skin
* The base64 skin texture or null
*/
public void setTexture(@Nullable String skin) {
headTexture.compute(skin);
}
/**
* This returns the total amount of contributions towards this project for this
* {@link Contributor}.
*
* @return The total amount of contributions
*/
public int getTotalContributions() {
return contributions.values().stream().mapToInt(Integer::intValue).sum();
}

View File

@ -0,0 +1,42 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
import java.time.LocalDateTime;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONObject;
class GitHubActivityConnector extends GitHubConnector {
private final ActivityCallback callback;
@ParametersAreNonnullByDefault
GitHubActivityConnector(GitHubService github, String repository, ActivityCallback callback) {
super(github, repository);
this.callback = callback;
}
@Override
public void onSuccess(@Nonnull JsonNode response) {
JSONObject object = response.getObject();
int forks = object.getInt("forks");
int stars = object.getInt("stargazers_count");
LocalDateTime lastPush = NumberUtils.parseGitHubDate(object.getString("pushed_at"));
callback.accept(forks, stars, lastPush);
}
@Override
public String getFileName() {
return "repo";
}
@Override
public String getURLSuffix() {
return "";
}
}

View File

@ -10,6 +10,7 @@ import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import kong.unirest.HttpResponse;
@ -19,8 +20,16 @@ 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.
* It can be extended by subclasses, this just serves as an abstract super class for
* other connectors.
*
* @author TheBusyBiscuit
* @author Walshy
*/
abstract class GitHubConnector {
private static final String API_URL = "https://api.github.com/";
protected File file;
@ -33,12 +42,23 @@ abstract class GitHubConnector {
this.repository = repository;
}
@Nonnull
public abstract String getFileName();
@Nonnull
public abstract String getURLSuffix();
public abstract void onSuccess(JsonNode element);
/**
* This method is called when the connection finished successfully.
*
* @param response
* The response
*/
public abstract void onSuccess(@Nonnull JsonNode response);
/**
* This method is called when the connection has failed.
*/
public void onFailure() {
// Don't do anything by default
}
@ -61,7 +81,7 @@ abstract class GitHubConnector {
}
else {
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] {repository + getURLSuffix(), resp.getStatus(), resp.getBody()});
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { repository + getURLSuffix(), resp.getStatus(), resp.getBody() });
}
// It has the cached file, let's just read that then
@ -94,12 +114,13 @@ abstract class GitHubConnector {
}
}
@Nullable
private JsonNode readCacheFile() {
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()});
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] { file.getName(), e.getClass().getSimpleName(), e.getMessage() });
return null;
}
}
@ -109,7 +130,7 @@ abstract class GitHubConnector {
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()});
Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] { e.getClass().getSimpleName(), e.getMessage() });
}
}
}

View File

@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.core.services.github;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import kong.unirest.JsonNode;
@ -9,20 +10,20 @@ import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class GitHubIssuesTracker extends GitHubConnector {
class GitHubIssuesConnector extends GitHubConnector {
private final IssuesTrackerConsumer callback;
private final IssuesCallback callback;
@ParametersAreNonnullByDefault
GitHubIssuesTracker(GitHubService github, String repository, IssuesTrackerConsumer callback) {
GitHubIssuesConnector(GitHubService github, String repository, IssuesCallback callback) {
super(github, repository);
this.callback = callback;
}
@Override
public void onSuccess(JsonNode element) {
if (element.isArray()) {
JSONArray array = element.getArray();
public void onSuccess(@Nonnull JsonNode response) {
if (response.isArray()) {
JSONArray array = response.getArray();
int issues = 0;
int pullRequests = 0;
@ -41,7 +42,7 @@ class GitHubIssuesTracker extends GitHubConnector {
callback.accept(issues, pullRequests);
}
else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", element);
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}

View File

@ -16,9 +16,6 @@ import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONObject;
/**
* This Service is responsible for grabbing every {@link Contributor} to this project
@ -39,11 +36,11 @@ public class GitHubService {
private boolean logging = false;
private int issues = 0;
private int pullRequests = 0;
private int forks = 0;
private int stars = 0;
private LocalDateTime lastUpdate = LocalDateTime.now();
private int openIssues = 0;
private int pendingPullRequests = 0;
private int publicForks = 0;
private int stargazers = 0;
/**
* This creates a new {@link GitHubService} for the given repository.
@ -63,6 +60,11 @@ public class GitHubService {
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new GitHubTask(this), 80L, 60 * 60 * 20L);
}
/**
* This method adds a few default {@link Contributor Contributors}.
* Think of them like honorable mentions that aren't listed through
* the usual methods.
*/
private void addDefaultContributors() {
addContributor("Fuffles_", "&dArtist");
addContributor("IMS_Art", "&dArtist");
@ -73,7 +75,7 @@ public class GitHubService {
private void addContributor(@Nonnull String name, @Nonnull String role) {
Contributor contributor = new Contributor(name);
contributor.setContribution(role, 0);
contributor.setContributions(role, 0);
contributor.setUniqueId(uuidCache.getUUID(name));
contributors.put(name, contributor);
}
@ -83,7 +85,7 @@ public class GitHubService {
String username = profileURL.substring(profileURL.lastIndexOf('/') + 1);
Contributor contributor = contributors.computeIfAbsent(username, key -> new Contributor(minecraftName, profileURL));
contributor.setContribution(role, commits);
contributor.setContributions(role, commits);
contributor.setUniqueId(uuidCache.getUUID(minecraftName));
return contributor;
}
@ -97,37 +99,22 @@ public class GitHubService {
connectors.add(new ContributionsConnector(this, "code2", 2, repository, "developer"));
// TheBusyBiscuit/Slimefun4-Wiki
connectors.add(new ContributionsConnector(this, "wiki", 1, "Slimefun/Slimefun-wiki", "wiki"));
connectors.add(new ContributionsConnector(this, "wiki", 1, "Slimefun/Wiki", "wiki"));
// TheBusyBiscuit/Slimefun4-Resourcepack
connectors.add(new ContributionsConnector(this, "resourcepack", 1, "Slimefun/Resourcepack", "resourcepack"));
// Issues and Pull Requests
connectors.add(new GitHubIssuesTracker(this, repository, (openIssues, openPullRequests) -> {
this.issues = openIssues;
this.pullRequests = openPullRequests;
connectors.add(new GitHubIssuesConnector(this, repository, (issues, pullRequests) -> {
this.openIssues = issues;
this.pendingPullRequests = pullRequests;
}));
connectors.add(new GitHubConnector(this, repository) {
@Override
public void onSuccess(JsonNode element) {
JSONObject object = element.getObject();
forks = object.getInt("forks");
stars = object.getInt("stargazers_count");
lastUpdate = NumberUtils.parseGitHubDate(object.getString("pushed_at"));
}
@Override
public String getFileName() {
return "repo";
}
@Override
public String getURLSuffix() {
return "";
}
});
connectors.add(new GitHubActivityConnector(this, repository, (forks, stars, date) -> {
this.publicForks = forks;
this.stargazers = stars;
this.lastUpdate = date;
}));
}
@Nonnull
@ -155,7 +142,7 @@ public class GitHubService {
* @return The amount of forks
*/
public int getForks() {
return forks;
return publicForks;
}
/**
@ -164,7 +151,7 @@ public class GitHubService {
* @return The amount of people who starred the repository
*/
public int getStars() {
return stars;
return stargazers;
}
/**
@ -173,7 +160,7 @@ public class GitHubService {
* @return The amount of open issues
*/
public int getOpenIssues() {
return issues;
return openIssues;
}
/**
@ -192,7 +179,7 @@ public class GitHubService {
* @return The amount of pending pull requests
*/
public int getPendingPullRequests() {
return pullRequests;
return pendingPullRequests;
}
/**
@ -212,7 +199,6 @@ public class GitHubService {
protected void saveCache() {
for (Contributor contributor : contributors.values()) {
Optional<UUID> uuid = contributor.getUniqueId();
uuid.ifPresent(value -> uuidCache.setValue(contributor.getName(), value));
if (contributor.hasTexture()) {

View File

@ -8,6 +8,7 @@ import java.util.UUID;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
@ -29,7 +30,6 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
class GitHubTask implements Runnable {
private static final int MAX_REQUESTS_PER_MINUTE = 16;
private final GitHubService gitHubService;
GitHubTask(@Nonnull GitHubService github) {
@ -39,7 +39,6 @@ class GitHubTask implements Runnable {
@Override
public void run() {
gitHubService.getConnectors().forEach(GitHubConnector::pullFile);
grabTextures();
}
@ -112,12 +111,12 @@ class GitHubTask implements Runnable {
return 0;
}
@Nullable
private String pullTexture(@Nonnull Contributor contributor, @Nonnull Map<String, String> skins) throws TooManyRequestsException, IOException {
Optional<UUID> uuid = contributor.getUniqueId();
if (!uuid.isPresent()) {
uuid = MinecraftAccount.getUUID(contributor.getMinecraftName());
uuid.ifPresent(contributor::setUniqueId);
}

View File

@ -1,10 +1,10 @@
package io.github.thebusybiscuit.slimefun4.core.services.github;
@FunctionalInterface
interface IssuesTrackerConsumer {
interface IssuesCallback {
/**
* This method is called when the {@link GitHubIssuesTracker} finished loading.
* This method is called when the {@link GitHubIssuesConnector} finished loading.
*
* @param issues
* The amount of open Issues

View File

@ -5,6 +5,7 @@ import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
@ -24,16 +25,19 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
this.author = plugin.getDescription().getAuthors().toString();
}
@Nonnull
@Override
public String getIdentifier() {
return "slimefun";
}
@Nonnull
@Override
public String getVersion() {
return version;
}
@Nonnull
@Override
public String getAuthor() {
return author;
@ -49,9 +53,18 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
return true;
}
private boolean isPlaceholder(@Nullable OfflinePlayer p, boolean requiresProfile, @Nonnull String params, @Nonnull String placeholder) {
if (requiresProfile) {
return p != null && placeholder.equals(params) && PlayerProfile.request(p);
}
else {
return placeholder.equals(params);
}
}
@Override
public String onRequest(OfflinePlayer p, String params) {
if (params.equals("researches_total_xp_levels_spent") && PlayerProfile.request(p)) {
public String onRequest(@Nullable OfflinePlayer p, @Nonnull String params) {
if (isPlaceholder(p, true, params, "researches_total_xp_levels_spent")) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
@ -60,7 +73,7 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
}
}
if (params.equals("researches_total_researches_unlocked") && PlayerProfile.request(p)) {
if (isPlaceholder(p, true, params, "researches_total_researches_unlocked")) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
@ -69,11 +82,11 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
}
}
if (params.equals("researches_total_researches")) {
if (isPlaceholder(p, false, params, "researches_total_researches")) {
return String.valueOf(SlimefunPlugin.getRegistry().getResearches().size());
}
if (params.equals("researches_percentage_researches_unlocked") && PlayerProfile.request(p)) {
if (isPlaceholder(p, true, params, "researches_percentage_researches_unlocked")) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
@ -82,7 +95,7 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
}
}
if (params.equals("researches_title") && PlayerProfile.request(p)) {
if (isPlaceholder(p, true, params, "researches_title")) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
@ -90,20 +103,17 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
}
}
if (params.equals("gps_complexity")) {
if (isPlaceholder(p, false, params, "gps_complexity") && p != null) {
return String.valueOf(SlimefunPlugin.getGPSNetwork().getNetworkComplexity(p.getUniqueId()));
}
if (params.equals("timings_lag")) {
if (isPlaceholder(p, false, params, "timings_lag")) {
return SlimefunPlugin.getProfiler().getTime();
}
if (params.equals("language")) {
if (!(p instanceof Player)) {
return "Unknown";
}
return SlimefunPlugin.getLocalization().getLanguage((Player) p).getName((Player) p);
if (isPlaceholder(p, false, params, "language") && p instanceof Player) {
Player player = (Player) p;
return SlimefunPlugin.getLocalization().getLanguage(player).getName(player);
}
return null;

View File

@ -675,6 +675,8 @@ public final class SlimefunItems {
public static final SlimefunItemStack BIG_CAPACITOR = new SlimefunItemStack("BIG_CAPACITOR", HeadTexture.CAPACITOR_25, "&aBig Energy Capacitor", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &71024 J Capacity");
public static final SlimefunItemStack LARGE_CAPACITOR = new SlimefunItemStack("LARGE_CAPACITOR", HeadTexture.CAPACITOR_25, "&aLarge Energy Capacitor", "", LoreBuilder.machine(MachineTier.GOOD, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &78192 J Capacity");
public static final SlimefunItemStack CARBONADO_EDGED_CAPACITOR = new SlimefunItemStack("CARBONADO_EDGED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aCarbonado Edged Energy Capacitor", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &765536 J Capacity");
public static final SlimefunItemStack ENERGIZED_CAPACITOR = new SlimefunItemStack("ENERGIZED_CAPACITOR", HeadTexture.CAPACITOR_25, "&aEnergized Energy Capacitor", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.CAPACITOR), "&8\u21E8 &e\u26A1 &7524288 J Capacity");
/* Robots */
public static final SlimefunItemStack PROGRAMMABLE_ANDROID = new SlimefunItemStack("PROGRAMMABLE_ANDROID", HeadTexture.PROGRAMMABLE_ANDROID, "&cProgrammable Android &7(Normal)", "", "&8\u21E8 &7Function: None", "&8\u21E8 &7Fuel Efficiency: 1.0x");

View File

@ -13,6 +13,7 @@ import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.Command;
@ -21,6 +22,7 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
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;
@ -101,7 +103,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.CSCoreLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
/**
@ -241,7 +242,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
registerListeners();
// Initiating various Stuff and all items with a slight delay (0ms after the Server finished loading)
Slimefun.runSync(new SlimefunStartupTask(this, () -> {
runSync(new SlimefunStartupTask(this, () -> {
protections = new ProtectionManager(getServer());
textureService.register(registry.getAllSlimefunItems(), true);
permissionsService.register(registry.getAllSlimefunItems(), true);
@ -706,4 +707,63 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return "https://github.com/Slimefun/Slimefun4/issues";
}
/**
* This method schedules a delayed synchronous task for Slimefun.
* <strong>For Slimefun only, not for addons.</strong>
*
* This method should only be invoked by Slimefun itself.
* Addons must schedule their own tasks using their own {@link Plugin} instance.
*
* @param runnable
* The {@link Runnable} to run
* @param delay
* The delay for this task
*
* @return The resulting {@link BukkitTask} or null if Slimefun was disabled
*/
@Nullable
public static BukkitTask runSync(@Nonnull Runnable runnable, long delay) {
Validate.notNull(runnable, "Cannot run null");
Validate.isTrue(delay >= 0, "The delay cannot be negative");
if (getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
runnable.run();
return null;
}
if (instance == null || !instance.isEnabled()) {
return null;
}
return instance.getServer().getScheduler().runTaskLater(instance, runnable, delay);
}
/**
* This method schedules a synchronous task for Slimefun.
* <strong>For Slimefun only, not for addons.</strong>
*
* This method should only be invoked by Slimefun itself.
* Addons must schedule their own tasks using their own {@link Plugin} instance.
*
* @param runnable
* The {@link Runnable} to run
*
* @return The resulting {@link BukkitTask} or null if Slimefun was disabled
*/
@Nullable
public static BukkitTask runSync(@Nonnull Runnable runnable) {
Validate.notNull(runnable, "Cannot run null");
if (getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
runnable.run();
return null;
}
if (instance == null || !instance.isEnabled()) {
return null;
}
return instance.getServer().getScheduler().runTask(instance, runnable);
}
}

View File

@ -80,7 +80,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
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 -> Slimefun.runSync(() -> {
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)));
@ -234,13 +234,13 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
component.setHoverEvent(new HoverEvent(lore));
component.setClickEvent(new ClickEvent(key, player -> Slimefun.runSync(() -> displayItem(profile, item, true))));
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> displayItem(profile, item, true))));
items.add(component);
}
}
private void research(Player p, PlayerProfile profile, SlimefunItem item, Research research, Category category, int page) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(p.getUniqueId())) {
if (research.canUnlock(p)) {
if (profile.hasUnlocked(research)) {

View File

@ -7,6 +7,8 @@ import java.util.Optional;
import java.util.function.Predicate;
import java.util.logging.Level;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@ -55,7 +57,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;
@ -221,6 +222,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
});
}
@ParametersAreNonnullByDefault
public void openScript(Player p, Block b, String sourceCode) {
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocalization().getMessage(p, "android.scripts.editor"));
menu.setEmptySlotsClickable(false);
@ -291,6 +293,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
menu.open(p);
}
@ParametersAreNonnullByDefault
private String addInstruction(String[] script, int index, Instruction instruction) {
int i = 0;
StringBuilder builder = new StringBuilder(Instruction.START.name() + '-');
@ -848,7 +851,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
});
block.setBlockData(blockData);
Slimefun.runSync(() -> SkullBlock.setFromBase64(block, texture));
SlimefunPlugin.runSync(() -> SkullBlock.setFromBase64(block, texture));
b.setType(Material.AIR);
BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation());

View File

@ -32,7 +32,6 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -156,7 +155,7 @@ public class BlockPlacer extends SlimefunItem {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
});
@ -171,7 +170,7 @@ public class BlockPlacer extends SlimefunItem {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
}
@ -209,7 +208,7 @@ public class BlockPlacer extends SlimefunItem {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
SlimefunPlugin.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
}

View File

@ -4,6 +4,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.Tag;
@ -24,7 +27,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements RecipeDisplayItem {
@ -100,6 +102,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
};
}
@ParametersAreNonnullByDefault
private boolean craft(Player p, ItemStack input) {
for (int i = 0; i < recipes.size(); i += 2) {
ItemStack convert = recipes.get(i);
@ -116,7 +119,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
return false;
}
private void generateLiquid(Block block, boolean water) {
private void generateLiquid(@Nonnull Block block, boolean water) {
if (block.getType() == (water ? Material.WATER : Material.LAVA)) {
addLiquidLevel(block, water);
}
@ -126,11 +129,11 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
block.getWorld().playSound(block.getLocation(), Sound.BLOCK_LAVA_EXTINGUISH, 1F, 1F);
}
else {
Slimefun.runSync(() -> placeLiquid(block, water), 50L);
SlimefunPlugin.runSync(() -> placeLiquid(block, water), 50L);
}
}
private void addLiquidLevel(Block block, boolean water) {
private void addLiquidLevel(@Nonnull Block block, boolean water) {
int level = ((Levelled) block.getBlockData()).getLevel();
if (level > 7) {
@ -142,11 +145,11 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
}
else {
int finalLevel = 7 - level;
Slimefun.runSync(() -> runPostTask(block, water ? Sound.ENTITY_PLAYER_SPLASH : Sound.BLOCK_LAVA_POP, finalLevel), 50L);
SlimefunPlugin.runSync(() -> runPostTask(block, water ? Sound.ENTITY_PLAYER_SPLASH : Sound.BLOCK_LAVA_POP, finalLevel), 50L);
}
}
private void placeLiquid(Block block, boolean water) {
private void placeLiquid(@Nonnull Block block, boolean water) {
if (block.getType() == Material.AIR || block.getType() == Material.CAVE_AIR || block.getType() == Material.VOID_AIR) {
block.setType(water ? Material.WATER : Material.LAVA);
}
@ -167,6 +170,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
runPostTask(block, water ? Sound.ENTITY_PLAYER_SPLASH : Sound.BLOCK_LAVA_POP, 1);
}
@ParametersAreNonnullByDefault
private void runPostTask(Block block, Sound sound, int times) {
if (!(block.getBlockData() instanceof Levelled)) {
block.getWorld().playSound(block.getLocation(), Sound.BLOCK_METAL_BREAK, 1F, 1F);
@ -180,7 +184,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
block.setBlockData(le, false);
if (times < 8) {
Slimefun.runSync(() -> runPostTask(block, sound, times + 1), 50L);
SlimefunPlugin.runSync(() -> runPostTask(block, sound, times + 1), 50L);
}
else {
block.getWorld().playSound(block.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1F, 1F);

View File

@ -83,7 +83,7 @@ abstract class AbstractCargoNode extends SlimefunItem {
menu.addMenuClickHandler(slotPrev, (p, slot, item, action) -> {
int newChannel = channel - 1;
if (channel < 0) {
if (newChannel < 0) {
if (isChestTerminalInstalled) {
newChannel = 16;
}

View File

@ -10,6 +10,8 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import javax.annotation.Nonnull;
public abstract class CoalGenerator extends AGenerator {
public CoalGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
@ -22,21 +24,62 @@ public abstract class CoalGenerator extends AGenerator {
registerFuel(new MachineFuel(12, new ItemStack(Material.BLAZE_ROD)));
registerFuel(new MachineFuel(20, new ItemStack(Material.DRIED_KELP_BLOCK)));
// Boats
for (Material mat : Tag.ITEMS_BOATS.getValues()) {
registerFuel(new MachineFuel(5, new ItemStack(mat)));
}
// Coal & Charcoal
registerFuel(new MachineFuel(8, new ItemStack(Material.COAL)));
registerFuel(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
// Logs
for (Material mat : Tag.LOGS.getValues()) {
registerFuel(new MachineFuel(2, new ItemStack(mat)));
registerFuel(new MachineFuel(4, new ItemStack(mat)));
}
// Wooden Planks
for (Material mat : Tag.PLANKS.getValues()) {
registerFuel(new MachineFuel(1, new ItemStack(mat)));
}
// Wooden Slabs
for (Material mat : Tag.WOODEN_SLABS.getValues()) {
registerFuel(new MachineFuel(1, new ItemStack(mat)));
}
// Wooden Buttons
for (Material mat : Tag.WOODEN_BUTTONS.getValues()) {
registerFuel(new MachineFuel(1, new ItemStack(mat)));
}
// Wooden Fences
for (Material mat : Tag.WOODEN_FENCES.getValues()) {
registerFuel(new MachineFuel(1, new ItemStack(mat)));
}
// wooden Trapdoors
for (Material mat : Tag.WOODEN_TRAPDOORS.getValues()) {
registerFuel(new MachineFuel(3, new ItemStack(mat)));
}
// Wooden Pressure Plates
for (Material mat : Tag.WOODEN_PRESSURE_PLATES.getValues()) {
registerFuel(new MachineFuel(2, new ItemStack(mat)));
}
// Wooden Doors
for (Material mat : Tag.WOODEN_DOORS.getValues()) {
registerFuel(new MachineFuel(2, new ItemStack(mat)));
}
// Signs
for (Material mat : Tag.SIGNS.getValues()) {
registerFuel(new MachineFuel(2, new ItemStack(mat)));
}
}
@Nonnull
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL);

View File

@ -28,7 +28,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
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;
@ -206,7 +205,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
removeCharge(b.getLocation(), getEnergyConsumption());
double offset = Double.parseDouble(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET));
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
Location loc = new Location(b.getWorld(), b.getX() + 0.5D, b.getY() + offset, b.getZ() + 0.5D);
spawnEntity(loc);

View File

@ -13,11 +13,11 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.holograms.ReactorHologram;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -43,7 +43,7 @@ public abstract class NetherStarReactor extends Reactor {
@Override
public void extraTick(@Nonnull Location l) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = ReactorHologram.getArmorStand(l, true);
for (Entity entity : hologram.getNearbyEntities(5, 5, 5)) {
if (entity instanceof LivingEntity && entity.isValid()) {

View File

@ -21,6 +21,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncReactorProcessCompleteEvent;
import io.github.thebusybiscuit.slimefun4.api.events.ReactorExplodeEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -37,7 +38,6 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
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;
@ -332,7 +332,7 @@ public abstract class Reactor extends AbstractEnergyProvider {
boolean explosion = explosionsQueue.contains(l);
if (explosion) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ReactorExplodeEvent event = new ReactorExplodeEvent(l, Reactor.this);
Bukkit.getPluginManager().callEvent(event);
@ -349,7 +349,7 @@ public abstract class Reactor extends AbstractEnergyProvider {
}
private void checkForWaterBlocks(Location l) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
// We will pick a surrounding block at random and see if this is water.
// If it isn't, then we will make it explode.
int index = ThreadLocalRandom.current().nextInt(WATER_BLOCKS.length);
@ -376,6 +376,8 @@ public abstract class Reactor extends AbstractEnergyProvider {
}
}
Bukkit.getPluginManager().callEvent(new AsyncReactorProcessCompleteEvent(l, Reactor.this, getProcessing(l)));
progress.remove(l);
processing.remove(l);
}

View File

@ -12,6 +12,7 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CoolerListener;
@ -19,7 +20,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -81,18 +81,18 @@ public class Juice extends SimpleSlimefunItem<ItemConsumptionHandler> {
private void removeGlassBottle(Player p, ItemStack item) {
if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInMainHand(), true)) {
if (p.getInventory().getItemInMainHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInMainHand().setAmount(0));
SlimefunPlugin.runSync(() -> p.getEquipment().getItemInMainHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
SlimefunPlugin.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
else if (SlimefunUtils.isItemSimilar(item, p.getInventory().getItemInOffHand(), true)) {
if (p.getInventory().getItemInOffHand().getAmount() == 1) {
Slimefun.runSync(() -> p.getEquipment().getItemInOffHand().setAmount(0));
SlimefunPlugin.runSync(() -> p.getEquipment().getItemInOffHand().setAmount(0));
}
else {
Slimefun.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
SlimefunPlugin.runSync(() -> p.getInventory().removeItem(new ItemStack(Material.GLASS_BOTTLE, 1)));
}
}
}

View File

@ -5,10 +5,10 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -27,7 +27,7 @@ public class MonsterJerky extends SimpleSlimefunItem<ItemConsumptionHandler> {
@Override
public ItemConsumptionHandler getItemHandler() {
return (e, p, item) -> Slimefun.runSync(() -> {
return (e, p, item) -> SlimefunPlugin.runSync(() -> {
if (p.hasPotionEffect(PotionEffectType.HUNGER)) {
p.removePotionEffect(PotionEffectType.HUNGER);
}

View File

@ -34,7 +34,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
@ -152,7 +151,7 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
@ParametersAreNonnullByDefault
private void teleport(Player player, String floorName, Block target) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
users.add(player.getUniqueId());
float yaw = player.getEyeLocation().getYaw() + 180;

View File

@ -67,7 +67,7 @@ public class EnchantmentRune extends SimpleSlimefunItem<ItemDropHandler> {
return (e, p, item) -> {
if (isItem(item.getItemStack())) {
if (Slimefun.hasUnlocked(p, this, true)) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
try {
addRandomEnchantment(p, item);
}
@ -124,7 +124,7 @@ public class EnchantmentRune extends SimpleSlimefunItem<ItemDropHandler> {
// This lightning is just an effect, it deals no damage.
l.getWorld().strikeLightningEffect(l);
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
// Being sure entities are still valid and not picked up or whatsoever.
if (rune.isValid() && item.isValid() && itemStack.getAmount() == 1) {

View File

@ -11,7 +11,10 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -31,10 +34,12 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see EntityInteractHandler
*
*/
public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler> {
public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler> implements NotPlaceable {
public MagicalZombiePills(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
addItemHandler(onRightClick());
}
@Override
@ -61,4 +66,12 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
};
}
/**
* This method cancels {@link PlayerRightClickEvent} to prevent placing {@link MagicalZombiePills}.
*
* @return the {@link ItemUseHandler} of this {@link SlimefunItem}
*/
public ItemUseHandler onRightClick() {
return PlayerRightClickEvent::cancel;
}
}

View File

@ -50,7 +50,7 @@ public class SoulboundRune extends SimpleSlimefunItem<ItemDropHandler> {
return true;
}
Slimefun.runSync(() -> activate(p, item), 20L);
SlimefunPlugin.runSync(() -> activate(p, item), 20L);
return true;
}
@ -76,7 +76,7 @@ public class SoulboundRune extends SimpleSlimefunItem<ItemDropHandler> {
// This lightning is just an effect, it deals no damage.
l.getWorld().strikeLightningEffect(l);
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
// Being sure entities are still valid and not picked up or whatsoever.
if (rune.isValid() && item.isValid() && itemStack.getAmount() == 1) {

View File

@ -2,6 +2,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.magical;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@ -40,10 +43,12 @@ public class StormStaff extends SimpleSlimefunItem<ItemUseHandler> {
private static final NamespacedKey usageKey = new NamespacedKey(SlimefunPlugin.instance(), "stormstaff_usage");
public static final int MAX_USES = 8;
@ParametersAreNonnullByDefault
public StormStaff(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe, getCraftedOutput());
}
@Nonnull
private static ItemStack getCraftedOutput() {
ItemStack item = SlimefunItems.STAFF_STORM.clone();
ItemMeta im = item.getItemMeta();
@ -82,10 +87,11 @@ public class StormStaff extends SimpleSlimefunItem<ItemUseHandler> {
};
}
@ParametersAreNonnullByDefault
private void useItem(Player p, ItemStack item, Location loc) {
loc.getWorld().strikeLightning(loc);
if (p.getInventory().getItemInMainHand().getType() == Material.SHEARS) {
if (item.getType() == Material.SHEARS) {
return;
}
@ -98,22 +104,43 @@ public class StormStaff extends SimpleSlimefunItem<ItemUseHandler> {
}
}
ItemMeta meta = item.getItemMeta();
int usesLeft = meta.getPersistentDataContainer().getOrDefault(usageKey, PersistentDataType.INTEGER, MAX_USES);
damageItem(p, item);
}
if (usesLeft == 1) {
p.playSound(p.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
item.setAmount(0);
@ParametersAreNonnullByDefault
private void damageItem(Player p, ItemStack item) {
if (item.getAmount() > 1) {
item.setAmount(item.getAmount() - 1);
// Seperate one item from the stack and damage it
ItemStack seperateItem = item.clone();
seperateItem.setAmount(1);
damageItem(p, seperateItem);
// Try to give the Player the new item
if (!p.getInventory().addItem(seperateItem).isEmpty()) {
// or throw it on the ground
p.getWorld().dropItemNaturally(p.getLocation(), seperateItem);
}
}
else {
usesLeft--;
meta.getPersistentDataContainer().set(usageKey, PersistentDataType.INTEGER, usesLeft);
ItemMeta meta = item.getItemMeta();
int usesLeft = meta.getPersistentDataContainer().getOrDefault(usageKey, PersistentDataType.INTEGER, MAX_USES);
List<String> lore = meta.getLore();
lore.set(4, ChatColors.color("&e" + usesLeft + ' ' + (usesLeft > 1 ? "Uses" : "Use") + " &7left"));
meta.setLore(lore);
if (usesLeft == 1) {
p.playSound(p.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
item.setAmount(0);
}
else {
usesLeft--;
meta.getPersistentDataContainer().set(usageKey, PersistentDataType.INTEGER, usesLeft);
item.setItemMeta(meta);
List<String> lore = meta.getLore();
lore.set(4, ChatColors.color("&e" + usesLeft + ' ' + (usesLeft > 1 ? "Uses" : "Use") + " &7left"));
meta.setLore(lore);
item.setItemMeta(meta);
}
}
}

View File

@ -84,7 +84,7 @@ public class ArmorForge extends MultiBlockMachine {
for (int j = 0; j < 4; j++) {
int current = j;
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (current < 3) {
p.getWorld().playSound(p.getLocation(), Sound.BLOCK_ANVIL_USE, 1F, 2F);
}

View File

@ -21,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Compressor extends MultiBlockMachine {
@ -83,7 +82,7 @@ public class Compressor extends MultiBlockMachine {
for (int i = 0; i < 4; i++) {
int j = i;
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (j < 3) {
p.getWorld().playSound(p.getLocation(), j == 1 ? Sound.BLOCK_PISTON_CONTRACT : Sound.BLOCK_PISTON_EXTEND, 1F, j == 0 ? 1F : 2F);
}

View File

@ -94,7 +94,7 @@ public class MagicWorkbench extends BackpackCrafter {
private void startAnimation(Player p, Block b, Inventory inv, ItemStack output) {
for (int j = 0; j < 4; j++) {
int current = j;
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
p.getWorld().playEffect(b.getLocation(), Effect.MOBSPAWNER_FLAMES, 1);
p.getWorld().playEffect(b.getLocation(), Effect.ENDER_SIGNAL, 1);

View File

@ -22,7 +22,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class PressureChamber extends MultiBlockMachine {
@ -75,7 +74,7 @@ public class PressureChamber extends MultiBlockMachine {
for (int i = 0; i < 4; i++) {
int j = i;
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
p.getWorld().playSound(b.getLocation(), Sound.ENTITY_TNT_PRIMED, 1, 1);
p.getWorld().playEffect(b.getRelative(BlockFace.UP).getLocation(), Effect.SMOKE, 4);
p.getWorld().playEffect(b.getRelative(BlockFace.UP).getLocation(), Effect.SMOKE, 4);

View File

@ -191,7 +191,7 @@ class ActiveMiner implements Runnable {
ores++;
// Repeat the same column when we hit an ore.
Slimefun.runSync(this, 4);
SlimefunPlugin.runSync(this, 4);
return;
}
}
@ -232,7 +232,7 @@ class ActiveMiner implements Runnable {
return;
}
Slimefun.runSync(this, 5);
SlimefunPlugin.runSync(this, 5);
}
/**
@ -317,7 +317,7 @@ class ActiveMiner implements Runnable {
}
}
}
return 0;
}

View File

@ -9,6 +9,9 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.GameMode;
@ -33,7 +36,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -55,6 +57,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
private final Map<Material, Double> materialSpeeds;
private final Set<UUID> users = new HashSet<>();
@ParametersAreNonnullByDefault
public ClimbingPick(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(dualWielding, damageOnUse);
@ -123,6 +126,8 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
};
}
@Nonnull
@ParametersAreNonnullByDefault
private ItemStack getOtherHandItem(Player p, EquipmentSlot hand) {
if (hand == EquipmentSlot.HAND) {
return p.getInventory().getItemInOffHand();
@ -132,6 +137,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
}
}
@ParametersAreNonnullByDefault
private void climb(Player p, EquipmentSlot hand, ItemStack item, Block block) {
double power = materialSpeeds.getOrDefault(block.getType(), 0.0);
@ -144,7 +150,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
power += efficiencyLevel * 0.1;
}
Slimefun.runSync(() -> users.remove(p.getUniqueId()), 3L);
SlimefunPlugin.runSync(() -> users.remove(p.getUniqueId()), 4L);
Vector velocity = new Vector(0, power * BASE_POWER, 0);
ClimbingPickLaunchEvent event = new ClimbingPickLaunchEvent(p, velocity, this, item, block);
Bukkit.getPluginManager().callEvent(event);
@ -162,25 +168,37 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
}
}
@ParametersAreNonnullByDefault
private void swing(Player p, Block b, EquipmentSlot hand, ItemStack item) {
if (p.getGameMode() != GameMode.CREATIVE) {
if (isDualWieldingEnabled()) {
if (ThreadLocalRandom.current().nextBoolean()) {
damageItem(p, p.getInventory().getItemInMainHand());
playAnimation(p, b, EquipmentSlot.HAND);
}
else {
damageItem(p, p.getInventory().getItemInOffHand());
playAnimation(p, b, EquipmentSlot.OFF_HAND);
}
if (isDualWieldingEnabled()) {
if (ThreadLocalRandom.current().nextBoolean()) {
damageItem(p, p.getInventory().getItemInMainHand());
playAnimation(p, b, EquipmentSlot.HAND);
}
else {
damageItem(p, item);
playAnimation(p, b, hand);
damageItem(p, p.getInventory().getItemInOffHand());
playAnimation(p, b, EquipmentSlot.OFF_HAND);
}
}
else {
damageItem(p, item);
playAnimation(p, b, hand);
}
}
@Override
public void damageItem(Player p, ItemStack item) {
if (p.getGameMode() != GameMode.CREATIVE) {
DamageableItem.super.damageItem(p, item);
}
}
@Override
public boolean isDamageable() {
return damageOnUse.getValue();
}
@ParametersAreNonnullByDefault
private void playAnimation(Player p, Block b, EquipmentSlot hand) {
MinecraftVersion version = SlimefunPlugin.getMinecraftVersion();
@ -198,11 +216,6 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
}
}
@Override
public boolean isDamageable() {
return damageOnUse.getValue();
}
@Override
public List<ItemStack> getDisplayRecipes() {
List<ItemStack> display = new ArrayList<>();

View File

@ -22,12 +22,14 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
private final ItemSetting<Boolean> consumeOnUse = new ItemSetting<>("consume-on-use", true);
private final ItemSetting<Integer> despawnTicks = new ItemSetting<>("despawn-seconds", 60);
public GrapplingHook(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(despawnTicks);
addItemSetting(consumeOnUse);
}
@Override
@ -35,6 +37,7 @@ public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
return e -> {
Player p = e.getPlayer();
UUID uuid = p.getUniqueId();
boolean consumeOnUseValue = consumeOnUse.getValue();
if (!e.getClickedBlock().isPresent() && !SlimefunPlugin.getGrapplingHookListener().isGrappling(uuid)) {
e.cancel();
@ -47,7 +50,10 @@ public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
ItemStack item = e.getItem();
if (item.getType() == Material.LEAD) {
item.setAmount(item.getAmount() - 1);
//If consume on use is enabled, the if statement below will take 1 grappling hook out of player's hand
if (consumeOnUseValue) {
item.setAmount(item.getAmount() - 1);
}
}
Vector direction = p.getEyeLocation().getDirection().multiply(2.0);
@ -63,7 +69,7 @@ public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
bat.setLeashHolder(arrow);
boolean state = item.getType() != Material.SHEARS;
SlimefunPlugin.getGrapplingHookListener().addGrapplingHook(p, arrow, bat, state, despawnTicks.getValue());
SlimefunPlugin.getGrapplingHookListener().addGrapplingHook(p, arrow, bat, state, despawnTicks.getValue(), consumeOnUseValue);
}
};
}

View File

@ -1,7 +1,10 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
@ -11,8 +14,16 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link PortableCrafter} is one of the oldest items in Slimefun.
* It allows a {@link Player} to open up the {@link CraftingInventory} via right click.
*
* @author TheBusyBiscuit
*
*/
public class PortableCrafter extends SimpleSlimefunItem<ItemUseHandler> implements NotPlaceable {
@ParametersAreNonnullByDefault
public PortableCrafter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}

View File

@ -4,6 +4,9 @@ import java.text.DecimalFormat;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
@ -34,6 +37,7 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
private final NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), "anchor");
private final DecimalFormat format = new DecimalFormat("##.###");
@ParametersAreNonnullByDefault
public TapeMeasure(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
@ -56,6 +60,7 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
};
}
@ParametersAreNonnullByDefault
private void setAnchor(Player p, ItemStack item, Block block) {
ItemMeta meta = item.getItemMeta();
@ -74,6 +79,8 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
}
@Nonnull
@ParametersAreNonnullByDefault
private Optional<Location> getAnchor(Player p, ItemStack item) {
ItemMeta meta = item.getItemMeta();
@ -102,6 +109,7 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
}
}
@ParametersAreNonnullByDefault
private void measure(Player p, ItemStack item, Block block) {
Optional<Location> anchor = getAnchor(p, item);

View File

@ -155,7 +155,7 @@ public class AncientAltarListener implements Listener {
UUID uuid = entity.getUniqueId();
removedItems.add(uuid);
Slimefun.runSync(() -> removedItems.remove(uuid), 30L);
SlimefunPlugin.runSync(() -> removedItems.remove(uuid), 30L);
entity.remove();
p.getInventory().addItem(pedestalItem.getOriginalItemStack(entity));
@ -228,7 +228,7 @@ public class AncientAltarListener implements Listener {
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_ILLUSIONER_PREPARE_MIRROR, 1, 1);
AncientAltarTask task = new AncientAltarTask(this, b, altarItem.getSpeed(), result.get(), pedestals, consumed, p);
Slimefun.runSync(task, 10L);
SlimefunPlugin.runSync(task, 10L);
}
else {
altars.remove(b);

View File

@ -23,7 +23,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AndroidInstance;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.ButcherAndroid;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} handles the collection of drops from an {@link Entity} that was
@ -45,7 +44,7 @@ public class ButcherAndroidListener implements Listener {
if (e.getEntity().hasMetadata(METADATA_KEY)) {
AndroidInstance obj = (AndroidInstance) e.getEntity().getMetadata(METADATA_KEY).get(0).value();
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
List<ItemStack> items = new ArrayList<>();
// Collect any nearby dropped items

View File

@ -23,8 +23,10 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} listens for a {@link FoodLevelChangeEvent} or an {@link EntityDamageEvent} for starvation damage
* and consumes a {@link Juice} from any {@link Cooler} that can be found in the {@link Inventory} of the given {@link Player}.
* This {@link Listener} listens for a {@link FoodLevelChangeEvent} or an {@link EntityDamageEvent} for starvation
* damage
* and consumes a {@link Juice} from any {@link Cooler} that can be found in the {@link Inventory} of the given
* {@link Player}.
*
* @author TheBusyBiscuit
* @author Linox
@ -55,18 +57,18 @@ public class CoolerListener implements Listener {
checkAndConsume(p);
}
}
@EventHandler
public void onHungerDamage(EntityDamageEvent e) {
if (cooler == null || cooler.isDisabled() || !(e.getEntity() instanceof Player)) {
return;
}
if (e.getCause() == DamageCause.STARVATION) {
checkAndConsume((Player) e.getEntity());
}
}
private void checkAndConsume(@Nonnull Player p) {
for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) {
@ -92,7 +94,7 @@ public class CoolerListener implements Listener {
private void takeJuiceFromCooler(@Nonnull Player p, @Nonnull ItemStack cooler) {
PlayerProfile.getBackpack(cooler, backpack -> {
if (backpack != null) {
Slimefun.runSync(() -> consumeJuice(p, backpack));
SlimefunPlugin.runSync(() -> consumeJuice(p, backpack));
}
});
}

View File

@ -15,13 +15,14 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
final class GrapplingHookEntity {
private final boolean dropItem;
private final boolean wasConsumed;
private final Arrow arrow;
private final Entity leashTarget;
@ParametersAreNonnullByDefault
GrapplingHookEntity(Player p, Arrow arrow, Entity leashTarget, boolean dropItem) {
GrapplingHookEntity(Player p, Arrow arrow, Entity leashTarget, boolean dropItem, boolean wasConsumed) {
this.arrow = arrow;
this.wasConsumed = wasConsumed;
this.leashTarget = leashTarget;
this.dropItem = p.getGameMode() != GameMode.CREATIVE && dropItem;
}
@ -33,8 +34,11 @@ final class GrapplingHookEntity {
public void drop(@Nonnull Location l) {
if (dropItem) {
Item item = l.getWorld().dropItem(l, SlimefunItems.GRAPPLING_HOOK.clone());
item.setPickupDelay(16);
//If a grappling hook was consumed, then the below if statement will be executed and will drop one grappling hook on the floor
if (wasConsumed) {
Item item = l.getWorld().dropItem(l, SlimefunItems.GRAPPLING_HOOK.clone());
item.setPickupDelay(16);
}
}
}

View File

@ -28,7 +28,6 @@ import org.bukkit.util.Vector;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.GrapplingHook;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for the mechanics behind the {@link GrapplingHook}.
@ -74,7 +73,7 @@ public class GrapplingHookListener implements Listener {
return;
}
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (e.getEntity() instanceof Arrow) {
handleGrapplingHook((Arrow) e.getEntity());
}
@ -174,7 +173,7 @@ public class GrapplingHookListener implements Listener {
p.setVelocity(velocity);
hook.remove();
Slimefun.runSync(() -> activeHooks.remove(p.getUniqueId()), 20L);
SlimefunPlugin.runSync(() -> activeHooks.remove(p.getUniqueId()), 20L);
}
}
}
@ -184,21 +183,21 @@ public class GrapplingHookListener implements Listener {
}
@ParametersAreNonnullByDefault
public void addGrapplingHook(Player p, Arrow arrow, Bat bat, boolean dropItem, long despawnTicks) {
GrapplingHookEntity hook = new GrapplingHookEntity(p, arrow, bat, dropItem);
public void addGrapplingHook(Player p, Arrow arrow, Bat bat, boolean dropItem, long despawnTicks, boolean wasConsumed) {
GrapplingHookEntity hook = new GrapplingHookEntity(p, arrow, bat, dropItem, wasConsumed);
UUID uuid = p.getUniqueId();
activeHooks.put(uuid, hook);
// To fix issue #253
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
GrapplingHookEntity entity = activeHooks.get(uuid);
if (entity != null) {
SlimefunPlugin.getBowListener().getProjectileData().remove(uuid);
entity.remove();
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
activeHooks.remove(uuid);
invulnerability.remove(uuid);
}, 20L);

View File

@ -21,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.core.handlers.BowShootHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.SlimefunBow;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for tracking {@link Arrow Arrows} fired from a
@ -64,7 +63,7 @@ public class SlimefunBowListener implements Listener {
@EventHandler
public void onArrowHit(ProjectileHitEvent e) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
if (e.getEntity().isValid() && e.getEntity() instanceof Arrow) {
projectiles.remove(e.getEntity().getUniqueId());
}

View File

@ -45,7 +45,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public class TalismanListener implements Listener {
@ -133,11 +132,19 @@ public class TalismanListener implements Listener {
LivingEntity entity = e.getEntity();
if (!(entity instanceof Player) && !(entity instanceof ArmorStand) && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) {
if (entity instanceof Player || entity instanceof ArmorStand) {
// We absolutely don't want to double the
// drops from players or ArmorStands
return;
}
// We are also excluding entities which can pickup items, this is not perfect
// but it at least prevents dupes by tossing items to zombies
if (!entity.getCanPickupItems() && Talisman.checkFor(e, SlimefunItems.TALISMAN_HUNTER)) {
Collection<ItemStack> extraDrops = getExtraDrops(e.getEntity(), e.getDrops());
for (ItemStack drop : extraDrops) {
if (drop != null) {
if (drop != null && drop.getType() != Material.AIR) {
e.getDrops().add(drop.clone());
}
}
@ -163,7 +170,10 @@ public class TalismanListener implements Listener {
}
}
// Prevent duplication of handheld items or armor
// WARNING: This check is broken as entities now set their
// equipment to NULL before calling the event!
// Prevents duplication of handheld items or armor
EntityEquipment equipment = entity.getEquipment();
if (equipment != null) {
for (ItemStack item : equipment.getArmorContents()) {
@ -205,7 +215,7 @@ public class TalismanListener implements Listener {
int itemSlot = slot;
// Update the item forcefully
Slimefun.runSync(() -> inv.setItem(itemSlot, item), 1L);
SlimefunPlugin.runSync(() -> inv.setItem(itemSlot, item), 1L);
}
}

View File

@ -104,7 +104,7 @@ public final class PostSetup {
sender.sendMessage(ChatColor.GREEN + " - Wiki: https://github.com/Slimefun/Slimefun4/wiki");
sender.sendMessage(ChatColor.GREEN + " - Addons: https://github.com/Slimefun/Slimefun4/wiki/Addons");
sender.sendMessage(ChatColor.GREEN + " - Bug Reports: https://github.com/Slimefun/Slimefun4/issues");
sender.sendMessage(ChatColor.GREEN + " - Discord: https://discord.gg/fsD4Bkh");
sender.sendMessage(ChatColor.GREEN + " - Discord: https://discord.gg/slimefun");
}
else {
sender.sendMessage(ChatColor.GREEN + " - UNOFFICIALLY MODIFIED BUILD - NO OFFICIAL SUPPORT GIVEN");

View File

@ -274,6 +274,7 @@ public final class ResearchSetup {
register("shulker_shell", 263, "Synthetic Shulkers", 30, SlimefunItems.SYNTHETIC_SHULKER_SHELL);
register("villager_rune", 264, "Reset Villager Trades", 26, SlimefunItems.VILLAGER_RUNE, SlimefunItems.STRANGE_NETHER_GOO);
register("climbing_pick", 265, "Block Raider", 20, SlimefunItems.CLIMBING_PICK);
register("even_higher_tier_capacitors", 266, "Tier 3 Capacitors", 40, SlimefunItems.ENERGIZED_CAPACITOR);
}
private static void register(String key, int id, String name, int defaultCost, ItemStack... items) {

View File

@ -1524,6 +1524,10 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.CARBONADO, SlimefunItems.REDSTONE_ALLOY, SlimefunItems.CARBONADO, new ItemStack(Material.REDSTONE), SlimefunItems.LARGE_CAPACITOR, new ItemStack(Material.REDSTONE), SlimefunItems.CARBONADO, SlimefunItems.REDSTONE_ALLOY, SlimefunItems.CARBONADO})
.register(plugin);
new Capacitor(categories.electricity, 524288, SlimefunItems.ENERGIZED_CAPACITOR, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.CARBONADO, SlimefunItems.REDSTONE_ALLOY, SlimefunItems.CARBONADO, new ItemStack(Material.NETHER_STAR), SlimefunItems.CARBONADO_EDGED_CAPACITOR, new ItemStack(Material.NETHER_STAR), SlimefunItems.CARBONADO, SlimefunItems.REDSTONE_ALLOY, SlimefunItems.CARBONADO})
.register(plugin);
new SolarGenerator(categories.electricity, 2, 0, SlimefunItems.SOLAR_GENERATOR, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.SOLAR_PANEL, SlimefunItems.SOLAR_PANEL, SlimefunItems.SOLAR_PANEL, SlimefunItems.ALUMINUM_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.ALUMINUM_INGOT, null, SlimefunItems.ALUMINUM_INGOT, null})
.register(plugin);

View File

@ -27,7 +27,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.AncientAltarListener;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link AncientAltarTask} is responsible for the animation that happens when a ritual
@ -103,7 +102,7 @@ public class AncientAltarTask implements Runnable {
}
this.stage += 1;
Slimefun.runSync(this, speed);
SlimefunPlugin.runSync(this, speed);
}
private boolean checkLockedItems() {

View File

@ -112,7 +112,7 @@ public class ArmorTask implements Runnable {
}
if (item != null && armorpiece.getItem().isPresent()) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
SlimefunArmorPiece slimefunArmor = armorpiece.getItem().get();
if (Slimefun.hasUnlocked(p, slimefunArmor, true)) {
@ -172,7 +172,7 @@ public class ArmorTask implements Runnable {
// If the item is enabled in the world, then make radioactivity do its job
SlimefunPlugin.getLocalization().sendMessage(p, "messages.radiation");
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
p.addPotionEffects(radiationEffects);
// if radiative fire is enabled

View File

@ -38,6 +38,9 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/
public class TickerTask implements Runnable {
// This Map holds all currently actively ticking locations
private final Map<String, Set<Location>> activeTickers = new ConcurrentHashMap<>();
// These are "Queues" of blocks that need to be removed or moved
private final Map<Location, Location> movingQueue = new ConcurrentHashMap<>();
private final Map<Location, Boolean> deletionQueue = new ConcurrentHashMap<>();
@ -90,8 +93,8 @@ public class TickerTask implements Runnable {
}
if (!halted) {
for (String chunk : BlockStorage.getTickingChunks()) {
tickChunk(tickers, chunk);
for (Map.Entry<String, Set<Location>> entry : activeTickers.entrySet()) {
tickChunk(tickers, entry.getKey(), entry.getValue());
}
}
@ -116,9 +119,9 @@ public class TickerTask implements Runnable {
}
}
private void tickChunk(@Nonnull Set<BlockTicker> tickers, @Nonnull String chunk) {
@ParametersAreNonnullByDefault
private void tickChunk(Set<BlockTicker> tickers, String chunk, Set<Location> locations) {
try {
Set<Location> locations = BlockStorage.getTickingLocations(chunk);
String[] components = PatternUtils.SEMICOLON.split(chunk);
World world = Bukkit.getWorld(components[0]);
@ -147,7 +150,7 @@ public class TickerTask implements Runnable {
item.getBlockTicker().update();
// We are inserting a new timestamp because synchronized
// actions are always ran with a 50ms delay (1 game tick)
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
Block b = l.getBlock();
tickBlock(l, b, item, data, System.nanoTime());
});
@ -223,13 +226,24 @@ public class TickerTask implements Runnable {
deletionQueue.put(l, destroy);
}
/**
* This returns the delay between ticks
*
* @return The tick delay
*/
public int getTickRate() {
return tickRate;
}
@Override
public String toString() {
return "TickerTask {\n" + " HALTED = " + halted + "\n" + " move = " + movingQueue + "\n" + " delete = " + deletionQueue + "}";
/**
* This method returns the {@link Map} of actively ticking locations according to
* their chunk id.
*
* @return The {@link Map} of active tickers
*/
@Nonnull
public Map<String, Set<Location>> getActiveTickers() {
return activeTickers;
}
}

View File

@ -31,6 +31,7 @@ public final class FireworkUtils {
createFirework(l, color);
}
@Nonnull
public static Firework createFirework(@Nonnull Location l, @Nonnull Color color) {
Firework fw = (Firework) l.getWorld().spawnEntity(l, EntityType.FIREWORK);
FireworkMeta meta = fw.getFireworkMeta();
@ -56,10 +57,12 @@ public final class FireworkUtils {
}
}
@Nonnull
public static FireworkEffect getRandomEffect(@Nonnull Random random, @Nonnull Color color) {
return FireworkEffect.builder().flicker(random.nextBoolean()).withColor(color).with(random.nextBoolean() ? Type.BALL : Type.BALL_LARGE).trail(random.nextBoolean()).build();
}
@Nonnull
private static Color getRandomColor() {
return COLORS[ThreadLocalRandom.current().nextInt(COLORS.length)];
}

View File

@ -36,7 +36,6 @@ import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.EmeraldEnchants.EmeraldEnchants;
import me.mrCookieSlime.EmeraldEnchants.ItemEnchantment;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -351,7 +350,7 @@ public final class SlimefunUtils {
Validate.notNull(l, "Cannot update a texture for null");
Validate.isTrue(capacity > 0, "Capacity must be greater than zero!");
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
Block b = l.getBlock();
if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.PLAYER_WALL_HEAD) {

View File

@ -8,7 +8,7 @@ import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
public final class ReactorHologram {
@ -35,7 +35,7 @@ public final class ReactorHologram {
}
public static void update(@Nonnull Location l, @Nonnull String name) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = getArmorStand(l, true);
if (!hologram.isCustomNameVisible()) {

View File

@ -10,7 +10,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
/**
* This utility class provides a few static methods for modifying a simple Text-based Hologram.
@ -23,14 +23,14 @@ public final class SimpleHologram {
private SimpleHologram() {}
public static void update(@Nonnull Block b, @Nonnull String name) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = getArmorStand(b, true);
hologram.setCustomName(ChatColors.color(name));
});
}
public static void remove(@Nonnull Block b) {
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
ArmorStand hologram = getArmorStand(b, false);
if (hologram != null) {

View File

@ -5,7 +5,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncMachineProcessCompleteEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -16,6 +15,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncMachineProcessCompleteEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
@ -253,7 +253,7 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
inv.pushItem(output.clone(), getOutputSlots());
}
Bukkit.getPluginManager().callEvent(new AsyncMachineProcessCompleteEvent(b, getProcessing(b)));
Bukkit.getPluginManager().callEvent(new AsyncMachineProcessCompleteEvent(b.getLocation(), AContainer.this, getProcessing(b)));
progress.remove(b);
processing.remove(b);

View File

@ -3,6 +3,7 @@ package me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -12,6 +13,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.AsyncGeneratorProcessCompleteEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.AbstractEnergyProvider;
@ -163,6 +165,8 @@ public abstract class AGenerator extends AbstractEnergyProvider {
inv.replaceExistingItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "));
Bukkit.getPluginManager().callEvent(new AsyncGeneratorProcessCompleteEvent(l, AGenerator.this, getProcessing(l)));
progress.remove(l);
processing.remove(l);
return 0;

View File

@ -15,6 +15,10 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@ -56,11 +60,11 @@ public class BlockStorage {
private static int chunkChanges = 0;
private int changes = 0;
public static BlockStorage getStorage(World world) {
public static BlockStorage getStorage(@Nonnull World world) {
return SlimefunPlugin.getRegistry().getWorlds().get(world.getName());
}
public static BlockStorage getForcedStorage(World world) {
public static BlockStorage getForcedStorage(@Nonnull World world) {
return isWorldRegistered(world.getName()) ? SlimefunPlugin.getRegistry().getWorlds().get(world.getName()) : new BlockStorage(world);
}
@ -196,13 +200,9 @@ public class BlockStorage {
storage.put(l, blockInfo);
if (SlimefunPlugin.getRegistry().getTickerBlocks().contains(file.getName().replace(".sfb", ""))) {
Set<Location> locations = SlimefunPlugin.getRegistry().getActiveTickers().getOrDefault(chunkString, new HashSet<>());
Map<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> locations = tickers.computeIfAbsent(chunkString, id -> new HashSet<>());
locations.add(l);
SlimefunPlugin.getRegistry().getActiveTickers().put(chunkString, locations);
if (!SlimefunPlugin.getRegistry().getActiveChunks().contains(chunkString)) {
SlimefunPlugin.getRegistry().getActiveChunks().add(chunkString);
}
}
}
}
@ -377,22 +377,22 @@ public class BlockStorage {
/**
* Retrieves the SlimefunItem's ItemStack from the specified Block.
* If the specified Block is registered in BlockStorage, its data will be erased from it, regardless of the returned
* value.
* If the specified Block is registered in BlockStorage,
* its data will be erased from it, regardless of the returned value.
*
* @param block
* the block to retrieve the ItemStack from
*
* @return the SlimefunItem's ItemStack corresponding to the block if it has one, otherwise null
*
* @since 4.0
*/
@Nullable
public static ItemStack retrieve(Block block) {
if (!hasBlockInfo(block)) {
return null;
}
else {
SlimefunItem item = SlimefunItem.getByID(getLocationInfo(block.getLocation(), "id"));
String id = getLocationInfo(block.getLocation(), "id");
SlimefunItem item = SlimefunItem.getByID(id);
clearBlockInfo(block);
if (item == null) {
@ -404,6 +404,7 @@ public class BlockStorage {
}
}
@Nonnull
public static Config getLocationInfo(Location l) {
BlockStorage storage = getStorage(l.getWorld());
@ -415,6 +416,7 @@ public class BlockStorage {
return cfg == null ? emptyBlockData : cfg;
}
@Nonnull
private static Map<String, String> parseJSON(String json) {
Map<String, String> map = new HashMap<>();
@ -608,22 +610,20 @@ public class BlockStorage {
}
String chunkString = locationToChunkString(l);
Map<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> locations = tickers.get(chunkString);
if (SlimefunPlugin.getRegistry().getActiveTickers().containsKey(chunkString)) {
Set<Location> locations = SlimefunPlugin.getRegistry().getActiveTickers().get(chunkString);
if (locations != null) {
locations.remove(l);
if (locations.isEmpty()) {
SlimefunPlugin.getRegistry().getActiveTickers().remove(chunkString);
SlimefunPlugin.getRegistry().getActiveChunks().remove(chunkString);
}
else {
SlimefunPlugin.getRegistry().getActiveTickers().put(chunkString, locations);
tickers.remove(chunkString);
}
}
}
}
@ParametersAreNonnullByDefault
public static void moveBlockInfo(Location from, Location to) {
SlimefunPlugin.getTickerTask().queueMove(from, to);
}
@ -637,6 +637,7 @@ public class BlockStorage {
* @param to
* The destination {@link Location}
*/
@ParametersAreNonnullByDefault
public static void moveLocationInfoUnsafely(Location from, Location to) {
if (!hasBlockInfo(from)) {
return;
@ -657,17 +658,14 @@ public class BlockStorage {
storage.storage.remove(from);
String chunkString = locationToChunkString(from);
Map<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> locations = tickers.get(chunkString);
if (SlimefunPlugin.getRegistry().getActiveTickers().containsKey(chunkString)) {
Set<Location> locations = SlimefunPlugin.getRegistry().getActiveTickers().get(chunkString);
if (locations != null) {
locations.remove(from);
if (locations.isEmpty()) {
SlimefunPlugin.getRegistry().getActiveTickers().remove(chunkString);
SlimefunPlugin.getRegistry().getActiveChunks().remove(chunkString);
}
else {
SlimefunPlugin.getRegistry().getActiveTickers().put(chunkString, locations);
tickers.remove(chunkString);
}
}
}
@ -689,10 +687,9 @@ public class BlockStorage {
String chunkString = locationToChunkString(l);
if (value != null) {
Set<Location> locations = SlimefunPlugin.getRegistry().getActiveTickers().computeIfAbsent(chunkString, c -> new HashSet<>());
Map<String, Set<Location>> tickers = SlimefunPlugin.getTickerTask().getActiveTickers();
Set<Location> locations = tickers.computeIfAbsent(chunkString, id -> new HashSet<>());
locations.add(l);
SlimefunPlugin.getRegistry().getActiveChunks().add(chunkString);
}
}
}
@ -754,14 +751,6 @@ public class BlockStorage {
return SlimefunPlugin.getRegistry().getWorlds().containsKey(name);
}
public static Set<String> getTickingChunks() {
return SlimefunPlugin.getRegistry().getActiveChunks();
}
public static Set<Location> getTickingLocations(String chunk) {
return SlimefunPlugin.getRegistry().getActiveTickers().getOrDefault(chunk, new HashSet<>());
}
public BlockMenu loadInventory(Location l, BlockMenuPreset preset) {
if (preset == null) {
return null;
@ -799,7 +788,7 @@ public class BlockStorage {
for (HumanEntity human : new ArrayList<>(menu.toInventory().getViewers())) {
// Prevents "java.lang.IllegalStateException: Asynchronous entity add!"
// when closing the inventory while holding an item
Slimefun.runSync(human::closeInventory);
SlimefunPlugin.runSync(human::closeInventory);
}
inventories.get(l).delete(l);

View File

@ -3,12 +3,11 @@ package me.mrCookieSlime.Slimefun.api;
import java.util.Optional;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import javax.annotation.Nonnull;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -26,6 +25,7 @@ public final class Slimefun {
private Slimefun() {}
@Nonnull
public static Logger getLogger() {
return SlimefunPlugin.instance().getLogger();
}
@ -180,30 +180,4 @@ public final class Slimefun {
}
return true;
}
public static BukkitTask runSync(Runnable r) {
if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
r.run();
return null;
}
if (SlimefunPlugin.instance() == null || !SlimefunPlugin.instance().isEnabled()) {
return null;
}
return Bukkit.getScheduler().runTask(SlimefunPlugin.instance(), r);
}
public static BukkitTask runSync(Runnable r, long delay) {
if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
r.run();
return null;
}
if (SlimefunPlugin.instance() == null || !SlimefunPlugin.instance().isEnabled()) {
return null;
}
return Bukkit.getScheduler().runTaskLater(SlimefunPlugin.instance(), r, delay);
}
}

View File

@ -243,16 +243,6 @@ public class SlimefunItemStack extends CustomItem {
locked = true;
}
@Override
public ItemStack clone() {
return new SlimefunItemStack(id, this);
}
@Override
public String toString() {
return "SlimefunItemStack (" + id + (getAmount() > 1 ? (" x " + getAmount()) : "") + ')';
}
@Nonnull
public Optional<String> getSkullTexture() {
return Optional.ofNullable(texture);
@ -292,4 +282,26 @@ public class SlimefunItemStack extends CustomItem {
throw new IllegalArgumentException("The provided texture for Item \"" + id + "\" does not seem to be a valid texture String!");
}
}
@Override
public ItemStack clone() {
return new SlimefunItemStack(id, this);
}
@Override
public String toString() {
return "SlimefunItemStack (" + id + (getAmount() > 1 ? (" x " + getAmount()) : "") + ')';
}
@Override
public final boolean equals(Object obj) {
// We don't want people to override this, it should use the super method
return super.equals(obj);
}
@Override
public final int hashCode() {
// We don't want people to override this, it should use the super method
return super.hashCode();
}
}

View File

@ -3,17 +3,20 @@ package me.mrCookieSlime.Slimefun.api.inventory;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
public abstract class BlockMenuPreset extends ChestMenu {
@ -30,13 +33,15 @@ public abstract class BlockMenuPreset extends ChestMenu {
private ItemManipulationEvent event;
public BlockMenuPreset(String id, String title) {
public BlockMenuPreset(@Nonnull String id, @Nonnull String title) {
this(id, title, false);
}
public BlockMenuPreset(String id, String title, boolean universal) {
public BlockMenuPreset(@Nonnull String id, @Nonnull String title, boolean universal) {
super(title);
Validate.notNull(id, "You need to specify an id!");
this.id = id;
this.inventoryTitle = title;
this.universal = universal;
@ -53,15 +58,57 @@ public abstract class BlockMenuPreset extends ChestMenu {
public abstract void init();
public abstract boolean canOpen(Block b, Player p);
/**
* This method returns whether a given {@link Player} is allowed to open the
* {@link BlockMenu} of that {@link Block}.
* Override this as necessary.
*
* @param b
* The {@link Block} trying to be opened
* @param p
* The {@link Player} who wants to open the {@link BlockMenu}
*
* @return Whether that {@link Player} is allowed
*/
public abstract boolean canOpen(@Nonnull Block b, @Nonnull Player p);
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;
}
public void newInstance(BlockMenu menu, Block b) {
/**
* This method is called whenever an {@link ItemStack} changes.
* You can override this as necessary if you need to listen to these events
*
* @param menu
* The {@link Inventory} affected by this
* @param slot
* The affected slot
* @param previous
* The {@link ItemStack} in that slot before the operation
* @param next
* The {@link ItemStack} that it changes to
*
* @return The new outcome of this operation
*/
@Nullable
protected ItemStack onItemStackChange(@Nonnull DirtyChestMenu menu, int slot, @Nullable ItemStack previous, @Nullable ItemStack next) {
// Override this as necessary
return next;
}
public void newInstance(@Nonnull BlockMenu menu, @Nonnull Block b) {
// This method can optionally be overridden by implementations
}
@ -76,7 +123,7 @@ public abstract class BlockMenuPreset extends ChestMenu {
}
@Override
public ChestMenu addItem(int slot, ItemStack item) {
public ChestMenu addItem(int slot, @Nullable ItemStack item) {
checkIfLocked();
occupiedSlots.add(slot);
@ -89,6 +136,7 @@ public abstract class BlockMenuPreset extends ChestMenu {
return super.addMenuClickHandler(slot, handler);
}
@Nonnull
public ChestMenu setSize(int size) {
checkIfLocked();
@ -134,10 +182,12 @@ public abstract class BlockMenuPreset extends ChestMenu {
return universal;
}
@Nonnull
public Set<Integer> getPresetSlots() {
return occupiedSlots;
}
@Nonnull
public Set<Integer> getInventorySlots() {
Set<Integer> emptySlots = new HashSet<>();
@ -159,7 +209,7 @@ public abstract class BlockMenuPreset extends ChestMenu {
return emptySlots;
}
protected void clone(DirtyChestMenu menu) {
protected void clone(@Nonnull DirtyChestMenu menu) {
menu.setPlayerInventoryClickable(true);
for (int slot : occupiedSlots) {
@ -186,10 +236,10 @@ public abstract class BlockMenuPreset extends ChestMenu {
menu.registerEvent(event);
}
public void newInstance(BlockMenu menu, Location l) {
public void newInstance(@Nonnull BlockMenu menu, @Nonnull Location l) {
Validate.notNull(l, "Cannot create a new BlockMenu without a Location");
Slimefun.runSync(() -> {
SlimefunPlugin.runSync(() -> {
locked = true;
try {
@ -207,6 +257,8 @@ public abstract class BlockMenuPreset extends ChestMenu {
*
* @return Our identifier
*/
@Nonnull
public String getID() {
return id;
}
@ -216,10 +268,13 @@ public abstract class BlockMenuPreset extends ChestMenu {
*
* @return The associated {@link SlimefunItem}
*/
@Nonnull
public SlimefunItem getSlimefunItem() {
return SlimefunItem.getByID(id);
}
@Nullable
public static BlockMenuPreset getPreset(String id) {
return id == null ? null : SlimefunPlugin.getRegistry().getMenuPresets().get(id);
}

View File

@ -2,6 +2,9 @@ package me.mrCookieSlime.Slimefun.api.inventory;
import java.util.ArrayList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.HumanEntity;
@ -21,7 +24,7 @@ public class DirtyChestMenu extends ChestMenu {
protected ItemManipulationEvent event;
protected int changes = 1;
public DirtyChestMenu(BlockMenuPreset preset) {
public DirtyChestMenu(@Nonnull BlockMenuPreset preset) {
super(preset.getTitle());
this.preset = preset;
@ -49,6 +52,7 @@ public class DirtyChestMenu extends ChestMenu {
return changes;
}
@Nonnull
public BlockMenuPreset getPreset() {
return preset;
}
@ -63,6 +67,15 @@ public class DirtyChestMenu extends ChestMenu {
}
}
/**
* 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;
}
@ -77,15 +90,23 @@ public class DirtyChestMenu extends ChestMenu {
}
}
public boolean fits(ItemStack item, int... slots) {
return InvUtils.fits(toInventory(), new ItemStackWrapper(item), slots);
public boolean fits(@Nonnull ItemStack item, int... slots) {
if (getItemInSlot(slots[0]) == null) {
// Very small optimization
return true;
}
else {
return InvUtils.fits(toInventory(), new ItemStackWrapper(item), slots);
}
}
@Nullable
public ItemStack pushItem(ItemStack item, int... slots) {
if (item == null || item.getType() == Material.AIR) {
throw new IllegalArgumentException("Cannot push null or AIR");
}
ItemStackWrapper wrapper = null;
int amount = item.getAmount();
for (int slot : slots) {
@ -99,9 +120,15 @@ public class DirtyChestMenu extends ChestMenu {
replaceExistingItem(slot, item);
return null;
}
else if (stack.getAmount() < stack.getMaxStackSize() && ItemUtils.canStack(item, stack)) {
amount -= (stack.getMaxStackSize() - stack.getAmount());
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize()));
else if (stack.getAmount() < stack.getMaxStackSize()) {
if (wrapper == null) {
wrapper = new ItemStackWrapper(item);
}
if (ItemUtils.canStack(wrapper, stack)) {
amount -= (stack.getMaxStackSize() - stack.getAmount());
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize()));
}
}
}
@ -132,9 +159,14 @@ public class DirtyChestMenu extends ChestMenu {
}
public void replaceExistingItem(int slot, ItemStack item, boolean event) {
if (event && this.event != null) {
if (event) {
ItemStack previous = getItemInSlot(slot);
item = this.event.onEvent(slot, previous, item);
if (this.event != null) {
item = this.event.onEvent(slot, previous, item);
}
item = preset.onItemStackChange(this, slot, previous, item);
}
super.replaceExistingItem(slot, item);

View File

@ -2,6 +2,13 @@ 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 {

View File

@ -144,6 +144,7 @@ slimefun:
hologram_projector: Holograms
capacitors: Tier 1 Capacitors
high_tier_capacitors: Tier 2 Capacitors
even_higher_tier_capacitors: Tier 3 Capacitors
solar_generators: Solar Power Plant
electric_furnaces: Powered Furnace
electric_ore_grinding: Crushing and Grinding

View File

@ -1,21 +1,5 @@
package io.github.thebusybiscuit.slimefun4.testing;
import static org.mockito.Mockito.when;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.junit.jupiter.api.Assertions;
import org.mockito.Mockito;
import be.seeseemelk.mockbukkit.ServerMock;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
@ -25,6 +9,21 @@ import io.github.thebusybiscuit.slimefun4.testing.mocks.MockSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.junit.jupiter.api.Assertions;
import org.mockito.Mockito;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.mockito.Mockito.when;
public final class TestUtilities {
@ -73,18 +72,60 @@ public final class TestUtilities {
public static void registerDefaultTags(ServerMock server) {
// We really don't need these to be accurate, just fill them with some examples
// that approximate the actual content
server.createMaterialTag(NamespacedKey.minecraft("logs"), Material.OAK_LOG, Material.STRIPPED_OAK_LOG, Material.OAK_WOOD, Material.STRIPPED_OAK_WOOD, Material.ACACIA_LOG, Material.STRIPPED_ACACIA_LOG, Material.ACACIA_WOOD, Material.STRIPPED_ACACIA_WOOD);
server.createMaterialTag(NamespacedKey.minecraft("wooden_trapdoors"), Material.OAK_TRAPDOOR, Material.BIRCH_TRAPDOOR, Material.SPRUCE_TRAPDOOR, Material.JUNGLE_TRAPDOOR, Material.ACACIA_TRAPDOOR, Material.DARK_OAK_TRAPDOOR);
server.createMaterialTag(NamespacedKey.minecraft("wooden_slabs"), Material.OAK_SLAB, Material.BIRCH_SLAB, Material.JUNGLE_SLAB, Material.SPRUCE_SLAB, Material.ACACIA_SLAB, Material.DARK_OAK_SLAB);
server.createMaterialTag(NamespacedKey.minecraft("wooden_fences"), Material.OAK_FENCE, Material.BIRCH_FENCE, Material.JUNGLE_FENCE, Material.SPRUCE_FENCE, Material.ACACIA_FENCE, Material.DARK_OAK_FENCE);
server.createMaterialTag(NamespacedKey.minecraft("planks"), Material.OAK_PLANKS, Material.BIRCH_PLANKS, Material.SPRUCE_PLANKS, Material.JUNGLE_PLANKS, Material.ACACIA_PLANKS, Material.DARK_OAK_PLANKS);
server.createMaterialTag(NamespacedKey.minecraft("small_flowers"), Material.POPPY, Material.DANDELION, Material.AZURE_BLUET, Material.LILY_OF_THE_VALLEY);
server.createMaterialTag(NamespacedKey.minecraft("leaves"), Material.OAK_LEAVES, Material.BIRCH_LEAVES, Material.SPRUCE_LEAVES, Material.JUNGLE_LEAVES, Material.ACACIA_LEAVES, Material.DARK_OAK_LEAVES);
server.createMaterialTag(NamespacedKey.minecraft("saplings"), Material.OAK_SAPLING, Material.BIRCH_SAPLING, Material.SPRUCE_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING);
server.createMaterialTag(NamespacedKey.minecraft("coral_blocks"), Material.BRAIN_CORAL_BLOCK, Material.BUBBLE_CORAL_BLOCK, Material.FIRE_CORAL_BLOCK, Material.HORN_CORAL_BLOCK, Material.TUBE_CORAL_BLOCK);
server.createMaterialTag(NamespacedKey.minecraft("corals"), Material.BRAIN_CORAL, Material.BUBBLE_CORAL, Material.FIRE_CORAL, Material.HORN_CORAL, Material.TUBE_CORAL);
server.createMaterialTag(NamespacedKey.minecraft("ice"), Material.ICE, Material.PACKED_ICE, Material.FROSTED_ICE, Material.BLUE_ICE);
server.createMaterialTag(NamespacedKey.minecraft("logs"), Material.OAK_LOG,
Material.STRIPPED_OAK_LOG, Material.OAK_WOOD, Material.STRIPPED_OAK_WOOD,
Material.ACACIA_LOG, Material.STRIPPED_ACACIA_LOG, Material.ACACIA_WOOD, Material.STRIPPED_ACACIA_WOOD
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_trapdoors"), Material.OAK_TRAPDOOR,
Material.BIRCH_TRAPDOOR, Material.SPRUCE_TRAPDOOR, Material.JUNGLE_TRAPDOOR,
Material.ACACIA_TRAPDOOR, Material.DARK_OAK_TRAPDOOR
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_slabs"), Material.OAK_SLAB, Material.BIRCH_SLAB,
Material.JUNGLE_SLAB, Material.SPRUCE_SLAB, Material.ACACIA_SLAB, Material.DARK_OAK_SLAB
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_fences"), Material.OAK_FENCE, Material.BIRCH_FENCE,
Material.JUNGLE_FENCE, Material.SPRUCE_FENCE, Material.ACACIA_FENCE, Material.DARK_OAK_FENCE
);
server.createMaterialTag(NamespacedKey.minecraft("planks"), Material.OAK_PLANKS, Material.BIRCH_PLANKS,
Material.SPRUCE_PLANKS, Material.JUNGLE_PLANKS, Material.ACACIA_PLANKS, Material.DARK_OAK_PLANKS
);
server.createMaterialTag(NamespacedKey.minecraft("small_flowers"), Material.POPPY, Material.DANDELION,
Material.AZURE_BLUET, Material.LILY_OF_THE_VALLEY
);
server.createMaterialTag(NamespacedKey.minecraft("leaves"), Material.OAK_LEAVES, Material.BIRCH_LEAVES,
Material.SPRUCE_LEAVES, Material.JUNGLE_LEAVES, Material.ACACIA_LEAVES, Material.DARK_OAK_LEAVES
);
server.createMaterialTag(NamespacedKey.minecraft("saplings"), Material.OAK_SAPLING, Material.BIRCH_SAPLING,
Material.SPRUCE_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING
);
server.createMaterialTag(NamespacedKey.minecraft("coral_blocks"), Material.BRAIN_CORAL_BLOCK,
Material.BUBBLE_CORAL_BLOCK, Material.FIRE_CORAL_BLOCK, Material.HORN_CORAL_BLOCK, Material.TUBE_CORAL_BLOCK
);
server.createMaterialTag(NamespacedKey.minecraft("corals"), Material.BRAIN_CORAL, Material.BUBBLE_CORAL,
Material.FIRE_CORAL, Material.HORN_CORAL, Material.TUBE_CORAL
);
server.createMaterialTag(NamespacedKey.minecraft("ice"), Material.ICE, Material.PACKED_ICE,
Material.FROSTED_ICE, Material.BLUE_ICE
);
server.createMaterialTag(NamespacedKey.minecraft("fire"), Material.FIRE, Material.SOUL_FIRE);
}
server.createMaterialTag(NamespacedKey.minecraft("boats"), Material.BIRCH_BOAT, Material.ACACIA_BOAT,
Material.DARK_OAK_BOAT, Material.JUNGLE_BOAT, Material.OAK_BOAT, Material.SPRUCE_BOAT
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_buttons"), Material.BIRCH_BUTTON,
Material.ACACIA_BUTTON, Material.SPRUCE_BUTTON, Material.DARK_OAK_BUTTON,
Material.JUNGLE_BOAT, Material.OAK_BUTTON
);
server.createMaterialTag(NamespacedKey.minecraft("signs"), Material.SPRUCE_SIGN, Material.ACACIA_SIGN,
Material.OAK_SIGN, Material.JUNGLE_SIGN, Material.DARK_OAK_SIGN, Material.BIRCH_SIGN
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_doors"), Material.SPRUCE_DOOR, Material.ACACIA_DOOR,
Material.OAK_DOOR, Material.JUNGLE_DOOR, Material.DARK_OAK_DOOR, Material.BIRCH_DOOR
);
server.createMaterialTag(NamespacedKey.minecraft("wooden_pressure_plates"), Material.SPRUCE_PRESSURE_PLATE,
Material.ACACIA_PRESSURE_PLATE, Material.OAK_PRESSURE_PLATE, Material.JUNGLE_PRESSURE_PLATE,
Material.DARK_OAK_PRESSURE_PLATE, Material.BIRCH_PRESSURE_PLATE
);
}
}
}

View File

@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -15,7 +16,7 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
public class TestWaypoints {
class TestWaypoints {
private static ServerMock server;
@ -31,7 +32,8 @@ public class TestWaypoints {
}
@Test
public void testAddWaypointToProfile() throws InterruptedException {
@DisplayName("Test Waypoints being added to the profile")
void testAddWaypointToProfile() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -48,7 +50,8 @@ public class TestWaypoints {
}
@Test
public void testRemoveWaypointFromProfile() throws InterruptedException {
@DisplayName("Test Waypoints being removed from the profile")
void testRemoveWaypointFromProfile() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -68,7 +71,8 @@ public class TestWaypoints {
}
@Test
public void testWaypointAlreadyExisting() throws InterruptedException {
@DisplayName("Verify that two waypoints cannot have the same name")
void testWaypointAlreadyExisting() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -81,7 +85,8 @@ public class TestWaypoints {
}
@Test
public void testTooManyWaypoints() throws InterruptedException {
@DisplayName("Verify that a maximum amount of waypoints is enforced")
void testTooManyWaypoints() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -95,7 +100,8 @@ public class TestWaypoints {
}
@Test
public void testWaypointEvent() throws InterruptedException {
@DisplayName("Verify that a WaypointCreateEvent is thrown")
void testWaypointEvent() throws InterruptedException {
GPSNetwork network = new GPSNetwork();
Player player = server.addPlayer();
TestUtilities.awaitProfile(player);
@ -105,7 +111,8 @@ public class TestWaypoints {
}
@Test
public void testWaypointComparison() throws InterruptedException {
@DisplayName("Test equal Waypoints being equal")
void testWaypointComparison() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
@ -121,7 +128,8 @@ public class TestWaypoints {
}
@Test
public void testIsDeathpoint() throws InterruptedException {
@DisplayName("Test Deathpoints being recognized as Deathpoints")
void testIsDeathpoint() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);

View File

@ -7,6 +7,7 @@ import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -19,7 +20,7 @@ import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestDietCookie implements SlimefunItemTest<DietCookie> {
class TestDietCookie implements SlimefunItemTest<DietCookie> {
private static ServerMock server;
private static SlimefunPlugin plugin;
@ -44,7 +45,8 @@ public class TestDietCookie implements SlimefunItemTest<DietCookie> {
}
@Test
public void testConsumptionBehaviour() {
@DisplayName("Test Diet Cookies giving Levitation Effect")
void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer();
DietCookie cookie = registerSlimefunItem(plugin, "TEST_DIET_COOKIE");

View File

@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -17,7 +18,7 @@ import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestMeatJerky implements SlimefunItemTest<MeatJerky> {
class TestMeatJerky implements SlimefunItemTest<MeatJerky> {
private static ServerMock server;
private static SlimefunPlugin plugin;
@ -42,7 +43,8 @@ public class TestMeatJerky implements SlimefunItemTest<MeatJerky> {
}
@Test
public void testConsumptionBehaviour() {
@DisplayName("Test Meat Jerky giving extra saturation")
void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer();
MeatJerky jerky = registerSlimefunItem(plugin, "TEST_MEAT_JERKY");
float saturation = player.getSaturation();

View File

@ -6,6 +6,7 @@ import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -18,7 +19,7 @@ import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestMonsterJerky implements SlimefunItemTest<MonsterJerky> {
class TestMonsterJerky implements SlimefunItemTest<MonsterJerky> {
private static ServerMock server;
private static SlimefunPlugin plugin;
@ -43,7 +44,8 @@ public class TestMonsterJerky implements SlimefunItemTest<MonsterJerky> {
}
@Test
public void testConsumptionBehaviour() {
@DisplayName("Test Monster Jerky giving Saturation and removing Hunger")
void testConsumptionBehaviour() {
PlayerMock player = server.addPlayer();
player.addPotionEffect(PotionEffectType.HUNGER.createEffect(20, 2));
MonsterJerky jerky = registerSlimefunItem(plugin, "TEST_MONSTER_JERKY");

View File

@ -0,0 +1,59 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.items.implementations.tools;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.PortableDustbin;
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
class TestPortableDustbin implements SlimefunItemTest<PortableDustbin> {
private static ServerMock server;
private static SlimefunPlugin plugin;
@BeforeAll
public static void load() {
server = MockBukkit.mock();
plugin = MockBukkit.load(SlimefunPlugin.class);
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@Override
public PortableDustbin registerSlimefunItem(SlimefunPlugin plugin, String id) {
SlimefunItemStack item = new SlimefunItemStack(id, Material.BUCKET, "&4Test Dustbin");
PortableDustbin dustbin = new PortableDustbin(TestUtilities.getCategory(plugin, "dustbin"), item, RecipeType.NULL, new ItemStack[9]);
dustbin.register(plugin);
return dustbin;
}
@Test
@DisplayName("Test Dustbin opening an empty Inventory")
void testRightClickBehaviour() {
Player player = server.addPlayer();
PortableDustbin dustbin = registerSlimefunItem(plugin, "TEST_PORTABLE_DUSTBIN");
simulateRightClick(player, dustbin);
// We expect an empty Inventory to be open now
Inventory openInventory = player.getOpenInventory().getTopInventory();
Assertions.assertTrue(openInventory.isEmpty());
}
}

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