9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2026-01-04 15:41:35 +00:00

checkpoint - 8

This commit is contained in:
XiaoMoMi
2024-05-23 00:12:30 +08:00
parent b83c140dd3
commit 06d39a9175
62 changed files with 1374 additions and 881 deletions

View File

@@ -25,6 +25,7 @@ import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.effect.EffectManager;
import net.momirealms.customfishing.api.mechanic.entity.EntityManager;
import net.momirealms.customfishing.api.mechanic.event.EventManager;
import net.momirealms.customfishing.api.mechanic.hook.HookManager;
import net.momirealms.customfishing.api.mechanic.item.ItemManager;
import net.momirealms.customfishing.api.mechanic.loot.LootManager;
import net.momirealms.customfishing.api.mechanic.market.MarketManager;
@@ -69,6 +70,7 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
protected BlockManager blockManager;
protected StatisticsManager statisticsManager;
protected EffectManager effectManager;
protected HookManager hookManager;
public BukkitCustomFishingPlugin() {
instance = this;
@@ -143,6 +145,10 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
return entityManager;
}
public HookManager getHookManager() {
return hookManager;
}
public BlockManager getBlockManager() {
return blockManager;
}

View File

@@ -28,6 +28,8 @@ import java.util.List;
*/
public interface BlockConfig {
String id();
/**
* Gets the unique identifier for the block.
*
@@ -49,20 +51,6 @@ public interface BlockConfig {
*/
List<BlockStateModifier> stateModifiers();
/**
* Gets the horizontal vector math value associated with the block.
*
* @return A {@link MathValue} representing the horizontal vector for a player.
*/
MathValue<Player> horizontalVector();
/**
* Gets the vertical vector math value associated with the block.
*
* @return A {@link MathValue} representing the vertical vector for a player.
*/
MathValue<Player> verticalVector();
/**
* Creates a new builder instance for constructing a {@link BlockConfig}.
*
@@ -77,6 +65,8 @@ public interface BlockConfig {
*/
interface Builder {
Builder id(String id);
/**
* Sets the block ID for the configuration.
*
@@ -101,22 +91,6 @@ public interface BlockConfig {
*/
Builder stateModifierList(List<BlockStateModifier> stateModifierList);
/**
* Sets the horizontal vector math value for the configuration.
*
* @param horizontalVector A {@link MathValue} representing the horizontal vector for a player.
* @return The current {@link Builder} instance.
*/
Builder horizontalVector(MathValue<Player> horizontalVector);
/**
* Sets the vertical vector math value for the configuration.
*
* @param verticalVector A {@link MathValue} representing the vertical vector for a player.
* @return The current {@link Builder} instance.
*/
Builder verticalVector(MathValue<Player> verticalVector);
/**
* Builds and returns the configured {@link BlockConfig} instance.
*

View File

@@ -28,15 +28,13 @@ public class BlockConfigImpl implements BlockConfig {
private final String blockID;
private final List<BlockDataModifier> dataModifierList;
private final List<BlockStateModifier> stateModifierList;
private final MathValue<Player> horizontalVector;
private final MathValue<Player> verticalVector;
private final String id;
public BlockConfigImpl(String blockID, List<BlockDataModifier> dataModifierList, List<BlockStateModifier> stateModifierList, MathValue<Player> horizontalVector, MathValue<Player> verticalVector) {
public BlockConfigImpl(String id, String blockID, List<BlockDataModifier> dataModifierList, List<BlockStateModifier> stateModifierList) {
this.blockID = blockID;
this.dataModifierList = dataModifierList;
this.stateModifierList = stateModifierList;
this.horizontalVector = horizontalVector;
this.verticalVector = verticalVector;
this.id = id;
}
@Override
@@ -54,22 +52,16 @@ public class BlockConfigImpl implements BlockConfig {
return stateModifierList;
}
@Override
public MathValue<Player> horizontalVector() {
return horizontalVector;
}
@Override
public MathValue<Player> verticalVector() {
return verticalVector;
}
public static class BuilderImpl implements Builder {
private String blockID;
private final List<BlockDataModifier> dataModifierList = new ArrayList<>();
private final List<BlockStateModifier> stateModifierList = new ArrayList<>();
private MathValue<Player> horizontalVector;
private MathValue<Player> verticalVector;
private String id;
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder blockID(String blockID) {
this.blockID = blockID;
@@ -86,18 +78,8 @@ public class BlockConfigImpl implements BlockConfig {
return this;
}
@Override
public Builder horizontalVector(MathValue<Player> horizontalVector) {
this.horizontalVector = horizontalVector;
return this;
}
@Override
public Builder verticalVector(MathValue<Player> verticalVector) {
this.verticalVector = verticalVector;
return this;
}
@Override
public BlockConfig build() {
return new BlockConfigImpl(blockID, dataModifierList, stateModifierList, horizontalVector, verticalVector);
return new BlockConfigImpl(id, blockID, dataModifierList, stateModifierList);
}
}
}

View File

@@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
public interface BlockManager extends Reloadable {
boolean registerBlock(@NotNull String id, @NotNull BlockConfig block);
boolean registerBlock(@NotNull BlockConfig block);
@Nullable
FallingBlock summonBlockLoot(@NotNull Context<Player> context);

View File

@@ -0,0 +1,94 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BaitConfigParser {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
private final List<Consumer<EffectModifier.Builder>> effectBuilderConsumers = new ArrayList<>();
public BaitConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
this.material = section.getString("material");
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case ITEM -> {
ItemParserFunction propertyFunction = (ItemParserFunction) function;
BiConsumer<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result));
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
case EFFECT_MODIFIER -> {
EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function;
Consumer<EffectModifier.Builder> consumer = effectModifierParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.id(id)
.tagConsumers(tagConsumers)
.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.BAIT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -0,0 +1,105 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.block.BlockConfig;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.common.config.node.Node;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class BlockConfigParser {
private final String id;
private final List<Consumer<BlockConfig.Builder>> blockBuilderConsumers = new ArrayList<>();
private final List<Consumer<LootBaseEffect.Builder>> effectBuilderConsumers = new ArrayList<>();
private final List<Consumer<Loot.Builder>> lootBuilderConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
public BlockConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case BLOCK -> {
BlockParserFunction blockParserFunction = (BlockParserFunction) function;
Consumer<BlockConfig.Builder> consumer = blockParserFunction.accept(entry.getValue());
blockBuilderConsumers.add(consumer);
}
case BASE_EFFECT -> {
BaseEffectParserFunction baseEffectParserFunction = (BaseEffectParserFunction) function;
Consumer<LootBaseEffect.Builder> consumer = baseEffectParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
case LOOT -> {
LootParserFunction lootParserFunction = (LootParserFunction) function;
Consumer<Loot.Builder> consumer = lootParserFunction.accept(entry.getValue());
lootBuilderConsumers.add(consumer);
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public BlockConfig getBlock() {
BlockConfig.Builder builder = BlockConfig.builder()
.id(id);
for (Consumer<BlockConfig.Builder> consumer : blockBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
private LootBaseEffect getBaseEffect() {
LootBaseEffect.Builder builder = LootBaseEffect.builder();
for (Consumer<LootBaseEffect.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.LOOT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -6,15 +6,19 @@ import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings;
import dev.dejvokep.boostedyaml.settings.general.GeneralSettings;
import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.misc.function.*;
import net.momirealms.customfishing.common.config.ConfigLoader;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -29,13 +33,13 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
public abstract class ConfigManager implements ConfigLoader {
public abstract class ConfigManager implements ConfigLoader, Reloadable {
private final CustomFishingPlugin plugin;
protected final BukkitCustomFishingPlugin plugin;
private final HashMap<String, Node<ConfigParserFunction>> formatFunctions = new HashMap<>();
protected final HashMap<String, Node<ConfigParserFunction>> formatFunctions = new HashMap<>();
public ConfigManager(CustomFishingPlugin plugin) {
public ConfigManager(BukkitCustomFishingPlugin plugin) {
this.plugin = plugin;
}
@@ -60,12 +64,15 @@ public abstract class ConfigManager implements ConfigLoader {
}
public static boolean enableFishingBag() {
return true;
}
public static int dataSaveInterval() {
return 360;
}
public static boolean logDataSaving() {
return true;
}
public static boolean lockData() {
@@ -84,10 +91,18 @@ public abstract class ConfigManager implements ConfigLoader {
registerNodeFunction(nodes, new ItemParserFunction(priority, function));
}
public void registerEffectModifierParser(Function<Object, Consumer<Effect>> function, String... nodes) {
public void registerEffectModifierParser(Function<Object, Consumer<EffectModifier.Builder>> function, String... nodes) {
registerNodeFunction(nodes, new EffectModifierParserFunction(function));
}
public void registerEntityParser(Function<Object, Consumer<EntityConfig.Builder>> function, String... nodes) {
registerNodeFunction(nodes, new EntityParserFunction(function));
}
public void registerEventParser(Function<Object, Consumer<EventCarrier.Builder>> function, String... nodes) {
registerNodeFunction(nodes, new EventParserFunction(function));
}
public void unregisterNodeFunction(String... nodes) {
Map<String, Node<ConfigParserFunction>> functionMap = formatFunctions;
for (int i = 0; i < nodes.length; i++) {
@@ -201,4 +216,8 @@ public abstract class ConfigManager implements ConfigLoader {
throw new RuntimeException(e);
}
}
public Map<String, Node<ConfigParserFunction>> getFormatFunctions() {
return formatFunctions;
}
}

View File

@@ -0,0 +1,110 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.config.function.ConfigParserFunction;
import net.momirealms.customfishing.api.mechanic.hook.HookConfig;
import net.momirealms.customfishing.common.config.node.Node;
import org.apache.logging.log4j.util.TriConsumer;
import java.util.Map;
public class ConfigType {
public static final ConfigType ITEM = of(
"item",
(id, section, functions) -> {
ItemConfigParser config = new ItemConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
public static final ConfigType ENTITY = of(
"entity",
(id, section, functions) -> {
EntityConfigParser config = new EntityConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getEntityManager().registerEntity(config.getEntity());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
public static final ConfigType BLOCK = of(
"block",
(id, section, functions) -> {
BlockConfigParser config = new BlockConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getBlockManager().registerBlock(config.getBlock());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
public static final ConfigType ROD = of(
"rod",
(id, section, functions) -> {
RodConfigParser config = new RodConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
public static final ConfigType BAIT = of(
"bait",
(id, section, functions) -> {
HookConfigParser config = new HookConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
public static final ConfigType HOOK = of(
"hook",
(id, section, functions) -> {
HookConfigParser config = new HookConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
BukkitCustomFishingPlugin.getInstance().getHookManager().registerHook(config.getHook());
}
);
public static final ConfigType UTIL = of(
"util",
(id, section, functions) -> {
UtilConfigParser config = new UtilConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem());
BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier());
BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier());
}
);
private static final ConfigType[] values = new ConfigType[] {ITEM, ENTITY, BLOCK, HOOK, ROD, BAIT, UTIL};
public static ConfigType[] values() {
return values;
}
private final String path;
private final TriConsumer<String, Section, Map<String, Node<ConfigParserFunction>>> argumentConsumer;
public ConfigType(String path, TriConsumer<String, Section, Map<String, Node<ConfigParserFunction>>> argumentConsumer) {
this.path = path;
this.argumentConsumer = argumentConsumer;
}
public static ConfigType of(String path, TriConsumer<String, Section, Map<String, Node<ConfigParserFunction>>> argumentConsumer) {
return new ConfigType(path, argumentConsumer);
}
public void parse(String id, Section section, Map<String, Node<ConfigParserFunction>> functions) {
argumentConsumer.accept(id, section, functions);
}
public String path() {
return path;
}
}

View File

@@ -0,0 +1,104 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.common.config.node.Node;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class EntityConfigParser {
private final String id;
private final List<Consumer<EntityConfig.Builder>> entityBuilderConsumers = new ArrayList<>();
private final List<Consumer<LootBaseEffect.Builder>> effectBuilderConsumers = new ArrayList<>();
private final List<Consumer<Loot.Builder>> lootBuilderConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
public EntityConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case ENTITY -> {
EntityParserFunction entityParserFunction = (EntityParserFunction) function;
Consumer<EntityConfig.Builder> consumer = entityParserFunction.accept(entry.getValue());
entityBuilderConsumers.add(consumer);
}
case BASE_EFFECT -> {
BaseEffectParserFunction baseEffectParserFunction = (BaseEffectParserFunction) function;
Consumer<LootBaseEffect.Builder> consumer = baseEffectParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
case LOOT -> {
LootParserFunction lootParserFunction = (LootParserFunction) function;
Consumer<Loot.Builder> consumer = lootParserFunction.accept(entry.getValue());
lootBuilderConsumers.add(consumer);
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public EntityConfig getEntity() {
EntityConfig.Builder builder = EntityConfig.builder()
.id(id);
for (Consumer<EntityConfig.Builder> consumer : entityBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
private LootBaseEffect getBaseEffect() {
LootBaseEffect.Builder builder = LootBaseEffect.builder();
for (Consumer<LootBaseEffect.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.LOOT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -0,0 +1,108 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.hook.HookConfig;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class HookConfigParser {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
private final List<Consumer<HookConfig.Builder>> hookBuilderConsumers = new ArrayList<>();
private final List<Consumer<EffectModifier.Builder>> effectBuilderConsumers = new ArrayList<>();
public HookConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
this.material = section.getString("material");
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case ITEM -> {
ItemParserFunction propertyFunction = (ItemParserFunction) function;
BiConsumer<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result));
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
case EFFECT_MODIFIER -> {
EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function;
Consumer<EffectModifier.Builder> consumer = effectModifierParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
case HOOK -> {
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.id(id)
.tagConsumers(tagConsumers)
.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.HOOK);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public HookConfig getHook() {
HookConfig.Builder builder = HookConfig.builder()
.id(id);
for (Consumer<HookConfig.Builder> consumer : hookBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -1,14 +1,15 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.misc.function.*;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.util.Key;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -18,15 +19,16 @@ import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ItemLootConfig {
public class ItemConfigParser {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<LootBaseEffect.Builder>> effectBuilderConsumers = new ArrayList<>();
private final List<Consumer<Loot.Builder>> lootBuilderConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
public ItemLootConfig(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
public ItemConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
this.material = section.getString("material");
analyze(section, functionMap);
@@ -57,7 +59,9 @@ public class ItemLootConfig {
lootBuilderConsumers.add(consumer);
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
}
continue;
@@ -68,13 +72,10 @@ public class ItemLootConfig {
}
}
public Key key() {
return Key.of("item", id);
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.id(id)
.tagConsumers(tagConsumers)
.build();
}
@@ -88,12 +89,22 @@ public class ItemLootConfig {
}
public Loot getLoot() {
Loot.Builder builder = Loot.builder();
builder.id(id);
builder.lootBaseEffect(getBaseEffect());
Loot.Builder builder = Loot.builder()
.id(id)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.LOOT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -0,0 +1,96 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class RodConfigParser {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
private final List<Consumer<EffectModifier.Builder>> effectBuilderConsumers = new ArrayList<>();
public RodConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
this.material = section.contains("material") ? section.getString("material") : Material.FISHING_ROD.name();
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case ITEM -> {
ItemParserFunction propertyFunction = (ItemParserFunction) function;
BiConsumer<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result));
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
case EFFECT_MODIFIER -> {
EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function;
Consumer<EffectModifier.Builder> consumer = effectModifierParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.id(id)
.tagConsumers(tagConsumers)
.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.ROD);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -0,0 +1,94 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.*;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class UtilConfigParser {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
private final List<Consumer<EffectModifier.Builder>> effectBuilderConsumers = new ArrayList<>();
public UtilConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
this.id = id;
this.material = section.getString("material");
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> node = functionMap.get(key);
if (node == null) continue;
ConfigParserFunction function = node.nodeValue();
if (function != null) {
switch (function.type()) {
case ITEM -> {
ItemParserFunction propertyFunction = (ItemParserFunction) function;
BiConsumer<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result));
}
case EVENT -> {
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumer = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumer);
}
case EFFECT_MODIFIER -> {
EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function;
Consumer<EffectModifier.Builder> consumer = effectModifierParserFunction.accept(entry.getValue());
effectBuilderConsumers.add(consumer);
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.id(id)
.tagConsumers(tagConsumers)
.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(ItemType.BAIT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -1,4 +1,4 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;

View File

@@ -0,0 +1,25 @@
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.block.BlockConfig;
import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import java.util.function.Consumer;
import java.util.function.Function;
public class BlockParserFunction implements ConfigParserFunction {
private final Function<Object, Consumer<BlockConfig.Builder>> function;
public BlockParserFunction(Function<Object, Consumer<BlockConfig.Builder>> function) {
this.function = function;
}
public Consumer<BlockConfig.Builder> accept(Object object) {
return function.apply(object);
}
@Override
public ParserType type() {
return ParserType.ENTITY;
}
}

View File

@@ -1,4 +1,4 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
public interface ConfigParserFunction {

View File

@@ -1,19 +1,20 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import java.util.function.Consumer;
import java.util.function.Function;
public class EffectModifierParserFunction implements ConfigParserFunction {
private final Function<Object, Consumer<Effect>> function;
private final Function<Object, Consumer<EffectModifier.Builder>> function;
public EffectModifierParserFunction(Function<Object, Consumer<Effect>> function) {
public EffectModifierParserFunction(Function<Object, Consumer<EffectModifier.Builder>> function) {
this.function = function;
}
public Consumer<Effect> accept(Object object) {
public Consumer<EffectModifier.Builder> accept(Object object) {
return function.apply(object);
}

View File

@@ -0,0 +1,24 @@
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import java.util.function.Consumer;
import java.util.function.Function;
public class EntityParserFunction implements ConfigParserFunction {
private final Function<Object, Consumer<EntityConfig.Builder>> function;
public EntityParserFunction(Function<Object, Consumer<EntityConfig.Builder>> function) {
this.function = function;
}
public Consumer<EntityConfig.Builder> accept(Object object) {
return function.apply(object);
}
@Override
public ParserType type() {
return ParserType.ENTITY;
}
}

View File

@@ -0,0 +1,24 @@
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import java.util.function.Consumer;
import java.util.function.Function;
public class EventParserFunction implements ConfigParserFunction {
private final Function<Object, Consumer<EventCarrier.Builder>> function;
public EventParserFunction(Function<Object, Consumer<EventCarrier.Builder>> function) {
this.function = function;
}
public Consumer<EventCarrier.Builder> accept(Object object) {
return function.apply(object);
}
@Override
public ParserType type() {
return ParserType.EVENT;
}
}

View File

@@ -1,4 +1,4 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.common.item.Item;

View File

@@ -1,4 +1,4 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
import net.momirealms.customfishing.api.mechanic.loot.Loot;

View File

@@ -0,0 +1,12 @@
package net.momirealms.customfishing.api.mechanic.config.function;
public enum ParserType {
ITEM,
EFFECT_MODIFIER,
BASE_EFFECT,
LOOT,
EVENT,
ENTITY,
HOOK,
BLOCK
}

View File

@@ -1,4 +1,4 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
package net.momirealms.customfishing.api.mechanic.config.function;
import org.jetbrains.annotations.NotNull;

View File

@@ -6,7 +6,7 @@ import java.util.Optional;
public interface EffectManager extends Reloadable {
boolean registerEffectModifier(String id, EffectModifier effect);
boolean registerEffectModifier(EffectModifier effect);
Optional<EffectModifier> getEffectModifier(String id);
}

View File

@@ -13,6 +13,8 @@ import java.util.function.BiConsumer;
*/
public interface EffectModifier {
String id();
/**
* Returns an array of requirements that must be met by a Player for the effect to be applied.
*
@@ -41,6 +43,8 @@ public interface EffectModifier {
*/
interface Builder {
Builder id(String id);
/**
* Sets the requirements for the EffectModifier being built.
*

View File

@@ -12,10 +12,17 @@ public class EffectModifierImpl implements EffectModifier {
private final Requirement<Player>[] requirements;
private final List<BiConsumer<Effect, Context<Player>>> modifiers;
private final String id;
public EffectModifierImpl(Requirement<Player>[] requirements, List<BiConsumer<Effect, Context<Player>>> modifiers) {
public EffectModifierImpl(String id, Requirement<Player>[] requirements, List<BiConsumer<Effect, Context<Player>>> modifiers) {
this.requirements = requirements;
this.modifiers = modifiers;
this.id = id;
}
@Override
public String id() {
return id;
}
@Override
@@ -31,6 +38,12 @@ public class EffectModifierImpl implements EffectModifier {
public static class BuilderImpl implements Builder {
private final List<Requirement<Player>> requirements = new ArrayList<>();
private final List<BiConsumer<Effect, Context<Player>>> modifiers = new ArrayList<>();
private String id;
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder requirements(List<Requirement<Player>> requirements) {
this.requirements.addAll(requirements);
@@ -44,7 +57,7 @@ public class EffectModifierImpl implements EffectModifier {
@Override
@SuppressWarnings("unchecked")
public EffectModifier build() {
return new EffectModifierImpl(this.requirements.toArray(new Requirement[0]), this.modifiers);
return new EffectModifierImpl(id, this.requirements.toArray(new Requirement[0]), this.modifiers);
}
}
}

View File

@@ -17,6 +17,8 @@
package net.momirealms.customfishing.api.mechanic.entity;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
@@ -28,24 +30,26 @@ import java.util.Map;
*/
public interface EntityConfig {
double DEFAULT_HORIZONTAL_VECTOR = 1;
double DEFAULT_VERTICAL_VECTOR = 1;
String DEFAULT_ENTITY_ID = "";
MathValue<Player> DEFAULT_HORIZONTAL_VECTOR = MathValue.plain(1.1);
MathValue<Player> DEFAULT_VERTICAL_VECTOR = MathValue.plain(1.2);
String DEFAULT_ENTITY_ID = "COD";
Map<String, Object> DEFAULT_PROPERTY_MAP = Map.of();
String id();
/**
* Retrieves the horizontal vector value for the entity.
*
* @return the horizontal vector value as a double
*/
double getHorizontalVector();
MathValue<Player> getHorizontalVector();
/**
* Retrieves the vertical vector value for the entity.
*
* @return the vertical vector value as a double
*/
double getVerticalVector();
MathValue<Player> getVerticalVector();
/**
* Retrieves the unique identifier for the entity.
@@ -77,6 +81,8 @@ public interface EntityConfig {
*/
interface Builder {
Builder id(String id);
/**
* Sets the entity ID for the EntityConfig being built.
*
@@ -91,7 +97,7 @@ public interface EntityConfig {
* @param value the vertical vector value as a double
* @return the current Builder instance
*/
Builder verticalVector(double value);
Builder verticalVector(MathValue<Player> value);
/**
* Sets the horizontal vector value for the EntityConfig being built.
@@ -99,7 +105,7 @@ public interface EntityConfig {
* @param value the horizontal vector value as a double
* @return the current Builder instance
*/
Builder horizontalVector(double value);
Builder horizontalVector(MathValue<Player> value);
/**
* Sets the property map for the EntityConfig being built.

View File

@@ -17,6 +17,8 @@
package net.momirealms.customfishing.api.mechanic.entity;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
@@ -24,31 +26,38 @@ import java.util.Map;
public class EntityConfigImpl implements EntityConfig {
private final String id;
private final double horizontalVector;
private final double verticalVector;
private final String entityID;
private final MathValue<Player> horizontalVector;
private final MathValue<Player> verticalVector;
private final Map<String, Object> propertyMap;
public EntityConfigImpl(String id, double horizontalVector, double verticalVector, Map<String, Object> propertyMap) {
public EntityConfigImpl(String id, String entityID, MathValue<Player> horizontalVector, MathValue<Player> verticalVector, Map<String, Object> propertyMap) {
this.id = id;
this.entityID = entityID;
this.horizontalVector = horizontalVector;
this.verticalVector = verticalVector;
this.propertyMap = propertyMap;
}
@Override
public double getHorizontalVector() {
public String id() {
return id;
}
@Override
public MathValue<Player> getHorizontalVector() {
return horizontalVector;
}
@Override
public double getVerticalVector() {
public MathValue<Player> getVerticalVector() {
return verticalVector;
}
@NotNull
@Override
public String getEntityID() {
return id;
return entityID;
}
@NotNull
@@ -59,21 +68,27 @@ public class EntityConfigImpl implements EntityConfig {
public static class BuilderImpl implements Builder {
private String entity = DEFAULT_ENTITY_ID;
private double horizontalVector = DEFAULT_HORIZONTAL_VECTOR;
private double verticalVector = DEFAULT_VERTICAL_VECTOR;
private MathValue<Player> horizontalVector = DEFAULT_HORIZONTAL_VECTOR;
private MathValue<Player> verticalVector = DEFAULT_VERTICAL_VECTOR;
private Map<String, Object> propertyMap = DEFAULT_PROPERTY_MAP;
private String id;
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public BuilderImpl entityID(String value) {
this.entity = value;
return this;
}
@Override
public BuilderImpl verticalVector(double value) {
public BuilderImpl verticalVector(MathValue<Player> value) {
this.verticalVector = value;
return this;
}
@Override
public BuilderImpl horizontalVector(double value) {
public BuilderImpl horizontalVector(MathValue<Player> value) {
this.horizontalVector = value;
return this;
}
@@ -84,7 +99,7 @@ public class EntityConfigImpl implements EntityConfig {
}
@Override
public EntityConfigImpl build() {
return new EntityConfigImpl(entity, horizontalVector, verticalVector, propertyMap);
return new EntityConfigImpl(id, entity, horizontalVector, verticalVector, propertyMap);
}
}
}

View File

@@ -38,7 +38,7 @@ public interface EntityManager extends Reloadable {
*/
Optional<EntityConfig> getEntity(String id);
boolean registerEntity(String id, EntityConfig entity);
boolean registerEntity(EntityConfig entity);
@Nullable
Entity summonEntityLoot(Context<Player> context);

View File

@@ -4,6 +4,7 @@ import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import org.bukkit.entity.Player;
import java.util.HashMap;
@@ -22,6 +23,8 @@ public interface EventCarrier {
*/
ItemType type();
String id();
/**
* Whether to disable global actions
*
@@ -61,6 +64,8 @@ public interface EventCarrier {
*/
interface Builder {
Builder id(String id);
/**
* Sets the map of actions associated with their triggers.
*
@@ -69,6 +74,8 @@ public interface EventCarrier {
*/
Builder actionMap(HashMap<ActionTrigger, Action<Player>[]> actionMap);
Builder action(ActionTrigger trigger, Action<Player>[] actions);
/**
* Sets the map of actions associated with their triggers and occurrence times.
*
@@ -77,6 +84,8 @@ public interface EventCarrier {
*/
Builder actionTimesMap(HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap);
Builder actionTimes(ActionTrigger trigger, TreeMap<Integer, Action<Player>[]> actions);
/**
* Set the type of the item
*

View File

@@ -5,6 +5,7 @@ import net.momirealms.customfishing.api.mechanic.action.ActionManager;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.item.ItemType;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import org.bukkit.entity.Player;
import java.util.HashMap;
@@ -20,12 +21,14 @@ public class EventCarrierImpl implements EventCarrier {
private final HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap;
private final ItemType type;
private final boolean disableGlobalActions;
private final String id;
public EventCarrierImpl(ItemType type, boolean disableGlobalActions, HashMap<ActionTrigger, Action<Player>[]> actionMap, HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap) {
public EventCarrierImpl(String id, ItemType type, boolean disableGlobalActions, HashMap<ActionTrigger, Action<Player>[]> actionMap, HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap) {
this.actionMap = actionMap;
this.actionTimesMap = actionTimesMap;
this.type = type;
this.disableGlobalActions = disableGlobalActions;
this.id = id;
}
@Override
@@ -33,6 +36,11 @@ public class EventCarrierImpl implements EventCarrier {
return type;
}
@Override
public String id() {
return id;
}
@Override
public boolean disableGlobalActions() {
return disableGlobalActions;
@@ -63,17 +71,33 @@ public class EventCarrierImpl implements EventCarrier {
private final HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap = new HashMap<>();
private ItemType type = null;
private boolean disableGlobalActions = false;
private String id;
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder actionMap(HashMap<ActionTrigger, Action<Player>[]> actionMap) {
this.actionMap.putAll(actionMap);
return this;
}
@Override
public Builder action(ActionTrigger trigger, Action<Player>[] actions) {
this.actionMap.put(trigger, actions);
return this;
}
@Override
public Builder actionTimesMap(HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap) {
this.actionTimesMap.putAll(actionTimesMap);
return this;
}
@Override
public Builder actionTimes(ActionTrigger trigger, TreeMap<Integer, Action<Player>[]> actions) {
this.actionTimesMap.put(trigger, actions);
return this;
}
@Override
public Builder type(ItemType type) {
this.type = type;
return this;
@@ -85,7 +109,7 @@ public class EventCarrierImpl implements EventCarrier {
}
@Override
public EventCarrier build() {
return new EventCarrierImpl(requireNonNull(type), disableGlobalActions, actionMap, actionTimesMap);
return new EventCarrierImpl(requireNonNull(id), requireNonNull(type), disableGlobalActions, actionMap, actionTimesMap);
}
}
}

View File

@@ -40,11 +40,10 @@ public interface EventManager extends Reloadable {
/**
* Registers a new EventCarrier with a specified identifier.
*
* @param id The unique identifier of the event carrier.
* @param carrier The EventCarrier to be registered.
* @return True if the registration was successful, false otherwise.
*/
boolean registerEventCarrier(String id, EventCarrier carrier);
boolean registerEventCarrier(EventCarrier carrier);
/**
* Triggers an event for a given context, identifier, and trigger.

View File

@@ -0,0 +1,23 @@
package net.momirealms.customfishing.api.mechanic.hook;
import java.util.List;
public interface HookConfig {
String id();
List<String> lore();
static Builder builder() {
return new HookConfigImpl.BuilderImpl();
}
interface Builder {
Builder id(String id);
Builder lore(List<String> lore);
HookConfig build();
}
}

View File

@@ -17,51 +17,47 @@
package net.momirealms.customfishing.api.mechanic.hook;
import java.util.ArrayList;
import java.util.List;
public class HookSetting {
public class HookConfigImpl implements HookConfig {
private final String key;
private int maxDurability;
private List<String> lore;
private final String id;
private final int maxDurability;
private final List<String> lore;
public HookSetting(String key) {
this.key = key;
public HookConfigImpl(String id, int maxDurability, List<String> lore) {
this.id = id;
this.maxDurability = maxDurability;
this.lore = lore;
}
public String getKey() {
return key;
@Override
public String id() {
return id;
}
public int getMaxDurability() {
return maxDurability;
@Override
public List<String> lore() {
return lore;
}
public List<String> getLore() {
return lore == null ? new ArrayList<>() : lore;
}
public static class Builder {
private final HookSetting setting;
public Builder(String key) {
this.setting = new HookSetting(key);
}
public Builder durability(int maxDurability) {
setting.maxDurability = maxDurability;
public static class BuilderImpl implements Builder {
private String id;
private int maxDurability;
private List<String> lore;
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder lore(List<String> lore) {
setting.lore = lore;
this.lore = lore;
return this;
}
public HookSetting build() {
return setting;
@Override
public HookConfig build() {
return new HookConfigImpl(id, maxDurability, lore);
}
}
}

View File

@@ -17,61 +17,14 @@
package net.momirealms.customfishing.api.mechanic.hook;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public interface HookManager {
/**
* Get the hook setting by its ID.
*
* @param id The ID of the hook setting to retrieve.
* @return The hook setting with the given ID, or null if not found.
*/
@Nullable HookSetting getHookSetting(String id);
boolean registerHook(HookConfig hook);
/**
* Decreases the durability of a fishing hook by a specified amount and optionally updates its lore.
* The hook would be removed if its durability is lower than 0
*
* @param rod The fishing rod ItemStack to modify.
* @param amount The amount by which to decrease the durability.
* @param updateLore Whether to update the lore of the fishing rod.
*/
void decreaseHookDurability(ItemStack rod, int amount, boolean updateLore);
/**
* Increases the durability of a hook by a specified amount and optionally updates its lore.
*
* @param rod The fishing rod ItemStack to modify.
* @param amount The amount by which to increase the durability.
* @param updateLore Whether to update the lore of the fishing rod.
*/
void increaseHookDurability(ItemStack rod, int amount, boolean updateLore);
/**
* Sets the durability of a fishing hook to a specific amount and optionally updates its lore.
*
* @param rod The fishing rod ItemStack to modify.
* @param amount The new durability value to set.
* @param updateLore Whether to update the lore of the fishing rod.
*/
void setHookDurability(ItemStack rod, int amount, boolean updateLore);
/**
* Equips a fishing hook on a fishing rod.
*
* @param rod The fishing rod ItemStack.
* @param hook The fishing hook ItemStack.
* @return True if the hook was successfully equipped, false otherwise.
*/
boolean equipHookOnRod(ItemStack rod, ItemStack hook);
/**
* Removes the fishing hook from a fishing rod.
*
* @param rod The fishing rod ItemStack.
* @return The removed fishing hook ItemStack, or null if no hook was found.
*/
@Nullable ItemStack removeHookFromRod(ItemStack rod);
@NotNull
Optional<HookConfig> getHook(String id);
}

View File

@@ -1,7 +1,8 @@
package net.momirealms.customfishing.api.mechanic.item;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.config.function.PriorityFunction;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.misc.function.PriorityFunction;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -20,6 +21,8 @@ public interface CustomFishingItem {
*/
String material();
String id();
/**
* Returns a list of tag consumers which are functions that take an item and context as parameters
* and perform some operation on them.
@@ -28,6 +31,10 @@ public interface CustomFishingItem {
*/
List<BiConsumer<Item<ItemStack>, Context<Player>>> tagConsumers();
default ItemStack build(Context<Player> context) {
return BukkitCustomFishingPlugin.getInstance().getItemManager().build(context, this);
}
/**
* Creates a new Builder instance to construct a CustomFishingItem.
*
@@ -42,6 +49,8 @@ public interface CustomFishingItem {
*/
interface Builder {
Builder id(String id);
/**
* Sets the material type for the CustomFishingItem being built.
*

View File

@@ -1,7 +1,7 @@
package net.momirealms.customfishing.api.mechanic.item;
import net.momirealms.customfishing.api.mechanic.config.function.PriorityFunction;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.misc.function.PriorityFunction;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -10,14 +10,18 @@ import java.util.List;
import java.util.TreeSet;
import java.util.function.BiConsumer;
import static java.util.Objects.requireNonNull;
public class CustomFishingItemImpl implements CustomFishingItem {
private final String material;
private final String id;
private final List<BiConsumer<Item<ItemStack>, Context<Player>>> tagConsumers;
public CustomFishingItemImpl(String material, List<BiConsumer<Item<ItemStack>, Context<Player>>> tagConsumers) {
public CustomFishingItemImpl(String id, String material, List<BiConsumer<Item<ItemStack>, Context<Player>>> tagConsumers) {
this.material = material;
this.id = id;
this.tagConsumers = tagConsumers;
}
@@ -26,6 +30,11 @@ public class CustomFishingItemImpl implements CustomFishingItem {
return material;
}
@Override
public String id() {
return id;
}
@Override
public List<BiConsumer<Item<ItemStack>, Context<Player>>> tagConsumers() {
return tagConsumers;
@@ -34,9 +43,15 @@ public class CustomFishingItemImpl implements CustomFishingItem {
public static class BuilderImpl implements Builder {
private String material = DEFAULT_MATERIAL;
private String id;
private final TreeSet<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new TreeSet<>();
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder material(String material) {
this.material = material;
@@ -51,7 +66,7 @@ public class CustomFishingItemImpl implements CustomFishingItem {
@Override
public CustomFishingItem build() {
return new CustomFishingItemImpl(material, tagConsumers.stream().map(PriorityFunction::get).toList());
return new CustomFishingItemImpl(requireNonNull(id), material, tagConsumers.stream().map(PriorityFunction::get).toList());
}
}
}

View File

@@ -17,8 +17,10 @@
package net.momirealms.customfishing.api.mechanic.item;
import net.kyori.adventure.key.Key;
import com.saicone.rtag.RtagItem;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.common.item.ItemFactory;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
@@ -28,13 +30,15 @@ import org.jetbrains.annotations.Nullable;
public interface ItemManager extends Reloadable {
boolean registerItem(@NotNull Key key, @NotNull CustomFishingItem item);
boolean registerItem(@NotNull CustomFishingItem item);
@Nullable
ItemStack buildInternal(@NotNull Context<Player> context, @NotNull Key key);
ItemStack buildInternal(@NotNull Context<Player> context, @NotNull String id);
ItemStack build(@NotNull Context<Player> context, CustomFishingItem item);
@Nullable
ItemStack buildAny(@NotNull Context<Player> context, @NotNull String item);
ItemStack buildAny(@NotNull Context<Player> context, @NotNull String id);
@NotNull
String getItemID(@NotNull ItemStack itemStack);
@@ -44,4 +48,6 @@ public interface ItemManager extends Reloadable {
@Nullable
Item dropItemLoot(@NotNull Context<Player> context);
ItemFactory<CustomFishingPlugin, RtagItem, ItemStack> getFactory();
}

View File

@@ -4,7 +4,11 @@ import java.util.Objects;
public class ItemType {
public static ItemType LOOT = of("loot");
public static final ItemType LOOT = of("loot");
public static final ItemType ROD = of("rod");
public static final ItemType UTIL = of("util");
public static final ItemType BAIT = of("bait");
public static final ItemType HOOK = of("hook");
private final String type;

View File

@@ -65,14 +65,14 @@ public interface Loot {
*
* @return The unique ID of the loot.
*/
String getID();
String id();
/**
* Get the type of this loot.
*
* @return The type of the loot.
*/
LootType getType();
LootType type();
/**
* Get the display nickname for this loot.
@@ -80,21 +80,21 @@ public interface Loot {
* @return The nickname of the loot.
*/
@NotNull
String getNick();
String nick();
/**
* Get the statistics key associated with this loot.
*
* @return The statistics key for this loot.
*/
StatisticsKeys getStatisticKey();
StatisticsKeys statisticKey();
/**
* Get the score value for this loot.
*
* @return The score associated with the loot.
*/
MathValue<Player> getScore();
MathValue<Player> score();
/**
* Get the groups this loot belongs to.

View File

@@ -44,23 +44,23 @@ public class LootImpl implements Loot {
}
@Override
public String getID() {
public String id() {
return id;
}
@Override
public LootType getType() {
public LootType type() {
return type;
}
@NotNull
@Override
public String getNick() {
public String nick() {
return nick;
}
@Override
public StatisticsKeys getStatisticKey() {
public StatisticsKeys statisticKey() {
return statisticsKeys;
}
@@ -70,7 +70,7 @@ public class LootImpl implements Loot {
}
@Override
public MathValue<Player> getScore() {
public MathValue<Player> score() {
return score;
}

View File

@@ -23,7 +23,9 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public interface LootManager {
@@ -35,13 +37,9 @@ public interface LootManager {
@NotNull
Optional<Loot> getLoot(String key);
HashMap<String, Double> getLootWithWeight(Context<Player> context);
Collection<String> getPossibleLootKeys(Context<Player> context);
@NotNull
Map<String, Double> getPossibleLootKeysWithWeight(Effect effect, Context<Player> context);
Map<String, Double> getWeightedLoots(Context<Player> context);
@Nullable
Loot getNextLoot(Effect effect, Context<Player> context);
Loot
getNextLoot(Effect effect, Context<Player> context);
}

View File

@@ -17,120 +17,17 @@
package net.momirealms.customfishing.api.mechanic.market;
import net.momirealms.customfishing.api.mechanic.context.Context;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
public interface MarketManager {
/**
* Open the market GUI for a player
*
* @param player player
*/
void openMarketGUI(Player player);
/**
* Retrieves the current date as an integer in the format MMDD (e.g., September 21 as 0921).
*
* @return An integer representing the current date.
*/
int getCachedDate();
double getItemPrice(Context<Player> context, ItemStack itemStack);
/**
* Retrieves the current date as an integer in the format MMDD (e.g., September 21 as 0921).
*
* @return An integer representing the current date.
*/
int getRealTimeDate();
/**
* Calculates the price of an ItemStack based on custom data or a predefined price map.
*
* @param itemStack The ItemStack for which the price is calculated.
* @return The calculated price of the ItemStack.
*/
double getItemPrice(ItemStack itemStack);
/**
* Retrieves the formula used for calculating prices.
*
* @return The pricing formula as a string.
*/
String getFormula();
/**
* Calculates the price based on a formula with provided variables.
*
* @return The calculated price based on the formula and provided variables.
*/
double getFishPrice(Player player, Map<String, String> vars);
/**
* Gets the character representing the item slot in the MarketGUI.
*
* @return The item slot character.
*/
char getItemSlot();
/**
* Gets the character representing the sell slot in the MarketGUI.
*
* @return The sell slot character.
*/
char getSellSlot();
/**
* Gets the character representing the sell-all slot in the MarketGUI.
*
* @return The sell-all slot character.
*/
char getSellAllSlot();
/**
* Gets the layout of the MarketGUI as an array of strings.
*
* @return The layout of the MarketGUI.
*/
String[] getLayout();
/**
* Gets the title of the MarketGUI.
*
* @return The title of the MarketGUI.
*/
String getTitle();
/**
* Gets the earning limit
*
* @return The earning limit
*/
double getEarningLimit(Player player);
/**
* Is market enabled
*
* @return enable or not
*/
boolean isEnable();
/**
* Should fish in bag also be sold
*
* @return sell or not
*/
boolean sellFishingBag();
/**
* Get the total worth of the items in inventory
*
* @param inventory inventory
* @return total worth
*/
double getInventoryTotalWorth(Inventory inventory);
int getInventorySellAmount(Inventory inventory);
double earningLimit(Context<Player> context);
}

View File

@@ -1,9 +0,0 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
public enum ParserType {
ITEM,
EFFECT_MODIFIER,
BASE_EFFECT,
LOOT,
EVENT
}

View File

@@ -20,7 +20,6 @@ package net.momirealms.customfishing.api.storage;
import net.momirealms.customfishing.api.storage.data.PlayerData;
import net.momirealms.customfishing.api.storage.user.UserData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Optional;
@@ -32,7 +31,7 @@ public interface StorageManager {
@NotNull
String getServerID();
@Nullable
@NotNull
Optional<UserData> getOnlineUser(UUID uuid);
@NotNull

View File

@@ -8,9 +8,7 @@ public record Key(String namespace, String value) {
@Override
public int hashCode() {
int result = this.namespace.hashCode();
result = (31 * result) + this.value.hashCode();
return result;
return toString().hashCode();
}
@Override

View File

@@ -76,13 +76,13 @@ public class CustomFishingPapi extends PlaceholderExpansion {
switch (split[1]) {
case "limit" -> {
if (split.length < 3) {
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(player));
return String.format("%.2f", plugin.getMarketManager().earningLimit(player));
} else {
Player another = Bukkit.getPlayer(split[2]);
if (another == null) {
return "";
}
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(another));
return String.format("%.2f", plugin.getMarketManager().earningLimit(another));
}
}
case "earnings" -> {
@@ -105,7 +105,7 @@ public class CustomFishingPapi extends PlaceholderExpansion {
OnlineUserData user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (user == null)
return "";
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(player) - user.getEarningData().earnings);
return String.format("%.2f", plugin.getMarketManager().earningLimit(player) - user.getEarningData().earnings);
} else {
Player another = Bukkit.getPlayer(split[2]);
if (another == null) {
@@ -115,7 +115,7 @@ public class CustomFishingPapi extends PlaceholderExpansion {
OnlineUserData user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
if (user == null)
return "";
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(another) - user.getEarningData().earnings);
return String.format("%.2f", plugin.getMarketManager().earningLimit(another) - user.getEarningData().earnings);
}
}
}

View File

@@ -57,10 +57,10 @@ public class BattlePassQuest implements Listener {
Player player = event.getPlayer();
// Single Fish Quest
if (event.getLoot().getID() != null)
if (event.getLoot().id() != null)
this.executionBuilder("loot")
.player(player)
.root(event.getLoot().getID())
.root(event.getLoot().id())
.progress(event.getAmount())
.buildAndExecute();

View File

@@ -79,7 +79,7 @@ public class BetonQuestQuest {
if (isInvalidLocation(event, onlineProfile)) {
return;
}
if (this.loot_ids.contains(event.getLoot().getID()) && this.checkConditions(onlineProfile)) {
if (this.loot_ids.contains(event.getLoot().id()) && this.checkConditions(onlineProfile)) {
getCountingData(onlineProfile).progress(event.getAmount());
completeIfDoneOrNotify(onlineProfile);
}

View File

@@ -57,7 +57,7 @@ public class ClueScrollsQuest implements Listener {
idClue.handle(
player,
event.getAmount(),
new ClueDataPair("id", loot.getID())
new ClueDataPair("id", loot.id())
);
}

View File

@@ -1,28 +1,68 @@
package net.momirealms.customfishing.bukkit.config;
import dev.dejvokep.boostedyaml.YamlDocument;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.config.ConfigType;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import net.momirealms.customfishing.common.helper.AdventureHelper;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.util.ListUtils;
import net.momirealms.customfishing.common.util.RandomUtils;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.io.File;
import java.util.*;
public class BukkitConfigLoader extends ConfigManager {
public BukkitConfigLoader(CustomFishingPlugin plugin) {
public BukkitConfigLoader(BukkitCustomFishingPlugin plugin) {
super(plugin);
this.registerBuiltInItemProperties();
this.registerBuiltInBaseEffectParser();
this.registerBuiltInLootParser();
this.registerBuiltInEntityParser();
this.registerBuiltInEventParser();
this.registerBuiltInEffectModifierParser();
}
@Override
public void load() {
this.loadConfigs();
}
private void loadConfigs() {
Deque<File> fileDeque = new ArrayDeque<>();
for (ConfigType type : ConfigType.values()) {
File typeFolder = new File(plugin.getDataFolder(), "contents" + File.separator + type.path());
if (!typeFolder.exists()) {
if (!typeFolder.mkdirs()) return;
plugin.getBoostrap().saveResource("contents" + File.separator + type.path() + File.separator + "default.yml", false);
}
fileDeque.push(typeFolder);
while (!fileDeque.isEmpty()) {
File file = fileDeque.pop();
File[] files = file.listFiles();
if (files == null) continue;
for (File subFile : files) {
if (subFile.isDirectory()) {
fileDeque.push(subFile);
} else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
YamlDocument document = plugin.getConfigManager().loadData(file);
for (Map.Entry<String, Object> entry : document.getStringRouteMappedValues(false).entrySet()) {
if (entry.getValue() instanceof Section section) {
type.parse(entry.getKey(), section, formatFunctions);
}
}
}
}
}
}
}
private void registerBuiltInItemProperties() {
@@ -84,6 +124,13 @@ public class BukkitConfigLoader extends ConfigManager {
}, 1_500, "price");
}
private void registerBuiltInEffectModifierParser() {
this.registerEffectModifierParser(object -> {
Section section = (Section) object;
return builder -> builder.requirements(List.of(plugin.getRequirementManager().parseRequirements(section, true)));
}, "requirements");
}
private void registerBuiltInBaseEffectParser() {
this.registerBaseEffectParser(object -> {
MathValue<Player> mathValue = MathValue.auto(object);
@@ -111,6 +158,87 @@ public class BukkitConfigLoader extends ConfigManager {
}, "base-effects", "wait-time-multiplier");
}
private void registerBuiltInEntityParser() {
this.registerEntityParser(object -> {
String entity = (String) object;
return builder -> builder.entityID(entity);
}, "entity");
this.registerEntityParser(object -> {
String entity = (String) object;
return builder -> builder.entityID(entity);
}, "velocity", "horizontal");
this.registerEntityParser(object -> {
String entity = (String) object;
return builder -> builder.entityID(entity);
}, "velocity", "vertical");
this.registerEntityParser(object -> {
Section section = (Section) object;
return builder -> builder.propertyMap(section.getStringRouteMappedValues(false));
}, "properties");
}
private void registerBuiltInEventParser() {
this.registerEventParser(object -> {
boolean disable = (boolean) object;
return builder -> builder.disableGlobalActions(disable);
}, "disable-global-event");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.SUCCESS, actions);
}, "events", "success");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.ACTIVATE, actions);
}, "events", "activate");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.FAILURE, actions);
}, "events", "failure");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.HOOK, actions);
}, "events", "hook");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.CONSUME, actions);
}, "events", "consume");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.CAST, actions);
}, "events", "cast");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.BITE, actions);
}, "events", "bite");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.LAND, actions);
}, "events", "land");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.TIMER, actions);
}, "events", "timer");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.INTERACT, actions);
}, "events", "interact");
this.registerEventParser(object -> {
Section section = (Section) object;
Action<Player>[] actions = plugin.getActionManager().parseActions(section);
return builder -> builder.action(ActionTrigger.NEW_SIZE_RECORD, actions);
}, "events", "new_size_record");
}
private void registerBuiltInLootParser() {
this.registerLootParser(object -> {
String string = (String) object;

View File

@@ -38,9 +38,9 @@ public class BukkitEffectManager implements EffectManager {
}
@Override
public boolean registerEffectModifier(String id, EffectModifier effect) {
if (effectModifiers.containsKey(id)) return false;
this.effectModifiers.put(id, effect);
public boolean registerEffectModifier(EffectModifier effect) {
if (effectModifiers.containsKey(effect.id())) return false;
this.effectModifiers.put(effect.id(), effect);
return true;
}

View File

@@ -44,9 +44,9 @@ public class BukkitEventManager implements EventManager, Listener {
}
@Override
public boolean registerEventCarrier(String id, EventCarrier carrier) {
if (carriers.containsKey(id)) return false;
carriers.put(id, carrier);
public boolean registerEventCarrier(EventCarrier carrier) {
if (carriers.containsKey(carrier.id())) return false;
carriers.put(carrier.id(), carrier);
return true;
}

View File

@@ -1,6 +1,5 @@
package net.momirealms.customfishing.bukkit.item;
import net.kyori.adventure.key.Key;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishingLootPreSpawnEvent;
import net.momirealms.customfishing.api.event.FishingLootSpawnEvent;
@@ -47,7 +46,7 @@ public class BukkitItemManager implements ItemManager, Listener {
private final BukkitCustomFishingPlugin plugin;
private final HashMap<String, ItemProvider> itemProviders = new HashMap<>();
private final HashMap<Key, CustomFishingItem> items = new HashMap<>();
private final HashMap<String, CustomFishingItem> items = new HashMap<>();
private final BukkitItemFactory factory;
private ItemProvider[] itemDetectArray;
@@ -83,16 +82,22 @@ public class BukkitItemManager implements ItemManager, Listener {
}
@Override
public boolean registerItem(@NotNull Key key, @NotNull CustomFishingItem item) {
if (items.containsKey(key)) return false;
items.put(key, item);
public boolean registerItem(@NotNull CustomFishingItem item) {
if (items.containsKey(item.id())) return false;
items.put(item.id(), item);
return true;
}
@Nullable
@Override
public ItemStack buildInternal(@NotNull Context<Player> context, @NotNull Key key) {
CustomFishingItem item = requireNonNull(items.get(key), () -> "No item found for " + key);
public ItemStack buildInternal(@NotNull Context<Player> context, @NotNull String id) {
CustomFishingItem item = requireNonNull(items.get(id), () -> "No item found for " + id);
return build(context, item);
}
@NotNull
@Override
public ItemStack build(@NotNull Context<Player> context, CustomFishingItem item) {
ItemStack itemStack = getOriginalStack(context.getHolder(), item.material());
Item<ItemStack> wrappedItemStack = factory.wrap(itemStack);
for (BiConsumer<Item<ItemStack>, Context<Player>> consumer : item.tagConsumers()) {
@@ -130,7 +135,7 @@ public class BukkitItemManager implements ItemManager, Listener {
@SuppressWarnings("all")
public org.bukkit.entity.Item dropItemLoot(@NotNull Context<Player> context) {
String id = requireNonNull(context.arg(ContextKeys.ID));
ItemStack itemStack = requireNonNull(buildInternal(context, Key.key("item", id)));
ItemStack itemStack = requireNonNull(buildInternal(context, id));
Player player = context.getHolder();
Location playerLocation = player.getLocation();
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
@@ -301,4 +306,9 @@ public class BukkitItemManager implements ItemManager, Listener {
}
blocks.removeAll(blockToRemove);
}
@Override
public BukkitItemFactory getFactory() {
return factory;
}
}

View File

@@ -48,7 +48,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected Optional<String> displayName(RtagItem item) {
if (item.getComponent(ComponentKeys.CUSTOM_NAME) == null) return Optional.empty();
if (!item.hasComponent(ComponentKeys.CUSTOM_NAME)) return Optional.empty();
return Optional.ofNullable(
(String) ComponentType.encodeJava(
ComponentKeys.CUSTOM_NAME,

View File

@@ -23,9 +23,9 @@ public class BukkitLootManager implements LootManager {
@Override
public void registerLoot(@NotNull Loot loot) {
this.lootMap.put(loot.getID(), loot);
this.lootMap.put(loot.id(), loot);
for (String group : loot.lootGroup()) {
addGroupMember(group, loot.getID());
addGroupMember(group, loot.id());
}
}
@@ -52,21 +52,10 @@ public class BukkitLootManager implements LootManager {
}
@Override
public HashMap<String, Double> getLootWithWeight(Context<Player> context) {
public HashMap<String, Double> getWeightedLoots(Context<Player> context) {
return null;
}
@Override
public Collection<String> getPossibleLootKeys(Context<Player> context) {
return List.of();
}
@NotNull
@Override
public Map<String, Double> getPossibleLootKeysWithWeight(Effect effect, Context<Player> context) {
return Map.of();
}
@Nullable
@Override
public Loot getNextLoot(Effect effect, Context<Player> context) {

View File

@@ -1,275 +0,0 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.bukkit.loot;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootManager;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import net.momirealms.customfishing.api.util.WeightUtils;
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
public class LootManagerImpl implements LootManager {
private final BukkitCustomFishingPlugin plugin;
// A map that associates loot IDs with their respective loot configurations.
private final HashMap<String, Loot> lootMap;
// A map that associates loot group IDs with lists of loot IDs.
private final HashMap<String, List<String>> lootGroupMap;
public LootManagerImpl(BukkitCustomFishingPlugin plugin) {
this.plugin = plugin;
this.lootMap = new HashMap<>();
this.lootGroupMap = new HashMap<>();
}
public void load() {
this.loadLootsFromPluginFolder();
}
public void unload() {
this.lootMap.clear();
this.lootGroupMap.clear();
}
public void disable() {
unload();
}
/**
* Loads loot configurations from the plugin's content folders.
* This method scans the "item," "entity," and "block" subfolders within the plugin's data folder
* and loads loot configurations from YAML files.
* If the subfolders or default loot files don't exist, it creates them.
*/
@SuppressWarnings("DuplicatedCode")
public void loadLootsFromPluginFolder() {
Deque<File> fileDeque = new ArrayDeque<>();
for (String type : List.of("item", "entity", "block")) {
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
if (!typeFolder.exists()) {
if (!typeFolder.mkdirs()) return;
plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false);
}
fileDeque.push(typeFolder);
while (!fileDeque.isEmpty()) {
File file = fileDeque.pop();
File[] files = file.listFiles();
if (files == null) continue;
for (File subFile : files) {
if (subFile.isDirectory()) {
fileDeque.push(subFile);
} else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
loadSingleFile(subFile, type);
}
}
}
}
}
/**
* Retrieves a list of loot IDs associated with a loot group key.
*
* @param key The key of the loot group.
* @return A list of loot IDs belonging to the specified loot group, or null if not found.
*/
@NotNull
@Override
public List<String> getGroupMembers(String key) {
return lootGroupMap.get(key);
}
/**
* Retrieves a loot configuration based on a provided loot key.
*
* @param key The key of the loot configuration.
* @return The Loot object associated with the specified loot key, or null if not found.
*/
@NotNull
@Override
public Loot getLoot(String key) {
return lootMap.get(key);
}
/**
* Retrieves a collection of all loot configuration keys.
*
* @return A collection of all loot configuration keys.
*/
@Override
public Collection<String> getAllLootKeys() {
return lootMap.keySet();
}
/**
* Retrieves a collection of all loot configurations.
*
* @return A collection of all loot configurations.
*/
@Override
public Collection<Loot> getAllLoots() {
return lootMap.values();
}
/**
* Retrieves loot configurations with weights based on a given condition.
*
* @param playerContext The condition used to filter loot configurations.
* @return A mapping of loot configuration keys to their associated weights.
*/
@Override
public HashMap<String, Double> getLootWithWeight(PlayerContext playerContext) {
return ((RequirementManagerImpl) plugin.getRequirementManager()).getLootWithWeight(playerContext);
}
/**
* Get a collection of possible loot keys based on a given condition.
*
* @param playerContext The condition to determine possible loot.
* @return A collection of loot keys.
*/
@Override
public Collection<String> getPossibleLootKeys(PlayerContext playerContext) {
return ((RequirementManagerImpl) plugin.getRequirementManager()).getLootWithWeight(playerContext).keySet();
}
/**
* Get a map of possible loot keys with their corresponding weights, considering fishing effect and condition.
*
* @param effect The effect to apply weight modifiers.
* @param playerContext The condition to determine possible loot.
* @return A map of loot keys and their weights.
*/
@NotNull
@Override
public Map<String, Double> getPossibleLootKeysWithWeight(Effect effect, PlayerContext playerContext) {
Map<String, Double> lootWithWeight = ((RequirementManagerImpl) plugin.getRequirementManager()).getLootWithWeight(playerContext);
Player player = playerContext.getPlayer();
for (Pair<String, WeightModifier> pair : effect.weightOperations()) {
Double previous = lootWithWeight.get(pair.left());
if (previous != null)
lootWithWeight.put(pair.left(), pair.right().modify(player, previous));
}
for (Pair<String, WeightModifier> pair : effect.weightOperationsIgnored()) {
double previous = lootWithWeight.getOrDefault(pair.left(), 0d);
lootWithWeight.put(pair.left(), pair.right().modify(player, previous));
}
return lootWithWeight;
}
/**
* Get the next loot item based on fishing effect and condition.
*
* @param effect The effect to apply weight modifiers.
* @param playerContext The condition to determine possible loot.
* @return The next loot item, or null if it doesn't exist.
*/
@Override
@Nullable
public Loot getNextLoot(Effect effect, PlayerContext playerContext) {
String key = WeightUtils.getRandom(getPossibleLootKeysWithWeight(effect, playerContext));
if (key == null) {
return null;
}
Loot loot = getLoot(key);
if (loot == null) {
LogUtils.warn(String.format("Loot %s doesn't exist in any of the subfolders[item/entity/block].", key));
return null;
}
return loot;
}
/**
* Loads loot configurations from a single YAML file and populates the lootMap and lootGroupMap.
*
* @param file The YAML file containing loot configurations.
* @param namespace The namespace indicating the type of loot (e.g., "item," "entity," "block").
*/
private void loadSingleFile(File file, String namespace) {
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file);
for (Map.Entry<String, Object> entry : yaml.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection section) {
var loot = getSingleSectionItem(
file.getPath(),
section,
namespace,
entry.getKey()
);
// Check for duplicate loot configurations and log an error if found.
if (lootMap.containsKey(entry.getKey())) {
LogUtils.severe("Duplicated loot found: " + entry.getKey() + ".");
} else {
lootMap.put(entry.getKey(), loot);
}
String[] group = loot.getLootGroup();
// If the loot configuration belongs to one or more groups, update lootGroupMap.
if (group != null) {
for (String g : group) {
List<String> groupMembers = lootGroupMap.computeIfAbsent(g, k -> new ArrayList<>());
groupMembers.add(loot.getID());
}
}
// legacy format support
if (section.contains("requirements") && section.contains("weight")) {
plugin.getRequirementManager().putLegacyLootToMap(
loot.getID(),
plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), false),
section.getDouble("weight", 0)
);
}
}
}
}
/**
* Creates a single loot configuration item from a ConfigurationSection.
*
* @param section The ConfigurationSection containing loot configuration data.
* @param namespace The namespace indicating the type of loot (e.g., "item," "entity," "block").
* @param key The unique key identifying the loot configuration.
* @return A CFLoot object representing the loot configuration.
*/
private CFLoot getSingleSectionItem(String filePath, ConfigurationSection section, String namespace, String key) {
return new CFLoot.Builder(key, LootType.valueOf(namespace.toUpperCase(Locale.ENGLISH)))
.filePath(filePath)
.disableStats(section.getBoolean("disable-stat", CFConfig.globalDisableStats))
.disableGames(section.getBoolean("disable-game", CFConfig.globalDisableGame))
.instantGame(section.getBoolean("instant-game", CFConfig.globalInstantGame))
.showInFinder(section.getBoolean("show-in-fishfinder", CFConfig.globalShowInFinder))
.disableGlobalActions(section.getBoolean("disable-global-event", false))
.score(section.getDouble("score"))
.baseEffect(plugin.getEffectManager().getBaseEffect(section.getConfigurationSection("effects")))
.lootGroup(ConfigUtils.stringListArgs(section.get("group")).toArray(new String[0]))
.nick(section.getString("nick", section.getString("display.name", key)))
.addActions(plugin.getActionManager().getActionMap(section.getConfigurationSection("events")))
.addTimesActions(plugin.getActionManager().getTimesActionMap(section.getConfigurationSection("events.success-times")))
.statsKey(new StatisticsKeys(section.getString("statistics.amount", key), section.getString("statistics.size", key)))
.build();
}
}

View File

@@ -17,24 +17,24 @@
package net.momirealms.customfishing.bukkit.market;
import de.tr7zw.changeme.nbtapi.NBTItem;
import dev.dejvokep.boostedyaml.YamlDocument;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder;
import net.momirealms.customfishing.api.mechanic.market.MarketManager;
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.storage.data.EarningData;
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
import net.momirealms.customfishing.api.storage.user.UserData;
import net.momirealms.customfishing.bukkit.item.BukkitItemFactory;
import net.momirealms.customfishing.bukkit.util.NumberUtils;
import net.momirealms.customfishing.common.helper.ExpressionHelper;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.objecthunter.exp4j.ExpressionBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
@@ -54,75 +54,79 @@ import java.util.concurrent.TimeUnit;
public class BukkitMarketManager implements MarketManager, Listener {
private final BukkitCustomFishingPlugin plugin;
private final HashMap<String, Double> priceMap;
private String[] layout;
private String title;
private boolean enable;
private final HashMap<String, MathValue<Player>> priceMap;
private String formula;
private final HashMap<Character, BuildableItem> decorativeIcons;
private MathValue<Player> earningsLimit;
private boolean allowItemWithNoPrice;
private boolean sellFishingBag;
private String title;
private String[] layout;
private final HashMap<Character, CustomFishingItem> decorativeIcons;
private final ConcurrentHashMap<UUID, MarketGUI> marketGUIMap;
private char itemSlot;
private char sellSlot;
private char sellAllSlot;
private BuildableItem sellIconAllowBuilder;
private BuildableItem sellIconDenyBuilder;
private BuildableItem sellIconLimitBuilder;
private BuildableItem sellAllIconAllowBuilder;
private BuildableItem sellAllIconDenyBuilder;
private BuildableItem sellAllIconLimitBuilder;
private Action[] sellDenyActions;
private Action[] sellAllowActions;
private Action[] sellLimitActions;
private Action[] sellAllDenyActions;
private Action[] sellAllAllowActions;
private Action[] sellAllLimitActions;
private String earningLimitExpression;
private boolean allowItemWithNoPrice;
private boolean sellFishingBag;
private final ConcurrentHashMap<UUID, MarketGUI> marketGUIMap;
private boolean enable;
private CustomFishingItem sellIconAllowItem;
private CustomFishingItem sellIconDenyItem;
private CustomFishingItem sellIconLimitItem;
private CustomFishingItem sellAllIconAllowItem;
private CustomFishingItem sellAllIconDenyItem;
private CustomFishingItem sellAllIconLimitItem;
private Action<Player>[] sellDenyActions;
private Action<Player>[] sellAllowActions;
private Action<Player>[] sellLimitActions;
private Action<Player>[] sellAllDenyActions;
private Action<Player>[] sellAllAllowActions;
private Action<Player>[] sellAllLimitActions;
private SchedulerTask resetEarningsTask;
private int date;
private int cachedDate;
public BukkitMarketManager(BukkitCustomFishingPlugin plugin) {
this.plugin = plugin;
this.priceMap = new HashMap<>();
this.decorativeIcons = new HashMap<>();
this.marketGUIMap = new ConcurrentHashMap<>();
this.date = getRealTimeDate();
this.cachedDate = getRealTimeDate();
}
public void load() {
this.loadConfig();
Bukkit.getPluginManager().registerEvents(this, plugin);
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
if (!enable) return;
this.resetEarningsTask = plugin.getScheduler().asyncRepeating(() -> {
int now = getRealTimeDate();
if (this.date != now) {
this.date = now;
for (OnlineUserData onlineUser : plugin.getStorageManager().getOnlineUsers()) {
onlineUser.getEarningData().date = now;
onlineUser.getEarningData().earnings = 0d;
if (this.cachedDate != now) {
this.cachedDate = now;
for (UserData userData : plugin.getStorageManager().getOnlineUsers()) {
userData.earningData().refresh();
}
}
}, 1, 1, TimeUnit.SECONDS);
}
private int getRealTimeDate() {
Calendar calendar = Calendar.getInstance();
return (calendar.get(Calendar.MONTH) +1) * 100 + calendar.get(Calendar.DATE);
}
public void unload() {
HandlerList.unregisterAll(this);
this.priceMap.clear();
this.decorativeIcons.clear();
if (this.resetEarningsTask != null && !this.resetEarningsTask.isCancelled()) {
if (this.resetEarningsTask != null)
this.resetEarningsTask.cancel();
this.resetEarningsTask = null;
}
}
public void disable() {
unload();
}
// Load configuration from the plugin's config file
private void loadConfig() {
YamlConfiguration config = plugin.getConfig("market.yml");
YamlDocument config = plugin.getConfigManager().loadConfig("market.yml");
this.enable = config.getBoolean("enable", true);
this.formula = config.getString("price-formula", "{base} + {bonus} * {size}");
if (!this.enable) return;
@@ -133,51 +137,51 @@ public class BukkitMarketManager implements MarketManager, Listener {
this.itemSlot = config.getString("item-slot.symbol", "I").charAt(0);
this.allowItemWithNoPrice = config.getBoolean("item-slot.allow-items-with-no-price", true);
ConfigurationSection sellAllSection = config.getConfigurationSection("sell-all-icons");
Section sellAllSection = config.getSection("sell-all-icons");
if (sellAllSection != null) {
this.sellAllSlot = sellAllSection.getString("symbol", "S").charAt(0);
this.sellFishingBag = sellAllSection.getBoolean("fishingbag", true);
this.sellAllIconAllowBuilder = plugin.getItemManager().getItemBuilder(sellAllSection.getConfigurationSection("allow-icon"), "gui", "sell-all");
this.sellAllIconDenyBuilder = plugin.getItemManager().getItemBuilder(sellAllSection.getConfigurationSection("deny-icon"), "gui", "sell-all");
this.sellAllIconLimitBuilder = plugin.getItemManager().getItemBuilder(sellAllSection.getConfigurationSection("limit-icon"), "gui", "sell-all");
this.sellAllIconAllowItem = plugin.getItemManager().getItemBuilder(sellAllSection.getSection("allow-icon"), "gui", "sell-all");
this.sellAllIconDenyItem = plugin.getItemManager().getItemBuilder(sellAllSection.getSection("deny-icon"), "gui", "sell-all");
this.sellAllIconLimitItem = plugin.getItemManager().getItemBuilder(sellAllSection.getSection("limit-icon"), "gui", "sell-all");
this.sellAllAllowActions = plugin.getActionManager().getActions(sellAllSection.getConfigurationSection("allow-icon.action"));
this.sellAllDenyActions = plugin.getActionManager().getActions(sellAllSection.getConfigurationSection("deny-icon.action"));
this.sellAllLimitActions = plugin.getActionManager().getActions(sellAllSection.getConfigurationSection("limit-icon.action"));
this.sellAllAllowActions = plugin.getActionManager().parseActions(sellAllSection.getSection("allow-icon.action"));
this.sellAllDenyActions = plugin.getActionManager().parseActions(sellAllSection.getSection("deny-icon.action"));
this.sellAllLimitActions = plugin.getActionManager().parseActions(sellAllSection.getSection("limit-icon.action"));
}
ConfigurationSection sellSection = config.getConfigurationSection("sell-icons");
Section sellSection = config.getSection("sell-icons");
if (sellSection == null) {
// for old config compatibility
sellSection = config.getConfigurationSection("functional-icons");
sellSection = config.getSection("functional-icons");
}
if (sellSection != null) {
this.sellSlot = sellSection.getString("symbol", "B").charAt(0);
this.sellIconAllowBuilder = plugin.getItemManager().getItemBuilder(sellSection.getConfigurationSection("allow-icon"), "gui", "allow");
this.sellIconDenyBuilder = plugin.getItemManager().getItemBuilder(sellSection.getConfigurationSection("deny-icon"), "gui", "deny");
this.sellIconLimitBuilder = plugin.getItemManager().getItemBuilder(sellSection.getConfigurationSection("limit-icon"), "gui", "limit");
this.sellIconAllowItem = plugin.getItemManager().getItemBuilder(sellSection.getSection("allow-icon"), "gui", "allow");
this.sellIconDenyItem = plugin.getItemManager().getItemBuilder(sellSection.getSection("deny-icon"), "gui", "deny");
this.sellIconLimitItem = plugin.getItemManager().getItemBuilder(sellSection.getSection("limit-icon"), "gui", "limit");
this.sellAllowActions = plugin.getActionManager().getActions(sellSection.getConfigurationSection("allow-icon.action"));
this.sellDenyActions = plugin.getActionManager().getActions(sellSection.getConfigurationSection("deny-icon.action"));
this.sellLimitActions = plugin.getActionManager().getActions(sellSection.getConfigurationSection("limit-icon.action"));
this.sellAllowActions = plugin.getActionManager().parseActions(sellSection.getSection("allow-icon.action"));
this.sellDenyActions = plugin.getActionManager().parseActions(sellSection.getSection("deny-icon.action"));
this.sellLimitActions = plugin.getActionManager().parseActions(sellSection.getSection("limit-icon.action"));
}
this.earningLimitExpression = config.getBoolean("limitation.enable", true) ? config.getString("limitation.earnings", "10000") : "-1";
this.earningsLimit = config.getBoolean("limitation.enable", true) ? MathValue.auto(config.getString("limitation.earnings", "10000")) : MathValue.plain(-1);
// Load item prices from the configuration
ConfigurationSection priceSection = config.getConfigurationSection("item-price");
Section priceSection = config.getSection("item-price");
if (priceSection != null) {
for (Map.Entry<String, Object> entry : priceSection.getValues(false).entrySet()) {
this.priceMap.put(entry.getKey(), ConfigUtils.getDoubleValue(entry.getValue()));
for (Map.Entry<String, Object> entry : priceSection.getStringRouteMappedValues(false).entrySet()) {
this.priceMap.put(entry.getKey(), MathValue.auto(entry.getValue()));
}
}
// Load decorative icons from the configuration
ConfigurationSection decorativeSection = config.getConfigurationSection("decorative-icons");
Section decorativeSection = config.getSection("decorative-icons");
if (decorativeSection != null) {
for (Map.Entry<String, Object> entry : decorativeSection.getValues(false).entrySet()) {
for (Map.Entry<String, Object> entry : decorativeSection.getStringRouteMappedValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection innerSection) {
char symbol = Objects.requireNonNull(innerSection.getString("symbol")).charAt(0);
var builder = plugin.getItemManager().getItemBuilder(innerSection, "gui", entry.getKey());
@@ -194,19 +198,19 @@ public class BukkitMarketManager implements MarketManager, Listener {
*/
@Override
public void openMarketGUI(Player player) {
if (!isEnable()) return;
OnlineUserData user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (user == null) {
LogUtils.warn("Player " + player.getName() + "'s market data is not loaded yet.");
if (!enable) return;
Optional<UserData> optionalUserData = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (optionalUserData.isEmpty()) {
plugin.getPluginLogger().warn("Player " + player.getName() + "'s market data is not loaded yet.");
return;
}
MarketGUI gui = new MarketGUI(this, player, user.getEarningData());
MarketGUI gui = new MarketGUI(this, player, optionalUserData.get().earningData());
gui.addElement(new MarketGUIElement(getItemSlot(), new ItemStack(Material.AIR)));
gui.addElement(new MarketDynamicGUIElement(getSellSlot(), new ItemStack(Material.AIR)));
gui.addElement(new MarketDynamicGUIElement(getSellAllSlot(), new ItemStack(Material.AIR)));
for (Map.Entry<Character, BuildableItem> entry : decorativeIcons.entrySet()) {
gui.addElement(new MarketGUIElement(entry.getKey(), entry.getValue().build(player)));
for (Map.Entry<Character, CustomFishingItem> entry : decorativeIcons.entrySet()) {
gui.addElement(new MarketGUIElement(entry.getKey(), ));
}
gui.build().refresh().show(player);
marketGUIMap.put(player.getUniqueId(), gui);
@@ -274,7 +278,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
}
}
plugin.getScheduler().runTaskSyncLater(gui::refresh, player.getLocation(), 50, TimeUnit.MILLISECONDS);
plugin.getScheduler().sync().runLater(gui::refresh, 1, player.getLocation());
}
/**
@@ -306,10 +310,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
if (clickedInv != player.getInventory()) {
EarningData data = gui.getEarningData();
if (data.date != getCachedDate()) {
data.date = getCachedDate();
data.earnings = 0;
}
data.refresh();
int slot = event.getSlot();
MarketGUIElement element = gui.getElement(slot);
@@ -325,8 +326,10 @@ public class BukkitMarketManager implements MarketManager, Listener {
if (element.getSymbol() == sellSlot) {
double worth = gui.getTotalWorthInMarketGUI();
int amount = gui.getSoldAmount();
double earningLimit = getEarningLimit(player);
PlayerContext playerContext = new PlayerContext(player, new HashMap<>(Map.of(
double earningLimit = earningLimit(player);
Context<Player> context = Context.player(player);
new Con(, new HashMap<>(Map.of(
"{money}", NumberUtils.money(worth),
"{rest}", NumberUtils.money(earningLimit - data.earnings),
"{money_formatted}", String.format("%.2f", worth)
@@ -337,8 +340,8 @@ public class BukkitMarketManager implements MarketManager, Listener {
if (earningLimit != -1 && (earningLimit - data.earnings) < worth) {
// Can't earn more money
if (getSellLimitActions() != null) {
for (Action action : getSellLimitActions()) {
action.trigger(playerContext);
for (Action<Player> action : getSellLimitActions()) {
action.trigger(context);
}
}
} else {
@@ -364,7 +367,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
} else if (element.getSymbol() == sellAllSlot) {
double worth = getInventoryTotalWorth(player.getInventory());
int amount = getInventorySellAmount(player.getInventory());
double earningLimit = getEarningLimit(player);
double earningLimit = earningLimit(player);
if (sellFishingBag() && BukkitCustomFishingPlugin.get().getBagManager().isEnabled()) {
Inventory bag = BukkitCustomFishingPlugin.get().getBagManager().getOnlineBagInventory(player.getUniqueId());
if (bag != null) {
@@ -457,154 +460,44 @@ public class BukkitMarketManager implements MarketManager, Listener {
}
// Refresh the GUI
plugin.getScheduler().runTaskSyncLater(gui::refresh, player.getLocation(), 50, TimeUnit.MILLISECONDS);
plugin.getScheduler().sync().runLater(gui::refresh, 1, player.getLocation());
}
@Override
public int getCachedDate() {
return date;
}
@Override
public int getRealTimeDate() {
Calendar calendar = Calendar.getInstance();
return (calendar.get(Calendar.MONTH) +1) * 100 + calendar.get(Calendar.DATE);
}
@Override
public double getItemPrice(ItemStack itemStack) {
public double getItemPrice(Context<Player> context, ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return 0;
NBTItem nbtItem = new NBTItem(itemStack);
Double price = nbtItem.getDouble("Price");
if (price != null && price != 0) {
Item<ItemStack> wrapped = ((BukkitItemFactory) plugin.getItemManager().getFactory()).wrap(itemStack);
double price = (double) wrapped.getTag("Price").orElse(0d);
if (price != 0) {
// If a custom price is defined in the ItemStack's NBT data, use it.
return price * itemStack.getAmount();
}
// If no custom price is defined, attempt to fetch the price from a predefined price map.
String itemID = itemStack.getType().name();
if (nbtItem.hasTag("CustomModelData")) {
itemID = itemID + ":" + nbtItem.getInteger("CustomModelData");
Optional<Integer> optionalCMD = wrapped.customModelData();
if (optionalCMD.isPresent()) {
itemID = itemID + ":" + optionalCMD.get();
}
// Use the price from the price map, or default to 0 if not found.
return priceMap.getOrDefault(itemID, 0d) * itemStack.getAmount();
MathValue<Player> formula = priceMap.get(itemID);
if (formula == null) return 0;
return formula.evaluate(context) * itemStack.getAmount();
}
@Override
public TextValue<Player> getFormula() {
return formula;
public String getFormula() {
return "";
}
@Override
public double getFishPrice(Context<Player> context) {
formula.
String temp = plugin.getPlaceholderManager().parse(player, formula, vars);
var placeholders = BukkitPlaceholderManager.getInstance().resolvePlaceholders(temp);
for (String placeholder : placeholders) {
temp = temp.replace(placeholder, "0");
}
return ExpressionHelper.evaluate(temp);
public double earningLimit(Context<Player> context) {
return 0;
}
@Override
public char getItemSlot() {
return itemSlot;
}
@Override
public char getSellSlot() {
return sellSlot;
}
@Override
public char getSellAllSlot() {
return sellAllSlot;
}
@Override
public String[] getLayout() {
return layout;
}
@Override
public String getTitle() {
return title;
}
@Override
public double getEarningLimit(Player player) {
return new ExpressionBuilder(
BukkitPlaceholderManager.getInstance().parse(
player,
earningLimitExpression,
new HashMap<>()
))
.build()
.evaluate();
}
public BuildableItem getSellIconLimitBuilder() {
return sellIconLimitBuilder;
}
public BuildableItem getSellIconAllowBuilder() {
return sellIconAllowBuilder;
}
public BuildableItem getSellIconDenyBuilder() {
return sellIconDenyBuilder;
}
public BuildableItem getSellAllIconAllowBuilder() {
return sellAllIconAllowBuilder;
}
public BuildableItem getSellAllIconDenyBuilder() {
return sellAllIconDenyBuilder;
}
public BuildableItem getSellAllIconLimitBuilder() {
return sellAllIconLimitBuilder;
}
public Action[] getSellDenyActions() {
return sellDenyActions;
}
public Action[] getSellAllowActions() {
return sellAllowActions;
}
public Action[] getSellLimitActions() {
return sellLimitActions;
}
public Action[] getSellAllDenyActions() {
return sellAllDenyActions;
}
public Action[] getSellAllAllowActions() {
return sellAllAllowActions;
}
public Action[] getSellAllLimitActions() {
return sellAllLimitActions;
}
@Override
public boolean isEnable() {
return enable;
}
@Override
public boolean sellFishingBag() {
return sellFishingBag;
}
@Override
public double getInventoryTotalWorth(Inventory inventory) {
double total = 0d;
for (ItemStack itemStack : inventory.getStorageContents()) {
@@ -614,7 +507,6 @@ public class BukkitMarketManager implements MarketManager, Listener {
return total;
}
@Override
public int getInventorySellAmount(Inventory inventory) {
int amount = 0;
for (ItemStack itemStack : inventory.getStorageContents()) {

View File

@@ -146,7 +146,7 @@ public class MarketGUI {
* @return The MarketGUI instance.
*/
public MarketGUI refresh() {
double earningLimit = manager.getEarningLimit(owner);
double earningLimit = manager.earningLimit(owner);
MarketDynamicGUIElement sellElement = (MarketDynamicGUIElement) getElement(manager.getSellSlot());
if (sellElement != null && sellElement.getSlots().size() > 0) {
double totalWorth = getTotalWorthInMarketGUI();

View File

@@ -539,7 +539,7 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
String loot = context.arg(ContextKeys.ID);
Optional<Loot> lootInstance = plugin.getLootManager().getLoot(loot);
if (lootInstance.isPresent()) {
if (types.contains(lootInstance.get().getType().name().toLowerCase(Locale.ENGLISH)))
if (types.contains(lootInstance.get().type().name().toLowerCase(Locale.ENGLISH)))
return true;
}
if (advanced) ActionManager.trigger(context, actions);
@@ -552,7 +552,7 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
String loot = context.arg(ContextKeys.ID);
Optional<Loot> lootInstance = plugin.getLootManager().getLoot(loot);
if (lootInstance.isPresent()) {
if (!types.contains(lootInstance.get().getType().name().toLowerCase(Locale.ENGLISH)))
if (!types.contains(lootInstance.get().type().name().toLowerCase(Locale.ENGLISH)))
return true;
}
if (advanced) ActionManager.trigger(context, actions);

View File

@@ -148,6 +148,7 @@ public class BukkitStorageManager implements StorageManager, Listener {
return serverID;
}
@NotNull
@Override
public Optional<UserData> getOnlineUser(UUID uuid) {
return Optional.ofNullable(onlineUserMap.get(uuid));

View File

@@ -25,7 +25,7 @@ import net.kyori.adventure.text.ScoreComponent;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.mechanic.hook.HookSetting;
import net.momirealms.customfishing.api.mechanic.hook.HookConfigImpl;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
@@ -68,17 +68,17 @@ public class ItemUtils {
if (cfCompound.hasTag("hook_id")) {
String hookID = cfCompound.getString("hook_id");
HookSetting setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(hookID);
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(hookID);
if (setting == null) {
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_item");
cfCompound.removeKey("hook_dur");
} else {
for (String newLore : setting.getLore()) {
for (String newLore : setting.lore()) {
ScoreComponent.Builder builder = Component.score().name("cf").objective("hook");
builder.append(AdventureHelper.getInstance().getComponentFromMiniMessage(
newLore.replace("{dur}", String.valueOf(cfCompound.getInteger("hook_dur")))
.replace("{max}", String.valueOf(setting.getMaxDurability()))
.replace("{max}", String.valueOf(setting.maxDurability()))
));
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
}
@@ -156,13 +156,13 @@ public class ItemUtils {
int hookDur = cfCompound.getInteger("hook_dur");
if (hookDur != -1) {
String id = cfCompound.getString("hook_id");
HookSetting setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
if (setting == null) {
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_dur");
cfCompound.removeKey("hook_item");
} else {
hookDur = Math.min(setting.getMaxDurability(), hookDur + amount);
hookDur = Math.min(setting.maxDurability(), hookDur + amount);
cfCompound.setInteger("hook_dur", hookDur);
}
}
@@ -187,13 +187,13 @@ public class ItemUtils {
int hookDur = cfCompound.getInteger("hook_dur");
if (hookDur != -1) {
String id = cfCompound.getString("hook_id");
HookSetting setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
if (setting == null) {
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_dur");
cfCompound.removeKey("hook_item");
} else {
hookDur = Math.min(setting.getMaxDurability(), amount);
hookDur = Math.min(setting.maxDurability(), amount);
cfCompound.setInteger("hook_dur", hookDur);
}
}