Compare commits

..

30 Commits
6.3.2 ... 6.5.0

Author SHA1 Message Date
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
36 changed files with 768 additions and 147 deletions

View File

@@ -158,8 +158,12 @@ Here's a list of some (not all) of the features of eco:
<h1 align="center">
<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">
<img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner">
</a>
<br>
</h1>

View File

@@ -71,10 +71,6 @@ public class Display {
*/
public ItemStack display(@NotNull final ItemStack itemStack,
@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<>();
for (DisplayPriority priority : DisplayPriority.values()) {
@@ -139,10 +135,6 @@ public class Display {
unfinalize(itemStack);
}
if (!itemStack.hasItemMeta()) {
return itemStack;
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {

View File

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

View File

@@ -47,6 +47,21 @@ public interface FastItemStack {
*/
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.
*

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.slot.SlotBuilder;
import org.bukkit.entity.Player;
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
/**
* 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)}.
@@ -19,7 +17,7 @@ public interface GUIFactory {
* @param provider The provider.
* @return The builder.
*/
SlotBuilder createSlotBuilder(@NotNull Function<Player, ItemStack> provider);
SlotBuilder createSlotBuilder(@NotNull SlotProvider provider);
/**
* 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.gui.slot.Slot;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
/**
* GUI version of {@link Inventory}.
@@ -44,6 +51,51 @@ public interface Menu {
*/
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.
*

View File

@@ -31,6 +31,14 @@ public interface MenuBuilder {
int column,
@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.
*
@@ -45,7 +53,18 @@ public interface MenuBuilder {
* @param action The handler.
* @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.

View File

@@ -7,6 +7,7 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
/**
@@ -39,35 +40,46 @@ public class FillerMask {
*/
public FillerMask(@NotNull final Material material,
@NotNull final String... pattern) {
if (material == Material.AIR) {
throw new IllegalArgumentException("Material cannot be air!");
this(new MaskMaterials(material), pattern);
}
/**
* 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);
ItemStack itemStack = new ItemStackBuilder(material)
.setDisplayName("&r")
.build();
for (int i = 0; i < materials.materials().length; i++) {
ItemStack itemStack = new ItemStackBuilder(materials.materials()[i])
.setDisplayName("&r")
.build();
int row = 0;
int row = 0;
for (String patternRow : pattern) {
int column = 0;
if (patternRow.length() != 9) {
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 (String patternRow : pattern) {
int column = 0;
if (patternRow.length() != 9) {
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 == 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) {
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;
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.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -19,6 +21,22 @@ public interface Slot {
*/
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.
*
@@ -26,7 +44,7 @@ public interface Slot {
* @return The builder.
*/
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.
*/
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);
}
}

View File

@@ -1,5 +1,7 @@
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.jetbrains.annotations.NotNull;
@@ -15,7 +17,17 @@ public interface SlotBuilder {
* @param action The handler.
* @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.
@@ -23,7 +35,17 @@ public interface SlotBuilder {
* @param action The handler.
* @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.
@@ -31,7 +53,17 @@ public interface SlotBuilder {
* @param action The handler.
* @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.
@@ -39,7 +71,17 @@ public interface SlotBuilder {
* @param action The handler.
* @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.
@@ -47,7 +89,32 @@ public interface SlotBuilder {
* @param action The handler.
* @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.

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

@@ -1,5 +1,6 @@
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.ItemStackBuilder;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
@@ -12,6 +13,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
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.
*/
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(" ");
if (args.length == 0) {
return new EmptyTestableItem();
@@ -117,9 +131,17 @@ public final class Items {
return item;
}
ItemBuilder builder = new ItemStackBuilder(item.getItem());
requiredEnchantments.forEach(builder::addEnchantment);
ItemStack example = builder.build();
ItemStack example = item.getItem();
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(
item,
@@ -132,12 +154,23 @@ public final class Items {
assert meta != null;
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!meta.hasEnchant(entry.getKey())) {
return false;
if (meta instanceof EnchantmentStorageMeta storageMeta) {
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!storageMeta.hasStoredEnchant(entry.getKey())) {
return false;
}
if (storageMeta.getStoredEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
} else {
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

@@ -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})" + ">"))
.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.
*
@@ -246,7 +255,7 @@ public class StringUtils {
public String legacyToJson(@NotNull final String legacy) {
return GsonComponentSerializer.gson().serialize(
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.
*/
public String jsonToLegacy(@NotNull final String json) {
return LegacyComponentSerializer.legacySection().serialize(
return LEGACY_COMPONENT_SERIALIZER.serialize(
GsonComponentSerializer.gson().deserialize(json)
);
}

View File

@@ -207,7 +207,8 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
return if (cache.containsKey("$path\$FMT")) {
cache["$path\$FMT"] as List<String>
} 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)
}
} else {

View File

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

View File

@@ -10,11 +10,14 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
val fetched = COLLATED_MAP[player]
if (fetched == null) {
COLLATED_MAP[player] = CollatedDrops(items, loc, xp)
COLLATED_MAP[player] = CollatedDrops(items, loc, xp, hasTelekinesis)
} else {
fetched.addDrops(items)
fetched.location = loc
fetched.addXp(xp)
if (this.hasTelekinesis) {
fetched.forceTelekinesis()
}
COLLATED_MAP[player] = fetched
}
@@ -23,8 +26,10 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
class CollatedDrops(
val drops: MutableList<ItemStack>,
var location: Location,
var xp: Int
var xp: Int,
var telekinetic: Boolean
) {
fun addDrops(toAdd: List<ItemStack>): CollatedDrops {
drops.addAll(toAdd)
return this
@@ -34,6 +39,10 @@ class EcoFastCollatedDropQueue(player: Player) : EcoDropQueue(player) {
this.xp += xp
return this
}
fun forceTelekinesis() {
telekinetic = true
}
}
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.menu.MenuBuilder
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.slot.EcoSlotBuilder
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.util.function.Function
class EcoGUIFactory : GUIFactory {
override fun createSlotBuilder(provider: Function<Player, ItemStack>): SlotBuilder {
override fun createSlotBuilder(provider: SlotProvider): SlotBuilder {
return EcoSlotBuilder(provider)
}

View File

@@ -1,23 +1,25 @@
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.slot.FillerSlot
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 org.bukkit.Bukkit
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryCloseEvent
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(
private val rows: Int,
private val slots: List<MutableList<Slot>>,
val slots: List<MutableList<EcoSlot>>,
private val title: String,
private val onClose: Consumer<InventoryCloseEvent>
private val onClose: CloseHandler
): Menu {
override fun getSlot(row: Int, column: Int): Slot {
if (row < 1 || row > this.rows) {
throw IllegalArgumentException("Invalid row number!")
@@ -27,14 +29,7 @@ class EcoMenu(
throw IllegalArgumentException("Invalid column number!")
}
val slot = slots[row - 1][column - 1]
if (slot is FillerSlot) {
slots[row - 1][column - 1] = EcoFillerSlot(slot.itemStack)
return getSlot(row, column)
}
return slot
return slots[row - 1][column - 1]
}
override fun open(player: Player): Inventory {
@@ -46,7 +41,7 @@ class EcoMenu(
if (i == rows * 9) {
break
}
val slotItem = item.getItemStack(player)
val slotItem = item.getItemStack(player, this)
val meta = slotItem.itemMeta
if (meta != null) {
val lore = meta.lore
@@ -67,7 +62,7 @@ class EcoMenu(
}
fun handleClose(event: InventoryCloseEvent) {
onClose.accept(event)
onClose.handle(event, this)
}
override fun getRows(): Int {
@@ -77,4 +72,34 @@ class EcoMenu(
override fun getTitle(): String {
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
import com.willfp.eco.core.gui.menu.CloseHandler
import com.willfp.eco.core.gui.menu.Menu
import com.willfp.eco.core.gui.menu.MenuBuilder
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.internal.gui.slot.EcoFillerSlot
import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.ListUtils
import com.willfp.eco.util.StringUtils
import org.bukkit.Material
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.ItemStack
import java.util.function.Consumer
class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
private var title = "Menu"
private var maskSlots: List<MutableList<Slot?>>
private val slots: List<MutableList<Slot>> = ListUtils.create2DList(rows, 9)
private var onClose = Consumer { _: InventoryCloseEvent -> }
private val slots: List<MutableList<Slot?>> = ListUtils.create2DList(rows, 9)
private var onClose = CloseHandler { _, _ -> }
override fun setTitle(title: String): MenuBuilder {
this.title = StringUtils.format(title)
@@ -34,35 +36,45 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
return this
}
override fun modfiy(modifier: Consumer<MenuBuilder>): MenuBuilder {
modifier.accept(this)
return this
}
override fun setMask(mask: FillerMask): MenuBuilder {
maskSlots = mask.mask
return this
}
override fun onClose(action: Consumer<InventoryCloseEvent>): MenuBuilder {
override fun onClose(action: CloseHandler): MenuBuilder {
onClose = action
return this
}
override fun build(): Menu {
val finalSlots: MutableList<MutableList<Slot>> = ArrayList()
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)
}
val tempSlots: MutableList<MutableList<Slot?>> = ArrayList(maskSlots)
for (i in slots.indices) {
for (j in slots[i].indices) {
val slot = slots[i][j]
finalSlots[i][j] = slot
val slot = slots[i][j] ?: continue
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)
}

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
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(
inventory: Inventory,
menu: Menu
menu: EcoMenu
) {
MENUS[inventory] = menu
val extendedInventory = ExtendedInventory(inventory, menu)
INVS[inventory] = extendedInventory
MENUS[extendedInventory] = menu
}
fun unregisterMenu(inventory: Inventory) {
MENUS.remove(inventory)
MENUS.remove(INVS[inventory])
INVS.remove(inventory)
}
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
import org.bukkit.inventory.ItemStack
import java.util.function.Function
class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
Function { itemStack },
{ _, _ -> },
{ _, _ -> },
{ _, _ -> },
{ _, _ -> },
{ _, _ -> }
{ _, _ -> itemStack },
{ _, _, _ -> },
{ _, _, _ -> },
{ _, _, _ -> },
{ _, _, _ -> },
{ _, _, _ -> },
{ _, _, _ -> }
)

View File

@@ -1,34 +1,58 @@
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.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.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.inventory.ItemStack
import java.util.function.BiConsumer
import java.util.function.Function
open class EcoSlot(
private val provider: Function<Player, ItemStack>,
private val onLeftClick: BiConsumer<InventoryClickEvent, Slot>,
private val onRightClick: BiConsumer<InventoryClickEvent, Slot>,
private val onShiftLeftClick: BiConsumer<InventoryClickEvent, Slot>,
private val onShiftRightClick: BiConsumer<InventoryClickEvent, Slot>,
private val onMiddleClick: BiConsumer<InventoryClickEvent, Slot>
private val provider: SlotProvider,
private val onLeftClick: SlotHandler,
private val onRightClick: SlotHandler,
private val onShiftLeftClick: SlotHandler,
private val onShiftRightClick: SlotHandler,
private val onMiddleClick: SlotHandler,
private val modifier: SlotModifier
) : Slot {
fun handleInventoryClick(event: InventoryClickEvent) {
fun handleInventoryClick(
event: InventoryClickEvent,
menu: Menu
) {
when (event.click) {
ClickType.LEFT -> this.onLeftClick.accept(event, this)
ClickType.RIGHT -> this.onRightClick.accept(event, this)
ClickType.SHIFT_LEFT -> this.onShiftLeftClick.accept(event, this)
ClickType.SHIFT_RIGHT -> this.onShiftRightClick.accept(event, this)
ClickType.MIDDLE -> this.onMiddleClick.accept(event, this)
else -> { }
ClickType.LEFT -> this.onLeftClick.handle(event, this, menu)
ClickType.RIGHT -> this.onRightClick.handle(event, this, menu)
ClickType.SHIFT_LEFT -> this.onShiftLeftClick.handle(event, this, menu)
ClickType.SHIFT_RIGHT -> this.onShiftRightClick.handle(event, this, menu)
ClickType.MIDDLE -> this.onMiddleClick.handle(event, this, menu)
else -> {
}
}
}
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.SlotBuilder
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.inventory.ItemStack
import java.util.function.BiConsumer
import java.util.function.Function
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
class EcoSlotBuilder(private val provider: Function<Player, ItemStack>) : SlotBuilder {
private var onLeftClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onRightClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onShiftLeftClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onShiftRightClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
private var onMiddleClick: BiConsumer<InventoryClickEvent, Slot> = BiConsumer { _, _ -> run { } }
class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
private var captive = false
var modifier: SlotModifier = SlotModifier{ player, menu, _ -> provider.provide(player, menu)}
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
return this
}
override fun onRightClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder {
override fun onRightClick(action: SlotHandler): SlotBuilder {
onRightClick = action
return this
}
override fun onShiftLeftClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder {
override fun onShiftLeftClick(action: SlotHandler): SlotBuilder {
onShiftLeftClick = action
return this
}
override fun onShiftRightClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder {
override fun onShiftRightClick(action: SlotHandler): SlotBuilder {
onShiftRightClick = action
return this
}
override fun onMiddleClick(action: BiConsumer<InventoryClickEvent, Slot>): SlotBuilder {
override fun onMiddleClick(action: SlotHandler): SlotBuilder {
onMiddleClick = action
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 {
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() {
if (bukkit !is CraftItemStack) {
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() {
if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta

View File

@@ -8,11 +8,17 @@ class CollatedRunnable(plugin: EcoPlugin) {
init {
plugin.scheduler.runTimer({
for ((key, value) in EcoFastCollatedDropQueue.COLLATED_MAP) {
EcoDropQueue(key)
val queue = EcoDropQueue(key)
.setLocation(value.location)
.addItems(value.drops)
.addXP(value.xp)
.push()
if (value.telekinetic) {
queue.forceTelekinesis()
}
queue.push()
EcoFastCollatedDropQueue.COLLATED_MAP.remove(key)
}
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.PluginDependent
import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.internal.gui.menu.EcoMenu
import com.willfp.eco.internal.gui.menu.MenuHandler
import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.MenuUtils
import org.apache.commons.lang.Validate
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Listener {
@EventHandler
fun handleSlotClick(event: InventoryClickEvent) {
if (event.whoClicked !is Player) {
val player = event.whoClicked
if (player !is Player) {
return
}
if (event.clickedInventory == null) {
return
}
val menu = MenuHandler.getMenu(event.clickedInventory!!) ?: return
val row = Math.floorDiv(event.slot, 9)
val column = event.slot - row * 9
val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return
val rowColumn = MenuUtils.convertSlotToRowColumn(event.slot)
val row = rowColumn.first!!
val column = rowColumn.second!!
val slot = menu.getSlot(row, column)
Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!")
val ecoSlot = menu.getSlot(row, column) as EcoSlot
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
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) {
if (event.player !is Player) {
val player = event.player
if (player !is Player) {
return
}
val menu = MenuHandler.getMenu(event.inventory) ?: return
Validate.isTrue(menu is EcoMenu, "Menu not instance of EcoMenu!")
val ecoMenu = menu as EcoMenu
ecoMenu.handleClose(event)
DropQueue(player)
.addItems(ecoMenu.getCaptiveItems(player))
.setLocation(player.location)
.forceTelekinesis()
.push()
plugin.scheduler.run { MenuHandler.unregisterMenu(event.inventory) }
}
}

View File

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