mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-20 03:35:51 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
df0d36f4f7
6
.github/ISSUE_TEMPLATE/bug-report.md
vendored
6
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@ -48,6 +48,6 @@ assignees: ''
|
||||
<!-- Make sure that the screenshot covers the entire output of that command. -->
|
||||
<!-- If your issue is related to other plugins, make sure to include the versions of these plugins too! -->
|
||||
|
||||
- Server Software:
|
||||
- Minecraft Version:
|
||||
- Slimefun Version:
|
||||
- Server software:
|
||||
- Minecraft version:
|
||||
- Slimefun version:
|
||||
|
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,16 +1,20 @@
|
||||
## Description
|
||||
<!-- Please explain what you changed/added and why you did it in detail. -->
|
||||
<!-- Please explain why you are making this pull request. -->
|
||||
<!-- Start writing below this line -->
|
||||
|
||||
## Changes
|
||||
<!-- Please list all the changes you have made. -->
|
||||
## Proposed changes
|
||||
<!-- Please explain what changes you have made to the code. -->
|
||||
<!-- Start writing below this line -->
|
||||
|
||||
## Related Issues
|
||||
## Related Issues (if applicable)
|
||||
<!-- Please tag any Issues related to your Pull Request -->
|
||||
<!-- Syntax: "Resolves #000" -->
|
||||
<!-- Start writing below this line -->
|
||||
|
||||
## Checklist
|
||||
<!-- Here is a little checklist you should follow. -->
|
||||
<!-- You can click those check boxes after you posted your issue. -->
|
||||
<!-- Here is a little checklist you can follow. -->
|
||||
<!-- Click on these checkboxes after you created the pull request. -->
|
||||
<!-- Don't worry, these are not requirements. They only serve as guidance. -->
|
||||
- [ ] I have fully tested the proposed changes and promise that they will not break everything into chaos.
|
||||
- [ ] I have also tested the proposed changes in combination with various popular addons and can confirm my changes do not break them.
|
||||
- [ ] I followed the existing code standards and didn't mess up the formatting.
|
||||
|
3
.github/workflows/discord-webhook.yml
vendored
3
.github/workflows/discord-webhook.yml
vendored
@ -18,8 +18,9 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2.3.4
|
||||
- name: Set up Java JDK 11
|
||||
uses: actions/setup-java@v1.4.3
|
||||
uses: actions/setup-java@v2.0.0
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
java-package: jdk
|
||||
architecture: x64
|
||||
|
5
.github/workflows/maven-compiler.yml
vendored
5
.github/workflows/maven-compiler.yml
vendored
@ -24,8 +24,9 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@master
|
||||
uses: actions/setup-java@v2.0.0
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'adopt'
|
||||
java-version: '8'
|
||||
- name: Build with Maven
|
||||
run: mvn package --file pom.xml
|
||||
|
53
CHANGELOG.md
53
CHANGELOG.md
@ -1,5 +1,6 @@
|
||||
# Table of contents
|
||||
- [Release Candidate 22 (TBD)](#release-candidate-22-tbd)
|
||||
- [Release Candidate 23 (TBD)](#release-candidate-23-tbd)
|
||||
- [Release Candidate 22 (18 Apr 2021)](#release-candidate-22-18-apr-2021)
|
||||
- [Release Candidate 21 (14 Mar 2021)](#release-candidate-21-14-mar-2021)
|
||||
- [Release Candidate 20 (30 Jan 2021)](#release-candidate-20-30-jan-2021)
|
||||
- [Release Candidate 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021)
|
||||
@ -22,15 +23,46 @@
|
||||
- [Release Candidate 2 (29 Sep 2019)](#release-candidate-2-29-sep-2019)
|
||||
- [Release Candidate 1 (26 Sep 2019)](#release-candidate-1-26-sep-2019)
|
||||
|
||||
## Release Candidate 22 (TBD)
|
||||
## Release Candidate 23 (TBD)
|
||||
|
||||
#### Additions
|
||||
* Added Vanilla Auto Crafter
|
||||
* Added Enhanced Auto Crafter
|
||||
* Added "Quartz Block -> 4 Quartz" recipe to Grind Stone
|
||||
|
||||
#### Changes
|
||||
* Renamed "Solar Panel" to "Photovoltaic Cell" to avoid confusions with solar generators
|
||||
* Photovoltaic Cells can no longer be placed
|
||||
* (API) Removed deprecated "SlimefunBlockHandler"
|
||||
|
||||
#### Fixes
|
||||
|
||||
## Release Candidate 22 (18 Apr 2021)
|
||||
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#22
|
||||
|
||||
#### Additions
|
||||
* Added Vanilla Auto-Crafter
|
||||
* Added Enhanced Auto-Crafter
|
||||
* Added "Smart-Filling" mode to Cargo Input nodes
|
||||
* Added "Netherite Ingot -> Netherite Block" recipe to Electric Press
|
||||
* Added "Slimeballs -> Slime Block" recipe to Electric Press
|
||||
* Added Armor Forge Auto-Crafter
|
||||
* Auto-Crafters can now be turned on and off
|
||||
* Added Produce Collector to automate Milk and Mushroom Stew
|
||||
* Added a new message when constructing a Multiblock successfully
|
||||
* Added Crafting Motor
|
||||
* Block Placers can now place down cake
|
||||
* Added support for the "FunnyGuilds" plugin
|
||||
* Added "magma cream -> slime ball" recipe to the Freezer
|
||||
* Added "2 magma blocks -> slime block" recipe to the Freezer
|
||||
* Added configurable enchantment level limit for both auto enchanter and auto disenchanter
|
||||
* (API) Added AutoEnchantEvent
|
||||
|
||||
#### Changes
|
||||
* Changed item order in guide for the Villager Rune and Nether Goo (All runes are now grouped together)
|
||||
* Ancient Pedestals can now be found under "Magical Gadgets"
|
||||
* Removed all functionality from the old Automated Crafting Chamber
|
||||
* Changed Cargo Motor texture
|
||||
* Lowered "Magma block -> Sulfate" recipe to only require 1 magma block
|
||||
* Small performance improvements
|
||||
|
||||
#### Fixes
|
||||
* Fixed #1161
|
||||
@ -41,6 +73,19 @@
|
||||
* Fixed #2896
|
||||
* Fixed #2899
|
||||
* Fixed #2906
|
||||
* Fixed #2903
|
||||
* Fixed #2913
|
||||
* Fixed #2914
|
||||
* Fixed Auto-Crafters swallowing buckets when crafting cake
|
||||
* Fixed Multimeter not working on Auto-Crafters
|
||||
* Fixed #2650
|
||||
* Fixed Slimefun items applying damage to items with an `unbreakable` tag
|
||||
* Fixed #2930
|
||||
* Fixed #2926
|
||||
* Fixed Grappling Hook vanishing in creative mode
|
||||
* Fixed #2944
|
||||
* Fixed #2837
|
||||
* Fixed #2942
|
||||
|
||||
## Release Candidate 21 (14 Mar 2021)
|
||||
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#21
|
||||
|
@ -67,7 +67,7 @@ Well, we asked some users on our [Discord server](#discord) to send us some scre
|
||||
| *Screenshot provided by GalaxyKat11#3816* | *Screenshot provided by TamThan#7987* | *Screenshot provided by Kilaruna#4981* |
|
||||
|
||||
## Discord
|
||||
You can find Slimefun's community on Discord and connect with **over 4000** users of this plugin from all over the world.<br>
|
||||
You can find Slimefun's community on Discord and connect with **over 5000** users of this plugin from all over the world.<br>
|
||||
Click the badge down below to join the server for suggestions/questions or other discussions about this plugin.<br>
|
||||
We are also hosting a community event every so often, join us to find out more.<br>
|
||||
**Important**: We do **not** accept bug reports on discord, please use our [Issue Tracker](https://github.com/Slimefun/Slimefun4/issues) to submit bug reports!
|
||||
|
8
pom.xml
8
pom.xml
@ -341,13 +341,13 @@
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.seeseemelk</groupId>
|
||||
<artifactId>MockBukkit-v1.16</artifactId>
|
||||
<version>0.32.1</version>
|
||||
<version>0.33.0</version>
|
||||
<scope>test</scope>
|
||||
|
||||
<exclusions>
|
||||
@ -364,7 +364,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||
<artifactId>CS-CoreLib2</artifactId>
|
||||
<version>0.30.3</version>
|
||||
<version>0.30.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -420,7 +420,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.1.182</version>
|
||||
<version>2.1.194</version>
|
||||
<scope>provided</scope>
|
||||
|
||||
<exclusions>
|
||||
|
@ -50,6 +50,18 @@ public class ErrorReport<T extends Throwable> {
|
||||
private T throwable;
|
||||
private File file;
|
||||
|
||||
/**
|
||||
* This is the base constructor for an {@link ErrorReport}. It will only
|
||||
* print the necessary info and provides a {@link Consumer} for any more detailed
|
||||
* needs.
|
||||
*
|
||||
* @param throwable
|
||||
* The {@link Throwable} which caused this {@link ErrorReport}.
|
||||
* @param addon
|
||||
* The {@link SlimefunAddon} responsible.
|
||||
* @param printer
|
||||
* A custom {@link Consumer} to add more details.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public ErrorReport(T throwable, SlimefunAddon addon, Consumer<PrintStream> printer) {
|
||||
this.throwable = throwable;
|
||||
@ -58,6 +70,17 @@ public class ErrorReport<T extends Throwable> {
|
||||
SlimefunPlugin.runSync(() -> print(printer));
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructs a new {@link ErrorReport} for the given {@link Location} and
|
||||
* {@link SlimefunItem}.
|
||||
*
|
||||
* @param throwable
|
||||
* The {@link Throwable} which caused this {@link ErrorReport}.
|
||||
* @param l
|
||||
* The {@link Location} at which the error was thrown.
|
||||
* @param item
|
||||
* The {@link SlimefunItem} responsible.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public ErrorReport(T throwable, Location l, SlimefunItem item) {
|
||||
this(throwable, item.getAddon(), stream -> {
|
||||
@ -91,6 +114,14 @@ public class ErrorReport<T extends Throwable> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructs a new {@link ErrorReport} for the given {@link SlimefunItem}.
|
||||
*
|
||||
* @param throwable
|
||||
* The {@link Throwable} which caused this {@link ErrorReport}.
|
||||
* @param item
|
||||
* The {@link SlimefunItem} responsible.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public ErrorReport(T throwable, SlimefunItem item) {
|
||||
this(throwable, item.getAddon(), stream -> {
|
||||
|
@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.api.events;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@ -26,7 +27,7 @@ public class AsyncMachineProcessCompleteEvent extends Event {
|
||||
private final MachineRecipe machineRecipe;
|
||||
|
||||
public AsyncMachineProcessCompleteEvent(@Nonnull Location l, @Nullable AContainer container, @Nullable MachineRecipe machineRecipe) {
|
||||
super(true);
|
||||
super(!Bukkit.isPrimaryThread());
|
||||
|
||||
this.location = l;
|
||||
this.container = container;
|
||||
|
@ -15,6 +15,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines
|
||||
*
|
||||
* @author poma123
|
||||
*
|
||||
* @see AutoEnchantEvent
|
||||
*/
|
||||
public class AutoDisenchantEvent extends Event implements Cancellable {
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
package io.github.thebusybiscuit.slimefun4.api.events;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoEnchanter;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* An {@link Event} that is called whenever an {@link AutoEnchanter} is trying to enchant
|
||||
* an {@link ItemStack}.
|
||||
*
|
||||
* @author WalshyDev
|
||||
*
|
||||
* @see AutoDisenchantEvent
|
||||
*/
|
||||
public class AutoEnchantEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final ItemStack item;
|
||||
private boolean cancelled;
|
||||
|
||||
public AutoEnchantEvent(@Nonnull ItemStack item) {
|
||||
super(true);
|
||||
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the {@link ItemStack} that is being enchanted.
|
||||
*
|
||||
* @return The {@link ItemStack} that is being enchanted
|
||||
*/
|
||||
@Nonnull
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
}
|
@ -15,10 +15,12 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
|
||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
@ -47,6 +49,12 @@ public class ResourceManager {
|
||||
private final int[] backgroundSlots = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 17, 18, 26, 27, 35, 36, 44, 45, 46, 48, 49, 50, 52, 53 };
|
||||
private final Config config;
|
||||
|
||||
/**
|
||||
* This will create a new {@link ResourceManager}.
|
||||
*
|
||||
* @param plugin
|
||||
* Our {@link SlimefunPlugin} instance
|
||||
*/
|
||||
public ResourceManager(@Nonnull SlimefunPlugin plugin) {
|
||||
config = new Config(plugin, "resources.yml");
|
||||
}
|
||||
@ -95,6 +103,7 @@ public class ResourceManager {
|
||||
*
|
||||
* @return An {@link OptionalInt}, either empty or containing the amount of the given {@link GEOResource}
|
||||
*/
|
||||
@Nonnull
|
||||
public OptionalInt getSupplies(@Nonnull GEOResource resource, @Nonnull World world, int x, int z) {
|
||||
Validate.notNull(resource, "Cannot get supplies for null");
|
||||
Validate.notNull(world, "World must not be null");
|
||||
@ -109,6 +118,20 @@ public class ResourceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will set the supplies in a given {@link Chunk} to the specified value.
|
||||
*
|
||||
* @param resource
|
||||
* The {@link GEOResource}
|
||||
* @param world
|
||||
* The {@link World}
|
||||
* @param x
|
||||
* The x coordinate of that {@link Chunk}
|
||||
* @param z
|
||||
* The z coordinate of that {@link Chunk}
|
||||
* @param value
|
||||
* The new supply value
|
||||
*/
|
||||
public void setSupplies(@Nonnull GEOResource resource, @Nonnull World world, int x, int z, int value) {
|
||||
Validate.notNull(resource, "Cannot set supplies for null");
|
||||
Validate.notNull(world, "World cannot be null");
|
||||
@ -117,13 +140,42 @@ public class ResourceManager {
|
||||
BlockStorage.setChunkInfo(world, x, z, key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will generate the default supplies for a given {@link GEOResource} at the
|
||||
* given {@link Chunk}.
|
||||
* <p>
|
||||
* This method will invoke {@link #setSupplies(GEOResource, World, int, int, int)} and also calls a
|
||||
* {@link GEOResourceGenerationEvent}.
|
||||
*
|
||||
* @param resource
|
||||
* The {@link GEOResource} to generate
|
||||
* @param world
|
||||
* The {@link World}
|
||||
* @param x
|
||||
* The x coordinate of that {@link Chunk}
|
||||
* @param z
|
||||
* The z coordinate of that {@link Chunk}
|
||||
*
|
||||
* @return The new supply value
|
||||
*/
|
||||
private int generate(@Nonnull GEOResource resource, @Nonnull World world, int x, int z) {
|
||||
Validate.notNull(resource, "Cannot generate resources for null");
|
||||
Validate.notNull(world, "World cannot be null");
|
||||
|
||||
// Get the corresponding Block (and Biome)
|
||||
Block block = world.getBlockAt(x << 4, 72, z << 4);
|
||||
int value = resource.getDefaultSupply(world.getEnvironment(), block.getBiome());
|
||||
Biome biome = block.getBiome();
|
||||
|
||||
/*
|
||||
* getBiome() is marked as NotNull, but it seems like some servers ignore this entirely.
|
||||
* We have seen multiple reports on Tuinity where it has indeed returned null.
|
||||
*/
|
||||
Validate.notNull(biome, "Biome appears to be null for position: " + new BlockPosition(block));
|
||||
|
||||
// Make sure the value is not below zero.
|
||||
int value = Math.max(0, resource.getDefaultSupply(world.getEnvironment(), biome));
|
||||
|
||||
// Check if more than zero units are to be generated.
|
||||
if (value > 0) {
|
||||
int max = resource.getMaxDeviation();
|
||||
|
||||
@ -134,7 +186,8 @@ public class ResourceManager {
|
||||
value += ThreadLocalRandom.current().nextInt(max);
|
||||
}
|
||||
|
||||
GEOResourceGenerationEvent event = new GEOResourceGenerationEvent(world, block.getBiome(), x, z, resource, value);
|
||||
// Fire an event, so that plugins can modify this.
|
||||
GEOResourceGenerationEvent event = new GEOResourceGenerationEvent(world, biome, x, z, resource, value);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
value = event.getValue();
|
||||
|
||||
@ -166,7 +219,8 @@ public class ResourceManager {
|
||||
int x = block.getX() >> 4;
|
||||
int z = block.getZ() >> 4;
|
||||
|
||||
ChestMenu menu = new ChestMenu("&4" + SlimefunPlugin.getLocalization().getResourceString(p, "tooltips.results"));
|
||||
String title = "&4" + SlimefunPlugin.getLocalization().getResourceString(p, "tooltips.results");
|
||||
ChestMenu menu = new ChestMenu(title);
|
||||
|
||||
for (int slot : backgroundSlots) {
|
||||
menu.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
|
||||
|
@ -58,6 +58,13 @@ public class GPSNetwork {
|
||||
private final TeleportationManager teleportation = new TeleportationManager();
|
||||
private final ResourceManager resourceManager;
|
||||
|
||||
/**
|
||||
* This constructs a new {@link GPSNetwork}.
|
||||
* Note that this network is per {@link Server} and not per {@link Player}.
|
||||
*
|
||||
* @param plugin
|
||||
* Our {@link SlimefunPlugin} instance
|
||||
*/
|
||||
public GPSNetwork(@Nonnull SlimefunPlugin plugin) {
|
||||
resourceManager = new ResourceManager(plugin);
|
||||
}
|
||||
@ -125,6 +132,13 @@ public class GPSNetwork {
|
||||
return locations == null ? 0 : locations.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method opens the {@link GPSTransmitter} control panel to the given
|
||||
* {@link Player}.
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player}
|
||||
*/
|
||||
public void openTransmitterControlPanel(@Nonnull Player p) {
|
||||
ChestMenu menu = new ChestMenu(ChatColor.BLUE + SlimefunPlugin.getLocalization().getMessage(p, "machines.GPS_CONTROL_PANEL.title"));
|
||||
|
||||
|
@ -7,6 +7,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@ -34,53 +35,103 @@ public class Waypoint {
|
||||
private final String name;
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* This constructs a new {@link Waypoint} object.
|
||||
*
|
||||
* @param profile
|
||||
* The owning {@link PlayerProfile}
|
||||
* @param id
|
||||
* The unique id for this {@link Waypoint}
|
||||
* @param loc
|
||||
* The {@link Location} of the {@link Waypoint}
|
||||
* @param name
|
||||
* The name of this {@link Waypoint}
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public Waypoint(PlayerProfile profile, String id, Location l, String name) {
|
||||
public Waypoint(PlayerProfile profile, String id, Location loc, String name) {
|
||||
Validate.notNull(profile, "Profile must never be null!");
|
||||
Validate.notNull(id, "id must never be null!");
|
||||
Validate.notNull(l, "Location must never be null!");
|
||||
Validate.notNull(loc, "Location must never be null!");
|
||||
Validate.notNull(name, "Name must never be null!");
|
||||
|
||||
this.profile = profile;
|
||||
this.id = id;
|
||||
this.location = l;
|
||||
this.location = loc;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the owner of the {@link Waypoint}.
|
||||
*
|
||||
* @return The corresponding {@link PlayerProfile}
|
||||
*/
|
||||
@Nonnull
|
||||
public PlayerProfile getOwner() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the unique identifier for this {@link Waypoint}.
|
||||
*
|
||||
* @return The {@link Waypoint} id
|
||||
*/
|
||||
@Nonnull
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the name of this {@link Waypoint}.
|
||||
*
|
||||
* @return The name of this {@link Waypoint}
|
||||
*/
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the {@link Location} of this {@link Waypoint}
|
||||
*
|
||||
* @return The {@link Waypoint} {@link Location}
|
||||
*/
|
||||
@Nonnull
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns whether this {@link Waypoint} is a Deathpoint.
|
||||
*
|
||||
* @return Whether this is a Deathpoint
|
||||
*/
|
||||
public boolean isDeathpoint() {
|
||||
return name.startsWith("player:death ");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the {@link ItemStack} icon for this {@link Waypoint}.
|
||||
* The icon is dependent on the {@link Environment} the {@link Waypoint} is in
|
||||
* and whether it is a Deathpoint.
|
||||
*
|
||||
* @return The {@link ItemStack} icon for this {@link Waypoint}
|
||||
*/
|
||||
@Nonnull
|
||||
public ItemStack getIcon() {
|
||||
return SlimefunPlugin.getGPSNetwork().getIcon(name, location.getWorld().getEnvironment());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(profile.getUUID(), id, name, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Waypoint)) {
|
||||
|
@ -1,44 +0,0 @@
|
||||
package io.github.thebusybiscuit.slimefun4.api.items;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
|
||||
public interface ItemRestriction {
|
||||
|
||||
/**
|
||||
* This method represents a check.
|
||||
* The returned boolean will decide whether to allow the action.
|
||||
*
|
||||
* @param profile
|
||||
* The Player's profile
|
||||
* @param p
|
||||
* The Player itself
|
||||
* @param item
|
||||
* The SlimefunItem that the {@link ItemStack} represents
|
||||
* @param itemstack
|
||||
* The ItemStack that is being tested.
|
||||
*
|
||||
* @return Whether the action was allowed
|
||||
*/
|
||||
boolean isAllowed(PlayerProfile profile, Player p, SlimefunItem item, ItemStack itemstack);
|
||||
|
||||
/**
|
||||
* This method is executed if an ItemRestriction took affect.
|
||||
* Override it to send a message to the Player telling them they cannot
|
||||
* use that item, or do something else in there.
|
||||
*
|
||||
* @param profile
|
||||
* The Player's profile
|
||||
* @param p
|
||||
* The Player to warn
|
||||
* @param item
|
||||
* The SlimefunItem that the {@link ItemStack} represents
|
||||
* @param itemstack
|
||||
* The ItemStack that was prevented from being used
|
||||
*/
|
||||
void warnPlayer(PlayerProfile profile, Player p, SlimefunItem item, ItemStack itemstack);
|
||||
|
||||
}
|
@ -471,6 +471,8 @@ public class PlayerProfile {
|
||||
}
|
||||
|
||||
public boolean hasFullProtectionAgainst(@Nonnull ProtectionType type) {
|
||||
Validate.notNull(type, "ProtectionType must not be null.");
|
||||
|
||||
int armorCount = 0;
|
||||
NamespacedKey setId = null;
|
||||
|
||||
|
@ -36,7 +36,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockInfoConfig;
|
||||
@ -92,7 +91,6 @@ public final class SlimefunRegistry {
|
||||
private final Map<String, BlockMenuPreset> blockMenuPresets = new HashMap<>();
|
||||
private final Map<String, UniversalBlockMenu> universalInventories = new HashMap<>();
|
||||
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
|
||||
private final Map<String, SlimefunBlockHandler> blockHandlers = new HashMap<>();
|
||||
|
||||
public void load(@Nonnull SlimefunPlugin plugin, @Nonnull Config cfg) {
|
||||
Validate.notNull(plugin, "The Plugin cannot be null!");
|
||||
@ -333,12 +331,6 @@ public final class SlimefunRegistry {
|
||||
return globalItemHandlers;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Nonnull
|
||||
public Map<String, SlimefunBlockHandler> getBlockHandlers() {
|
||||
return blockHandlers;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, BlockStorage> getWorlds() {
|
||||
return worlds;
|
||||
|
@ -3,7 +3,7 @@ package io.github.thebusybiscuit.slimefun4.core.attributes;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.UnbreakingAlgorithm;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -22,7 +22,10 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
* option that decides whether or not this {@link SlimefunItem} shall be damageable.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @author RobotHanzo
|
||||
*
|
||||
* @see UnbreakingAlgorithm
|
||||
*
|
||||
*/
|
||||
public interface DamageableItem extends ItemAttribute {
|
||||
|
||||
@ -47,24 +50,43 @@ public interface DamageableItem extends ItemAttribute {
|
||||
* The {@link ItemStack} to damage
|
||||
*/
|
||||
default void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
|
||||
if (isDamageable() && item != null && item.getType() != Material.AIR && item.getAmount() > 0) {
|
||||
if (isDamageable() && item != null && !item.getType().isAir() && item.getAmount() > 0) {
|
||||
int unbreakingLevel = item.getEnchantmentLevel(Enchantment.DURABILITY);
|
||||
|
||||
if (unbreakingLevel > 0 && Math.random() * 100 <= (60 + Math.floorDiv(40, (unbreakingLevel + 1)))) {
|
||||
if (evaluateUnbreakingEnchantment(unbreakingLevel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
Damageable damageable = (Damageable) meta;
|
||||
|
||||
if (damageable.getDamage() >= item.getType().getMaxDurability()) {
|
||||
p.playSound(p.getEyeLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
|
||||
item.setAmount(0);
|
||||
} else {
|
||||
damageable.setDamage(damageable.getDamage() + 1);
|
||||
item.setItemMeta(meta);
|
||||
if (!meta.isUnbreakable()) {
|
||||
Damageable damageable = (Damageable) meta;
|
||||
|
||||
if (damageable.getDamage() >= item.getType().getMaxDurability()) {
|
||||
p.playSound(p.getEyeLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
|
||||
item.setAmount(0);
|
||||
} else {
|
||||
damageable.setDamage(damageable.getDamage() + 1);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will randomly decide if the item should be damaged or not
|
||||
* This does not damage the item, it is called by {@link #damageItem(Player, ItemStack)} to randomly generate a
|
||||
* boolean
|
||||
* This function should be overridden when the item type is not a tool which is the default value
|
||||
*
|
||||
* @param unbreakingLevel
|
||||
* The {@link Integer} level of the unbreaking {@link Enchantment}
|
||||
*
|
||||
* @return Whether to save the item from taking damage
|
||||
*
|
||||
*/
|
||||
default boolean evaluateUnbreakingEnchantment(int unbreakingLevel) {
|
||||
return UnbreakingAlgorithm.TOOLS.evaluate(unbreakingLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
@ -19,6 +20,7 @@ import io.github.thebusybiscuit.slimefun4.api.network.Network;
|
||||
import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
|
||||
/**
|
||||
@ -47,10 +49,12 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
protected final Map<Location, Integer> roundRobin = new HashMap<>();
|
||||
private int tickDelayThreshold = 0;
|
||||
|
||||
@Nullable
|
||||
public static CargoNet getNetworkFromLocation(@Nonnull Location l) {
|
||||
return SlimefunPlugin.getNetworkManager().getNetworkFromLocation(l, CargoNet.class).orElse(null);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CargoNet getNetworkFromLocationOrCreate(@Nonnull Location l) {
|
||||
Optional<CargoNet> cargoNetwork = SlimefunPlugin.getNetworkManager().getNetworkFromLocation(l, CargoNet.class);
|
||||
|
||||
@ -145,7 +149,7 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
}
|
||||
}
|
||||
|
||||
public void tick(Block b) {
|
||||
public void tick(@Nonnull Block b) {
|
||||
if (!regulator.equals(b.getLocation())) {
|
||||
updateHologram(b, "&4Multiple Cargo Regulators connected");
|
||||
return;
|
||||
@ -186,7 +190,8 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Location, Integer> mapInputNodes(Set<Location> chestTerminalNodes) {
|
||||
@Nonnull
|
||||
private Map<Location, Integer> mapInputNodes(@Nonnull Set<Location> chestTerminalNodes) {
|
||||
Map<Location, Integer> inputs = new HashMap<>();
|
||||
|
||||
for (Location node : inputNodes) {
|
||||
@ -202,7 +207,8 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
private Map<Integer, List<Location>> mapOutputNodes(Set<Location> chestTerminalOutputs) {
|
||||
@Nonnull
|
||||
private Map<Integer, List<Location>> mapOutputNodes(@Nonnull Set<Location> chestTerminalOutputs) {
|
||||
Map<Integer, List<Location>> output = new HashMap<>();
|
||||
|
||||
List<Location> list = new LinkedList<>();
|
||||
@ -241,7 +247,7 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
|
||||
/**
|
||||
* This method returns the frequency a given node is set to.
|
||||
* Should there be an {@link Exception} to this method it will fall back to zero in
|
||||
* Should there be invalid data this method it will fall back to zero in
|
||||
* order to preserve the integrity of the {@link CargoNet}.
|
||||
*
|
||||
* @param node
|
||||
@ -249,13 +255,16 @@ public class CargoNet extends AbstractItemNetwork implements HologramOwner {
|
||||
*
|
||||
* @return The frequency of the given node
|
||||
*/
|
||||
private static int getFrequency(Location node) {
|
||||
try {
|
||||
String str = BlockStorage.getLocationInfo(node).getString("frequency");
|
||||
return str == null ? 0 : Integer.parseInt(str);
|
||||
} catch (Exception x) {
|
||||
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while parsing a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + "," + node.getBlockY() + "," + +node.getBlockZ() + ")");
|
||||
private static int getFrequency(@Nonnull Location node) {
|
||||
String frequency = BlockStorage.getLocationInfo(node, "frequency");
|
||||
|
||||
if (frequency == null) {
|
||||
return 0;
|
||||
} else if (!PatternUtils.NUMERIC.matcher(frequency).matches()) {
|
||||
SlimefunPlugin.logger().log(Level.SEVERE, () -> "Failed to parse a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + ',' + node.getBlockY() + ',' + node.getBlockZ() + "): " + frequency);
|
||||
return 0;
|
||||
} else {
|
||||
return Integer.parseInt(frequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.networks.cargo;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -158,13 +160,24 @@ class CargoNetworkTask implements Runnable {
|
||||
private ItemStack distributeItem(ItemStack stack, Location inputNode, List<Location> outputNodes) {
|
||||
ItemStack item = stack;
|
||||
|
||||
Deque<Location> destinations = new LinkedList<>(outputNodes);
|
||||
Config cfg = BlockStorage.getLocationInfo(inputNode);
|
||||
boolean roundrobin = Objects.equals(cfg.getString("round-robin"), "true");
|
||||
boolean smartFill = Objects.equals(cfg.getString("smart-fill"), "true");
|
||||
|
||||
Collection<Location> destinations;
|
||||
if (roundrobin) {
|
||||
roundRobinSort(inputNode, destinations);
|
||||
// Use an ArrayDeque to perform round-robin sorting
|
||||
// Since the impl for roundRobinSort just does Deque.addLast(Deque#removeFirst)
|
||||
// An ArrayDequeue is preferable as opposed to a LinkedList:
|
||||
// - The number of elements does not change.
|
||||
// - ArrayDequeue has better iterative performance
|
||||
Deque<Location> tempDestinations = new ArrayDeque<>(outputNodes);
|
||||
roundRobinSort(inputNode, tempDestinations);
|
||||
destinations = tempDestinations;
|
||||
} else {
|
||||
// Using an ArrayList here since we won't need to sort the destinations
|
||||
// The ArrayList has the best performance for iteration bar a primitive array
|
||||
destinations = new ArrayList<>(outputNodes);
|
||||
}
|
||||
|
||||
for (Location output : destinations) {
|
||||
|
@ -292,6 +292,11 @@ final class CargoUtils {
|
||||
int maxStackSize = itemInSlot.getType().getMaxStackSize();
|
||||
int currentAmount = itemInSlot.getAmount();
|
||||
|
||||
if (!smartFill && currentAmount == maxStackSize) {
|
||||
// Skip full stacks - Performance optimization for non-smartfill nodes
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
|
||||
if (currentAmount < maxStackSize) {
|
||||
int amount = currentAmount + stack.getAmount();
|
||||
@ -339,11 +344,17 @@ final class CargoUtils {
|
||||
inv.setItem(slot, stack);
|
||||
return null;
|
||||
} else {
|
||||
int currentAmount = itemInSlot.getAmount();
|
||||
int maxStackSize = itemInSlot.getType().getMaxStackSize();
|
||||
|
||||
if (!smartFill && currentAmount == maxStackSize) {
|
||||
// Skip full stacks - Performance optimization for non-smartfill nodes
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
|
||||
if (itemInSlot.getAmount() < maxStackSize) {
|
||||
int amount = itemInSlot.getAmount() + stack.getAmount();
|
||||
if (currentAmount < maxStackSize) {
|
||||
int amount = currentAmount + stack.getAmount();
|
||||
|
||||
if (amount > maxStackSize) {
|
||||
stack.setAmount(amount - maxStackSize);
|
||||
|
@ -150,7 +150,7 @@ public class LocalizationService extends SlimefunLocalization {
|
||||
|
||||
@Override
|
||||
public Language getLanguage(@Nonnull Player p) {
|
||||
Validate.notNull("Player cannot be null!");
|
||||
Validate.notNull(p, "Player cannot be null!");
|
||||
|
||||
PersistentDataContainer container = p.getPersistentDataContainer();
|
||||
String language = container.get(languageKey, PersistentDataType.STRING);
|
||||
@ -253,7 +253,7 @@ public class LocalizationService extends SlimefunLocalization {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Set<String> getKeys(FileConfiguration... files) {
|
||||
private Set<String> getKeys(@Nonnull FileConfiguration... files) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
|
||||
for (FileConfiguration cfg : files) {
|
||||
|
@ -50,8 +50,11 @@ class ContributionsConnector extends GitHubConnector {
|
||||
* These people are... "special cases".
|
||||
*/
|
||||
private void loadConfiguration() {
|
||||
// Bots and invalid accounts we want to ignore.
|
||||
ignoredAccounts.add("invalid-email-address");
|
||||
ignoredAccounts.add("renovate");
|
||||
ignoredAccounts.add("renovate-bot");
|
||||
ignoredAccounts.add("renovate[bot]");
|
||||
ignoredAccounts.add("TheBusyBot");
|
||||
ignoredAccounts.add("ImgBotApp");
|
||||
ignoredAccounts.add("imgbot");
|
||||
@ -61,6 +64,7 @@ class ContributionsConnector extends GitHubConnector {
|
||||
ignoredAccounts.add("gitlocalize-app[bot]");
|
||||
ignoredAccounts.add("mt-gitlocalize");
|
||||
|
||||
// Known Minecraft aliases.
|
||||
aliases.put("WalshyDev", "HumanRightsAct");
|
||||
aliases.put("J3fftw1", "_lagpc_");
|
||||
aliases.put("ajan-12", "ajan_12");
|
||||
|
@ -13,6 +13,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||
import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
@ -78,10 +80,14 @@ public class GitHubService {
|
||||
* the usual methods.
|
||||
*/
|
||||
private void addDefaultContributors() {
|
||||
// Artists
|
||||
addContributor("Fuffles_", "&dArtist");
|
||||
addContributor("IMS_Art", "&dArtist");
|
||||
addContributor("IMS_Art", "https://github.com/IAmSorryArt", "&dArtist", 0);
|
||||
|
||||
// Addon Jam winners
|
||||
addContributor("nahkd123", "&aWinner of the 2020 Addon Jam");
|
||||
|
||||
// Translators
|
||||
new Translators(this);
|
||||
}
|
||||
|
||||
@ -94,6 +100,11 @@ public class GitHubService {
|
||||
|
||||
@Nonnull
|
||||
public Contributor addContributor(@Nonnull String minecraftName, @Nonnull String profileURL, @Nonnull String role, int commits) {
|
||||
Validate.notNull(minecraftName, "Minecraft username must not be null.");
|
||||
Validate.notNull(profileURL, "GitHub profile url must not be null.");
|
||||
Validate.notNull(role, "Role should not be null.");
|
||||
Validate.isTrue(commits >= 0, "Commit count cannot be negative.");;
|
||||
|
||||
String username = profileURL.substring(profileURL.lastIndexOf('/') + 1);
|
||||
|
||||
Contributor contributor = contributors.computeIfAbsent(username, key -> new Contributor(minecraftName, profileURL));
|
||||
@ -106,9 +117,10 @@ public class GitHubService {
|
||||
this.logging = logging;
|
||||
addDefaultContributors();
|
||||
|
||||
// TheBusyBiscuit/Slimefun4 (twice because there may me multiple pages)
|
||||
// TheBusyBiscuit/Slimefun4 (multiple times because there may me multiple pages)
|
||||
connectors.add(new ContributionsConnector(this, "code", 1, repository, "developer"));
|
||||
connectors.add(new ContributionsConnector(this, "code2", 2, repository, "developer"));
|
||||
connectors.add(new ContributionsConnector(this, "code3", 3, repository, "developer"));
|
||||
|
||||
// TheBusyBiscuit/Slimefun4-Wiki
|
||||
connectors.add(new ContributionsConnector(this, "wiki", 1, "Slimefun/Wiki", "wiki"));
|
||||
@ -122,6 +134,7 @@ public class GitHubService {
|
||||
this.pendingPullRequests = pullRequests;
|
||||
}));
|
||||
|
||||
// Forks, star count and last commit date
|
||||
connectors.add(new GitHubActivityConnector(this, repository, (forks, stars, date) -> {
|
||||
this.publicForks = forks;
|
||||
this.stargazers = stars;
|
||||
|
@ -160,8 +160,7 @@ public final class Language {
|
||||
*/
|
||||
@Nonnull
|
||||
public String getName(@Nonnull Player p) {
|
||||
String name = SlimefunPlugin.getLocalization().getMessage(p, "languages." + id);
|
||||
return name != null ? name : toString();
|
||||
return SlimefunPlugin.getLocalization().getMessage(p, "languages." + id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,13 +1,15 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.services.localization;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@ -33,9 +35,9 @@ import net.md_5.bungee.api.chat.TextComponent;
|
||||
/**
|
||||
* This is an abstract parent class of {@link LocalizationService}.
|
||||
* There is not really much more I can say besides that...
|
||||
*
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*
|
||||
* @see LocalizationService
|
||||
*
|
||||
*/
|
||||
@ -48,10 +50,10 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
/**
|
||||
* This method attempts to return the {@link Language} with the given
|
||||
* language code.
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* The language code
|
||||
*
|
||||
*
|
||||
* @return A {@link Language} with the given id or null
|
||||
*/
|
||||
@Nullable
|
||||
@ -59,28 +61,30 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
|
||||
/**
|
||||
* This method returns the currently selected {@link Language} of a {@link Player}.
|
||||
*
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} to query
|
||||
*
|
||||
*
|
||||
* @return The {@link Language} that was selected by the given {@link Player}
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Language getLanguage(@Nonnull Player p);
|
||||
|
||||
/**
|
||||
* This method returns the default {@link Language} of this {@link Server}
|
||||
*
|
||||
*
|
||||
* @return The default {@link Language}
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Language getDefaultLanguage();
|
||||
|
||||
/**
|
||||
* This returns whether a {@link Language} with the given id exists within
|
||||
* the project resources.
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* The {@link Language} id
|
||||
*
|
||||
*
|
||||
* @return Whether the project contains a {@link Language} with that id
|
||||
*/
|
||||
protected abstract boolean hasLanguage(@Nonnull String id);
|
||||
@ -88,7 +92,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
/**
|
||||
* This method returns a full {@link Collection} of every {@link Language} that was
|
||||
* found.
|
||||
*
|
||||
*
|
||||
* @return A {@link Collection} that contains every installed {@link Language}
|
||||
*/
|
||||
@Nonnull
|
||||
@ -96,7 +100,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
|
||||
/**
|
||||
* This method adds a new {@link Language} with the given id and texture.
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* The {@link Language} id
|
||||
* @param texture
|
||||
@ -117,7 +121,28 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage(Player p, String key) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMessage(@Nonnull String key) {
|
||||
Validate.notNull(key, "Message key must not be null!");
|
||||
|
||||
Language language = getDefaultLanguage();
|
||||
|
||||
String message = language == null ? null : language.getMessagesFile().getString(key);
|
||||
|
||||
if (message == null) {
|
||||
Language fallback = getLanguage(SupportedLanguage.ENGLISH.getLanguageId());
|
||||
return fallback.getMessagesFile().getString(key);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getMessage(@Nonnull Player p, @Nonnull String key) {
|
||||
Validate.notNull(p, "Player must not be null!");
|
||||
Validate.notNull(key, "Message key must not be null!");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
|
||||
if (language == null) {
|
||||
@ -134,11 +159,15 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
return message;
|
||||
}
|
||||
|
||||
public List<String> getMessages(Player p, String key) {
|
||||
@Nonnull
|
||||
public List<String> getMessages(@Nonnull Player p, @Nonnull String key) {
|
||||
Validate.notNull(p, "Player should not be null.");
|
||||
Validate.notNull(key, "Message key cannot be null.");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
|
||||
if (language == null) {
|
||||
return Arrays.asList("NO LANGUAGE FOUND");
|
||||
return Collections.singletonList("NO LANGUAGE FOUND");
|
||||
}
|
||||
|
||||
List<String> messages = language.getMessagesFile().getStringList(key);
|
||||
@ -151,37 +180,55 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ParametersAreNonnullByDefault
|
||||
public List<String> getMessages(Player p, String key, UnaryOperator<String> function) {
|
||||
Validate.notNull(p, "Player cannot be null.");
|
||||
Validate.notNull(key, "Message key cannot be null.");
|
||||
Validate.notNull(function, "Function cannot be null.");
|
||||
|
||||
List<String> messages = getMessages(p, key);
|
||||
messages.replaceAll(function);
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
public String getResearchName(Player p, NamespacedKey key) {
|
||||
@Nullable
|
||||
public String getResearchName(@Nonnull Player p, @Nonnull NamespacedKey key) {
|
||||
Validate.notNull(p, "Player must not be null.");
|
||||
Validate.notNull(key, "NamespacedKey cannot be null.");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
|
||||
if (language.getResearchesFile() == null) {
|
||||
if (language == null || language.getResearchesFile() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return language.getResearchesFile().getString(key.getNamespace() + "." + key.getKey());
|
||||
return language.getResearchesFile().getString(key.getNamespace() + '.' + key.getKey());
|
||||
}
|
||||
|
||||
public String getCategoryName(Player p, NamespacedKey key) {
|
||||
@Nullable
|
||||
public String getCategoryName(@Nonnull Player p, @Nonnull NamespacedKey key) {
|
||||
Validate.notNull(p, "Player must not be null.");
|
||||
Validate.notNull(key, "NamespacedKey cannot be null!");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
|
||||
if (language.getCategoriesFile() == null) {
|
||||
if (language == null || language.getCategoriesFile() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return language.getCategoriesFile().getString(key.getNamespace() + "." + key.getKey());
|
||||
return language.getCategoriesFile().getString(key.getNamespace() + '.' + key.getKey());
|
||||
}
|
||||
|
||||
public String getResourceString(Player p, String key) {
|
||||
@Nullable
|
||||
public String getResourceString(@Nonnull Player p, @Nonnull String key) {
|
||||
Validate.notNull(p, "Player should not be null!");
|
||||
Validate.notNull(key, "Message key should not be null!");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
|
||||
String value = language.getResourcesFile() != null ? language.getResourcesFile().getString(key) : null;
|
||||
String value = language != null && language.getResourcesFile() != null ? language.getResourcesFile().getString(key) : null;
|
||||
|
||||
if (value != null) {
|
||||
return value;
|
||||
@ -191,16 +238,20 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack getRecipeTypeItem(Player p, RecipeType recipeType) {
|
||||
@Nullable
|
||||
public ItemStack getRecipeTypeItem(@Nonnull Player p, @Nonnull RecipeType recipeType) {
|
||||
Validate.notNull(p, "Player cannot be null!");
|
||||
Validate.notNull(recipeType, "Recipe type cannot be null!");
|
||||
|
||||
Language language = getLanguage(p);
|
||||
ItemStack item = recipeType.toItem();
|
||||
NamespacedKey key = recipeType.getKey();
|
||||
|
||||
if (language.getRecipeTypesFile() == null || !language.getRecipeTypesFile().contains(key.getNamespace() + "." + key.getKey())) {
|
||||
if (language == null || language.getRecipeTypesFile() == null || !language.getRecipeTypesFile().contains(key.getNamespace() + '.' + key.getKey())) {
|
||||
language = getLanguage("en");
|
||||
}
|
||||
|
||||
if (!language.getRecipeTypesFile().contains(key.getNamespace() + "." + key.getKey())) {
|
||||
if (!language.getRecipeTypesFile().contains(key.getNamespace() + '.' + key.getKey())) {
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -218,7 +269,10 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandSender recipient, String key, boolean addPrefix) {
|
||||
public void sendMessage(@Nonnull CommandSender recipient, @Nonnull String key, boolean addPrefix) {
|
||||
Validate.notNull(recipient, "Recipient cannot be null!");
|
||||
Validate.notNull(key, "Message key cannot be null!");
|
||||
|
||||
String prefix = addPrefix ? getPrefix() : "";
|
||||
|
||||
if (recipient instanceof Player) {
|
||||
@ -229,6 +283,9 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
|
||||
public void sendActionbarMessage(@Nonnull Player player, @Nonnull String key, boolean addPrefix) {
|
||||
Validate.notNull(player, "Player cannot be null!");
|
||||
Validate.notNull(key, "Message key cannot be null!");
|
||||
|
||||
String prefix = addPrefix ? getPrefix() : "";
|
||||
String message = ChatColors.color(prefix + getMessage(player, key));
|
||||
|
||||
@ -237,15 +294,17 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandSender recipient, String key) {
|
||||
public void sendMessage(@Nonnull CommandSender recipient, @Nonnull String key) {
|
||||
sendMessage(recipient, key, true);
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public void sendMessage(CommandSender recipient, String key, UnaryOperator<String> function) {
|
||||
sendMessage(recipient, key, true, function);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void sendMessage(CommandSender recipient, String key, boolean addPrefix, UnaryOperator<String> function) {
|
||||
if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
|
||||
return;
|
||||
@ -261,7 +320,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessages(CommandSender recipient, String key) {
|
||||
public void sendMessages(@Nonnull CommandSender recipient, @Nonnull String key) {
|
||||
String prefix = getPrefix();
|
||||
|
||||
if (recipient instanceof Player) {
|
||||
@ -278,6 +337,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void sendMessages(CommandSender recipient, String key, boolean addPrefix, UnaryOperator<String> function) {
|
||||
String prefix = addPrefix ? getPrefix() : "";
|
||||
|
||||
@ -294,8 +354,8 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public void sendMessages(CommandSender recipient, String key, UnaryOperator<String> function) {
|
||||
sendMessages(recipient, key, true, function);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack PURE_ORE_CLUSTER = new SlimefunItemStack("PURE_ORE_CLUSTER", Material.GUNPOWDER, "&6Pure Ore Cluster");
|
||||
public static final SlimefunItemStack SMALL_URANIUM = new SlimefunItemStack("SMALL_URANIUM", HeadTexture.URANIUM, "&cSmall Chunk of Uranium", "", LoreBuilder.radioactive(Radioactivity.MODERATE), LoreBuilder.HAZMAT_SUIT_REQUIRED);
|
||||
public static final SlimefunItemStack TINY_URANIUM = new SlimefunItemStack("TINY_URANIUM", HeadTexture.URANIUM, "&cTiny Pile of Uranium", "", LoreBuilder.radioactive(Radioactivity.LOW));
|
||||
public static final SlimefunItemStack SOLAR_PANEL = new SlimefunItemStack("SOLAR_PANEL", Material.DAYLIGHT_DETECTOR, "&bSolar Panel", "", "&a&oTransforms Sunlight to Energy");
|
||||
public static final SlimefunItemStack SOLAR_PANEL = new SlimefunItemStack("SOLAR_PANEL", Material.DAYLIGHT_DETECTOR, "&9Photovoltaic Cell", "", "&7Important component for", "&7crafting a &bSolar Generator");
|
||||
public static final SlimefunItemStack PLASTIC_SHEET = new SlimefunItemStack("PLASTIC_SHEET", Material.PAPER, "&fPlastic Sheet");
|
||||
|
||||
public static final SlimefunItemStack MAGNET = new SlimefunItemStack("MAGNET", HeadTexture.MAGNET, "&cMagnet");
|
||||
@ -415,7 +415,7 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack HEATING_COIL = new SlimefunItemStack("HEATING_COIL", HeadTexture.HEATING_COIL, "&cHeating Coil");
|
||||
public static final SlimefunItemStack COOLING_UNIT = new SlimefunItemStack("COOLING_UNIT", HeadTexture.COOLING_UNIT, "&bCooling Unit");
|
||||
public static final SlimefunItemStack ELECTRIC_MOTOR = new SlimefunItemStack("ELECTRIC_MOTOR", HeadTexture.MOTOR, "&cElectric Motor");
|
||||
public static final SlimefunItemStack CARGO_MOTOR = new SlimefunItemStack("CARGO_MOTOR", HeadTexture.MOTOR, "&3Cargo Motor");
|
||||
public static final SlimefunItemStack CARGO_MOTOR = new SlimefunItemStack("CARGO_MOTOR", HeadTexture.CARGO_MOTOR, "&3Cargo Motor", "", "&7Important ingredient for items", "&7related to Cargo Management");
|
||||
public static final SlimefunItemStack SCROLL_OF_DIMENSIONAL_TELEPOSITION = new SlimefunItemStack("SCROLL_OF_DIMENSIONAL_TELEPOSITION", Material.PAPER, "&6Scroll of Dimensional Teleposition", "", "&cThis Scroll is capable of creating", "&ca temporary black Hole which pulls", "&cnearby Entities into itself and sends", "&cthem into another Dimension where", "&ceverything is turned around", "", "&fIn other words: Makes Entities turn by 180 Degrees");
|
||||
public static final SlimefunItemStack TOME_OF_KNOWLEDGE_SHARING = new SlimefunItemStack("TOME_OF_KNOWLEDGE_SHARING", Material.ENCHANTED_BOOK, "&6Tome of Knowledge Sharing", "&7Owner: &bNone", "", "&eRight Click&7 to bind this Tome to yourself", "", "", "&eRight Click&7 to obtain all Researches by", "&7the previously assigned Owner");
|
||||
public static final SlimefunItemStack HARDENED_GLASS = new SlimefunItemStack("HARDENED_GLASS", Material.LIGHT_GRAY_STAINED_GLASS, "&7Hardened Glass", "", "&fWithstands Explosions");
|
||||
@ -425,6 +425,7 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack ANCIENT_PEDESTAL = new SlimefunItemStack("ANCIENT_PEDESTAL", Material.DISPENSER, "&dAncient Pedestal", "", "&5Part of the Ancient Altar");
|
||||
public static final SlimefunItemStack ANCIENT_ALTAR = new SlimefunItemStack("ANCIENT_ALTAR", Material.ENCHANTING_TABLE, "&dAncient Altar", "", "&5Multi-Block Altar for", "&5magical Crafting Processes");
|
||||
public static final SlimefunItemStack COPPER_WIRE = new SlimefunItemStack("COPPER_WIRE", Material.STRING, "&6Copper Wire", "", "&6Crucial component in electric modules");
|
||||
public static final SlimefunItemStack CRAFTING_MOTOR = new SlimefunItemStack("CRAFTING_MOTOR", HeadTexture.CRAFTING_MOTOR, "&6Crafting Motor", "", "&7Important component of Auto-Crafters");
|
||||
|
||||
/* Rainbow blocks */
|
||||
private static final String RAINBOW = "&dCycles through all Colors of the Rainbow!";
|
||||
@ -782,7 +783,9 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack CARGO_OUTPUT_NODE = new SlimefunItemStack("CARGO_NODE_OUTPUT", HeadTexture.CARGO_OUTPUT_NODE, "&7Cargo Node &c(Output)", "", "&fCargo Output Pipe");
|
||||
public static final SlimefunItemStack CARGO_OUTPUT_NODE_2 = new SlimefunItemStack("CARGO_NODE_OUTPUT_ADVANCED", HeadTexture.CARGO_OUTPUT_NODE, "&6Advanced Cargo Node &c(Output)", "", "&fCargo Output Pipe");
|
||||
|
||||
// Animal farm
|
||||
public static final SlimefunItemStack AUTO_BREEDER = new SlimefunItemStack("AUTO_BREEDER", Material.HAY_BLOCK, "&eAuto-Breeder", "", "&fRuns on &aOrganic Food", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.powerBuffer(1024), "&8\u21E8 &e\u26A1 &760 J/Animal");
|
||||
public static final SlimefunItemStack PRODUCE_COLLECTOR = new SlimefunItemStack("PRODUCE_COLLECTOR", Material.HAY_BLOCK, "&bProduce Collector", "", "&fThis machine allows you to", "&fcollect produce from nearby animals.", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.powerBuffer(512), LoreBuilder.powerPerSecond(32));
|
||||
|
||||
public static final SlimefunItemStack ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9???");
|
||||
public static final SlimefunItemStack WHEAT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_WHEAT", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Wheat");
|
||||
@ -849,6 +852,7 @@ public final class SlimefunItems {
|
||||
|
||||
public static final SlimefunItemStack VANILLA_AUTO_CRAFTER = new SlimefunItemStack("VANILLA_AUTO_CRAFTER", HeadTexture.VANILLA_AUTO_CRAFTER, "&2Auto-Crafter &8(Vanilla)", "", "&fPlace this machine on top of a", "&fchest or similar and make it craft", "&fanything that can be crafted using a", "&fnormal &eCrafting Table", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &716 J/Item");
|
||||
public static final SlimefunItemStack ENHANCED_AUTO_CRAFTER = new SlimefunItemStack("ENHANCED_AUTO_CRAFTER", HeadTexture.ENHANCED_AUTO_CRAFTER, "&2Auto-Crafter &8(Enhanced)", "", "&fPlace this machine on top of a", "&fchest or similar and make it craft", "&fanything that can be crafted using an", "&eEnhanced Crafting Table", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &716 J/Item");
|
||||
public static final SlimefunItemStack ARMOR_AUTO_CRAFTER = new SlimefunItemStack("ARMOR_AUTO_CRAFTER", HeadTexture.ARMOR_AUTO_CRAFTER, "&2Auto-Crafter &8(Armor Forge)", "", "&fPlace this machine on top of a", "&fchest or similar and make it craft", "&fanything that can be crafted using an", "&eArmor Forge", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), "&8\u21E8 &e\u26A1 &732 J/Item");
|
||||
|
||||
public static final SlimefunItemStack IRON_GOLEM_ASSEMBLER = new SlimefunItemStack("IRON_GOLEM_ASSEMBLER", Material.IRON_BLOCK, "&6Iron Golem Assembler", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Cooldown: &b30 Seconds", LoreBuilder.powerBuffer(4096), "&8\u21E8 &e\u26A1 &72048 J/Golem");
|
||||
public static final SlimefunItemStack WITHER_ASSEMBLER = new SlimefunItemStack("WITHER_ASSEMBLER", Material.OBSIDIAN, "&5Wither Assembler", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Cooldown: &b30 Seconds", LoreBuilder.powerBuffer(4096), "&8\u21E8 &e\u26A1 &74096 J/Wither");
|
||||
|
@ -34,6 +34,7 @@ import io.github.thebusybiscuit.cscorelib2.protection.ProtectionManager;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
||||
import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException;
|
||||
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
|
||||
import io.github.thebusybiscuit.slimefun4.api.gps.GPSNetwork;
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import io.github.thebusybiscuit.slimefun4.core.SlimefunRegistry;
|
||||
@ -778,6 +779,13 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
return instance.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns our {@link GPSNetwork} instance.
|
||||
* The {@link GPSNetwork} is responsible for handling any GPS-related
|
||||
* operations and for managing any {@link GEOResource}.
|
||||
*
|
||||
* @return Our {@link GPSNetwork} instance
|
||||
*/
|
||||
@Nonnull
|
||||
public static GPSNetwork getGPSNetwork() {
|
||||
validateInstance();
|
||||
|
@ -153,7 +153,7 @@ public enum Instruction {
|
||||
* ahead of them.
|
||||
*/
|
||||
ATTACK_MOBS(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
|
||||
Predicate<LivingEntity> predicate = e -> e instanceof Monster;
|
||||
Predicate<LivingEntity> predicate = Monster.class::isInstance;
|
||||
android.attack(b, face, predicate);
|
||||
}),
|
||||
|
||||
@ -162,7 +162,7 @@ public enum Instruction {
|
||||
* ahead of them.
|
||||
*/
|
||||
ATTACK_ANIMALS(AndroidType.FIGHTER, HeadTexture.SCRIPT_ATTACK, (android, b, inv, face) -> {
|
||||
Predicate<LivingEntity> predicate = e -> e instanceof Animals;
|
||||
Predicate<LivingEntity> predicate = Animals.class::isInstance;
|
||||
android.attack(b, face, predicate);
|
||||
}),
|
||||
|
||||
|
@ -24,6 +24,7 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@ -36,6 +37,7 @@ import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
@ -52,7 +54,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
@ -132,23 +133,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Move this into a BlockBreakHandler
|
||||
registerBlockHandler(getId(), (p, b, stack, reason) -> {
|
||||
boolean allow = reason == UnregisterReason.PLAYER_BREAK && (BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(p.getUniqueId().toString()) || p.hasPermission("slimefun.android.bypass"));
|
||||
|
||||
if (allow) {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), 43);
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
}
|
||||
|
||||
return allow;
|
||||
});
|
||||
|
||||
addItemHandler(onPlace());
|
||||
addItemHandler(onPlace(), onBreak());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -178,6 +163,31 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private BlockBreakHandler onBreak() {
|
||||
return new BlockBreakHandler(false, false) {
|
||||
|
||||
@Override
|
||||
public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List<ItemStack> drops) {
|
||||
Block b = e.getBlock();
|
||||
String owner = BlockStorage.getLocationInfo(b.getLocation(), "owner");
|
||||
|
||||
if (!e.getPlayer().hasPermission("slimefun.android.bypass") && !e.getPlayer().getUniqueId().toString().equals(owner)) {
|
||||
// The Player is not allowed to break this android
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), 43);
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the {@link AndroidType} that is associated with this {@link ProgrammableAndroid}.
|
||||
*
|
||||
|
@ -1,8 +1,10 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.armor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.utils.UnbreakingAlgorithm;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -41,12 +43,17 @@ public class ElytraCap extends SlimefunArmorPiece implements DamageableItem, Pro
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damageItem(Player p, ItemStack item) {
|
||||
public void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
|
||||
if (p.getGameMode() != GameMode.CREATIVE) {
|
||||
DamageableItem.super.damageItem(p, item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluateUnbreakingEnchantment(int unbreakingLevel) {
|
||||
return UnbreakingAlgorithm.ARMOR.evaluate(unbreakingLevel);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ProtectionType[] getProtectionTypes() {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -9,7 +11,6 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@ -27,6 +28,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
|
||||
@ -35,6 +37,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.AutoCrafterListener;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
|
||||
@ -73,6 +76,11 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
*/
|
||||
protected final NamespacedKey recipeStorageKey;
|
||||
|
||||
/**
|
||||
* The {@link NamespacedKey} used to determine whether the recipe is enabled.
|
||||
*/
|
||||
protected final NamespacedKey recipeEnabledKey;
|
||||
|
||||
// @formatter:off
|
||||
protected final int[] background = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
@ -84,10 +92,11 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
// @formatter:on
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AbstractAutoCrafter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
protected AbstractAutoCrafter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
recipeStorageKey = new NamespacedKey(SlimefunPlugin.instance(), "recipe_key");
|
||||
recipeEnabledKey = new NamespacedKey(SlimefunPlugin.instance(), "recipe_enabled");
|
||||
|
||||
addItemHandler(new BlockTicker() {
|
||||
|
||||
@ -142,19 +151,28 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method performs one tick for the {@link AbstractAutoCrafter}.
|
||||
*
|
||||
* @param b
|
||||
* The block for this {@link AbstractAutoCrafter}
|
||||
* @param data
|
||||
* The data stored on this block
|
||||
*/
|
||||
protected void tick(@Nonnull Block b, @Nonnull Config data) {
|
||||
AbstractRecipe recipe = getSelectedRecipe(b);
|
||||
|
||||
if (recipe == null || getCharge(b.getLocation(), data) < getEnergyConsumption()) {
|
||||
// No valid recipe selected, abort...
|
||||
if (recipe == null || !recipe.isEnabled() || getCharge(b.getLocation(), data) < getEnergyConsumption()) {
|
||||
// No recipe / disabled recipe / no energy, abort...
|
||||
return;
|
||||
}
|
||||
|
||||
Block chest = b.getRelative(BlockFace.DOWN);
|
||||
// The block below where we would expect our inventory holder.
|
||||
Block targetBlock = b.getRelative(BlockFace.DOWN);
|
||||
|
||||
// Make sure this is a Chest
|
||||
if (isValidInventory(chest)) {
|
||||
BlockState state = PaperLib.getBlockState(chest, false).getState();
|
||||
if (isValidInventory(targetBlock)) {
|
||||
BlockState state = PaperLib.getBlockState(targetBlock, false).getState();
|
||||
|
||||
if (state instanceof InventoryHolder) {
|
||||
Inventory inv = ((InventoryHolder) state).getInventory();
|
||||
@ -236,6 +254,9 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
if (recipe == null) {
|
||||
// Clear the value from persistent data storage
|
||||
PersistentDataAPI.remove((Skull) state, recipeStorageKey);
|
||||
|
||||
// Also remove the "enabled" state since this should be per-recipe.
|
||||
PersistentDataAPI.remove((Skull) state, recipeEnabledKey);
|
||||
} else {
|
||||
// Store the value to persistent data storage
|
||||
PersistentDataAPI.setString((Skull) state, recipeStorageKey, recipe.toString());
|
||||
@ -271,14 +292,29 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
ChestMenuUtils.drawBackground(menu, background);
|
||||
ChestMenuUtils.drawBackground(menu, 45, 46, 47, 48, 50, 51, 52, 53);
|
||||
|
||||
menu.addItem(49, new CustomItem(Material.BARRIER, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "messages.auto-crafting.remove")));
|
||||
menu.addMenuClickHandler(49, (pl, item, slot, action) -> {
|
||||
setSelectedRecipe(b, null);
|
||||
pl.closeInventory();
|
||||
p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.recipe-removed");
|
||||
return false;
|
||||
});
|
||||
if (recipe.isEnabled()) {
|
||||
menu.addItem(49, new CustomItem(Material.BARRIER, SlimefunPlugin.getLocalization().getMessages(p, "messages.auto-crafting.tooltips.enabled")));
|
||||
menu.addMenuClickHandler(49, (pl, item, slot, action) -> {
|
||||
if (action.isRightClicked()) {
|
||||
deleteRecipe(pl, b);
|
||||
} else {
|
||||
setRecipeEnabled(pl, b, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
menu.addItem(49, new CustomItem(HeadTexture.EXCLAMATION_MARK.getAsItemStack(), SlimefunPlugin.getLocalization().getMessages(p, "messages.auto-crafting.tooltips.disabled")));
|
||||
menu.addMenuClickHandler(49, (pl, item, slot, action) -> {
|
||||
if (action.isRightClicked()) {
|
||||
deleteRecipe(pl, b);
|
||||
} else {
|
||||
setRecipeEnabled(pl, b, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// This makes the slots cycle through different ingredients
|
||||
AsyncRecipeChoiceTask task = new AsyncRecipeChoiceTask();
|
||||
@ -293,6 +329,32 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private void setRecipeEnabled(Player p, Block b, boolean enabled) {
|
||||
p.closeInventory();
|
||||
p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1);
|
||||
BlockState state = PaperLib.getBlockState(b, false).getState();
|
||||
|
||||
// Make sure the block is still a Skull
|
||||
if (state instanceof Skull) {
|
||||
if (enabled) {
|
||||
PersistentDataAPI.remove((Skull) state, recipeEnabledKey);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.re-enabled");
|
||||
} else {
|
||||
PersistentDataAPI.setByte((Skull) state, recipeEnabledKey, (byte) 1);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.temporarily-disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private void deleteRecipe(Player p, Block b) {
|
||||
setSelectedRecipe(b, null);
|
||||
p.closeInventory();
|
||||
p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.recipe-removed");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks whether the given {@link Predicate} matches the provided {@link ItemStack}.
|
||||
*
|
||||
@ -347,6 +409,11 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
Validate.notNull(inv, "The Inventory must not be null");
|
||||
Validate.notNull(recipe, "The Recipe shall not be null");
|
||||
|
||||
// Make sure that the Recipe is actually enabled
|
||||
if (!recipe.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have an empty slot
|
||||
if (inv.firstEmpty() != -1) {
|
||||
Map<Integer, Integer> itemQuantities = new HashMap<>();
|
||||
@ -358,23 +425,79 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
|
||||
}
|
||||
}
|
||||
|
||||
List<ItemStack> leftoverItems = new ArrayList<>();
|
||||
|
||||
// Remove ingredients
|
||||
for (Map.Entry<Integer, Integer> entry : itemQuantities.entrySet()) {
|
||||
ItemStack item = inv.getItem(entry.getKey());
|
||||
|
||||
// Double-check to be extra safe
|
||||
if (item != null) {
|
||||
// Handle leftovers
|
||||
ItemStack leftover = getLeftoverItem(item);
|
||||
|
||||
if (leftover != null) {
|
||||
// Account for the amount of removed items
|
||||
leftover.setAmount(item.getAmount() - entry.getValue());
|
||||
leftoverItems.add(leftover);
|
||||
}
|
||||
|
||||
// Update the item amount
|
||||
item.setAmount(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// All Predicates have found a match
|
||||
return inv.addItem(recipe.getResult().clone()).isEmpty();
|
||||
boolean success = inv.addItem(recipe.getResult().clone()).isEmpty();
|
||||
|
||||
if (success) {
|
||||
// Fixes #2926 - Push leftover items to the inventory.
|
||||
for (ItemStack leftoverItem : leftoverItems) {
|
||||
inv.addItem(leftoverItem);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the "leftovers" from a crafting operation.
|
||||
* The method functions very similarly to {@link Material#getCraftingRemainingItem()}.
|
||||
* However we cannot use this method as it is only available in the latest 1.16 snapshots
|
||||
* of Spigot, not even on earlier 1.16 builds...
|
||||
* But this gives us more control over the leftovers anyway!
|
||||
*
|
||||
* @param item
|
||||
* The {@link ItemStack} that is being consumed
|
||||
*
|
||||
* @return The leftover item or null if the item is fully consumed
|
||||
*/
|
||||
@Nullable
|
||||
private ItemStack getLeftoverItem(@Nonnull ItemStack item) {
|
||||
Material type = item.getType();
|
||||
|
||||
switch (type) {
|
||||
case WATER_BUCKET:
|
||||
case LAVA_BUCKET:
|
||||
case MILK_BUCKET:
|
||||
return new ItemStack(Material.BUCKET);
|
||||
case DRAGON_BREATH:
|
||||
case POTION:
|
||||
return new ItemStack(Material.GLASS_BOTTLE);
|
||||
default:
|
||||
MinecraftVersion minecraftVersion = SlimefunPlugin.getMinecraftVersion();
|
||||
|
||||
// Honey does not exist in 1.14
|
||||
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15) && type == Material.HONEY_BOTTLE) {
|
||||
return new ItemStack(Material.GLASS_BOTTLE);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the max amount of electricity this machine can hold.
|
||||
*
|
||||
|
@ -44,6 +44,11 @@ public abstract class AbstractRecipe {
|
||||
*/
|
||||
private final ItemStack result;
|
||||
|
||||
/**
|
||||
* Whether this recipe is enabled.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Protected constructor. For implementation classes only.
|
||||
*
|
||||
@ -83,6 +88,27 @@ public abstract class AbstractRecipe {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns whether or not this recipe has been enabled.
|
||||
* A disabled recipe will not be crafted.
|
||||
*
|
||||
* @return Whether this recipe is enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method enables or disables this recipe.
|
||||
* A disabled recipe will not be crafted.
|
||||
*
|
||||
* @param enabled
|
||||
* Whether this recipe is enabled
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will visually represent this {@link AbstractRecipe} in the given {@link ChestMenu}.
|
||||
* Any {@link MaterialChoice} will be cycled through using the {@link AsyncRecipeChoiceTask}.
|
||||
|
@ -0,0 +1,31 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.ArmorForge;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link ArmorAutoCrafter} is an implementation of the {@link AbstractAutoCrafter}.
|
||||
* It can craft items that are crafted using the {@link ArmorForge}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see ArmorForge
|
||||
* @see AbstractAutoCrafter
|
||||
* @see SlimefunAutoCrafter
|
||||
* @see SlimefunItemRecipe
|
||||
*
|
||||
*/
|
||||
public class ArmorAutoCrafter extends SlimefunAutoCrafter {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public ArmorAutoCrafter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe, RecipeType.ARMOR_FORGE);
|
||||
}
|
||||
|
||||
}
|
@ -13,8 +13,9 @@ import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Skull;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
|
||||
@ -60,11 +61,15 @@ public class SlimefunAutoCrafter extends AbstractAutoCrafter {
|
||||
|
||||
if (state instanceof Skull) {
|
||||
// Read the stored value from persistent data storage
|
||||
String value = PersistentDataAPI.getString((Skull) state, recipeStorageKey);
|
||||
PersistentDataContainer container = ((Skull) state).getPersistentDataContainer();
|
||||
String value = container.get(recipeStorageKey, PersistentDataType.STRING);
|
||||
SlimefunItem item = SlimefunItem.getByID(value);
|
||||
|
||||
if (item != null) {
|
||||
return AbstractRecipe.of(item, targetRecipeType);
|
||||
boolean enabled = !container.has(recipeEnabledKey, PersistentDataType.BYTE);
|
||||
AbstractRecipe recipe = AbstractRecipe.of(item, targetRecipeType);
|
||||
recipe.setEnabled(enabled);
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@ -22,9 +21,11 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
||||
@ -58,16 +59,12 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter {
|
||||
@Override
|
||||
@Nullable
|
||||
public AbstractRecipe getSelectedRecipe(@Nonnull Block b) {
|
||||
return AbstractRecipe.of(getRecipe(b));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Recipe getRecipe(@Nonnull Block b) {
|
||||
BlockState state = PaperLib.getBlockState(b, false).getState();
|
||||
|
||||
if (state instanceof Skull) {
|
||||
// Read the stored value from persistent data storage
|
||||
String value = PersistentDataAPI.getString((Skull) state, recipeStorageKey);
|
||||
PersistentDataContainer container = ((Skull) state).getPersistentDataContainer();
|
||||
String value = container.get(recipeStorageKey, PersistentDataType.STRING);
|
||||
|
||||
if (value != null) {
|
||||
String[] values = PatternUtils.COLON.split(value);
|
||||
@ -79,8 +76,15 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
NamespacedKey key = new NamespacedKey(values[0], values[1]);
|
||||
Recipe keyedRecipe = SlimefunPlugin.getMinecraftRecipeService().getRecipe(key);
|
||||
|
||||
return SlimefunPlugin.getMinecraftRecipeService().getRecipe(key);
|
||||
if (keyedRecipe != null) {
|
||||
boolean enabled = !container.has(recipeEnabledKey, PersistentDataType.BYTE);
|
||||
AbstractRecipe recipe = AbstractRecipe.of(keyedRecipe);
|
||||
recipe.setEnabled(enabled);
|
||||
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +173,10 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter {
|
||||
private List<Recipe> getRecipesFor(@Nonnull ItemStack item) {
|
||||
List<Recipe> recipes = new ArrayList<>();
|
||||
|
||||
for (Recipe recipe : Bukkit.getRecipesFor(item)) {
|
||||
// Fixes #2913 - Bukkit.getRecipesFor() only checks for Materials
|
||||
MinecraftRecipeService recipeService = SlimefunPlugin.getMinecraftRecipeService();
|
||||
|
||||
for (Recipe recipe : recipeService.getRecipesFor(item)) {
|
||||
if (recipe instanceof ShapedRecipe || recipe instanceof ShapelessRecipe) {
|
||||
recipes.add(recipe);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.Nameable;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Dispenser;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
@ -97,16 +98,7 @@ public class BlockPlacer extends SlimefunItem {
|
||||
|
||||
e.setCancelled(true);
|
||||
|
||||
if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) {
|
||||
/*
|
||||
* Some materials cannot be reliably placed, like beds,
|
||||
* it would look kinda wonky, so we just ignore these altogether.
|
||||
* The event has already been cancelled too, so they won't drop.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (facedBlock.isEmpty() && isAllowed(material) && dispenser.getInventory().getViewers().isEmpty()) {
|
||||
if (facedBlock.isEmpty() && dispenser.getInventory().getViewers().isEmpty() && isAllowed(facedBlock, material)) {
|
||||
SlimefunItem item = SlimefunItem.getByItem(e.getItem());
|
||||
|
||||
if (item != null) {
|
||||
@ -158,14 +150,33 @@ public class BlockPlacer extends SlimefunItem {
|
||||
*
|
||||
* @return Whether placing this {@link Material} is allowed
|
||||
*/
|
||||
private boolean isAllowed(@Nonnull Material type) {
|
||||
for (String blockType : unplaceableBlocks.getValue()) {
|
||||
if (type.toString().equals(blockType)) {
|
||||
return false;
|
||||
private boolean isAllowed(@Nonnull Block facedBlock, @Nonnull Material type) {
|
||||
if (!type.isBlock()) {
|
||||
// Make sure the material is actually a block.
|
||||
return false;
|
||||
} else if (type == Material.CAKE) {
|
||||
/*
|
||||
* Special case for cakes.
|
||||
* Cakes are a lie but I really want the Block Placer to place them down!!!
|
||||
*/
|
||||
return !facedBlock.getRelative(BlockFace.DOWN).isPassable();
|
||||
} else if (SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(type)) {
|
||||
/*
|
||||
* Some materials cannot be reliably placed, like beds,
|
||||
* it would look kinda wonky, so we just ignore these altogether.
|
||||
* The event has already been cancelled too, so they won't drop.
|
||||
*/
|
||||
return false;
|
||||
} else {
|
||||
// Check for all unplaceable block
|
||||
for (String blockType : unplaceableBlocks.getValue()) {
|
||||
if (type.toString().equals(blockType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
|
@ -188,7 +188,8 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
|
||||
|
||||
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);
|
||||
// Fixes #2903 - Cancel physics update to resolve weird overlapping
|
||||
block.setType(water ? Material.WATER : Material.LAVA, false);
|
||||
} else {
|
||||
if (water && block.getBlockData() instanceof Waterlogged) {
|
||||
Waterlogged wl = (Waterlogged) block.getBlockData();
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -31,7 +32,7 @@ public class UnplaceableBlock extends SimpleSlimefunItem<ItemUseHandler> impleme
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public UnplaceableBlock(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
|
||||
public UnplaceableBlock(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, @Nullable ItemStack recipeOutput) {
|
||||
super(category, item, recipeType, recipe, recipeOutput);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -27,6 +29,7 @@ public class AutoDrier extends AContainer implements RecipeDisplayItem, NotHoppe
|
||||
|
||||
private List<ItemStack> recipeList;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AutoDrier(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ -21,21 +19,18 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.EnhancedCraftingTable;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.AbstractAutoCrafter;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item.CustomItemSerializer;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item.CustomItemSerializer.ItemFlag;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
@ -44,10 +39,9 @@ import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
||||
|
||||
/**
|
||||
* This class needs to be rewritten VERY BADLY.
|
||||
* But we should focus on rewriting the recipe system first.
|
||||
* This machine is disabled and has been replaced by Auto Crafters.
|
||||
*
|
||||
* @deprecated This is horribly done. Someone needs to rewrite this.
|
||||
* @deprecated This has been replaced by the {@link AbstractAutoCrafter}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
@ -58,13 +52,11 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
private final int[] inputBorder = { 9, 10, 11, 12, 13, 18, 22, 27, 31, 36, 40, 45, 46, 47, 48, 49 };
|
||||
private final int[] outputBorder = { 23, 24, 25, 26, 32, 35, 41, 42, 43, 44 };
|
||||
|
||||
private final Map<String, ItemStack> craftingRecipes = new HashMap<>();
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AutomatedCraftingChamber(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
new BlockMenuPreset(getId(), "&4Deprecated item. Do not use.") {
|
||||
new BlockMenuPreset(getId(), "&4Machine is disabled.") {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
@ -88,17 +80,11 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
menu.replaceExistingItem(7, new CustomItem(Material.CRAFTING_TABLE, "&7Craft Last", "", "&e> Click to craft the last shaped recipe", "&cOnly works with the last one"));
|
||||
menu.addMenuClickHandler(7, (p, slot, item, action) -> {
|
||||
tick(b, true);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canOpen(Block b, Player p) {
|
||||
p.sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!");
|
||||
p.sendMessage(ChatColor.DARK_RED + "This item has been disabled and will be removed soon. Please switch over to the new Auto Crafters in the Cargo Category.");
|
||||
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
|
||||
}
|
||||
|
||||
@ -132,17 +118,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
}
|
||||
};
|
||||
|
||||
addItemHandler(onPlace());
|
||||
registerBlockHandler(getId(), (p, b, stack, reason) -> {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
addItemHandler(onPlace(), onBreak());
|
||||
}
|
||||
|
||||
private BlockPlaceHandler onPlace() {
|
||||
@ -150,7 +126,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
|
||||
@Override
|
||||
public void onPlayerPlace(BlockPlaceEvent e) {
|
||||
e.getPlayer().sendMessage(ChatColor.DARK_RED + "This item has been deprecated. It will be removed soon!");
|
||||
e.getPlayer().sendMessage(ChatColor.DARK_RED + "This item has been disabled and will be removed soon. Please switch over to the new Auto Crafters in the Cargo Category.");
|
||||
BlockStorage.addBlockInfo(e.getBlock(), "enabled", String.valueOf(false));
|
||||
}
|
||||
|
||||
@ -161,6 +137,21 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
};
|
||||
}
|
||||
|
||||
private BlockBreakHandler onBreak() {
|
||||
return new SimpleBlockBreakHandler() {
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(Block b) {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
|
||||
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount();
|
||||
}
|
||||
@ -212,106 +203,4 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
|
||||
public EnergyNetComponentType getEnergyComponentType() {
|
||||
return EnergyNetComponentType.CONSUMER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRegister() {
|
||||
addItemHandler(new BlockTicker() {
|
||||
|
||||
@Override
|
||||
public void tick(Block b, SlimefunItem sf, Config data) {
|
||||
AutomatedCraftingChamber.this.tick(b, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronized() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void tick(Block block, boolean craftLast) {
|
||||
if (!craftLast && BlockStorage.getLocationInfo(block.getLocation(), "enabled").equals(String.valueOf(false))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getCharge(block.getLocation()) < getEnergyConsumption()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String input = getSerializedInput(block, craftLast);
|
||||
testInputAgainstRecipes(block, input);
|
||||
}
|
||||
|
||||
private String getSerializedInput(Block block, boolean craftLast) {
|
||||
BlockMenu menu = BlockStorage.getInventory(block);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int i = 0;
|
||||
boolean lastIteration = false;
|
||||
|
||||
for (int j = 0; j < 9; j++) {
|
||||
if (i > 0) {
|
||||
builder.append(" </slot> ");
|
||||
}
|
||||
|
||||
ItemStack item = menu.getItemInSlot(getInputSlots()[j]);
|
||||
|
||||
if (item != null && item.getAmount() == 1) {
|
||||
if (craftLast) {
|
||||
lastIteration = true;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
builder.append(CustomItemSerializer.serialize(item, ItemFlag.MATERIAL, ItemFlag.ITEMMETA_DISPLAY_NAME, ItemFlag.ITEMMETA_LORE));
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// we're only executing the last possible shaped recipe
|
||||
// we don't want to allow this to be pressed instead of the default timer-based
|
||||
// execution to prevent abuse and auto clickers
|
||||
if (craftLast && !lastIteration) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void testInputAgainstRecipes(Block block, String input) {
|
||||
BlockMenu menu = BlockStorage.getInventory(block);
|
||||
|
||||
ItemStack output = craftingRecipes.get(input);
|
||||
if (output != null && menu.fits(output, getOutputSlots())) {
|
||||
menu.pushItem(output.clone(), getOutputSlots());
|
||||
removeCharge(block.getLocation(), getEnergyConsumption());
|
||||
|
||||
for (int j = 0; j < 9; j++) {
|
||||
if (menu.getItemInSlot(getInputSlots()[j]) != null) {
|
||||
menu.consumeItem(getInputSlots()[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadRecipes() {
|
||||
EnhancedCraftingTable machine = (EnhancedCraftingTable) SlimefunItems.ENHANCED_CRAFTING_TABLE.getItem();
|
||||
|
||||
for (ItemStack[] inputs : RecipeType.getRecipeInputList(machine)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int i = 0;
|
||||
|
||||
for (ItemStack item : inputs) {
|
||||
if (i > 0) {
|
||||
builder.append(" </slot> ");
|
||||
}
|
||||
|
||||
builder.append(CustomItemSerializer.serialize(item, ItemFlag.MATERIAL, ItemFlag.ITEMMETA_DISPLAY_NAME, ItemFlag.ITEMMETA_LORE));
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
craftingRecipes.put(builder.toString(), RecipeType.getRecipeOutputList(machine, inputs));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@ -13,6 +15,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
public class CarbonPress extends AContainer implements RecipeDisplayItem {
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public CarbonPress(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
}
|
||||
|
@ -6,8 +6,10 @@ import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
@ -34,6 +36,7 @@ public class ElectricPress extends AContainer implements RecipeDisplayItem {
|
||||
addRecipe(5, new ItemStack(Material.GLASS), new ItemStack(Material.GLASS_PANE, 3));
|
||||
addRecipe(4, new ItemStack(Material.SNOWBALL, 4), new ItemStack(Material.SNOW_BLOCK));
|
||||
addRecipe(4, new ItemStack(Material.MAGMA_CREAM, 4), new ItemStack(Material.MAGMA_BLOCK));
|
||||
addRecipe(4, new ItemStack(Material.SLIME_BALL, 9), new ItemStack(Material.SLIME_BLOCK));
|
||||
|
||||
addRecipe(3, new ItemStack(Material.DRIED_KELP, 9), new ItemStack(Material.DRIED_KELP_BLOCK));
|
||||
addRecipe(3, new ItemStack(Material.BONE_MEAL, 9), new ItemStack(Material.BONE_BLOCK));
|
||||
@ -70,6 +73,10 @@ public class ElectricPress extends AContainer implements RecipeDisplayItem {
|
||||
|
||||
addRecipe(8, new ItemStack(Material.EMERALD, 9), new ItemStack(Material.EMERALD_BLOCK));
|
||||
addRecipe(8, new ItemStack(Material.DIAMOND, 9), new ItemStack(Material.DIAMOND_BLOCK));
|
||||
|
||||
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
|
||||
addRecipe(16, new ItemStack(Material.NETHERITE_INGOT, 9), new ItemStack(Material.NETHERITE_BLOCK));
|
||||
}
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
|
@ -186,13 +186,15 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
|
||||
|
||||
@Nonnull
|
||||
private ItemStack getFilledBucket(@Nonnull Block fluid) {
|
||||
if (fluid.getType() == Material.LAVA) {
|
||||
return new ItemStack(Material.LAVA_BUCKET);
|
||||
} else if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
|
||||
return new ItemStack(Material.WATER_BUCKET);
|
||||
} else {
|
||||
// Fallback for any new liquids
|
||||
return new ItemStack(Material.BUCKET);
|
||||
switch (fluid.getType()) {
|
||||
case LAVA:
|
||||
return new ItemStack(Material.LAVA_BUCKET);
|
||||
case WATER:
|
||||
case BUBBLE_COLUMN:
|
||||
return new ItemStack(Material.WATER_BUCKET);
|
||||
default:
|
||||
// Fallback for any new liquids
|
||||
return new ItemStack(Material.BUCKET);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +216,7 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
|
||||
return levelled.getLevel() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@ public class Freezer extends AContainer implements RecipeDisplayItem {
|
||||
registerRecipe(6, new ItemStack[] { new ItemStack(Material.PACKED_ICE) }, new ItemStack[] { new ItemStack(Material.BLUE_ICE) });
|
||||
registerRecipe(8, new ItemStack[] { new ItemStack(Material.BLUE_ICE) }, new ItemStack[] { SlimefunItems.REACTOR_COOLANT_CELL });
|
||||
registerRecipe(6, new ItemStack[] { new ItemStack(Material.SNOW_BLOCK, 2) }, new ItemStack[] { new ItemStack(Material.ICE) });
|
||||
registerRecipe(6, new ItemStack[] { new ItemStack(Material.MAGMA_CREAM) }, new ItemStack[] { new ItemStack(Material.SLIME_BALL) });
|
||||
registerRecipe(6, new ItemStack[] { new ItemStack(Material.MAGMA_BLOCK, 2) }, new ItemStack[] { new ItemStack(Material.SLIME_BLOCK) });
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,48 +110,25 @@ public class BookBinder extends AContainer {
|
||||
@ParametersAreNonnullByDefault
|
||||
private Map<Enchantment, Integer> combineEnchantments(Map<Enchantment, Integer> ech1, Map<Enchantment, Integer> ech2) {
|
||||
Map<Enchantment, Integer> enchantments = new HashMap<>();
|
||||
boolean conflicts = false;
|
||||
enchantments.putAll(ech1);
|
||||
boolean hasConflicts = false;
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : ech2.entrySet()) {
|
||||
for (Map.Entry<Enchantment, Integer> conflictsWith : enchantments.entrySet()) {
|
||||
|
||||
// Check if entry enchantment and conflictsWith enchantment conflict, and confirm that the enchantsments
|
||||
// aren't the exact same.
|
||||
/*
|
||||
* Check if entry enchantment and conflictsWith enchantment conflict
|
||||
* and confirm that the enchantsments aren't the exact same.
|
||||
*/
|
||||
if (entry.getKey().conflictsWith(conflictsWith.getKey()) && !entry.getKey().equals(conflictsWith.getKey())) {
|
||||
conflicts = true;
|
||||
hasConflicts = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conflicts) {
|
||||
if (!hasConflicts) {
|
||||
enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> {
|
||||
int enchantMaxLevel = entry.getKey().getMaxLevel();
|
||||
|
||||
if (a.intValue() == b.intValue()) {
|
||||
|
||||
// Confirm the entry's enchant level doesn't go over the maximum unless it uses
|
||||
// bypass-vanilla-max-level
|
||||
if (enchantMaxLevel <= a && !bypassVanillaMaxLevel.getValue()) {
|
||||
return enchantMaxLevel;
|
||||
} else if (hasCustomMaxLevel.getValue()) {
|
||||
return a + 1 > customMaxLevel.getValue() ? customMaxLevel.getValue() : a + 1;
|
||||
} else {
|
||||
return a + 1;
|
||||
}
|
||||
} else {
|
||||
int highestLevel = Math.max(a, b);
|
||||
|
||||
// Confirm the entry's enchant level doesn't go over the maximum unless it uses
|
||||
// bypass-vanilla-max-level
|
||||
if (enchantMaxLevel <= highestLevel && !bypassVanillaMaxLevel.getValue()) {
|
||||
return enchantMaxLevel;
|
||||
} else if (hasCustomMaxLevel.getValue()) {
|
||||
return highestLevel > customMaxLevel.getValue() ? customMaxLevel.getValue() : highestLevel;
|
||||
} else {
|
||||
return highestLevel;
|
||||
}
|
||||
|
||||
}
|
||||
int maxLevel = entry.getKey().getMaxLevel();
|
||||
return combineEnchantmentLevels(maxLevel, a, b);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -159,4 +136,35 @@ public class BookBinder extends AContainer {
|
||||
return enchantments;
|
||||
|
||||
}
|
||||
|
||||
private int combineEnchantmentLevels(int maxLevel, int lvl1, int lvl2) {
|
||||
if (lvl1 == lvl2) {
|
||||
/*
|
||||
* Confirm the entry's enchant level doesn't go over the maximum
|
||||
* unless it uses bypass-vanilla-max-level
|
||||
*/
|
||||
if (maxLevel <= lvl1 && !bypassVanillaMaxLevel.getValue()) {
|
||||
return maxLevel;
|
||||
} else if (hasCustomMaxLevel.getValue()) {
|
||||
return lvl1 + 1 > customMaxLevel.getValue() ? customMaxLevel.getValue() : lvl1 + 1;
|
||||
} else {
|
||||
return lvl1 + 1;
|
||||
}
|
||||
} else {
|
||||
int highestLevel = Math.max(lvl1, lvl2);
|
||||
|
||||
/*
|
||||
* Confirm the entry's enchant level doesn't go over the maximum
|
||||
* unless it uses bypass-vanilla-max-level
|
||||
*/
|
||||
if (maxLevel <= highestLevel && !bypassVanillaMaxLevel.getValue()) {
|
||||
return maxLevel;
|
||||
} else if (hasCustomMaxLevel.getValue()) {
|
||||
return highestLevel > customMaxLevel.getValue() ? customMaxLevel.getValue() : highestLevel;
|
||||
} else {
|
||||
return highestLevel;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,17 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -14,6 +20,7 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
@ -25,7 +32,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
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.SlimefunItemStack;
|
||||
@ -59,7 +65,8 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
|
||||
|
||||
private int lifetime = 0;
|
||||
|
||||
public AbstractEntityAssembler(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
@ParametersAreNonnullByDefault
|
||||
protected AbstractEntityAssembler(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
new BlockMenuPreset(getId(), item.getImmutableMeta().getDisplayName().orElse("Entity Assembler")) {
|
||||
@ -108,23 +115,10 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
|
||||
}
|
||||
};
|
||||
|
||||
addItemHandler(onPlace());
|
||||
registerBlockHandler(getId(), (p, b, stack, reason) -> {
|
||||
if (reason == UnregisterReason.EXPLODE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), headSlots);
|
||||
inv.dropItems(b.getLocation(), bodySlots);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
addItemHandler(onPlace(), onBreak());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private BlockPlaceHandler onPlace() {
|
||||
return new BlockPlaceHandler(true) {
|
||||
|
||||
@ -145,6 +139,23 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private BlockBreakHandler onBreak() {
|
||||
return new BlockBreakHandler(false, false) {
|
||||
|
||||
@Override
|
||||
public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List<ItemStack> drops) {
|
||||
Block b = e.getBlock();
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), headSlots);
|
||||
inv.dropItems(b.getLocation(), bodySlots);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void updateBlockInventory(BlockMenu menu, Block b) {
|
||||
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), KEY_ENABLED) == null || BlockStorage.getLocationInfo(b.getLocation(), KEY_ENABLED).equals(String.valueOf(false))) {
|
||||
menu.replaceExistingItem(22, new CustomItem(Material.GUNPOWDER, "&7Enabled: &4\u2718", "", "&e> Click to enable this Machine"));
|
||||
|
@ -0,0 +1,39 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
|
||||
|
||||
/**
|
||||
* An {@link AnimalProduce} can be obtained via the {@link ProduceCollector}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see ProduceCollector
|
||||
*
|
||||
*/
|
||||
public class AnimalProduce extends MachineRecipe implements Predicate<LivingEntity> {
|
||||
|
||||
private final Predicate<LivingEntity> predicate;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AnimalProduce(ItemStack input, ItemStack result, Predicate<LivingEntity> predicate) {
|
||||
super(5, new ItemStack[] { input }, new ItemStack[] { result });
|
||||
Validate.notNull(predicate, "The Predicate must not be null");
|
||||
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(@Nonnull LivingEntity entity) {
|
||||
return predicate.test(entity);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
@ -0,0 +1,164 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Cow;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.MushroomCow;
|
||||
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.items.ItemSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
|
||||
/**
|
||||
* The {@link ProduceCollector} allows you to collect produce from animals.
|
||||
* Providing it with a bucket and a nearby {@link Cow} will allow you to obtain milk.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
*/
|
||||
public class ProduceCollector extends AContainer implements RecipeDisplayItem {
|
||||
|
||||
private final ItemSetting<Integer> range = new IntRangeSetting(this, "range", 1, 2, 32);
|
||||
private final Set<AnimalProduce> animalProduces = new HashSet<>();
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public ProduceCollector(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemSetting(range);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultRecipes() {
|
||||
// Milk from adult cows
|
||||
addProduce(new AnimalProduce(new ItemStack(Material.BUCKET), new ItemStack(Material.MILK_BUCKET), n -> {
|
||||
if (n instanceof Cow) {
|
||||
return ((Cow) n).isAdult();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
// Mushroom Stew from Mooshrooms
|
||||
addProduce(new AnimalProduce(new ItemStack(Material.BOWL), new ItemStack(Material.MUSHROOM_STEW), n -> {
|
||||
if (n instanceof MushroomCow) {
|
||||
return ((MushroomCow) n).isAdult();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds a new {@link AnimalProduce} to this machine.
|
||||
*
|
||||
* @param produce
|
||||
* The {@link AnimalProduce} to add
|
||||
*/
|
||||
public void addProduce(@Nonnull AnimalProduce produce) {
|
||||
Validate.notNull(produce, "A produce cannot be null");
|
||||
|
||||
this.animalProduces.add(produce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRegister() {
|
||||
addItemHandler(new BlockTicker() {
|
||||
|
||||
@Override
|
||||
public void tick(Block b, SlimefunItem sf, Config data) {
|
||||
ProduceCollector.this.tick(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronized() {
|
||||
// We override the preRegister() method to override the sync setting here
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getDisplayRecipes() {
|
||||
List<ItemStack> displayRecipes = new ArrayList<>();
|
||||
|
||||
displayRecipes.add(new CustomItem(Material.BUCKET, null, "&fRequires &bCow &fnearby"));
|
||||
displayRecipes.add(new ItemStack(Material.MILK_BUCKET));
|
||||
|
||||
displayRecipes.add(new CustomItem(Material.BOWL, null, "&fRequires &bMooshroom &fnearby"));
|
||||
displayRecipes.add(new ItemStack(Material.MUSHROOM_STEW));
|
||||
|
||||
return displayRecipes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MachineRecipe findNextRecipe(@Nonnull BlockMenu inv) {
|
||||
for (int slot : getInputSlots()) {
|
||||
for (AnimalProduce produce : animalProduces) {
|
||||
ItemStack item = inv.getItemInSlot(slot);
|
||||
|
||||
if (!SlimefunUtils.isItemSimilar(item, produce.getInput()[0], true) || !InvUtils.fits(inv.toInventory(), produce.getOutput()[0], getOutputSlots())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isAnimalNearby(inv.getBlock(), produce::test)) {
|
||||
inv.consumeItem(slot);
|
||||
return produce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean isAnimalNearby(Block b, Predicate<LivingEntity> predicate) {
|
||||
int radius = range.getValue();
|
||||
return !b.getWorld().getNearbyEntities(b.getLocation(), radius, radius, radius, n -> isValidAnimal(n, predicate)).isEmpty();
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private boolean isValidAnimal(Entity n, Predicate<LivingEntity> predicate) {
|
||||
if (n instanceof LivingEntity) {
|
||||
return predicate.test((LivingEntity) n);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineIdentifier() {
|
||||
return "PRODUCE_COLLECTOR";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getProgressBar() {
|
||||
return new ItemStack(Material.SHEARS);
|
||||
}
|
||||
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||
|
||||
public class XPCollector extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
|
||||
|
||||
private final int[] border = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
|
||||
|
||||
private static final int ENERGY_CONSUMPTION = 10;
|
||||
private static final String DATA_KEY = "stored-exp";
|
||||
|
||||
public XPCollector(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
createPreset(this, this::constructMenu);
|
||||
|
||||
addItemHandler(onPlace());
|
||||
registerBlockHandler(getId(), (p, b, stack, reason) -> {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private BlockPlaceHandler onPlace() {
|
||||
return new BlockPlaceHandler(false) {
|
||||
|
||||
@Override
|
||||
public void onPlayerPlace(BlockPlaceEvent e) {
|
||||
BlockStorage.addBlockInfo(e.getBlock(), "owner", e.getPlayer().getUniqueId().toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputSlots() {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getOutputSlots() {
|
||||
return new int[] { 12, 13, 14 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnergyNetComponentType getEnergyComponentType() {
|
||||
return EnergyNetComponentType.CONSUMER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCapacity() {
|
||||
return 1024;
|
||||
}
|
||||
|
||||
protected void constructMenu(BlockMenuPreset preset) {
|
||||
for (int slot : border) {
|
||||
preset.addItem(slot, new CustomItem(Material.PURPLE_STAINED_GLASS_PANE, " "), (p, s, item, action) -> false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRegister() {
|
||||
addItemHandler(new BlockTicker() {
|
||||
|
||||
@Override
|
||||
public void tick(Block b, SlimefunItem sf, Config data) {
|
||||
XPCollector.this.tick(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronized() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void tick(Block b) {
|
||||
Iterator<Entity> iterator = b.getWorld().getNearbyEntities(b.getLocation(), 4.0, 4.0, 4.0, n -> n instanceof ExperienceOrb && n.isValid()).iterator();
|
||||
int experiencePoints = 0;
|
||||
|
||||
while (iterator.hasNext() && experiencePoints == 0) {
|
||||
Entity entity = iterator.next();
|
||||
|
||||
if (getCharge(b.getLocation()) < ENERGY_CONSUMPTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
experiencePoints = getStoredExperience(b) + ((ExperienceOrb) entity).getExperience();
|
||||
|
||||
removeCharge(b.getLocation(), ENERGY_CONSUMPTION);
|
||||
entity.remove();
|
||||
|
||||
int withdrawn = 0;
|
||||
BlockMenu menu = BlockStorage.getInventory(b);
|
||||
|
||||
for (int level = 0; level < getStoredExperience(b); level = level + 10) {
|
||||
if (menu.fits(SlimefunItems.FILLED_FLASK_OF_KNOWLEDGE, getOutputSlots())) {
|
||||
withdrawn = withdrawn + 10;
|
||||
menu.pushItem(SlimefunItems.FILLED_FLASK_OF_KNOWLEDGE.clone(), getOutputSlots());
|
||||
}
|
||||
}
|
||||
|
||||
BlockStorage.addBlockInfo(b, DATA_KEY, String.valueOf(experiencePoints - withdrawn));
|
||||
}
|
||||
}
|
||||
|
||||
private int getStoredExperience(Block b) {
|
||||
Config cfg = BlockStorage.getLocationInfo(b.getLocation());
|
||||
String value = cfg.getString(DATA_KEY);
|
||||
|
||||
if (value != null) {
|
||||
return Integer.parseInt(value);
|
||||
} else {
|
||||
BlockStorage.addBlockInfo(b, DATA_KEY, "0");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -53,7 +53,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
public GEOMiner(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemHandler(onPlace(), onBreak());
|
||||
addItemHandler(onPlace());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -68,7 +68,8 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private BlockBreakHandler onBreak() {
|
||||
@Override
|
||||
protected BlockBreakHandler onBlockBreak() {
|
||||
return new SimpleBlockBreakHandler() {
|
||||
|
||||
@Override
|
||||
@ -87,26 +88,31 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMachineIdentifier() {
|
||||
return "GEO_MINER";
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack getProgressBar() {
|
||||
return new ItemStack(Material.DIAMOND_PICKAXE);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public int[] getInputSlots() {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public int[] getOutputSlots() {
|
||||
return OUTPUT_SLOTS;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<ItemStack> getDisplayRecipes() {
|
||||
List<ItemStack> displayRecipes = new LinkedList<>();
|
||||
@ -120,13 +126,14 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
return displayRecipes;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getLabelLocalPath() {
|
||||
return "guide.tooltips.recipes.miner";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void constructMenu(BlockMenuPreset preset) {
|
||||
protected void constructMenu(@Nonnull BlockMenuPreset preset) {
|
||||
for (int i : BORDER) {
|
||||
preset.addItem(i, new CustomItem(Material.GRAY_STAINED_GLASS_PANE, " "), (p, slot, item, action) -> false);
|
||||
}
|
||||
@ -154,7 +161,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(Block b) {
|
||||
protected void tick(@Nonnull Block b) {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (isProcessing(b)) {
|
||||
@ -183,7 +190,7 @@ public class GEOMiner extends AContainer implements RecipeDisplayItem, HologramO
|
||||
}
|
||||
}
|
||||
|
||||
private void start(Block b, BlockMenu inv) {
|
||||
private void start(@Nonnull Block b, @Nonnull BlockMenu inv) {
|
||||
for (GEOResource resource : SlimefunPlugin.getRegistry().getGEOResources().values()) {
|
||||
if (resource.isObtainableFromGEOMiner()) {
|
||||
OptionalInt optional = SlimefunPlugin.getGPSNetwork().getResourceManager().getSupplies(resource, b.getWorld(), b.getX() >> 4, b.getZ() >> 4);
|
||||
|
@ -0,0 +1,60 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.misc;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Smeltery;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
/**
|
||||
* The {@link GoldIngot} from Slimefun is a simple resource which is divided into different
|
||||
* levels of carat ratings.
|
||||
* <p>
|
||||
* It can be obtained via gold dust and other gold ingots in a {@link Smeltery}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see Smeltery
|
||||
*
|
||||
*/
|
||||
public class GoldIngot extends SlimefunItem {
|
||||
|
||||
/**
|
||||
* The carat rating.
|
||||
*/
|
||||
private final int caratRating;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public GoldIngot(Category category, int caratRating, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
Validate.isTrue(caratRating > 0, "Carat rating must be above zero.");
|
||||
Validate.isTrue(caratRating <= 24, "Carat rating cannot go above 24.");
|
||||
this.caratRating = caratRating;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the carat rating of this {@link GoldIngot}.
|
||||
* <p>
|
||||
* The purity of the {@link GoldIngot} is measured in carat (1-24).
|
||||
*
|
||||
* <pre>
|
||||
* 24k = 100% gold.
|
||||
* 18k = 75% gold.
|
||||
* 12k = 50% gold.
|
||||
* </pre>
|
||||
*
|
||||
* and so on...
|
||||
*
|
||||
* @return The carat rating of this {@link GoldIngot}
|
||||
*/
|
||||
public int getCaratRating() {
|
||||
return caratRating;
|
||||
}
|
||||
|
||||
}
|
@ -51,7 +51,11 @@ public class ArmorForge extends AbstractCraftingTable {
|
||||
}
|
||||
}
|
||||
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
if (inv.isEmpty()) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.inventory-empty", true);
|
||||
} else {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,11 @@ public class EnhancedCraftingTable extends AbstractCraftingTable {
|
||||
}
|
||||
}
|
||||
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
if (inv.isEmpty()) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.inventory-empty", true);
|
||||
} else {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,9 @@ public class GrindStone extends MultiBlockMachine {
|
||||
|
||||
recipes.add(new ItemStack(Material.NETHER_WART_BLOCK));
|
||||
recipes.add(new ItemStack(Material.NETHER_WART, 9));
|
||||
|
||||
recipes.add(new ItemStack(Material.QUARTZ_BLOCK));
|
||||
recipes.add(new ItemStack(Material.QUARTZ, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,7 +57,11 @@ public class MagicWorkbench extends AbstractCraftingTable {
|
||||
}
|
||||
}
|
||||
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
if (inv.isEmpty()) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.inventory-empty", true);
|
||||
} else {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class OreCrusher extends MultiBlockMachine {
|
||||
recipes.add(new ItemStack(Material.GRAVEL));
|
||||
recipes.add(new ItemStack(Material.SAND));
|
||||
|
||||
recipes.add(new ItemStack(Material.MAGMA_BLOCK, 4));
|
||||
recipes.add(new ItemStack(Material.MAGMA_BLOCK));
|
||||
recipes.add(SlimefunItems.SULFATE);
|
||||
|
||||
recipes.add(SlimefunItems.CARBON);
|
||||
|
@ -11,6 +11,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
@ -235,7 +236,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damageItem(Player p, ItemStack item) {
|
||||
public void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
|
||||
if (p.getGameMode() != GameMode.CREATIVE) {
|
||||
DamageableItem.super.damageItem(p, item);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@ -20,15 +21,14 @@ import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEve
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
@ -64,12 +64,12 @@ public class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements
|
||||
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
||||
|
||||
List<Block> blocks = findBlocks(b);
|
||||
breakBlocks(p, tool, b, blocks, drops);
|
||||
breakBlocks(e, p, tool, b, blocks, drops);
|
||||
};
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private void breakBlocks(Player p, ItemStack item, Block b, List<Block> blocks, List<ItemStack> drops) {
|
||||
private void breakBlocks(BlockBreakEvent e, Player p, ItemStack item, Block b, List<Block> blocks, List<ItemStack> drops) {
|
||||
List<Block> blocksToDestroy = new ArrayList<>();
|
||||
|
||||
if (callExplosionEvent.getValue().booleanValue()) {
|
||||
@ -96,7 +96,7 @@ public class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
for (Block block : blocksToDestroy) {
|
||||
breakBlock(p, item, block, drops);
|
||||
breakBlock(e, p, item, block, drops);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,7 +141,7 @@ public class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private void breakBlock(Player p, ItemStack item, Block b, List<ItemStack> drops) {
|
||||
private void breakBlock(BlockBreakEvent e, Player p, ItemStack item, Block b, List<ItemStack> drops) {
|
||||
SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK);
|
||||
Material material = b.getType();
|
||||
|
||||
@ -149,10 +149,8 @@ public class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements
|
||||
SlimefunItem sfItem = BlockStorage.check(b);
|
||||
|
||||
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
|
||||
SlimefunBlockHandler handler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getId());
|
||||
|
||||
if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) {
|
||||
drops.add(BlockStorage.retrieve(b));
|
||||
if (!sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(e, item, drops))) {
|
||||
drops.addAll(sfItem.getDrops(p));
|
||||
}
|
||||
} else {
|
||||
b.breakNaturally(item);
|
||||
|
@ -4,6 +4,7 @@ import java.util.UUID;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Bat;
|
||||
@ -54,7 +55,7 @@ public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
|
||||
return e -> {
|
||||
Player p = e.getPlayer();
|
||||
UUID uuid = p.getUniqueId();
|
||||
boolean isConsumed = consumeOnUse.getValue();
|
||||
boolean isConsumed = consumeOnUse.getValue() && p.getGameMode() != GameMode.CREATIVE;
|
||||
|
||||
if (!e.getClickedBlock().isPresent() && !SlimefunPlugin.getGrapplingHookListener().isGrappling(uuid)) {
|
||||
e.cancel();
|
||||
|
@ -14,6 +14,7 @@ import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.AbstractAutoCrafter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.EnhancedAutoCrafter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.Multimeter;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
|
||||
/**
|
||||
@ -50,6 +51,13 @@ public class AutoCrafterListener implements Listener {
|
||||
SlimefunItem block = slimefunBlock.get();
|
||||
|
||||
if (block instanceof AbstractAutoCrafter) {
|
||||
Optional<SlimefunItem> slimefunItem = e.getSlimefunItem();
|
||||
|
||||
if (!e.getPlayer().isSneaking() && slimefunItem.isPresent() && slimefunItem.get() instanceof Multimeter) {
|
||||
// Allow Multimeters to pass through and do their job
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent blocks from being placed, food from being eaten, etc...
|
||||
e.cancel();
|
||||
|
||||
|
@ -21,6 +21,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
|
||||
@ -29,9 +30,7 @@ import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
|
||||
@ -156,22 +155,10 @@ public class BlockListener implements Listener {
|
||||
}
|
||||
|
||||
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
|
||||
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getId());
|
||||
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(e, item, drops));
|
||||
|
||||
if (blockHandler != null) {
|
||||
try {
|
||||
if (!blockHandler.onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK)) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
} catch (Exception | LinkageError x) {
|
||||
sfItem.error("Something went wrong while triggering a BlockHandler", x);
|
||||
}
|
||||
} else {
|
||||
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(e, item, drops));
|
||||
if (e.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
if (e.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
drops.addAll(sfItem.getDrops());
|
||||
@ -191,6 +178,7 @@ public class BlockListener implements Listener {
|
||||
e.setDropItems(false);
|
||||
|
||||
for (ItemStack drop : drops) {
|
||||
// Prevent null or air from being dropped
|
||||
if (drop != null && drop.getType() != Material.AIR) {
|
||||
e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), drop);
|
||||
}
|
||||
@ -217,33 +205,27 @@ public class BlockListener implements Listener {
|
||||
SlimefunItem sfItem = BlockStorage.check(blockAbove);
|
||||
|
||||
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
|
||||
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(sfItem.getId());
|
||||
/*
|
||||
* We create a dummy here to pass onto the BlockBreakHandler.
|
||||
* This will set the correct block context.
|
||||
*/
|
||||
BlockBreakEvent dummyEvent = new BlockBreakEvent(blockAbove, e.getPlayer());
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
drops.addAll(sfItem.getDrops(e.getPlayer()));
|
||||
|
||||
if (blockHandler != null) {
|
||||
if (blockHandler.onBreak(e.getPlayer(), blockAbove, sfItem, UnregisterReason.PLAYER_BREAK)) {
|
||||
blockAbove.getWorld().dropItemNaturally(blockAbove.getLocation(), BlockStorage.retrieve(blockAbove));
|
||||
blockAbove.setType(Material.AIR);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We create a dummy here to pass onto the BlockBreakHandler.
|
||||
* This will set the correct block context.
|
||||
*/
|
||||
BlockBreakEvent dummyEvent = new BlockBreakEvent(blockAbove, e.getPlayer());
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
drops.addAll(sfItem.getDrops(e.getPlayer()));
|
||||
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops));
|
||||
blockAbove.setType(Material.AIR);
|
||||
|
||||
sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops));
|
||||
blockAbove.setType(Material.AIR);
|
||||
|
||||
if (!dummyEvent.isCancelled() && dummyEvent.isDropItems()) {
|
||||
for (ItemStack drop : drops) {
|
||||
if (drop != null && drop.getType() != Material.AIR) {
|
||||
blockAbove.getWorld().dropItemNaturally(blockAbove.getLocation(), drop);
|
||||
}
|
||||
if (!dummyEvent.isCancelled() && dummyEvent.isDropItems()) {
|
||||
for (ItemStack drop : drops) {
|
||||
if (drop != null && !drop.getType().isAir()) {
|
||||
blockAbove.getWorld().dropItemNaturally(blockAbove.getLocation(), drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes #2944 - Don't forget to clear the Block Data
|
||||
BlockStorage.clearBlockInfo(blockAbove);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -251,10 +233,17 @@ public class BlockListener implements Listener {
|
||||
private int getBonusDropsWithFortune(@Nullable ItemStack item, @Nonnull Block b) {
|
||||
int amount = 1;
|
||||
|
||||
if (item != null) {
|
||||
int fortuneLevel = item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS);
|
||||
if (item != null && !item.getType().isAir() && item.hasItemMeta()) {
|
||||
/*
|
||||
* Small performance optimization:
|
||||
* ItemStack#getEnchantmentLevel() calls ItemStack#getItemMeta(), so if
|
||||
* we are handling more than one Enchantment, we should access the ItemMeta
|
||||
* directly and re use it.
|
||||
*/
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
int fortuneLevel = meta.getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS);
|
||||
|
||||
if (fortuneLevel > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
|
||||
if (fortuneLevel > 0 && !meta.hasEnchant(Enchantment.SILK_TOUCH)) {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
|
||||
amount = Math.max(1, random.nextInt(fortuneLevel + 2) - 1);
|
||||
|
@ -5,6 +5,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
@ -18,9 +19,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.WitherProof;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
|
||||
/**
|
||||
@ -58,36 +57,26 @@ public class ExplosionsListener implements Listener {
|
||||
if (item != null) {
|
||||
blocks.remove();
|
||||
|
||||
if (!(item instanceof WitherProof)) {
|
||||
SlimefunBlockHandler blockHandler = SlimefunPlugin.getRegistry().getBlockHandlers().get(item.getId());
|
||||
boolean success = true;
|
||||
if (!(item instanceof WitherProof) && !item.callItemHandler(BlockBreakHandler.class, handler -> handleExplosion(handler, block))) {
|
||||
BlockStorage.clearBlockInfo(block);
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blockHandler != null) {
|
||||
success = blockHandler.onBreak(null, block, item, UnregisterReason.EXPLODE);
|
||||
} else {
|
||||
item.callItemHandler(BlockBreakHandler.class, handler -> {
|
||||
if (handler.isExplosionAllowed(block)) {
|
||||
BlockStorage.clearBlockInfo(block);
|
||||
block.setType(Material.AIR);
|
||||
@ParametersAreNonnullByDefault
|
||||
private void handleExplosion(BlockBreakHandler handler, Block block) {
|
||||
if (handler.isExplosionAllowed(block)) {
|
||||
BlockStorage.clearBlockInfo(block);
|
||||
block.setType(Material.AIR);
|
||||
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
handler.onExplode(block, drops);
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
handler.onExplode(block, drops);
|
||||
|
||||
for (ItemStack drop : drops) {
|
||||
if (drop != null && !drop.getType().isAir()) {
|
||||
block.getWorld().dropItemNaturally(block.getLocation(), drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
BlockStorage.clearBlockInfo(block);
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
for (ItemStack drop : drops) {
|
||||
if (drop != null && !drop.getType().isAir()) {
|
||||
block.getWorld().dropItemNaturally(block.getLocation(), drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -43,7 +42,7 @@ public class SoulboundListener implements Listener {
|
||||
ItemStack item = p.getInventory().getItem(slot);
|
||||
|
||||
// Store soulbound items for later retrieval
|
||||
if (SlimefunUtils.isSoulbound(item)) {
|
||||
if (SlimefunUtils.isSoulbound(item, p.getWorld())) {
|
||||
items.put(slot, item);
|
||||
}
|
||||
}
|
||||
@ -58,14 +57,7 @@ public class SoulboundListener implements Listener {
|
||||
}
|
||||
|
||||
// Remove soulbound items from our drops
|
||||
Iterator<ItemStack> drops = e.getDrops().iterator();
|
||||
while (drops.hasNext()) {
|
||||
ItemStack item = drops.next();
|
||||
|
||||
if (SlimefunUtils.isSoulbound(item)) {
|
||||
drops.remove();
|
||||
}
|
||||
}
|
||||
e.getDrops().removeIf(itemStack -> SlimefunUtils.isSoulbound(itemStack, p.getWorld()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -278,7 +278,14 @@ public class TalismanListener implements Listener {
|
||||
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
|
||||
|
||||
// We are going to ignore Silk Touch here
|
||||
if (item.getType() != Material.AIR && item.getAmount() > 0 && !item.containsEnchantment(Enchantment.SILK_TOUCH)) {
|
||||
if (item.getType() != Material.AIR && item.getAmount() > 0) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
// Ignore Silk Touch Enchantment
|
||||
if (meta.hasEnchant(Enchantment.SILK_TOUCH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material type = e.getBlockState().getType();
|
||||
|
||||
// We only want to double ores
|
||||
@ -286,7 +293,7 @@ public class TalismanListener implements Listener {
|
||||
Collection<Item> drops = e.getItems();
|
||||
|
||||
if (Talisman.trigger(e, SlimefunItems.TALISMAN_MINER, false)) {
|
||||
int dropAmount = getAmountWithFortune(type, item.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS));
|
||||
int dropAmount = getAmountWithFortune(type, meta.getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS));
|
||||
|
||||
// Keep track of whether we actually doubled the drops or not
|
||||
boolean doubledDrops = false;
|
||||
|
@ -27,7 +27,6 @@ import com.google.gson.JsonParser;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutomatedCraftingChamber;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.GrindStone;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.MakeshiftSmeltery;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.OreCrusher;
|
||||
@ -78,7 +77,6 @@ public final class PostSetup {
|
||||
}
|
||||
}
|
||||
|
||||
loadAutomaticCraftingChamber();
|
||||
loadOreGrinderRecipes();
|
||||
loadSmelteryRecipes();
|
||||
|
||||
@ -128,14 +126,6 @@ public final class PostSetup {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static void loadAutomaticCraftingChamber() {
|
||||
AutomatedCraftingChamber crafter = (AutomatedCraftingChamber) SlimefunItems.AUTOMATED_CRAFTING_CHAMBER.getItem();
|
||||
|
||||
if (crafter != null) {
|
||||
crafter.loadRecipes();
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadOreGrinderRecipes() {
|
||||
List<ItemStack[]> grinderRecipes = new ArrayList<>();
|
||||
|
||||
|
@ -181,7 +181,7 @@ public final class ResearchSetup {
|
||||
register("electric_furnaces", 170, "Powered Furnace", 15, SlimefunItems.ELECTRIC_FURNACE);
|
||||
register("electric_ore_grinding", 171, "Crushing and Grinding", 20, SlimefunItems.ELECTRIC_ORE_GRINDER, SlimefunItems.ELECTRIC_INGOT_PULVERIZER);
|
||||
register("heated_pressure_chamber", 172, "Heated Pressure Chamber", 22, SlimefunItems.HEATED_PRESSURE_CHAMBER);
|
||||
register("coal_generator", 173, "Coal Generator", 18, SlimefunItems.COAL_GENERATOR);
|
||||
register("coal_generator", 173, "Coal Generator", 14, SlimefunItems.COAL_GENERATOR);
|
||||
register("bio_reactor", 173, "Bio-Reactor", 18, SlimefunItems.BIO_REACTOR);
|
||||
register("auto_enchanting", 174, "Automatic Enchanting and Disenchanting", 24, SlimefunItems.AUTO_ENCHANTER, SlimefunItems.AUTO_DISENCHANTER);
|
||||
register("auto_anvil", 175, "Automatic Anvil", 34, SlimefunItems.AUTO_ANVIL, SlimefunItems.AUTO_ANVIL_2);
|
||||
@ -217,7 +217,8 @@ public final class ResearchSetup {
|
||||
register("cargo_basics", 205, "Cargo Basics", 30, SlimefunItems.CARGO_MOTOR, SlimefunItems.CARGO_MANAGER, SlimefunItems.CARGO_CONNECTOR_NODE);
|
||||
register("cargo_nodes", 206, "Cargo Setup", 30, SlimefunItems.CARGO_INPUT_NODE, SlimefunItems.CARGO_OUTPUT_NODE);
|
||||
register("electric_ingot_machines", 207, "Electric Ingot Fabrication", 18, SlimefunItems.ELECTRIC_GOLD_PAN, SlimefunItems.ELECTRIC_DUST_WASHER, SlimefunItems.ELECTRIC_INGOT_FACTORY);
|
||||
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2, SlimefunItems.ELECTRIC_ORE_GRINDER_3);
|
||||
register("medium_tier_electric_ingot_machines", 208, "Fast Ingot Fabrication", 25, SlimefunItems.ELECTRIC_GOLD_PAN_2, SlimefunItems.ELECTRIC_DUST_WASHER_2, SlimefunItems.ELECTRIC_INGOT_FACTORY_2, SlimefunItems.ELECTRIC_ORE_GRINDER_2);
|
||||
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_3);
|
||||
register("automated_crafting_chamber", 210, "Automated Crafting", 20, SlimefunItems.AUTOMATED_CRAFTING_CHAMBER);
|
||||
register("better_food_fabricator", 211, "Upgraded Food Fabrication", 28, SlimefunItems.FOOD_FABRICATOR_2, SlimefunItems.FOOD_COMPOSTER_2);
|
||||
register("reactor_access_port", 212, "Reactor Interaction", 18, SlimefunItems.REACTOR_ACCESS_PORT);
|
||||
@ -242,7 +243,7 @@ public final class ResearchSetup {
|
||||
register("better_electric_crucibles", 231, "Hot Crucibles", 30, SlimefunItems.ELECTRIFIED_CRUCIBLE_2, SlimefunItems.ELECTRIFIED_CRUCIBLE_3);
|
||||
register("advanced_electric_smeltery", 232, "Advanced Electric Smeltery", 28, SlimefunItems.ELECTRIC_SMELTERY_2);
|
||||
register("advanced_farmer_android", 233, "Advanced Androids - Farmer", 30, SlimefunItems.PROGRAMMABLE_ANDROID_2_FARMER);
|
||||
register("lava_generator", 234, "Lava Generator", 38, SlimefunItems.LAVA_GENERATOR);
|
||||
register("lava_generator", 234, "Lava Generator", 16, SlimefunItems.LAVA_GENERATOR);
|
||||
register("nether_ice", 235, "Nether Ice Coolant", 45, SlimefunItems.NETHER_ICE, SlimefunItems.ENRICHED_NETHER_ICE, SlimefunItems.NETHER_ICE_COOLANT_CELL);
|
||||
register("nether_star_reactor", 236, "Nether Star Reactor", 60, SlimefunItems.NETHER_STAR_REACTOR);
|
||||
register("blistering_ingots", 237, "Blistering Radioactivity", 38, SlimefunItems.BLISTERING_INGOT, SlimefunItems.BLISTERING_INGOT_2, SlimefunItems.BLISTERING_INGOT_3);
|
||||
@ -282,7 +283,10 @@ public final class ResearchSetup {
|
||||
register("bee_armor", 270, "Bee Armor", 24, SlimefunItems.BEE_HELMET, SlimefunItems.BEE_WINGS, SlimefunItems.BEE_LEGGINGS, SlimefunItems.BEE_BOOTS);
|
||||
register("wise_talisman", 271, "Talisman of the Wise", 20, SlimefunItems.TALISMAN_WISE);
|
||||
register("book_binder", 272, "Enchantment Book Binding", 26, SlimefunItems.BOOK_BINDER);
|
||||
register("auto_crafting", 273, "Automatic Crafting", 30, SlimefunItems.VANILLA_AUTO_CRAFTER, SlimefunItems.ENHANCED_AUTO_CRAFTER);
|
||||
register("auto_crafting", 273, "Automatic Crafting", 30, SlimefunItems.CRAFTING_MOTOR, SlimefunItems.VANILLA_AUTO_CRAFTER, SlimefunItems.ENHANCED_AUTO_CRAFTER, SlimefunItems.ARMOR_AUTO_CRAFTER);
|
||||
register("produce_collector", 274, "Automatic Milking", 20, SlimefunItems.PRODUCE_COLLECTOR);
|
||||
register("improved_generators", 275, "Improved Generators", 24, SlimefunItems.COAL_GENERATOR_2, SlimefunItems.LAVA_GENERATOR_2);
|
||||
register("ingredients_and_cheese", 276, "Slimefun Cuisine", 5, SlimefunItems.SALT, SlimefunItems.WHEAT_FLOUR, SlimefunItems.HEAVY_CREAM, SlimefunItems.CHEESE, SlimefunItems.BUTTER);
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
|
@ -40,6 +40,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.armor.LongFallBoo
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.Parachute;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.ArmorAutoCrafter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.EnhancedAutoCrafter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.autocrafters.VanillaAutoCrafter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler;
|
||||
@ -82,7 +83,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.generato
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.generators.MagnesiumGenerator;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.generators.SolarGenerator;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoAnvil;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoBreeder;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoBrewer;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoDrier;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutomatedCraftingChamber;
|
||||
@ -109,9 +109,11 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoDisenchanter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoEnchanter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.BookBinder;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.IronGolemAssembler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.WitherAssembler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.AutoBreeder;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.ExpCollector;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.IronGolemAssembler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.ProduceCollector;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.entities.WitherAssembler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NetherStarReactor;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NuclearReactor;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate;
|
||||
@ -157,6 +159,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.medical.Splint;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.medical.Vitamins;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.BasicCircuitBoard;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.CoolantCell;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.GoldIngot;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.OrganicFertilizer;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.OrganicFood;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.misc.SteelThruster;
|
||||
@ -715,47 +718,47 @@ public final class SlimefunItemSetup {
|
||||
|
||||
new OreWasher(categories.basicMachines, SlimefunItems.ORE_WASHER).register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_24K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 24, SlimefunItems.GOLD_24K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_22K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_22K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 22, SlimefunItems.GOLD_22K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_20K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_20K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 20, SlimefunItems.GOLD_20K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_18K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_18K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 18, SlimefunItems.GOLD_18K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_16K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_16K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 16, SlimefunItems.GOLD_16K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_14K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_14K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 14, SlimefunItems.GOLD_14K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_12K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_12K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 12, SlimefunItems.GOLD_12K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_10K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_10K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 10, SlimefunItems.GOLD_10K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_8K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_8K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 8, SlimefunItems.GOLD_8K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_6K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_6K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 6, SlimefunItems.GOLD_6K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, SlimefunItems.GOLD_4K, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GOLD_4K, RecipeType.SMELTERY,
|
||||
new GoldIngot(categories.resources, 4, SlimefunItems.GOLD_4K, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_DUST, null, null, null, null, null, null, null, null})
|
||||
.setUseableInWorkbench(true)
|
||||
.register(plugin);
|
||||
@ -768,7 +771,7 @@ public final class SlimefunItemSetup {
|
||||
new ItemStack[] {new ItemStack(Material.QUARTZ_BLOCK), null, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.technicalComponents, SlimefunItems.SOLAR_PANEL, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new UnplaceableBlock(categories.technicalComponents, SlimefunItems.SOLAR_PANEL, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {new ItemStack(Material.GLASS), new ItemStack(Material.GLASS), new ItemStack(Material.GLASS), SlimefunItems.SILICON, SlimefunItems.SILICON, SlimefunItems.SILICON, SlimefunItems.FERROSILICON, SlimefunItems.FERROSILICON, SlimefunItems.FERROSILICON})
|
||||
.register(plugin);
|
||||
|
||||
@ -1481,7 +1484,7 @@ public final class SlimefunItemSetup {
|
||||
new SlimefunItemStack(SlimefunItems.WITHER_PROOF_OBSIDIAN, 4))
|
||||
.register(plugin);
|
||||
|
||||
new AncientPedestal(categories.magicalResources, SlimefunItems.ANCIENT_PEDESTAL, RecipeType.MAGIC_WORKBENCH,
|
||||
new AncientPedestal(categories.magicalGadgets, SlimefunItems.ANCIENT_PEDESTAL, RecipeType.MAGIC_WORKBENCH,
|
||||
new ItemStack[] {new ItemStack(Material.OBSIDIAN), SlimefunItems.GOLD_8K, new ItemStack(Material.OBSIDIAN), null, new ItemStack(Material.STONE), null, new ItemStack(Material.OBSIDIAN), SlimefunItems.GOLD_8K, new ItemStack(Material.OBSIDIAN)},
|
||||
new SlimefunItemStack(SlimefunItems.ANCIENT_PEDESTAL, 4))
|
||||
.register(plugin);
|
||||
@ -2476,7 +2479,7 @@ public final class SlimefunItemSetup {
|
||||
.register(plugin);
|
||||
|
||||
new AutomatedCraftingChamber(categories.electricity, SlimefunItems.AUTOMATED_CRAFTING_CHAMBER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, new ItemStack(Material.CRAFTING_TABLE), null, SlimefunItems.CARGO_MOTOR, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.CARGO_MOTOR, null, SlimefunItems.ELECTRIC_MOTOR, null}) {
|
||||
new ItemStack[] {null, null, null, null, new CustomItem(Material.BARRIER, "&4This Item has been disabled.", "&cIt will soon be removed!", "&cPlease switch over to the new", "&cAuto-Crafters from the Cargo Category."), null, null, null, null}) {
|
||||
|
||||
@Override
|
||||
public int getEnergyConsumption() {
|
||||
@ -2584,19 +2587,37 @@ public final class SlimefunItemSetup {
|
||||
new ElytraCap(categories.magicalArmor, SlimefunItems.ELYTRA_CAP, RecipeType.ARMOR_FORGE,
|
||||
new ItemStack[] {new ItemStack(Material.SLIME_BALL), new ItemStack(Material.SLIME_BALL), new ItemStack(Material.SLIME_BALL), SlimefunItems.ELYTRA_SCALE, SlimefunItems.ELYTRA_SCALE, SlimefunItems.ELYTRA_SCALE, new ItemStack(Material.SLIME_BALL), new ItemStack(Material.LEATHER_HELMET), new ItemStack(Material.SLIME_BALL)})
|
||||
.register(plugin);
|
||||
|
||||
new UnplaceableBlock(categories.cargo, SlimefunItems.CRAFTING_MOTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.BLISTERING_INGOT_3, new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.REDSTONE_ALLOY, SlimefunItems.CARGO_MOTOR, SlimefunItems.REDSTONE_ALLOY, new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.BLISTERING_INGOT_3, new ItemStack(Material.CRAFTING_TABLE)},
|
||||
new SlimefunItemStack(SlimefunItems.CRAFTING_MOTOR, 2))
|
||||
.register(plugin);
|
||||
|
||||
new VanillaAutoCrafter(categories.cargo, SlimefunItems.VANILLA_AUTO_CRAFTER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, SlimefunItems.BLISTERING_INGOT_3, null, new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.CARGO_MOTOR, new ItemStack(Material.CRAFTING_TABLE), null, SlimefunItems.ELECTRIC_MOTOR, null})
|
||||
new ItemStack[] {null, SlimefunItems.CARGO_MOTOR, null, new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.CRAFTING_MOTOR, new ItemStack(Material.CRAFTING_TABLE), null, SlimefunItems.ELECTRIC_MOTOR, null})
|
||||
.setCapacity(256)
|
||||
.setEnergyConsumption(16)
|
||||
.register(plugin);
|
||||
|
||||
new EnhancedAutoCrafter(categories.cargo, SlimefunItems.ENHANCED_AUTO_CRAFTER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, SlimefunItems.VANILLA_AUTO_CRAFTER, null, new ItemStack(Material.CRAFTING_TABLE), new ItemStack(Material.DISPENSER), new ItemStack(Material.CRAFTING_TABLE), null, SlimefunItems.CARGO_MOTOR, null})
|
||||
new ItemStack[] {null, SlimefunItems.CRAFTING_MOTOR, null, new ItemStack(Material.CRAFTING_TABLE), new ItemStack(Material.DISPENSER), new ItemStack(Material.CRAFTING_TABLE), null, SlimefunItems.CARGO_MOTOR, null})
|
||||
.setCapacity(256)
|
||||
.setEnergyConsumption(16)
|
||||
.register(plugin);
|
||||
|
||||
new ArmorAutoCrafter(categories.cargo, SlimefunItems.ARMOR_AUTO_CRAFTER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, SlimefunItems.CRAFTING_MOTOR, null, new ItemStack(Material.DISPENSER), new ItemStack(Material.ANVIL), new ItemStack(Material.DISPENSER), new ItemStack(Material.CRAFTING_TABLE), SlimefunItems.ELECTRIC_MOTOR, new ItemStack(Material.CRAFTING_TABLE)})
|
||||
.setCapacity(256)
|
||||
.setEnergyConsumption(32)
|
||||
.register(plugin);
|
||||
|
||||
new ProduceCollector(categories.electricity, SlimefunItems.PRODUCE_COLLECTOR, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, new ItemStack(Material.HAY_BLOCK), null, new ItemStack(Material.BUCKET), SlimefunItems.MEDIUM_CAPACITOR, new ItemStack(Material.BUCKET), SlimefunItems.ALUMINUM_BRASS_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.ALUMINUM_BRASS_INGOT})
|
||||
.setCapacity(256)
|
||||
.setProcessingSpeed(1)
|
||||
.setEnergyConsumption(16)
|
||||
.register(plugin);
|
||||
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,11 @@ public enum HeadTexture {
|
||||
PIGLIN_HEAD("2882af1294a74023e6919a31d1a027310f2e142afb4667d230d155e7f21dbb41"),
|
||||
NECROTIC_SKULL("7953b6c68448e7e6b6bf8fb273d7203acd8e1be19e81481ead51f45de59a8"),
|
||||
VANILLA_AUTO_CRAFTER("80a4334f6a61e40c0c63deb665fa7b581e6eb259f7a3207ced7a1ff8bdc8a9f9"),
|
||||
ENHANCED_AUTO_CRAFTER("5038298306a5e28584df39e88896917c38d40a326226d8c83070723c95798b24");
|
||||
ENHANCED_AUTO_CRAFTER("5038298306a5e28584df39e88896917c38d40a326226d8c83070723c95798b24"),
|
||||
ARMOR_AUTO_CRAFTER("5cbd9f5ec1ed007259996491e69ff649a3106cf920227b1bb3a71ee7a89863f"),
|
||||
EXCLAMATION_MARK("2e3f50ba62cbda3ecf5479b62fedebd61d76589771cc19286bf2745cd71e47c6"),
|
||||
CARGO_MOTOR("8e47f99abcd645a3ef1122c9d850a981979f431ba293255c1680e91ab117ed35"),
|
||||
CRAFTING_MOTOR("1003620899f1afa271e8e521ecbee2977a06c8529d3f389e8cc04af06d8c7940");
|
||||
|
||||
private final String texture;
|
||||
private final UUID uuid;
|
||||
|
@ -14,6 +14,7 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@ -79,15 +80,29 @@ public final class SlimefunUtils {
|
||||
|
||||
/**
|
||||
* This method checks whether the given {@link ItemStack} is considered {@link Soulbound}.
|
||||
*
|
||||
*
|
||||
* @param item
|
||||
* The {@link ItemStack} to check for
|
||||
* @return Whether the given item is soulbound
|
||||
*/
|
||||
public static boolean isSoulbound(@Nullable ItemStack item) {
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
return false;
|
||||
} else {
|
||||
return isSoulbound(item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks whether the given {@link ItemStack} is considered {@link Soulbound}.
|
||||
* If the provided item is a {@link SlimefunItem} then this method will also check that the item
|
||||
* is enabled in the provided {@link World}.
|
||||
*
|
||||
* @param item
|
||||
* The {@link ItemStack} to check for
|
||||
* @param world
|
||||
* The {@link World} to check if the {@link SlimefunItem} is enabled in if applicable.
|
||||
* If {@code null} then this will not do a world check.
|
||||
* @return Whether the given item is soulbound
|
||||
*/
|
||||
public static boolean isSoulbound(@Nullable ItemStack item, @Nullable World world) {
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : null;
|
||||
|
||||
if (hasSoulboundFlag(meta)) {
|
||||
@ -97,13 +112,17 @@ public final class SlimefunUtils {
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
|
||||
if (sfItem instanceof Soulbound) {
|
||||
return !sfItem.isDisabled();
|
||||
if (world != null) {
|
||||
return !sfItem.isDisabledIn(world);
|
||||
} else {
|
||||
return !sfItem.isDisabled();
|
||||
}
|
||||
} else if (meta != null) {
|
||||
return meta.hasLore() && meta.getLore().contains(SOULBOUND_LORE);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasSoulboundFlag(@Nullable ItemMeta meta) {
|
||||
@ -111,9 +130,7 @@ public final class SlimefunUtils {
|
||||
PersistentDataContainer container = meta.getPersistentDataContainer();
|
||||
NamespacedKey key = SlimefunPlugin.getRegistry().getSoulboundDataKey();
|
||||
|
||||
if (container.has(key, PersistentDataType.BYTE)) {
|
||||
return true;
|
||||
}
|
||||
return container.has(key, PersistentDataType.BYTE);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -0,0 +1,56 @@
|
||||
package io.github.thebusybiscuit.slimefun4.utils;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
|
||||
|
||||
/**
|
||||
* This a enum evaluating and indicating a {@link DamageableItem} 's chance to be damaged
|
||||
* depending if it is a tool or an armor
|
||||
*
|
||||
* @author RobotHanzo
|
||||
*
|
||||
* @see DamageableItem
|
||||
*/
|
||||
public enum UnbreakingAlgorithm {
|
||||
|
||||
/**
|
||||
* For armor sets, unbreaking is capped at max. 40% effectiveness.
|
||||
*/
|
||||
ARMOR(lvl -> Math.random() >= 0.6 + (0.4 / (lvl + 1))),
|
||||
|
||||
/**
|
||||
* For tools, unbreaking is calculated like this.
|
||||
* The effect increases indefinitely.
|
||||
*/
|
||||
TOOLS(lvl -> Math.random() >= 1.0 / (lvl + 1));
|
||||
|
||||
private final IntFunction<Boolean> function;
|
||||
|
||||
UnbreakingAlgorithm(@Nonnull IntFunction<Boolean> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will randomly decide if the item should be damaged or not
|
||||
* based on the internal formula of this {@link UnbreakingAlgorithm}.
|
||||
* If this method returns true, the item should not take damage.
|
||||
*
|
||||
* @param unbreakingLevel
|
||||
* The {@link Integer} level of the unbreaking {@link Enchantment}
|
||||
*
|
||||
* @return Whether to save the item from taking damage
|
||||
*
|
||||
*/
|
||||
public boolean evaluate(int unbreakingLevel) {
|
||||
if (unbreakingLevel > 0) {
|
||||
return function.apply(unbreakingLevel);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
* @deprecated This was a horrible idea. Don't use it.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class CustomItemSerializer {
|
||||
|
||||
public enum ItemFlag {
|
||||
|
||||
MATERIAL(0),
|
||||
DATA(1),
|
||||
AMOUNT(2),
|
||||
DURABILITY(3),
|
||||
ENCHANTMENTS(4),
|
||||
ITEMMETA_DISPLAY_NAME(5),
|
||||
ITEMMETA_LORE(6);
|
||||
|
||||
private int weight;
|
||||
|
||||
ItemFlag(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static ItemFlagComparator comparator = new ItemFlagComparator();
|
||||
|
||||
public static String serialize(ItemStack item, ItemFlag... flags) {
|
||||
if (item == null)
|
||||
return "NULL";
|
||||
List<ItemFlag> flaglist = Arrays.asList(flags);
|
||||
|
||||
Collections.sort(flaglist, comparator);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
for (ItemFlag flag : flags) {
|
||||
if (i > 0)
|
||||
builder.append(" </sep> ");
|
||||
builder.append(flag.toString() + "=");
|
||||
|
||||
switch (flag) {
|
||||
case AMOUNT: {
|
||||
builder.append(item.getAmount());
|
||||
break;
|
||||
}
|
||||
case DATA: {
|
||||
builder.append((int) item.getData().getData());
|
||||
break;
|
||||
}
|
||||
case DURABILITY: {
|
||||
builder.append((int) item.getDurability());
|
||||
break;
|
||||
}
|
||||
case ENCHANTMENTS:
|
||||
for (Enchantment enchantment : Enchantment.values()) {
|
||||
if (item.getEnchantments().containsKey(enchantment)) {
|
||||
builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment));
|
||||
} else {
|
||||
builder.append(enchantment.getName() + ":0");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ITEMMETA_DISPLAY_NAME: {
|
||||
if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
|
||||
builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&"));
|
||||
} else {
|
||||
builder.append("NONE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEMMETA_LORE: {
|
||||
if (item.hasItemMeta() && item.getItemMeta().hasLore()) {
|
||||
builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&"));
|
||||
} else {
|
||||
builder.append("NONE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MATERIAL: {
|
||||
builder.append(item.getType().toString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static boolean equals(ItemStack stack1, ItemStack stack2, ItemFlag... flags) {
|
||||
return serialize(stack1, flags).equals(serialize(stack2, flags));
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item.CustomItemSerializer.ItemFlag;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
* @deprecated This was a horrible idea. Don't use it.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ItemFlagComparator implements Comparator<ItemFlag> {
|
||||
|
||||
@Override
|
||||
public int compare(ItemFlag flag1, ItemFlag flag2) {
|
||||
return flag1.getWeight() - flag2.getWeight();
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package me.mrCookieSlime.Slimefun.Objects;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||
|
||||
/**
|
||||
* A {@link SlimefunBlockHandler} handles breaking and placing of blocks.
|
||||
* You can use this class to initialize block data but also to correctly
|
||||
* destroy blocks.
|
||||
*
|
||||
* {@code SlimefunItem.registerBlockHandler(String, SlimefunBlockHandler); }
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @deprecated Please use the {@link BlockBreakHandler} instead.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface SlimefunBlockHandler {
|
||||
|
||||
/**
|
||||
* This method gets called when the {@link Block} is broken.
|
||||
* The {@link Player} will be null if the {@link Block} exploded
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} who broke the {@link Block}
|
||||
* @param b
|
||||
* The {@link Block} that was broken
|
||||
* @param item
|
||||
* The {@link SlimefunItem} that was stored in that {@link Block}
|
||||
* @param reason
|
||||
* The reason for the {@link Block} breaking
|
||||
* @return Whether the {@link Event} should be cancelled
|
||||
*/
|
||||
boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason);
|
||||
}
|
@ -40,7 +40,6 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
|
||||
@ -805,14 +804,13 @@ public class SlimefunItem implements Placeable {
|
||||
Validate.notEmpty(handlers, "You cannot add zero handlers...");
|
||||
Validate.noNullElements(handlers, "You cannot add any 'null' ItemHandler!");
|
||||
|
||||
// Make sure they are added before the item was registered.
|
||||
if (state != ItemState.UNREGISTERED) {
|
||||
throw new UnsupportedOperationException("You cannot add an ItemHandler after the SlimefunItem was registered.");
|
||||
}
|
||||
|
||||
for (ItemHandler handler : handlers) {
|
||||
if (itemhandlers.put(handler.getIdentifier(), handler).isPresent()) {
|
||||
warn("ItemHandler \"" + handler.getIdentifier().getSimpleName() + "\" has already been assigned to this item. It was overridden.");
|
||||
}
|
||||
itemhandlers.put(handler.getIdentifier(), handler);
|
||||
|
||||
// Tickers are a special case (at the moment at least)
|
||||
if (handler instanceof BlockTicker) {
|
||||
@ -1196,19 +1194,4 @@ public class SlimefunItem implements Placeable {
|
||||
return SlimefunPlugin.getRegistry().getPublicItemHandlers().computeIfAbsent(identifier, c -> new HashSet<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* This has been deprecated.
|
||||
*
|
||||
* @deprecated Please use {@link #addItemHandler(ItemHandler...)} and {@link BlockBreakHandler} instead
|
||||
*
|
||||
* @param id
|
||||
* The id
|
||||
* @param handler
|
||||
* The handler
|
||||
*/
|
||||
@Deprecated
|
||||
public static void registerBlockHandler(@Nonnull String id, @Nullable me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler handler) {
|
||||
SlimefunPlugin.getRegistry().getBlockHandlers().put(id, handler);
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package me.mrCookieSlime.Slimefun.Objects.SlimefunItem;
|
||||
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
|
||||
|
||||
/**
|
||||
* Defines how a block handled by Slimefun is being unregistered.
|
||||
* <p>
|
||||
* It is notably used by
|
||||
* {@link me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler#onBreak(org.bukkit.entity.Player, org.bukkit.block.Block, SlimefunItem, UnregisterReason)}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @deprecated This enum is no longer needed
|
||||
*
|
||||
* @see SlimefunBlockHandler
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public enum UnregisterReason {
|
||||
|
||||
/**
|
||||
* An explosion destroys the block.
|
||||
*/
|
||||
EXPLODE,
|
||||
|
||||
/**
|
||||
* A player breaks the block.
|
||||
*/
|
||||
PLAYER_BREAK,
|
||||
|
||||
/**
|
||||
* An android miner breaks the block.
|
||||
*/
|
||||
ANDROID_DIG
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@ -24,7 +25,9 @@ import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.AsyncMachineProcessCompleteEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
|
||||
@ -47,8 +50,9 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
private static final int[] BORDER_IN = { 9, 10, 11, 12, 18, 21, 27, 28, 29, 30 };
|
||||
private static final int[] BORDER_OUT = { 14, 15, 16, 17, 23, 26, 32, 33, 34, 35 };
|
||||
|
||||
public static Map<Block, MachineRecipe> processing = new HashMap<>();
|
||||
public static Map<Block, Integer> progress = new HashMap<>();
|
||||
// These will be replaced by proper recipe handler
|
||||
public static Map<Block, MachineRecipe> processing = new ConcurrentHashMap<>();
|
||||
public static Map<Block, Integer> progress = new ConcurrentHashMap<>();
|
||||
|
||||
protected final List<MachineRecipe> recipes = new ArrayList<>();
|
||||
|
||||
@ -57,27 +61,35 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
private int processingSpeed = -1;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AContainer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
protected AContainer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
createPreset(this, getInventoryTitle(), this::constructMenu);
|
||||
|
||||
registerBlockHandler(item.getItemId(), (p, b, tool, reason) -> {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
addItemHandler(onBlockBreak());
|
||||
}
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
@Nonnull
|
||||
protected BlockBreakHandler onBlockBreak() {
|
||||
return new SimpleBlockBreakHandler() {
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(Block b) {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
|
||||
progress.remove(b);
|
||||
processing.remove(b);
|
||||
}
|
||||
|
||||
progress.remove(b);
|
||||
processing.remove(b);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public AContainer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
|
||||
protected AContainer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
|
||||
this(category, item, recipeType, recipe);
|
||||
this.recipeOutput = recipeOutput;
|
||||
}
|
||||
|
@ -21,8 +21,10 @@ import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.AsyncGeneratorProcessCompleteEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
|
||||
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.AbstractEnergyProvider;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
@ -76,22 +78,29 @@ public abstract class AGenerator extends AbstractEnergyProvider {
|
||||
}
|
||||
};
|
||||
|
||||
registerBlockHandler(item.getItemId(), (p, b, tool, reason) -> {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
|
||||
progress.remove(b.getLocation());
|
||||
processing.remove(b.getLocation());
|
||||
return true;
|
||||
});
|
||||
|
||||
addItemHandler(onBlockBreak());
|
||||
registerDefaultFuelTypes();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected BlockBreakHandler onBlockBreak() {
|
||||
return new SimpleBlockBreakHandler() {
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(Block b) {
|
||||
BlockMenu inv = BlockStorage.getInventory(b);
|
||||
|
||||
if (inv != null) {
|
||||
inv.dropItems(b.getLocation(), getInputSlots());
|
||||
inv.dropItems(b.getLocation(), getOutputSlots());
|
||||
}
|
||||
|
||||
progress.remove(b.getLocation());
|
||||
processing.remove(b.getLocation());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void constructMenu(BlockMenuPreset preset) {
|
||||
for (int i : border) {
|
||||
preset.addItem(i, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
|
||||
|
@ -38,7 +38,7 @@ placeholderapi:
|
||||
guide:
|
||||
locked: 'LOCKED'
|
||||
work-in-progress: 'This feature is not fully finished yet!'
|
||||
|
||||
|
||||
locked-category:
|
||||
- 'To unlock this category you will'
|
||||
- 'need to unlock all items from the'
|
||||
@ -64,11 +64,11 @@ guide:
|
||||
|
||||
cheat:
|
||||
no-multiblocks: '&4You cannot cheat in Multiblocks, you have to build them!'
|
||||
|
||||
|
||||
pages:
|
||||
previous: 'Previous page'
|
||||
next: 'Next page'
|
||||
|
||||
|
||||
back:
|
||||
title: 'Back'
|
||||
guide: 'Go back to the Slimefun Guide'
|
||||
@ -86,11 +86,11 @@ guide:
|
||||
- '&7the language in which Slimefun'
|
||||
- '&7will be presented to you. Items'
|
||||
- '&7cannot be translated for now.'
|
||||
|
||||
|
||||
translations:
|
||||
name: '&aIs something missing?'
|
||||
lore: 'Click to add your own translation'
|
||||
|
||||
|
||||
title:
|
||||
main: 'Slimefun Guide'
|
||||
settings: 'Settings & Info'
|
||||
@ -101,7 +101,7 @@ guide:
|
||||
bugs: 'Bug Reports'
|
||||
source: 'Source Code'
|
||||
versions: 'Installed versions'
|
||||
|
||||
|
||||
credits:
|
||||
commit: 'Commit'
|
||||
commits: 'Commits'
|
||||
@ -151,9 +151,22 @@ messages:
|
||||
recipe-set: '&aYou have successfully set the recipe for this machine.'
|
||||
recipe-removed: '&eYou have successfully removed the recipe from this machine. You can set a new recipe at any time!'
|
||||
no-recipes: '&cWe could not find any valid recipes for the item you are holding.'
|
||||
missing-chest: '&cMissing chest! Auto Crafters need to be placed above a chest.'
|
||||
missing-chest: '&cMissing chest! Auto-Crafters need to be placed above a chest.'
|
||||
select: 'Select this recipe'
|
||||
remove: 'Remove this recipe'
|
||||
temporarily-disabled: '&eThis Auto-Crafter was temporarily disabled. You can re-enable it at any time!'
|
||||
re-enabled: '&eThis Auto-Crafter was re-enabled!'
|
||||
|
||||
tooltips:
|
||||
enabled:
|
||||
- '&aThis recipe is currently enabled'
|
||||
- ''
|
||||
- '&eLeft Click &7to temporarily disable the recipe'
|
||||
- '&eRight Click &7to remove this recipe'
|
||||
disabled:
|
||||
- '&cThis recipe is currently disabled'
|
||||
- ''
|
||||
- '&eLeft Click &7to re-enable this recipe'
|
||||
- '&eRight Click &7to remove this recipe'
|
||||
|
||||
talisman:
|
||||
anvil: '&a&oYour Talisman saved your tool from breaking'
|
||||
@ -180,17 +193,17 @@ messages:
|
||||
fail: '&cYou cannot enchant this item.'
|
||||
no-enchantment: '&cCouldn''t find any applicable enchantment for this item.'
|
||||
success: '&aYou have successfully applied a random applicable enchantment to this item.'
|
||||
|
||||
|
||||
research:
|
||||
start: '&7The Ancient Spirits whisper mysterious words into your ear!'
|
||||
progress: '&7You start to wonder about &b%research% &e(%progress%)'
|
||||
|
||||
|
||||
tape-measure:
|
||||
no-anchor: '&cYou need to set an anchor before you can start to measure!'
|
||||
wrong-world: '&cYour anchor seems to be in a different world!'
|
||||
distance: '&7Measurement taken. &eDistance: %distance%'
|
||||
anchor-set: '&aSuccessfully set the anchor:&e %anchor%'
|
||||
|
||||
|
||||
climbing-pick:
|
||||
dual-wielding: '&4You need to hold Climbing Picks in both hands to use them!'
|
||||
wrong-material: '&cYou cannot climb this surface. Check your Slimefun Guide for more info!'
|
||||
@ -204,7 +217,7 @@ messages:
|
||||
no-iron-golem-heal: '&cThat is not an Iron Ingot. You cannot use this to heal Iron Golems!'
|
||||
link-prompt: '&eClick here:'
|
||||
diet-cookie: '&eYou are starting to feel very light...'
|
||||
|
||||
|
||||
fortune-cookie:
|
||||
- '&7Help me, I am trapped in a Fortune Cookie Factory!'
|
||||
- '&7You will die tomorrow... by a Creeper'
|
||||
@ -230,6 +243,7 @@ machines:
|
||||
full-inventory: '&eSorry, my inventory is too full!'
|
||||
in-use: '&cThis Block''s inventory is currently opened by a different Player.'
|
||||
ignition-chamber-no-flint: '&cIgnition Chamber is missing Flint and Steel.'
|
||||
inventory-empty: '&6You have successfully constructed this Multiblock. Proceed by placing items inside the dispenser and click me again to craft the item you want!'
|
||||
|
||||
ANCIENT_ALTAR:
|
||||
not-enough-pedestals: '&4The Altar is not surrounded by the needed amount of Pedestals &c(%pedestals% / 8)'
|
||||
@ -242,7 +256,7 @@ machines:
|
||||
HOLOGRAM_PROJECTOR:
|
||||
enter-text: '&7Please enter your desired Hologram Text into your Chat. &r(Color Codes are supported!)'
|
||||
inventory-title: 'Hologram Editor'
|
||||
|
||||
|
||||
ELEVATOR:
|
||||
no-destinations: '&4No destinations found'
|
||||
pick-a-floor: '&3- Pick a floor -'
|
||||
@ -250,26 +264,26 @@ machines:
|
||||
click-to-teleport: '&eClick &7to teleport to this floor:'
|
||||
enter-name: '&7Please enter your desired floor name into your Chat. &r(Color Codes are supported!)'
|
||||
named: '&2Successfully named this floor: &r%floor%'
|
||||
|
||||
|
||||
TELEPORTER:
|
||||
teleporting: '&3Teleporting...'
|
||||
teleported: '&3Teleported!'
|
||||
cancelled: '&4Teleportation cancelled!'
|
||||
invulnerability: '&b&lYou have been given 30 seconds of Invulnerability!'
|
||||
|
||||
|
||||
gui:
|
||||
title: 'Your waypoints'
|
||||
tooltip: 'Click to teleport'
|
||||
time: 'Estimated time'
|
||||
|
||||
|
||||
GPS_CONTROL_PANEL:
|
||||
title: 'GPS - Control Panel'
|
||||
transmitters: 'Transmitter Overview'
|
||||
waypoints: 'Waypoint Overview'
|
||||
|
||||
|
||||
CARGO_NODES:
|
||||
must-be-placed: '&4Must be placed onto a chest or machine!'
|
||||
|
||||
|
||||
INDUSTRIAL_MINER:
|
||||
no-fuel: '&cYour Industrial Miner ran out of fuel! Put your fuel into the chest above.'
|
||||
piston-facing: '&cYour Industrial Miner requires pistons to face upwards!'
|
||||
@ -279,7 +293,7 @@ machines:
|
||||
full-chest: '&cThe Chest of your Industrial Miner is full!'
|
||||
no-permission: '&4You do not seem to have permission to operate an Industrial Miner here!'
|
||||
finished: '&eYour Industrial Miner has finished! It obtained a total of %ores% ore(s)!'
|
||||
|
||||
|
||||
anvil:
|
||||
not-working: '&4You cannot use Slimefun items in an anvil!'
|
||||
mcmmo-salvaging: '&4You cannot salvage Slimefun items!'
|
||||
@ -325,12 +339,12 @@ inventory:
|
||||
android:
|
||||
started: '&7Your Android resumed running its script'
|
||||
stopped: '&7Your Android has paused its script'
|
||||
|
||||
|
||||
scripts:
|
||||
already-uploaded: '&4This script has already been uploaded.'
|
||||
editor: 'Script Editor'
|
||||
too-long: '&cThe script is too long to edit!'
|
||||
|
||||
|
||||
instructions:
|
||||
START: '&2Start Script'
|
||||
REPEAT: '&9Repeat Script'
|
||||
|
@ -188,6 +188,7 @@ slimefun:
|
||||
cargo_basics: Cargo Basics
|
||||
cargo_nodes: Cargo Setup
|
||||
electric_ingot_machines: Electric Ingot Fabrication
|
||||
medium_tier_electric_ingot_machines: Fast Ingot Fabrication
|
||||
high_tier_electric_ingot_machines: Super Fast Ingot Fabrication
|
||||
automated_crafting_chamber: Automated Crafting
|
||||
better_food_fabricator: Upgraded Food Fabrication
|
||||
@ -250,3 +251,6 @@ slimefun:
|
||||
bee_armor: Bee Armor
|
||||
book_binder: Enchantment Book Binding
|
||||
auto_crafting: Automatic Crafting
|
||||
produce_collector: Automatic Milking
|
||||
improved_generators: Improved Generators
|
||||
ingredients_and_cheese: Slimefun Cuisine
|
||||
|
@ -0,0 +1,34 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.mocks;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
public class DamageableMock extends SlimefunItem implements DamageableItem {
|
||||
|
||||
private final boolean itemDamageable;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public DamageableMock(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, boolean damageable) {
|
||||
super(category, item, recipeType, recipe);
|
||||
itemDamageable = damageable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDamageable() {
|
||||
return itemDamageable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damageItem(@Nonnull Player p, @Nullable ItemStack item) {
|
||||
DamageableItem.super.damageItem(p, item);
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.mocks.DamageableMock;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
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 javax.annotation.Nullable;
|
||||
|
||||
class TestDamageableItem {
|
||||
|
||||
private static SlimefunPlugin plugin;
|
||||
private static ServerMock server;
|
||||
|
||||
@BeforeAll
|
||||
public static void load() {
|
||||
server = MockBukkit.mock();
|
||||
plugin = MockBukkit.load(SlimefunPlugin.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void unload() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
public static DamageableMock getDummyItem(String id, boolean damageable, @Nullable Enchantment enchantment, @Nullable Integer enchantmentLevel) {
|
||||
Category category = TestUtilities.getCategory(plugin, "damageable_item_test");
|
||||
SlimefunItemStack stack = new SlimefunItemStack("DAMAGEABLE_PICKAXE_" + id, Material.DIAMOND_PICKAXE, "&4This pickaxe can break", "&6It appears, it breaks, but most importantly, it tests.");
|
||||
if (enchantment != null && enchantmentLevel != null) {
|
||||
ItemMeta im = stack.getItemMeta();
|
||||
im.addEnchant(enchantment, enchantmentLevel, true);
|
||||
stack.setItemMeta(im);
|
||||
}
|
||||
DamageableMock item = new DamageableMock(category, stack, RecipeType.NULL, new ItemStack[9], damageable);
|
||||
item.register(plugin);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test DamageableItem actually damages")
|
||||
void testDamageableItemDamagesItem() {
|
||||
DamageableMock unDamageableItem = getDummyItem("UDM", false, null, null);
|
||||
// Check if damageable is successfully registered
|
||||
Assertions.assertFalse(unDamageableItem.isDamageable());
|
||||
|
||||
Player player = server.addPlayer();
|
||||
ItemStack unDamageableDummy = unDamageableItem.getItem().clone();
|
||||
unDamageableItem.damageItem(player, unDamageableDummy);
|
||||
Assertions.assertTrue(unDamageableDummy.hasItemMeta());
|
||||
// Check if the item is not damaged as we intended it to not be
|
||||
Assertions.assertEquals(((Damageable) unDamageableDummy.getItemMeta()).getDamage(), 0);
|
||||
|
||||
DamageableMock damageableItem = getDummyItem("DM", true, null, null);
|
||||
// Check if damageable is successfully registered
|
||||
Assertions.assertTrue(damageableItem.isDamageable());
|
||||
|
||||
ItemStack damageableDummy = damageableItem.getItem().clone();
|
||||
damageableItem.damageItem(player, damageableDummy);
|
||||
Assertions.assertTrue(damageableDummy.hasItemMeta());
|
||||
// Check if the item is damaged as we intended it to not be
|
||||
Assertions.assertEquals(((Damageable) damageableDummy.getItemMeta()).getDamage(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test if DamageableItem cares about unbreaking levels")
|
||||
void testDamageableItemCaresUnbreaking() {
|
||||
DamageableMock noUnbreakingItem = getDummyItem("NU", true, null, null);
|
||||
DamageableMock iiiUnbreakingItem = getDummyItem("IIIU", true, Enchantment.DURABILITY, 3);
|
||||
DamageableMock xUnbreakingItem = getDummyItem("XU", true, Enchantment.DURABILITY, 10);
|
||||
ItemStack noUnbreakingItemIS = noUnbreakingItem.getItem().clone();
|
||||
ItemStack iiiUnbreakingItemIS = iiiUnbreakingItem.getItem().clone();
|
||||
ItemStack xUnbreakingItemIS = xUnbreakingItem.getItem().clone();
|
||||
Player player = server.addPlayer();
|
||||
for (int i = 0; i < 500; ++i) {
|
||||
noUnbreakingItem.damageItem(player, noUnbreakingItemIS);
|
||||
noUnbreakingItem.damageItem(player, iiiUnbreakingItemIS);
|
||||
noUnbreakingItem.damageItem(player, xUnbreakingItemIS);
|
||||
}
|
||||
Assertions.assertTrue(noUnbreakingItemIS.hasItemMeta());
|
||||
Assertions.assertTrue(iiiUnbreakingItemIS.hasItemMeta());
|
||||
Assertions.assertTrue(xUnbreakingItemIS.hasItemMeta());
|
||||
Assertions.assertTrue(((Damageable) xUnbreakingItemIS.getItemMeta()).getDamage() < ((Damageable) iiiUnbreakingItemIS.getItemMeta()).getDamage());
|
||||
Assertions.assertTrue(((Damageable) iiiUnbreakingItemIS.getItemMeta()).getDamage() < ((Damageable) noUnbreakingItemIS.getItemMeta()).getDamage());
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items.auto_crafters;
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items.autocrafters;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items.auto_crafters;
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items.autocrafters;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -69,6 +69,58 @@ class TestAutoCrafter {
|
||||
Assertions.assertTrue(inv.containsAtLeast(result, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test crafting a valid ShapelessRecipe")
|
||||
void testDisabledRecipe() {
|
||||
NamespacedKey key = new NamespacedKey(plugin, "disabled_recipe_test");
|
||||
ItemStack result = new CustomItem(Material.DIAMOND, "&bAmazing Diamond :o");
|
||||
ShapelessRecipe recipe = new ShapelessRecipe(key, result);
|
||||
recipe.addIngredient(new MaterialChoice(Material.GOLD_NUGGET));
|
||||
|
||||
AbstractRecipe abstractRecipe = AbstractRecipe.of(recipe);
|
||||
AbstractAutoCrafter crafter = getVanillaAutoCrafter();
|
||||
InventoryMock inv = new ChestInventoryMock(null, 9);
|
||||
|
||||
// Test enabled Recipe
|
||||
abstractRecipe.setEnabled(true);
|
||||
inv.addItem(new ItemStack(Material.GOLD_NUGGET));
|
||||
Assertions.assertTrue(crafter.craft(inv, abstractRecipe));
|
||||
Assertions.assertFalse(inv.contains(Material.GOLD_NUGGET, 1));
|
||||
Assertions.assertTrue(inv.containsAtLeast(result, 1));
|
||||
|
||||
inv.clear();
|
||||
|
||||
// Test disabled Recipe
|
||||
abstractRecipe.setEnabled(false);
|
||||
inv.addItem(new ItemStack(Material.GOLD_NUGGET));
|
||||
Assertions.assertFalse(crafter.craft(inv, abstractRecipe));
|
||||
Assertions.assertTrue(inv.contains(Material.GOLD_NUGGET, 1));
|
||||
Assertions.assertFalse(inv.containsAtLeast(result, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test resource leftovers when crafting")
|
||||
void testResourceLeftovers() {
|
||||
NamespacedKey key = new NamespacedKey(plugin, "resource_leftovers_test");
|
||||
ItemStack result = new CustomItem(Material.DIAMOND, "&9Diamond. Nuff said.");
|
||||
ShapelessRecipe recipe = new ShapelessRecipe(key, result);
|
||||
recipe.addIngredient(new MaterialChoice(Material.HONEY_BOTTLE));
|
||||
recipe.addIngredient(new MaterialChoice(Material.HONEY_BOTTLE));
|
||||
|
||||
AbstractRecipe abstractRecipe = AbstractRecipe.of(recipe);
|
||||
AbstractAutoCrafter crafter = getVanillaAutoCrafter();
|
||||
InventoryMock inv = new ChestInventoryMock(null, 9);
|
||||
|
||||
inv.addItem(new ItemStack(Material.HONEY_BOTTLE, 2));
|
||||
Assertions.assertTrue(crafter.craft(inv, abstractRecipe));
|
||||
|
||||
Assertions.assertFalse(inv.contains(Material.HONEY_BOTTLE, 2));
|
||||
Assertions.assertTrue(inv.containsAtLeast(result, 1));
|
||||
|
||||
// Check for leftovers
|
||||
Assertions.assertTrue(inv.contains(Material.GLASS_BOTTLE, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test crafting an invalid ShapelessRecipe")
|
||||
void testInvalidShapelessRecipe() {
|
@ -1,11 +1,16 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.listeners;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.SoulboundItem;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
@ -17,7 +22,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundListener;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
|
||||
public class TestSoulboundListener {
|
||||
class TestSoulboundListener {
|
||||
|
||||
private static SlimefunPlugin plugin;
|
||||
private static ServerMock server;
|
||||
@ -36,7 +41,8 @@ public class TestSoulboundListener {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = { true, false })
|
||||
public void testItemDrop(boolean soulbound) {
|
||||
@DisplayName("Test if the soulbound item is dropped or not")
|
||||
void testItemDrop(boolean soulbound) {
|
||||
PlayerMock player = server.addPlayer();
|
||||
ItemStack item = new CustomItem(Material.DIAMOND_SWORD, "&4Cool Sword");
|
||||
SlimefunUtils.setSoulbound(item, soulbound);
|
||||
@ -50,7 +56,32 @@ public class TestSoulboundListener {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = { true, false })
|
||||
public void testItemRecover(boolean soulbound) {
|
||||
@DisplayName("Test if soulbound item is dropped if disabled")
|
||||
void testItemDropIfItemDisabled(boolean enabled) {
|
||||
PlayerMock player = server.addPlayer();
|
||||
|
||||
SlimefunItemStack item = new SlimefunItemStack("SOULBOUND_ITEM_" + (enabled ? "ENABLED" : "DISABLED"), Material.DIAMOND_SWORD, "&5Soulbound Sword");
|
||||
SoulboundItem soulboundItem = new SoulboundItem(TestUtilities.getCategory(plugin, "soulbound"), item, RecipeType.NULL, new ItemStack[9]);
|
||||
soulboundItem.register(plugin);
|
||||
|
||||
if (!enabled) {
|
||||
SlimefunPlugin.getWorldSettingsService().setEnabled(player.getWorld(), soulboundItem, false);
|
||||
}
|
||||
|
||||
player.getInventory().setItem(0, item);
|
||||
player.setHealth(0);
|
||||
|
||||
server.getPluginManager().assertEventFired(EntityDeathEvent.class, event -> {
|
||||
// If the item is enabled, we don't want it to drop.
|
||||
return enabled == !event.getDrops().contains(item);
|
||||
});
|
||||
SlimefunPlugin.getRegistry().getEnabledSlimefunItems().remove(soulboundItem);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = { true, false })
|
||||
@DisplayName("Test if soulbound item is returned to player")
|
||||
void testItemRecover(boolean soulbound) {
|
||||
PlayerMock player = server.addPlayer();
|
||||
ItemStack item = new CustomItem(Material.DIAMOND_SWORD, "&4Cool Sword");
|
||||
SlimefunUtils.setSoulbound(item, soulbound);
|
||||
|
Loading…
Reference in New Issue
Block a user