Compare commits

..

34 Commits
6.3.2 ... 6.5.2

Author SHA1 Message Date
Auxilor
ad861b10bb Updated to 6.5.2 2021-08-23 17:14:41 +01:00
Auxilor
db5b7f89f6 Fixed null placeholder bug and improved config loading 2021-08-23 17:14:23 +01:00
Auxilor
2c33ce25c0 Merge remote-tracking branch 'origin/master' 2021-08-22 23:14:30 +01:00
Auxilor
9c3ca429c9 Fixed recipe stack bug 2021-08-22 23:14:24 +01:00
Auxilor
70e294501a Fixed enchanted books in Items.lookup modifier 2021-08-21 13:50:33 +01:00
Will FP
65a0a0ecc7 Update README.md 2021-08-21 01:22:16 +01:00
Auxilor
d4431e7569 Changes 2021-08-20 23:02:45 +01:00
Auxilor
a6191b0870 Added data read/write to menu, updated to 6.5.0, removed event deprecation 2021-08-20 22:29:25 +01:00
Auxilor
5eecef83ee Merge remote-tracking branch 'origin/master' 2021-08-20 17:35:34 +01:00
Auxilor
82a02f3738 Updated to 6.4.2 2021-08-20 17:35:30 +01:00
Auxilor
804142799b Fixed NPE 2021-08-20 17:35:20 +01:00
Will FP
e1de9b9ab3 Update README.md 2021-08-18 15:15:50 +01:00
Will FP
cc56343041 Update README.md 2021-08-18 15:15:36 +01:00
Auxilor
69d28e8bc2 Updated to 6.4.1 2021-08-15 14:34:40 +01:00
Auxilor
6878a74724 Fixed NPE 2021-08-15 14:34:19 +01:00
Auxilor
ebc76bba76 Changed display 2021-08-12 16:30:15 +01:00
Auxilor
378218b7da Minor display change 2021-08-12 16:13:59 +01:00
Auxilor
e053514b94 Added mask materials option 2021-08-12 13:56:29 +01:00
Auxilor
341a30e6da Removed unused var 2021-08-12 13:40:19 +01:00
Auxilor
70eb6d4420 Removed logging 2021-08-12 13:40:01 +01:00
Auxilor
aa368909ae Finished GUI 2021-08-12 13:38:14 +01:00
Auxilor
606a54bcf8 Your brain gets smart but your head gets dumb 2021-08-12 13:17:52 +01:00
Auxilor
7f8fb3d87b Didn't make sense not to live for fun 2021-08-12 13:00:31 +01:00
Auxilor
e97d454ff6 Fed to the rules and I hit the ground running 2021-08-12 01:51:47 +01:00
Auxilor
109b9aa3f3 And the changes start coming and they don't stop coming 2021-08-12 01:46:32 +01:00
Auxilor
4a90385b27 The gui changes don't stop 2021-08-12 01:38:20 +01:00
Auxilor
0edd50832c Even more GUI 2021-08-12 01:05:47 +01:00
Auxilor
46415268b7 More GUI 2021-08-12 00:24:35 +01:00
Auxilor
b652dbad2d Added captivator slots 2021-08-11 23:56:09 +01:00
Auxilor
50550d077a Added ? syntax to recipes 2021-08-11 23:07:25 +01:00
Auxilor
60c3b58a33 Updated to 6.3.3 2021-08-10 18:19:46 +01:00
Auxilor
7216d0b09f Fixed component serialization 2021-08-10 18:18:09 +01:00
Auxilor
97eeea8d48 Updated to 6.3.2 2021-08-10 16:18:49 +01:00
Auxilor
82061ee6a3 Added get/set repair cost methods to FastItemStack 2021-08-09 17:30:09 +01:00
42 changed files with 808 additions and 160 deletions

View File

@@ -158,8 +158,12 @@ Here's a list of some (not all) of the features of eco:
<h1 align="center"> <h1 align="center">
<br> <br>
<a href="http://gamersupps.gg/discount/Auxilor?afmc=Auxilor" target="_blank">
<img src="https://i.imgur.com/uFDpBAC.png" alt="supps banner">
</a>
<a href="https://dedimc.promo/Auxilor" target="_blank"> <a href="https://dedimc.promo/Auxilor" target="_blank">
<img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner"> <img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner">
</a> </a>
<br> <br>
</h1> </h1>

View File

@@ -71,10 +71,6 @@ public class Display {
*/ */
public ItemStack display(@NotNull final ItemStack itemStack, public ItemStack display(@NotNull final ItemStack itemStack,
@Nullable final Player player) { @Nullable final Player player) {
if (!itemStack.hasItemMeta()) {
return itemStack; // return early if there's no customization of the item
}
Map<String, Object[]> pluginVarArgs = new HashMap<>(); Map<String, Object[]> pluginVarArgs = new HashMap<>();
for (DisplayPriority priority : DisplayPriority.values()) { for (DisplayPriority priority : DisplayPriority.values()) {
@@ -139,10 +135,6 @@ public class Display {
unfinalize(itemStack); unfinalize(itemStack);
} }
if (!itemStack.hasItemMeta()) {
return itemStack;
}
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
if (meta == null) { if (meta == null) {

View File

@@ -16,7 +16,6 @@ import org.jetbrains.annotations.NotNull;
* *
* @see ArmorChangeEvent * @see ArmorChangeEvent
*/ */
@Deprecated
public class ArmorEquipEvent extends PlayerEvent { public class ArmorEquipEvent extends PlayerEvent {
/** /**
* Bukkit parity. * Bukkit parity.

View File

@@ -47,6 +47,21 @@ public interface FastItemStack {
*/ */
List<String> getLore(); List<String> getLore();
/**
* Set the rework penalty.
*
* @param cost The rework penalty to set.
*/
void setRepairCost(int cost);
/**
* Get the rework penalty.
*.
* @return The rework penalty found on the item.
*/
int getRepairCost();
/** /**
* Get the Bukkit ItemStack again. * Get the Bukkit ItemStack again.
* *

View File

@@ -2,12 +2,10 @@ package com.willfp.eco.core.gui;
import com.willfp.eco.core.gui.menu.MenuBuilder; import com.willfp.eco.core.gui.menu.MenuBuilder;
import com.willfp.eco.core.gui.slot.SlotBuilder; import com.willfp.eco.core.gui.slot.SlotBuilder;
import org.bukkit.entity.Player; import com.willfp.eco.core.gui.slot.functional.SlotProvider;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
/** /**
* Internal component used by {@link com.willfp.eco.core.gui.menu.Menu#builder(int)} * Internal component used by {@link com.willfp.eco.core.gui.menu.Menu#builder(int)}
* and {@link com.willfp.eco.core.gui.slot.Slot#builder(ItemStack)}. * and {@link com.willfp.eco.core.gui.slot.Slot#builder(ItemStack)}.
@@ -19,7 +17,7 @@ public interface GUIFactory {
* @param provider The provider. * @param provider The provider.
* @return The builder. * @return The builder.
*/ */
SlotBuilder createSlotBuilder(@NotNull Function<Player, ItemStack> provider); SlotBuilder createSlotBuilder(@NotNull SlotProvider provider);
/** /**
* Create menu builder. * Create menu builder.

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.core.gui.menu;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on menu close.
*/
@FunctionalInterface
public interface CloseHandler {
/**
* Performs this operation on the given arguments.
*
* @param event The close event.
* @param menu The menu.
*/
void handle(@NotNull InventoryCloseEvent event,
@NotNull Menu menu);
}

View File

@@ -2,9 +2,16 @@ package com.willfp.eco.core.gui.menu;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.gui.slot.Slot; import com.willfp.eco.core.gui.slot.Slot;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
/** /**
* GUI version of {@link Inventory}. * GUI version of {@link Inventory}.
@@ -44,6 +51,51 @@ public interface Menu {
*/ */
Inventory open(@NotNull Player player); Inventory open(@NotNull Player player);
/**
* Get captive items.
*
* @param player The player.
* @return The items.
*/
List<ItemStack> getCaptiveItems(@NotNull Player player);
/**
* Write data.
*
* @param player The player.
* @param key The key.
* @param type The type.
* @param value The value.
* @param <T> The type.
* @param <Z> The type.
*/
<T, Z> void writeData(@NotNull Player player,
@NotNull NamespacedKey key,
@NotNull PersistentDataType<T, Z> type,
@NotNull Z value);
/**
* Read data.
*
* @param player The player.
* @param key The key.
* @param type The type.
* @param <T> The type.
* @param <Z> The type.
* @return The data.
*/
@Nullable <T, Z> T readData(@NotNull Player player,
@NotNull NamespacedKey key,
@NotNull PersistentDataType<T, Z> type);
/**
* Get all data keys for a player.
*
* @param player The player.
* @return The keys.
*/
Set<NamespacedKey> getKeys(@NotNull Player player);
/** /**
* Create a builder with a given amount of rows. * Create a builder with a given amount of rows.
* *

View File

@@ -31,6 +31,14 @@ public interface MenuBuilder {
int column, int column,
@NotNull Slot slot); @NotNull Slot slot);
/**
* Run function to modify the builder.
*
* @param modifier The modifier.
* @return The builder.
*/
MenuBuilder modfiy(@NotNull Consumer<MenuBuilder> modifier);
/** /**
* Set the menu mask. * Set the menu mask.
* *
@@ -45,7 +53,18 @@ public interface MenuBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
MenuBuilder onClose(@NotNull Consumer<InventoryCloseEvent> action); default MenuBuilder onClose(@NotNull Consumer<InventoryCloseEvent> action) {
onClose((event, menu) -> action.accept(event));
return this;
}
/**
* Set the menu close handler.
*
* @param action The handler.
* @return The builder.
*/
MenuBuilder onClose(@NotNull CloseHandler action);
/** /**
* Build the menu. * Build the menu.

View File

@@ -7,6 +7,7 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@@ -39,35 +40,46 @@ public class FillerMask {
*/ */
public FillerMask(@NotNull final Material material, public FillerMask(@NotNull final Material material,
@NotNull final String... pattern) { @NotNull final String... pattern) {
if (material == Material.AIR) { this(new MaskMaterials(material), pattern);
throw new IllegalArgumentException("Material cannot be air!"); }
/**
* Create a new filler mask.
*
* @param materials The mask materials.
* @param pattern The pattern.
*/
public FillerMask(@NotNull final MaskMaterials materials,
@NotNull final String... pattern) {
if (Arrays.stream(materials.materials()).anyMatch(material -> material == Material.AIR)) {
throw new IllegalArgumentException("Materials cannot be air!");
} }
mask = ListUtils.create2DList(6, 9); mask = ListUtils.create2DList(6, 9);
ItemStack itemStack = new ItemStackBuilder(material) for (int i = 0; i < materials.materials().length; i++) {
.setDisplayName("&r") ItemStack itemStack = new ItemStackBuilder(materials.materials()[i])
.build(); .setDisplayName("&r")
.build();
int row = 0; int row = 0;
for (String patternRow : pattern) { for (String patternRow : pattern) {
int column = 0; int column = 0;
if (patternRow.length() != 9) { if (patternRow.length() != 9) {
throw new IllegalArgumentException("Invalid amount of columns in pattern!"); throw new IllegalArgumentException("Invalid amount of columns in pattern!");
}
for (char c : patternRow.toCharArray()) {
if (c == '0') {
mask.get(row).set(column, null);
} else if (c == '1') {
mask.get(row).set(column, new FillerSlot(itemStack));
} else {
throw new IllegalArgumentException("Invalid character in pattern! (Must only be 0 and 1)");
} }
for (char c : patternRow.toCharArray()) {
if (c == '0') {
mask.get(row).set(column, null);
} else if (c == Character.forDigit(i + 1, 10)) {
mask.get(row).set(column, new FillerSlot(itemStack));
}
column++; column++;
}
row++;
} }
row++;
} }
} }
} }

View File

@@ -30,4 +30,9 @@ public class FillerSlot implements Slot {
public ItemStack getItemStack(@NotNull final Player player) { public ItemStack getItemStack(@NotNull final Player player) {
return itemStack; return itemStack;
} }
@Override
public boolean isCaptive() {
return false;
}
} }

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.core.gui.slot;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
/**
* Mask materials store a set of materials which can be accessed by
* a filler mask.
*
* @param materials The materials.
*/
public record MaskMaterials(@NotNull Material... materials) {
}

View File

@@ -1,6 +1,8 @@
package com.willfp.eco.core.gui.slot; package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -19,6 +21,22 @@ public interface Slot {
*/ */
ItemStack getItemStack(@NotNull Player player); ItemStack getItemStack(@NotNull Player player);
/**
* If the slot is captive. (Can items be placed in it).
*
* @return If captive.
*/
boolean isCaptive();
/**
* Create a builder for an ItemStack.
*
* @return The builder.
*/
static SlotBuilder builder() {
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> new ItemStack(Material.AIR));
}
/** /**
* Create a builder for an ItemStack. * Create a builder for an ItemStack.
* *
@@ -26,7 +44,7 @@ public interface Slot {
* @return The builder. * @return The builder.
*/ */
static SlotBuilder builder(@NotNull final ItemStack itemStack) { static SlotBuilder builder(@NotNull final ItemStack itemStack) {
return Eco.getHandler().getGUIFactory().createSlotBuilder(player -> itemStack); return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> itemStack);
} }
/** /**
@@ -36,6 +54,16 @@ public interface Slot {
* @return The builder. * @return The builder.
*/ */
static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) { static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) {
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> provider.apply(player));
}
/**
* Create a builder for a player-specific ItemStack.
*
* @param provider The provider.
* @return The builder.
*/
static SlotBuilder builder(@NotNull final SlotProvider provider) {
return Eco.getHandler().getGUIFactory().createSlotBuilder(provider); return Eco.getHandler().getGUIFactory().createSlotBuilder(provider);
} }
} }

View File

@@ -1,5 +1,7 @@
package com.willfp.eco.core.gui.slot; package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
import com.willfp.eco.core.gui.slot.functional.SlotModifier;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -15,7 +17,17 @@ public interface SlotBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
SlotBuilder onLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action); default SlotBuilder onLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onLeftClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onLeftClick(@NotNull SlotHandler handler);
/** /**
* Set click handler. * Set click handler.
@@ -23,7 +35,17 @@ public interface SlotBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
SlotBuilder onRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action); default SlotBuilder onRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onRightClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onRightClick(@NotNull SlotHandler handler);
/** /**
* Set click handler. * Set click handler.
@@ -31,7 +53,17 @@ public interface SlotBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
SlotBuilder onShiftLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action); default SlotBuilder onShiftLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onShiftLeftClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onShiftLeftClick(@NotNull SlotHandler handler);
/** /**
* Set click handler. * Set click handler.
@@ -39,7 +71,17 @@ public interface SlotBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
SlotBuilder onShiftRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action); default SlotBuilder onShiftRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onShiftRightClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onShiftRightClick(@NotNull SlotHandler handler);
/** /**
* Set click handler. * Set click handler.
@@ -47,7 +89,32 @@ public interface SlotBuilder {
* @param action The handler. * @param action The handler.
* @return The builder. * @return The builder.
*/ */
SlotBuilder onMiddleClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action); default SlotBuilder onMiddleClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onMiddleClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onMiddleClick(@NotNull SlotHandler handler);
/**
* Modify the ItemStack.
*
* @param modifier The modifier.
* @return The builder.
*/
SlotBuilder setModifier(@NotNull SlotModifier modifier);
/**
* Set slot to be a captive slot.
*
* @return The builder.
*/
SlotBuilder setCaptive();
/** /**
* Build the slot. * Build the slot.

View File

@@ -0,0 +1,23 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import com.willfp.eco.core.gui.slot.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot click.
*/
@FunctionalInterface
public interface SlotHandler {
/**
* Performs this operation on the given arguments.
*
* @param event The click event.
* @param slot The slot
* @param menu The menu.
*/
void handle(@NotNull InventoryClickEvent event,
@NotNull Slot slot,
@NotNull Menu menu);
}

View File

@@ -0,0 +1,23 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot modify.
*/
@FunctionalInterface
public interface SlotModifier {
/**
* Performs this operation on the given arguments.
*
* @param player The player.
* @param menu The menu.
* @param previous The previous ItemStack.
*/
void modify(@NotNull Player player,
@NotNull Menu menu,
@NotNull ItemStack previous);
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot display.
*/
@FunctionalInterface
public interface SlotProvider {
/**
* Performs this operation on the given arguments.
*
* @param player The player.
* @param menu The menu.
* @return The ItemStack.
*/
ItemStack provide(@NotNull Player player,
@NotNull Menu menu);
}

View File

@@ -56,7 +56,7 @@ public class PlaceholderManager {
@NotNull final String identifier) { @NotNull final String identifier) {
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst(); Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
if (matching.isEmpty()) { if (matching.isEmpty()) {
return null; return "";
} }
PlaceholderEntry entry = matching.get(); PlaceholderEntry entry = matching.get();
if (player == null && entry.requiresPlayer()) { if (player == null && entry.requiresPlayer()) {

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.items; package com.willfp.eco.core.items;
import com.willfp.eco.core.items.builder.EnchantedBookBuilder;
import com.willfp.eco.core.items.builder.ItemBuilder; import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.core.items.builder.ItemStackBuilder; import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem; import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
@@ -12,6 +13,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -60,6 +62,18 @@ public final class Items {
* @return The found testable item, or an empty item if not found. * @return The found testable item, or an empty item if not found.
*/ */
public TestableItem lookup(@NotNull final String key) { public TestableItem lookup(@NotNull final String key) {
if (key.contains("?")) {
String[] options = key.split("\\?");
for (String option : options) {
TestableItem lookup = lookup(option);
if (!(lookup instanceof EmptyTestableItem)) {
return lookup;
}
}
return new EmptyTestableItem();
}
String[] args = key.split(" "); String[] args = key.split(" ");
if (args.length == 0) { if (args.length == 0) {
return new EmptyTestableItem(); return new EmptyTestableItem();
@@ -117,9 +131,17 @@ public final class Items {
return item; return item;
} }
ItemBuilder builder = new ItemStackBuilder(item.getItem()); ItemStack example = item.getItem();
requiredEnchantments.forEach(builder::addEnchantment);
ItemStack example = builder.build(); if (example.getItemMeta() instanceof EnchantmentStorageMeta storageMeta) {
requiredEnchantments.forEach((enchantment, integer) -> storageMeta.addStoredEnchant(enchantment, integer, true));
example.setItemMeta(storageMeta);
} else {
ItemMeta meta = example.getItemMeta();
assert meta != null;
requiredEnchantments.forEach((enchantment, integer) -> meta.addEnchant(enchantment, integer, true));
example.setItemMeta(meta);
}
return new ModifiedTestableItem( return new ModifiedTestableItem(
item, item,
@@ -132,12 +154,23 @@ public final class Items {
assert meta != null; assert meta != null;
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) { if (meta instanceof EnchantmentStorageMeta storageMeta) {
if (!meta.hasEnchant(entry.getKey())) { for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
return false; if (!storageMeta.hasStoredEnchant(entry.getKey())) {
return false;
}
if (storageMeta.getStoredEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
} }
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) { } else {
return false; for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!meta.hasEnchant(entry.getKey())) {
return false;
}
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
} }
} }

View File

@@ -17,6 +17,7 @@ public class ModifiedTestableItem implements TestableItem {
/** /**
* The item. * The item.
*/ */
@Getter
private final TestableItem handle; private final TestableItem handle;
/** /**

View File

@@ -19,6 +19,7 @@ public class TestableStack implements TestableItem {
/** /**
* The item. * The item.
*/ */
@Getter
private final TestableItem handle; private final TestableItem handle;
/** /**

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.util;
import com.willfp.eco.core.tuples.Pair;
import lombok.experimental.UtilityClass;
/**
* Utilities / API methods for menus.
*/
@UtilityClass
public class MenuUtils {
/**
* Convert 0-53 slot to row and column pair.
*
* @param slot The slot.
* @return The pair of row and columns.
*/
public Pair<Integer, Integer> convertSlotToRowColumn(final int slot) {
int row = Math.floorDiv(slot, 9);
int column = slot - row * 9;
return new Pair<>(row + 1, column + 1);
}
}

View File

@@ -47,6 +47,15 @@ public class StringUtils {
.add(Pattern.compile("<#" + "([A-Fa-f0-9]{6})" + ">")) .add(Pattern.compile("<#" + "([A-Fa-f0-9]{6})" + ">"))
.build(); .build();
/**
* Legacy serializer.
*/
private static final LegacyComponentSerializer LEGACY_COMPONENT_SERIALIZER = LegacyComponentSerializer.builder()
.character('\u00a7')
.useUnusualXRepeatedCharacterHexFormat()
.hexColors()
.build();
/** /**
* Format a list of strings - converts Placeholders and Color codes. * Format a list of strings - converts Placeholders and Color codes.
* *
@@ -246,7 +255,7 @@ public class StringUtils {
public String legacyToJson(@NotNull final String legacy) { public String legacyToJson(@NotNull final String legacy) {
return GsonComponentSerializer.gson().serialize( return GsonComponentSerializer.gson().serialize(
Component.empty().decoration(TextDecoration.ITALIC, false).append( Component.empty().decoration(TextDecoration.ITALIC, false).append(
LegacyComponentSerializer.legacySection().deserialize(legacy) LEGACY_COMPONENT_SERIALIZER.deserialize(legacy)
) )
); );
} }
@@ -258,7 +267,7 @@ public class StringUtils {
* @return The legacy string. * @return The legacy string.
*/ */
public String jsonToLegacy(@NotNull final String json) { public String jsonToLegacy(@NotNull final String json) {
return LegacyComponentSerializer.legacySection().serialize( return LEGACY_COMPONENT_SERIALIZER.serialize(
GsonComponentSerializer.gson().deserialize(json) GsonComponentSerializer.gson().deserialize(json)
); );
} }

View File

@@ -27,7 +27,6 @@ class EcoLoadableJSONConfig(
} }
override fun createFile() { override fun createFile() {
val resourcePath = resourcePath
val inputStream = source.getResourceAsStream(resourcePath)!! val inputStream = source.getResourceAsStream(resourcePath)!!
val outFile = File(this.plugin.dataFolder, resourcePath) val outFile = File(this.plugin.dataFolder, resourcePath)
val lastIndex = resourcePath.lastIndexOf('/') val lastIndex = resourcePath.lastIndexOf('/')
@@ -37,11 +36,7 @@ class EcoLoadableJSONConfig(
} }
if (!outFile.exists()) { if (!outFile.exists()) {
val out: OutputStream = FileOutputStream(outFile) val out: OutputStream = FileOutputStream(outFile)
val buf = ByteArray(1024) inputStream.copyTo(out, 1024)
var len: Int
while (inputStream.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
out.close() out.close()
inputStream.close() inputStream.close()
} }

View File

@@ -31,7 +31,6 @@ open class EcoLoadableYamlConfig(
} }
final override fun createFile() { final override fun createFile() {
val resourcePath = resourcePath
val inputStream = source.getResourceAsStream(resourcePath)!! val inputStream = source.getResourceAsStream(resourcePath)!!
val outFile = File(this.plugin.dataFolder, resourcePath) val outFile = File(this.plugin.dataFolder, resourcePath)
val lastIndex = resourcePath.lastIndexOf('/') val lastIndex = resourcePath.lastIndexOf('/')
@@ -41,11 +40,7 @@ open class EcoLoadableYamlConfig(
} }
if (!outFile.exists()) { if (!outFile.exists()) {
val out: OutputStream = FileOutputStream(outFile) val out: OutputStream = FileOutputStream(outFile)
val buf = ByteArray(1024) inputStream.copyTo(out, 1024)
var len: Int
while (inputStream.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
out.close() out.close()
inputStream.close() inputStream.close()
} }

View File

@@ -207,7 +207,8 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
return if (cache.containsKey("$path\$FMT")) { return if (cache.containsKey("$path\$FMT")) {
cache["$path\$FMT"] as List<String> cache["$path\$FMT"] as List<String>
} else { } else {
cache["$path\$FMT"] = StringUtils.formatList(if (has(path)) ArrayList(handle.getStringList(path)) else ArrayList<String>()) val list = if (has(path)) handle.getStringList(path) else ArrayList()
cache["$path\$FMT"] = StringUtils.formatList(list);
getStrings(path, true) getStrings(path, true)
} }
} else { } else {

View File

@@ -17,8 +17,8 @@ open class EcoDropQueue(player: Player) : InternalDropQueue {
var xp: Int var xp: Int
val player: Player val player: Player
var loc: Location var loc: Location
var hasTelekinesis = false
private var hasTelekinesis = false
override fun addItem(item: ItemStack): InternalDropQueue { override fun addItem(item: ItemStack): InternalDropQueue {
items.add(item) items.add(item)
return this return this

View File

@@ -10,11 +10,14 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
val fetched = COLLATED_MAP[player] val fetched = COLLATED_MAP[player]
if (fetched == null) { if (fetched == null) {
COLLATED_MAP[player] = CollatedDrops(items, loc, xp) COLLATED_MAP[player] = CollatedDrops(items, loc, xp, hasTelekinesis)
} else { } else {
fetched.addDrops(items) fetched.addDrops(items)
fetched.location = loc fetched.location = loc
fetched.addXp(xp) fetched.addXp(xp)
if (this.hasTelekinesis) {
fetched.forceTelekinesis()
}
COLLATED_MAP[player] = fetched COLLATED_MAP[player] = fetched
} }
@@ -23,8 +26,10 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
class CollatedDrops( class CollatedDrops(
val drops: MutableList<ItemStack>, val drops: MutableList<ItemStack>,
var location: Location, var location: Location,
var xp: Int var xp: Int,
var telekinetic: Boolean
) { ) {
fun addDrops(toAdd: List<ItemStack>): CollatedDrops { fun addDrops(toAdd: List<ItemStack>): CollatedDrops {
drops.addAll(toAdd) drops.addAll(toAdd)
return this return this
@@ -34,6 +39,10 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
this.xp += xp this.xp += xp
return this return this
} }
fun forceTelekinesis() {
telekinetic = true
}
} }
companion object { companion object {

View File

@@ -3,14 +3,12 @@ package com.willfp.eco.internal.gui
import com.willfp.eco.core.gui.GUIFactory import com.willfp.eco.core.gui.GUIFactory
import com.willfp.eco.core.gui.menu.MenuBuilder import com.willfp.eco.core.gui.menu.MenuBuilder
import com.willfp.eco.core.gui.slot.SlotBuilder import com.willfp.eco.core.gui.slot.SlotBuilder
import com.willfp.eco.core.gui.slot.functional.SlotProvider
import com.willfp.eco.internal.gui.menu.EcoMenuBuilder import com.willfp.eco.internal.gui.menu.EcoMenuBuilder
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder import com.willfp.eco.internal.gui.slot.EcoSlotBuilder
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.util.function.Function
class EcoGUIFactory : GUIFactory { class EcoGUIFactory : GUIFactory {
override fun createSlotBuilder(provider: Function<Player, ItemStack>): SlotBuilder { override fun createSlotBuilder(provider: SlotProvider): SlotBuilder {
return EcoSlotBuilder(provider) return EcoSlotBuilder(provider)
} }

View File

@@ -1,23 +1,25 @@
package com.willfp.eco.internal.gui.menu package com.willfp.eco.internal.gui.menu
import com.willfp.eco.core.gui.menu.CloseHandler
import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.gui.menu.Menu
import com.willfp.eco.core.gui.slot.FillerSlot
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.internal.gui.slot.EcoFillerSlot import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.Inventory import org.bukkit.inventory.Inventory
import java.util.function.Consumer import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataType
@Suppress("UNCHECKED_CAST")
class EcoMenu( class EcoMenu(
private val rows: Int, private val rows: Int,
private val slots: List<MutableList<Slot>>, val slots: List<MutableList<EcoSlot>>,
private val title: String, private val title: String,
private val onClose: Consumer<InventoryCloseEvent> private val onClose: CloseHandler
): Menu { ): Menu {
override fun getSlot(row: Int, column: Int): Slot { override fun getSlot(row: Int, column: Int): Slot {
if (row < 1 || row > this.rows) { if (row < 1 || row > this.rows) {
throw IllegalArgumentException("Invalid row number!") throw IllegalArgumentException("Invalid row number!")
@@ -27,14 +29,7 @@ class EcoMenu(
throw IllegalArgumentException("Invalid column number!") throw IllegalArgumentException("Invalid column number!")
} }
val slot = slots[row - 1][column - 1] return slots[row - 1][column - 1]
if (slot is FillerSlot) {
slots[row - 1][column - 1] = EcoFillerSlot(slot.itemStack)
return getSlot(row, column)
}
return slot
} }
override fun open(player: Player): Inventory { override fun open(player: Player): Inventory {
@@ -46,7 +41,7 @@ class EcoMenu(
if (i == rows * 9) { if (i == rows * 9) {
break break
} }
val slotItem = item.getItemStack(player) val slotItem = item.getItemStack(player, this)
val meta = slotItem.itemMeta val meta = slotItem.itemMeta
if (meta != null) { if (meta != null) {
val lore = meta.lore val lore = meta.lore
@@ -67,7 +62,7 @@ class EcoMenu(
} }
fun handleClose(event: InventoryCloseEvent) { fun handleClose(event: InventoryCloseEvent) {
onClose.accept(event) onClose.handle(event, this)
} }
override fun getRows(): Int { override fun getRows(): Int {
@@ -77,4 +72,34 @@ class EcoMenu(
override fun getTitle(): String { override fun getTitle(): String {
return title return title
} }
override fun getCaptiveItems(player: Player): MutableList<ItemStack> {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return ArrayList()
return inventory.captiveItems
}
override fun <T : Any, Z : Any> writeData(
player: Player,
key: NamespacedKey,
type: PersistentDataType<T, Z>,
value: Z
) {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return
inventory.data[key] = value
inventory.refresh(player)
}
override fun <T : Any, Z : Any> readData(player: Player, key: NamespacedKey, type: PersistentDataType<T, Z>): T? {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return null
return inventory.data[key] as T?
}
override fun getKeys(player: Player): MutableSet<NamespacedKey> {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return HashSet()
return inventory.data.keys
}
} }

View File

@@ -1,22 +1,24 @@
package com.willfp.eco.internal.gui.menu package com.willfp.eco.internal.gui.menu
import com.willfp.eco.core.gui.menu.CloseHandler
import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.gui.menu.Menu
import com.willfp.eco.core.gui.menu.MenuBuilder import com.willfp.eco.core.gui.menu.MenuBuilder
import com.willfp.eco.core.gui.slot.FillerMask import com.willfp.eco.core.gui.slot.FillerMask
import com.willfp.eco.core.gui.slot.FillerSlot
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.internal.gui.slot.EcoFillerSlot import com.willfp.eco.internal.gui.slot.EcoFillerSlot
import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.ListUtils import com.willfp.eco.util.ListUtils
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.function.Consumer import java.util.function.Consumer
class EcoMenuBuilder(private val rows: Int) : MenuBuilder { class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
private var title = "Menu" private var title = "Menu"
private var maskSlots: List<MutableList<Slot?>> private var maskSlots: List<MutableList<Slot?>>
private val slots: List<MutableList<Slot>> = ListUtils.create2DList(rows, 9) private val slots: List<MutableList<Slot?>> = ListUtils.create2DList(rows, 9)
private var onClose = Consumer { _: InventoryCloseEvent -> } private var onClose = CloseHandler { _, _ -> }
override fun setTitle(title: String): MenuBuilder { override fun setTitle(title: String): MenuBuilder {
this.title = StringUtils.format(title) this.title = StringUtils.format(title)
@@ -34,35 +36,45 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
return this return this
} }
override fun modfiy(modifier: Consumer<MenuBuilder>): MenuBuilder {
modifier.accept(this)
return this
}
override fun setMask(mask: FillerMask): MenuBuilder { override fun setMask(mask: FillerMask): MenuBuilder {
maskSlots = mask.mask maskSlots = mask.mask
return this return this
} }
override fun onClose(action: Consumer<InventoryCloseEvent>): MenuBuilder { override fun onClose(action: CloseHandler): MenuBuilder {
onClose = action onClose = action
return this return this
} }
override fun build(): Menu { override fun build(): Menu {
val finalSlots: MutableList<MutableList<Slot>> = ArrayList() val tempSlots: MutableList<MutableList<Slot?>> = ArrayList(maskSlots)
for (maskRow in maskSlots) {
val row = ArrayList<Slot>()
for (slot in maskRow) {
row.add(slot ?: EcoFillerSlot(ItemStack(Material.AIR)))
}
finalSlots.add(ArrayList())
finalSlots.add(row)
}
for (i in slots.indices) { for (i in slots.indices) {
for (j in slots[i].indices) { for (j in slots[i].indices) {
val slot = slots[i][j] val slot = slots[i][j] ?: continue
finalSlots[i][j] = slot tempSlots[i][j] = slot
} }
} }
val finalSlots: MutableList<MutableList<EcoSlot>> = ArrayList()
for (row in tempSlots) {
val tempRow = ArrayList<EcoSlot>()
for (slot in row) {
var tempSlot = slot
if (tempSlot is FillerSlot) {
tempSlot = EcoFillerSlot(tempSlot.itemStack)
}
tempRow.add((tempSlot ?: EcoFillerSlot(ItemStack(Material.AIR))) as EcoSlot)
}
finalSlots.add(tempRow)
}
return EcoMenu(rows, finalSlots, title, onClose) return EcoMenu(rows, finalSlots, title, onClose)
} }

View File

@@ -0,0 +1,57 @@
package com.willfp.eco.internal.gui.menu
import com.willfp.eco.internal.gui.slot.EcoCaptivatorSlot
import com.willfp.eco.util.MenuUtils
import com.willfp.eco.util.StringUtils
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
class ExtendedInventory(
val inventory: Inventory,
private val menu: EcoMenu
) {
val captiveItems: MutableList<ItemStack> = ArrayList()
val data: MutableMap<NamespacedKey, Any> = HashMap()
fun refresh(player: Player) {
captiveItems.clear()
for (i in 0 until inventory.size) {
val pair = MenuUtils.convertSlotToRowColumn(i)
val row = pair.first!!
val column = pair.second!!
val slot = menu.getSlot(row, column)
if (slot is EcoCaptivatorSlot) {
val defaultItem = slot.getItemStack(player)
val item = inventory.getItem(i) ?: continue
if (item != defaultItem) {
captiveItems.add(item)
}
}
}
var i = 0
for (row in menu.slots) {
for (slot in row) {
if (i == menu.rows * 9) {
break
}
val slotItem = slot.getItemStack(player, menu)
val meta = slotItem.itemMeta
if (meta != null) {
val lore = meta.lore
if (lore != null) {
lore.replaceAll{ s -> StringUtils.format(s, player) }
meta.lore = lore
}
slotItem.itemMeta = meta
}
if (!slot.isCaptive) {
inventory.setItem(i, slotItem)
}
i++
}
}
}
}

View File

@@ -4,20 +4,28 @@ import com.willfp.eco.core.gui.menu.Menu
import org.bukkit.inventory.Inventory import org.bukkit.inventory.Inventory
object MenuHandler { object MenuHandler {
private val MENUS: MutableMap<Inventory, Menu> = HashMap() private val MENUS: MutableMap<ExtendedInventory, EcoMenu> = HashMap()
private val INVS: MutableMap<Inventory, ExtendedInventory> = HashMap()
fun registerMenu( fun registerMenu(
inventory: Inventory, inventory: Inventory,
menu: Menu menu: EcoMenu
) { ) {
MENUS[inventory] = menu val extendedInventory = ExtendedInventory(inventory, menu)
INVS[inventory] = extendedInventory
MENUS[extendedInventory] = menu
} }
fun unregisterMenu(inventory: Inventory) { fun unregisterMenu(inventory: Inventory) {
MENUS.remove(inventory) MENUS.remove(INVS[inventory])
INVS.remove(inventory)
} }
fun getMenu(inventory: Inventory): Menu? { fun getMenu(inventory: Inventory): Menu? {
return MENUS[inventory] return MENUS[INVS[inventory]]
}
fun getExtendedInventory(inventory: Inventory): ExtendedInventory? {
return INVS[inventory]
} }
} }

View File

@@ -0,0 +1,28 @@
package com.willfp.eco.internal.gui.slot
import com.willfp.eco.core.Eco
import com.willfp.eco.core.gui.slot.functional.SlotHandler
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
class EcoCaptivatorSlot : EcoSlot(
{ _, _ -> ItemStack(Material.AIR) },
allowMovingItem,
allowMovingItem,
allowMovingItem,
allowMovingItem,
allowMovingItem,
{ _, _, _ -> }
) {
companion object {
val plugin = Eco.getHandler().ecoPlugin!!
val allowMovingItem = SlotHandler { event, _, _ ->
event.isCancelled = false
}
}
override fun isCaptive(): Boolean {
return true
}
}

View File

@@ -1,13 +1,13 @@
package com.willfp.eco.internal.gui.slot package com.willfp.eco.internal.gui.slot
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.function.Function
class EcoFillerSlot(itemStack: ItemStack) : EcoSlot( class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
Function { itemStack }, { _, _ -> itemStack },
{ _, _ -> }, { _, _, _ -> },
{ _, _ -> }, { _, _, _ -> },
{ _, _ -> }, { _, _, _ -> },
{ _, _ -> }, { _, _, _ -> },
{ _, _ -> } { _, _, _ -> },
{ _, _, _ -> }
) )

View File

@@ -1,34 +1,58 @@
package com.willfp.eco.internal.gui.slot package com.willfp.eco.internal.gui.slot
import com.willfp.eco.core.gui.menu.Menu
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.core.gui.slot.functional.SlotHandler
import com.willfp.eco.core.gui.slot.functional.SlotModifier
import com.willfp.eco.core.gui.slot.functional.SlotProvider
import com.willfp.eco.internal.gui.menu.MenuHandler
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.function.BiConsumer
import java.util.function.Function
open class EcoSlot( open class EcoSlot(
private val provider: Function<Player, ItemStack>, private val provider: SlotProvider,
private val onLeftClick: BiConsumer<InventoryClickEvent, Slot>, private val onLeftClick: SlotHandler,
private val onRightClick: BiConsumer<InventoryClickEvent, Slot>, private val onRightClick: SlotHandler,
private val onShiftLeftClick: BiConsumer<InventoryClickEvent, Slot>, private val onShiftLeftClick: SlotHandler,
private val onShiftRightClick: BiConsumer<InventoryClickEvent, Slot>, private val onShiftRightClick: SlotHandler,
private val onMiddleClick: BiConsumer<InventoryClickEvent, Slot> private val onMiddleClick: SlotHandler,
private val modifier: SlotModifier
) : Slot { ) : Slot {
fun handleInventoryClick(event: InventoryClickEvent) { fun handleInventoryClick(
event: InventoryClickEvent,
menu: Menu
) {
when (event.click) { when (event.click) {
ClickType.LEFT -> this.onLeftClick.accept(event, this) ClickType.LEFT -> this.onLeftClick.handle(event, this, menu)
ClickType.RIGHT -> this.onRightClick.accept(event, this) ClickType.RIGHT -> this.onRightClick.handle(event, this, menu)
ClickType.SHIFT_LEFT -> this.onShiftLeftClick.accept(event, this) ClickType.SHIFT_LEFT -> this.onShiftLeftClick.handle(event, this, menu)
ClickType.SHIFT_RIGHT -> this.onShiftRightClick.accept(event, this) ClickType.SHIFT_RIGHT -> this.onShiftRightClick.handle(event, this, menu)
ClickType.MIDDLE -> this.onMiddleClick.accept(event, this) ClickType.MIDDLE -> this.onMiddleClick.handle(event, this, menu)
else -> { } else -> {
}
} }
} }
override fun getItemStack(player: Player): ItemStack { override fun getItemStack(player: Player): ItemStack {
return provider.apply(player) val menu = MenuHandler.getMenu(player.openInventory.topInventory)!!
val prev = provider.provide(player, menu)
modifier.modify(player, menu, prev)
return prev
}
fun getItemStack(
player: Player,
menu: Menu
): ItemStack {
val prev = provider.provide(player, menu)
modifier.modify(player, menu, prev)
return prev
}
override fun isCaptive(): Boolean {
return false
} }
} }

View File

@@ -2,45 +2,65 @@ package com.willfp.eco.internal.gui.slot
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.core.gui.slot.SlotBuilder import com.willfp.eco.core.gui.slot.SlotBuilder
import org.bukkit.entity.Player import com.willfp.eco.core.gui.slot.functional.SlotHandler
import org.bukkit.event.inventory.InventoryClickEvent import com.willfp.eco.core.gui.slot.functional.SlotModifier
import org.bukkit.inventory.ItemStack import com.willfp.eco.core.gui.slot.functional.SlotProvider
import java.util.function.BiConsumer
import java.util.function.Function
class EcoSlotBuilder(private val provider: Function<Player, ItemStack>) : SlotBuilder { class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
private var onLeftClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } } private var captive = false
private var onRightClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } } var modifier: SlotModifier = SlotModifier{ player, menu, _ -> provider.provide(player, menu)}
private var onShiftLeftClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onShiftRightClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onMiddleClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
override fun onLeftClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder { private var onLeftClick =
SlotHandler { _, _, _ -> run { } }
private var onRightClick =
SlotHandler { _, _, _ -> run { } }
private var onShiftLeftClick =
SlotHandler { _, _, _ -> run { } }
private var onShiftRightClick =
SlotHandler { _, _, _ -> run { } }
private var onMiddleClick =
SlotHandler { _, _, _ -> run { } }
override fun onLeftClick(action: SlotHandler): SlotBuilder {
onLeftClick = action onLeftClick = action
return this return this
} }
override fun onRightClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder { override fun onRightClick(action: SlotHandler): SlotBuilder {
onRightClick = action onRightClick = action
return this return this
} }
override fun onShiftLeftClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder { override fun onShiftLeftClick(action: SlotHandler): SlotBuilder {
onShiftLeftClick = action onShiftLeftClick = action
return this return this
} }
override fun onShiftRightClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder { override fun onShiftRightClick(action: SlotHandler): SlotBuilder {
onShiftRightClick = action onShiftRightClick = action
return this return this
} }
override fun onMiddleClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder { override fun onMiddleClick(action: SlotHandler): SlotBuilder {
onMiddleClick = action onMiddleClick = action
return this return this
} }
override fun setCaptive(): SlotBuilder {
captive = true
return this
}
override fun setModifier(modifier: SlotModifier): SlotBuilder {
this.modifier = modifier
return this
}
override fun build(): Slot { override fun build(): Slot {
return EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick) return if (captive) {
EcoCaptivatorSlot()
} else {
EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick, modifier)
}
} }
} }

View File

@@ -96,6 +96,14 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
} }
} }
override fun getRepairCost(): Int {
return handle.repairCost;
}
override fun setRepairCost(cost: Int) {
handle.repairCost = cost;
}
private fun apply() { private fun apply() {
if (bukkit !is CraftItemStack) { if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta

View File

@@ -115,6 +115,14 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
} }
} }
override fun getRepairCost(): Int {
return handle.baseRepairCost;
}
override fun setRepairCost(cost: Int) {
handle.setRepairCost(cost);
}
private fun apply() { private fun apply() {
if (bukkit !is CraftItemStack) { if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta

View File

@@ -6,6 +6,7 @@ import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.TestableItem; import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.recipe.Recipes; import com.willfp.eco.core.recipe.Recipes;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem; import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack; import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.core.recipe.recipes.CraftingRecipe; import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe; import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
@@ -130,6 +131,22 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
return; return;
} }
} }
if (part instanceof ModifiedTestableItem modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
if (part instanceof TestableStack modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
} }
} }
@@ -156,6 +173,24 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
return; return;
} }
} }
if (part instanceof ModifiedTestableItem modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
event.setResult(Event.Result.DENY);
event.setCancelled(true);
return;
}
}
}
if (part instanceof TestableStack modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
} }
} }

View File

@@ -8,11 +8,17 @@ class CollatedRunnable(plugin: EcoPlugin) {
init { init {
plugin.scheduler.runTimer({ plugin.scheduler.runTimer({
for ((key, value) in EcoFastCollatedDropQueue.COLLATED_MAP) { for ((key, value) in EcoFastCollatedDropQueue.COLLATED_MAP) {
EcoDropQueue(key) val queue = EcoDropQueue(key)
.setLocation(value.location) .setLocation(value.location)
.addItems(value.drops) .addItems(value.drops)
.addXP(value.xp) .addXP(value.xp)
.push()
if (value.telekinetic) {
queue.forceTelekinesis()
}
queue.push()
EcoFastCollatedDropQueue.COLLATED_MAP.remove(key) EcoFastCollatedDropQueue.COLLATED_MAP.remove(key)
} }
EcoFastCollatedDropQueue.COLLATED_MAP.clear() EcoFastCollatedDropQueue.COLLATED_MAP.clear()

View File

@@ -2,44 +2,105 @@ package com.willfp.eco.spigot.gui
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent import com.willfp.eco.core.PluginDependent
import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.internal.gui.menu.EcoMenu import com.willfp.eco.internal.gui.menu.EcoMenu
import com.willfp.eco.internal.gui.menu.MenuHandler import com.willfp.eco.internal.gui.menu.MenuHandler
import com.willfp.eco.internal.gui.slot.EcoSlot import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.MenuUtils
import org.apache.commons.lang.Validate import org.apache.commons.lang.Validate
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.inventory.InventoryCloseEvent
class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Listener { class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Listener {
@EventHandler @EventHandler
fun handleSlotClick(event: InventoryClickEvent) { fun handleSlotClick(event: InventoryClickEvent) {
if (event.whoClicked !is Player) { val player = event.whoClicked
if (player !is Player) {
return return
} }
if (event.clickedInventory == null) { val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return
return val rowColumn = MenuUtils.convertSlotToRowColumn(event.slot)
} val row = rowColumn.first!!
val menu = MenuHandler.getMenu(event.clickedInventory!!) ?: return val column = rowColumn.second!!
val row = Math.floorDiv(event.slot, 9)
val column = event.slot - row * 9
val slot = menu.getSlot(row, column) val slot = menu.getSlot(row, column)
Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!") Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!")
val ecoSlot = menu.getSlot(row, column) as EcoSlot val ecoSlot = menu.getSlot(row, column) as EcoSlot
event.isCancelled = true event.isCancelled = true
ecoSlot.handleInventoryClick(event) ecoSlot.handleInventoryClick(event, menu)
if (event.clickedInventory == null) {
return
}
val extendedInventory = MenuHandler.getExtendedInventory(event.clickedInventory!!) ?: return
plugin.scheduler.run{ extendedInventory.refresh(player) }
} }
@EventHandler @EventHandler
fun handleCaptivatorSlots(event: InventoryClickEvent) {
val player = event.whoClicked
if (player !is Player) {
return
}
MenuHandler.getMenu(player.openInventory.topInventory) ?: return
MenuHandler.getExtendedInventory(player.openInventory.topInventory) ?: return
plugin.scheduler.run{ MenuHandler.getExtendedInventory(player.openInventory.topInventory)?.refresh(player) }
}
@EventHandler
fun handleShiftClick(event: InventoryClickEvent) {
if (!(event.click == ClickType.SHIFT_RIGHT || event.click == ClickType.SHIFT_LEFT)) {
return
}
val player = event.whoClicked
if (player !is Player) {
return
}
val inv = player.openInventory.topInventory
if (inv == event.clickedInventory) {
return
}
val menu = MenuHandler.getMenu(inv) ?: return
val rowColumn = MenuUtils.convertSlotToRowColumn(inv.firstEmpty())
val row = rowColumn.first!!
val column = rowColumn.second!!
val slot = menu.getSlot(row, column)
if (!slot.isCaptive) {
event.isCancelled = true
}
}
@EventHandler(priority = EventPriority.HIGH)
fun handleClose(event: InventoryCloseEvent) { fun handleClose(event: InventoryCloseEvent) {
if (event.player !is Player) { val player = event.player
if (player !is Player) {
return return
} }
val menu = MenuHandler.getMenu(event.inventory) ?: return val menu = MenuHandler.getMenu(event.inventory) ?: return
Validate.isTrue(menu is EcoMenu, "Menu not instance of EcoMenu!") Validate.isTrue(menu is EcoMenu, "Menu not instance of EcoMenu!")
val ecoMenu = menu as EcoMenu val ecoMenu = menu as EcoMenu
ecoMenu.handleClose(event) ecoMenu.handleClose(event)
DropQueue(player)
.addItems(ecoMenu.getCaptiveItems(player))
.setLocation(player.location)
.forceTelekinesis()
.push()
plugin.scheduler.run { MenuHandler.unregisterMenu(event.inventory) } plugin.scheduler.run { MenuHandler.unregisterMenu(event.inventory) }
} }
} }

View File

@@ -1,2 +1,2 @@
version = 6.3.1 version = 6.5.2
plugin-name = eco plugin-name = eco