9
0
mirror of https://github.com/Auxilor/Reforges.git synced 2025-12-29 11:59:21 +00:00

Reworked most of the internals to stop using AttributeModifiers

This commit is contained in:
Auxilor
2021-10-04 10:22:46 +01:00
parent b61f8cc6fd
commit 561e1ef428
13 changed files with 364 additions and 145 deletions

View File

@@ -15,10 +15,14 @@ import com.willfp.reforges.effects.Effects;
import com.willfp.reforges.reforges.Reforges;
import com.willfp.reforges.reforges.util.ReforgeArgParser;
import com.willfp.reforges.reforges.util.WatcherTriggers;
import com.willfp.reforges.reforges.util.equip.ReforgeEnableListeners;
import com.willfp.reforges.reforges.util.equip.SyncReforgeEnableTask;
import com.willfp.reforges.util.AntiPlaceListener;
import com.willfp.reforges.util.DiscoverRecipeListener;
import com.willfp.reforges.vault.EconomyHandler;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.Nullable;
@@ -76,6 +80,11 @@ public class ReforgesPlugin extends EcoPlugin {
}
this.getLogger().info(Reforges.values().size() + " Reforges Loaded");
this.getScheduler().runTimer((Runnable) Conditions.HAS_PERMISSION, 103, 100);
this.getScheduler().runTimer(() -> {
for (Player player : Bukkit.getOnlinePlayers()) {
SyncReforgeEnableTask.CHECK.accept(player);
}
}, 81, 81);
}
@Override
@@ -83,7 +92,8 @@ public class ReforgesPlugin extends EcoPlugin {
return Arrays.asList(
new DiscoverRecipeListener(this),
new AntiPlaceListener(),
new WatcherTriggers(this)
new WatcherTriggers(this),
new ReforgeEnableListeners(this)
);
}
@@ -102,7 +112,7 @@ public class ReforgesPlugin extends EcoPlugin {
@Override
public String getMinimumEcoVersion() {
return "6.8.0";
return "6.9.0";
}
/**

View File

@@ -4,6 +4,7 @@ import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.YamlBaseConfig;
import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.reforges.reforges.meta.ReforgeTarget;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
@@ -37,7 +38,17 @@ public class TargetYml extends YamlBaseConfig {
*/
public Set<TestableItem> getTargetItems(@NotNull final String target) {
Set<TestableItem> items = new HashSet<>();
this.getStrings(target, false).forEach(s -> items.add(Items.lookup(s.toUpperCase())));
this.getStrings(target + ".items", false).forEach(s -> items.add(Items.lookup(s.toUpperCase())));
return items;
}
/**
* Get all materials from a target name.
*
* @param target The name of the target.
* @return All materials.
*/
public ReforgeTarget.Slot getSlot(@NotNull final String target) {
return ReforgeTarget.Slot.valueOf(this.getString(target + ".slot").toUpperCase());
}
}

View File

@@ -5,8 +5,8 @@ import com.willfp.reforges.ReforgesPlugin;
import com.willfp.reforges.reforges.util.Watcher;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -59,21 +59,21 @@ public abstract class Effect implements Listener, Watcher {
/**
* Handle application of a reforge containing this effect.
*
* @param meta The ItemMeta.
* @param player The player.
* @param config The config.
*/
public void handleEnabling(@NotNull final ItemMeta meta,
public void handleEnabling(@NotNull final Player player,
@NotNull final JSONConfig config) {
// Override when needed
// Override when needed.
}
/**
* Handle removal of a reforge containing this effect.
*
* @param meta The ItemMeta.
* @param player The player.
*/
public void handleDisabling(@NotNull final ItemMeta meta) {
// Override when needed
public void handleDisabling(@NotNull final Player player) {
// Override when needed.
}
@Override

View File

@@ -2,32 +2,35 @@ package com.willfp.reforges.reforges;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.reforges.ReforgesPlugin;
import com.willfp.reforges.reforges.meta.ReforgeTarget;
import com.willfp.reforges.reforges.util.ReforgeUtils;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ReforgeLookup {
/**
* All registered providers.
*/
private static final Set<Function<Player, Collection<ItemStack>>> PROVIDERS = new HashSet<>();
private static final Set<Function<Player, Map<ItemStack, ReforgeTarget.Slot>>> PROVIDERS = new HashSet<>();
/**
* Cached items.
*/
private static final Map<UUID, Collection<ItemStack>> ITEM_CACHE = new WeakHashMap<>();
private static final Map<UUID, Map<ItemStack, ReforgeTarget.Slot>> ITEM_CACHE = new WeakHashMap<>();
/**
* Cached reforges.
@@ -44,7 +47,7 @@ public class ReforgeLookup {
*
* @param provider The provider.
*/
public static void registerProvider(@NotNull final Function<Player, Collection<ItemStack>> provider) {
public static void registerProvider(@NotNull final Function<Player, Map<ItemStack, ReforgeTarget.Slot>> provider) {
PROVIDERS.add(provider);
}
@@ -54,16 +57,16 @@ public class ReforgeLookup {
* @param player The player.
* @return The ItemStacks.
*/
public static Set<ItemStack> provide(@NotNull final Player player) {
public static Map<ItemStack, ReforgeTarget.Slot> provide(@NotNull final Player player) {
if (ITEM_CACHE.containsKey(player.getUniqueId())) {
return new HashSet<>(ITEM_CACHE.get(player.getUniqueId()));
return new HashMap<>(ITEM_CACHE.get(player.getUniqueId()));
}
Set<ItemStack> found = new HashSet<>();
for (Function<Player, Collection<ItemStack>> provider : PROVIDERS) {
found.addAll(provider.apply(player));
Map<ItemStack, ReforgeTarget.Slot> found = new HashMap<>();
for (Function<Player, Map<ItemStack, ReforgeTarget.Slot>> provider : PROVIDERS) {
found.putAll(provider.apply(player));
}
found.removeIf(Objects::isNull);
found.keySet().removeIf(Objects::isNull);
ITEM_CACHE.put(player.getUniqueId(), found);
PLUGIN.getScheduler().runLater(() -> ITEM_CACHE.remove(player.getUniqueId()), 40);
@@ -77,14 +80,17 @@ public class ReforgeLookup {
* @param player The player.
* @return The Reforges.
*/
public static Set<Reforge> provideReforges(@NotNull final Player player) {
public static List<Reforge> provideReforges(@NotNull final Player player) {
if (REFORGE_CACHE.containsKey(player.getUniqueId())) {
return new HashSet<>(REFORGE_CACHE.get(player.getUniqueId()));
return new ArrayList<>(REFORGE_CACHE.get(player.getUniqueId()));
}
Set<Reforge> found = new HashSet<>();
List<Reforge> found = new ArrayList<>();
for (Map.Entry<ItemStack, ReforgeTarget.Slot> entry : provide(player).entrySet()) {
ItemStack itemStack = entry.getKey();
ReforgeTarget.Slot slot = entry.getValue();
for (ItemStack itemStack : provide(player)) {
if (itemStack == null) {
continue;
}
@@ -95,6 +101,13 @@ public class ReforgeLookup {
continue;
}
if (!reforge.getTargets().stream()
.map(ReforgeTarget::getSlot)
.collect(Collectors.toList())
.contains(slot)) {
continue;
}
found.add(reforge);
}
@@ -104,9 +117,31 @@ public class ReforgeLookup {
return found;
}
/**
* Clear caches.
*
* @param player The player.
*/
public static void clearCaches(@NotNull final Player player) {
REFORGE_CACHE.remove(player.getUniqueId());
ITEM_CACHE.remove(player.getUniqueId());
}
static {
registerProvider(player -> Collections.singletonList(player.getInventory().getItemInMainHand()));
registerProvider(player -> Collections.singletonList(player.getInventory().getItemInOffHand()));
registerProvider(player -> Arrays.asList(player.getInventory().getArmorContents()));
registerProvider(player -> Map.of(
player.getInventory().getItemInMainHand(),
ReforgeTarget.Slot.HANDS
));
registerProvider(player -> Map.of(
player.getInventory().getItemInOffHand(),
ReforgeTarget.Slot.HANDS
));
registerProvider(player -> {
Map<ItemStack, ReforgeTarget.Slot> items = new HashMap<>();
for (ItemStack stack : player.getInventory().getArmorContents()) {
items.put(stack, ReforgeTarget.Slot.ARMOR);
}
return items;
});
}
}

View File

@@ -21,7 +21,7 @@ public class ReforgeTarget {
/**
* Target containing the materials from all other targets.
*/
public static final ReforgeTarget ALL = new ReforgeTarget("all", new HashSet<>());
public static final ReforgeTarget ALL = new ReforgeTarget("all", Slot.ANY, new HashSet<>());
/**
* All registered targets.
@@ -38,12 +38,19 @@ public class ReforgeTarget {
*/
@Getter
private final String name;
/**
* The materials of the target.
*/
@Getter
private final Set<TestableItem> items;
/**
* The slot for the target.
*/
@Getter
private final Slot slot;
/**
* Create new target.
*
@@ -51,10 +58,12 @@ public class ReforgeTarget {
* @param items The items for the target.
*/
public ReforgeTarget(@NotNull final String name,
@NotNull final Slot slot,
@NotNull final Set<TestableItem> items) {
this.name = name;
items.removeIf(item -> item instanceof EmptyTestableItem);
this.items = items;
this.slot = slot;
}
/**
@@ -115,7 +124,11 @@ public class ReforgeTarget {
}
for (String id : plugin.getTargetYml().getTargets()) {
ReforgeTarget target = new ReforgeTarget(id, plugin.getTargetYml().getTargetItems(id));
ReforgeTarget target = new ReforgeTarget(
id,
plugin.getTargetYml().getSlot(id),
plugin.getTargetYml().getTargetItems(id)
);
REGISTERED.put(id, target);
ALL.items.addAll(target.items);
}
@@ -129,4 +142,13 @@ public class ReforgeTarget {
public static Set<ReforgeTarget> values() {
return ImmutableSet.copyOf(REGISTERED.values());
}
/**
* Reforge slots.
*/
public enum Slot {
HANDS,
ARMOR,
ANY
}
}

View File

@@ -151,12 +151,6 @@ public class ReforgeUtils {
return;
}
Reforge previous = getReforge(item);
if (previous != null) {
previous.handleRemoval(item);
}
ItemMeta meta = item.getItemMeta();
setReforge(meta, reforge);
@@ -175,8 +169,6 @@ public class ReforgeUtils {
PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(REFORGE_KEY, PersistentDataType.STRING, reforge.getId());
reforge.handleApplication(meta);
}
/**

View File

@@ -0,0 +1,123 @@
package com.willfp.reforges.reforges.util.equip;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.reforges.effects.ConfiguredEffect;
import com.willfp.reforges.reforges.Reforge;
import com.willfp.reforges.reforges.Reforges;
import com.willfp.reforges.reforges.meta.ReforgeTarget;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ReforgeEnableListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Initialize new listeners and link them to a plugin.
*
* @param plugin The plugin to link to.
*/
public ReforgeEnableListeners(@NotNull final EcoPlugin plugin) {
super(plugin);
}
/**
* Called on item pickup.
*
* @param event The event to listen for.
*/
@EventHandler
public void onItemPickup(@NotNull final EntityPickupItemEvent event) {
if (!(event.getEntity() instanceof Player player)) {
return;
}
if (!ReforgeTarget.ALL.matches(event.getItem().getItemStack())) {
return;
}
refreshPlayer(player);
}
/**
* Called on player join.
*
* @param event The event to listen for.
*/
@EventHandler
public void onPlayerJoin(@NotNull final PlayerJoinEvent event) {
refresh();
}
/**
* Called on player leave.
*
* @param event The event to listen for.
*/
@EventHandler
public void onPlayerLeave(@NotNull final PlayerQuitEvent event) {
refresh();
Player player = event.getPlayer();
for (Reforge value : Reforges.values()) {
for (ConfiguredEffect effect : value.getEffects()) {
effect.getEffect().handleDisabling(player);
}
}
}
/**
* Called on item drop.
*
* @param event The event to listen for.
*/
@EventHandler
public void onInventoryDrop(@NotNull final PlayerDropItemEvent event) {
if (!ReforgeTarget.ALL.matches(event.getItemDrop().getItemStack())) {
return;
}
refreshPlayer(event.getPlayer(), event.getItemDrop().getItemStack());
}
@EventHandler
public void onSwitchHands(@NotNull final PlayerSwapHandItemsEvent event) {
refreshPlayer(event.getPlayer(), event.getPlayer().getInventory().getItemInOffHand());
}
/**
* Called on inventory click.
*
* @param event The event to listen for.
*/
@EventHandler
public void onInventoryClick(@NotNull final InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
refreshPlayer((Player) event.getWhoClicked());
}
/**
* Force refresh all online players.
* <p>
* This is a very expensive method.
*/
public void refresh() {
this.getPlugin().getServer().getOnlinePlayers().forEach(this::refreshPlayer);
}
private void refreshPlayer(@NotNull final Player player,
@NotNull final ItemStack... extra) {
SyncReforgeEnableTask.CHECK.accept(player);
}
}

View File

@@ -0,0 +1,29 @@
package com.willfp.reforges.reforges.util.equip;
import com.willfp.reforges.reforges.Reforge;
import com.willfp.reforges.reforges.ReforgeLookup;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class SyncReforgeEnableTask {
public static final Consumer<Player> CHECK = (player) -> {
List<Reforge> before = ReforgeLookup.provideReforges(player);
ReforgeLookup.clearCaches(player);
List<Reforge> after = ReforgeLookup.provideReforges(player);
List<Reforge> added = new ArrayList<>(after);
added.removeAll(before);
for (Reforge reforge : added) {
reforge.handleActivation(player);
}
before.removeAll(after);
for (Reforge reforge : before) {
reforge.handleDeactivation(player);
}
};
}

View File

@@ -4,16 +4,13 @@ import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.reforges.effects.Effect
import org.bukkit.attribute.Attribute
import org.bukkit.attribute.AttributeModifier
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.entity.Player
class EffectAttackSpeedMultiplier : Effect("attack_speed_multiplier") {
override fun handleEnabling(
meta: ItemMeta,
config: JSONConfig
) {
meta.addAttributeModifier(
Attribute.GENERIC_ATTACK_SPEED,
override fun handleEnabling(player: Player,
config: JSONConfig) {
val attribute = player.getAttribute(Attribute.GENERIC_ATTACK_SPEED) ?: return
attribute.addModifier(
AttributeModifier(
this.getUUID(1),
this.id,
@@ -21,13 +18,11 @@ class EffectAttackSpeedMultiplier : Effect("attack_speed_multiplier") {
AttributeModifier.Operation.MULTIPLY_SCALAR_1
)
)
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES)
}
override fun handleDisabling(meta: ItemMeta) {
meta.removeAttributeModifier(
Attribute.GENERIC_ATTACK_SPEED,
override fun handleDisabling(player: Player) {
val attribute = player.getAttribute(Attribute.GENERIC_ATTACK_SPEED) ?: return
attribute.removeModifier(
AttributeModifier(
this.getUUID(1),
this.id,

View File

@@ -4,16 +4,13 @@ import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.reforges.effects.Effect
import org.bukkit.attribute.Attribute
import org.bukkit.attribute.AttributeModifier
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.entity.Player
class EffectKnockbackMultiplier : Effect("knockback_multiplier") {
override fun handleEnabling(
meta: ItemMeta,
config: JSONConfig
) {
meta.addAttributeModifier(
Attribute.GENERIC_ATTACK_KNOCKBACK,
override fun handleEnabling(player: Player,
config: JSONConfig) {
val attribute = player.getAttribute(Attribute.GENERIC_ATTACK_KNOCKBACK) ?: return
attribute.addModifier(
AttributeModifier(
this.getUUID(1),
this.id,
@@ -21,13 +18,11 @@ class EffectKnockbackMultiplier : Effect("knockback_multiplier") {
AttributeModifier.Operation.MULTIPLY_SCALAR_1
)
)
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES)
}
override fun handleDisabling(meta: ItemMeta) {
meta.removeAttributeModifier(
Attribute.GENERIC_ATTACK_KNOCKBACK,
override fun handleDisabling(player: Player) {
val attribute = player.getAttribute(Attribute.GENERIC_ATTACK_KNOCKBACK) ?: return
attribute.removeModifier(
AttributeModifier(
this.getUUID(1),
this.id,

View File

@@ -4,16 +4,13 @@ import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.reforges.effects.Effect
import org.bukkit.attribute.Attribute
import org.bukkit.attribute.AttributeModifier
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.entity.Player
class EffectMovementSpeedMultiplier : Effect("movement_speed_multiplier") {
override fun handleEnabling(
meta: ItemMeta,
config: JSONConfig
) {
meta.addAttributeModifier(
Attribute.GENERIC_MOVEMENT_SPEED,
override fun handleEnabling(player: Player,
config: JSONConfig) {
val attribute = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED) ?: return
attribute.addModifier(
AttributeModifier(
this.getUUID(1),
this.id,
@@ -21,13 +18,11 @@ class EffectMovementSpeedMultiplier : Effect("movement_speed_multiplier") {
AttributeModifier.Operation.MULTIPLY_SCALAR_1
)
)
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES)
}
override fun handleDisabling(meta: ItemMeta) {
meta.removeAttributeModifier(
Attribute.GENERIC_MOVEMENT_SPEED,
override fun handleDisabling(player: Player) {
val attribute = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED) ?: return
attribute.removeModifier(
AttributeModifier(
this.getUUID(1),
this.id,

View File

@@ -12,10 +12,11 @@ import com.willfp.reforges.effects.ConfiguredEffect
import com.willfp.reforges.effects.Effects
import com.willfp.reforges.reforges.meta.ReforgeTarget
import com.willfp.reforges.reforges.util.ReforgeUtils
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import java.util.*
@Suppress("DEPRECATION")
class Reforge(
internal val config: JSONConfig,
private val plugin: ReforgesPlugin
@@ -68,27 +69,17 @@ class Reforge(
}
}
fun handleApplication(itemStack: ItemStack) {
itemStack.itemMeta = this.handleApplication(itemStack.itemMeta ?: return)
}
fun handleApplication(meta: ItemMeta): ItemMeta {
handleRemoval(meta)
fun handleActivation(player: Player) {
handleDeactivation(player)
for ((effect, config) in this.effects) {
effect.handleEnabling(meta, config)
effect.handleEnabling(player, config)
}
return meta
}
fun handleRemoval(itemStack: ItemStack) {
itemStack.itemMeta = this.handleRemoval(itemStack.itemMeta ?: return)
}
fun handleRemoval(meta: ItemMeta): ItemMeta {
fun handleDeactivation(player: Player) {
for ((effect, _) in this.effects) {
effect.handleDisabling(meta)
effect.handleDisabling(player)
}
return meta
}
override fun equals(other: Any?): Boolean {

View File

@@ -1,61 +1,82 @@
#
# A target consists of items and a slot.
# The slot is either hands, armor, or any.
# Hands means the reforge will activate on hands, armor
# means it will only work on armor, and any
# means it will activate whenever its on the player.
#
pickaxe:
- wooden_pickaxe
- stone_pickaxe
- iron_pickaxe
- golden_pickaxe
- diamond_pickaxe
- netherite_pickaxe
slot: hands
items:
- wooden_pickaxe
- stone_pickaxe
- iron_pickaxe
- golden_pickaxe
- diamond_pickaxe
- netherite_pickaxe
axe:
- wooden_axe
- stone_axe
- iron_axe
- golden_axe
- diamond_axe
- netherite_axe
slot: hands
items:
- wooden_axe
- stone_axe
- iron_axe
- golden_axe
- diamond_axe
- netherite_axe
melee:
- wooden_axe
- stone_axe
- iron_axe
- golden_axe
- diamond_axe
- netherite_axe
- wooden_sword
- stone_sword
- iron_sword
- golden_sword
- diamond_sword
- netherite_sword
slot: hands
items:
- wooden_axe
- stone_axe
- iron_axe
- golden_axe
- diamond_axe
- netherite_axe
- wooden_sword
- stone_sword
- iron_sword
- golden_sword
- diamond_sword
- netherite_sword
trident:
- trident
slot: hands
items:
- trident
bow:
- bow
- crossbow
slot: hands
items:
- bow
- crossbow
armor:
- turtle_helmet
- leather_helmet
- chainmail_helmet
- iron_helmet
- golden_helmet
- diamond_helmet
- netherite_helmet
slot: armor
items:
- turtle_helmet
- leather_helmet
- chainmail_helmet
- iron_helmet
- golden_helmet
- diamond_helmet
- netherite_helmet
- leather_chestplate
- chainmail_chestplate
- iron_chestplate
- golden_chestplate
- diamond_chestplate
- netherite_chestplate
- leather_chestplate
- chainmail_chestplate
- iron_chestplate
- golden_chestplate
- diamond_chestplate
- netherite_chestplate
- leather_leggings
- chainmail_leggings
- iron_leggings
- golden_leggings
- diamond_leggings
- netherite_leggings
- leather_leggings
- chainmail_leggings
- iron_leggings
- golden_leggings
- diamond_leggings
- netherite_leggings
- leather_boots
- chainmail_boots
- iron_boots
- golden_boots
- diamond_boots
- netherite_boots
- leather_boots
- chainmail_boots
- iron_boots
- golden_boots
- diamond_boots
- netherite_boots