9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-19 15:09:24 +00:00

checkpoint - 2

This commit is contained in:
XiaoMoMi
2024-05-18 23:31:53 +08:00
parent 5166989a48
commit ddc1f4245f
197 changed files with 2673 additions and 5089 deletions

View File

@@ -17,155 +17,34 @@
package net.momirealms.customfishing.api;
import net.momirealms.customfishing.api.integration.IntegrationManager;
import net.momirealms.customfishing.api.manager.*;
import net.momirealms.customfishing.api.mechanic.action.ActionManager;
import net.momirealms.customfishing.api.mechanic.bag.BagManager;
import net.momirealms.customfishing.api.mechanic.block.BlockManager;
import net.momirealms.customfishing.api.mechanic.competition.CompetitionManager;
import net.momirealms.customfishing.api.mechanic.effect.EffectManager;
import net.momirealms.customfishing.api.mechanic.entity.EntityManager;
import net.momirealms.customfishing.api.mechanic.fishing.FishingManager;
import net.momirealms.customfishing.api.mechanic.game.GameManager;
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;
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsManager;
import net.momirealms.customfishing.api.mechanic.totem.TotemManager;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.event.EventManager;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerAdapter;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
public abstract class BukkitCustomFishingPlugin extends JavaPlugin implements CustomFishingPlugin {
protected boolean initialized;
protected SchedulerAdapter<Location> scheduler;
protected CustomFishingCommandManager<CommandSender> commandManager;
protected VersionManager versionManager;
protected ItemManager itemManager;
protected RequirementManager requirementManager;
protected ActionManager actionManager;
protected LootManager lootManager;
protected FishingManager fishingManager;
protected EffectManager effectManager;
protected EntityManager entityManager;
protected BlockManager blockManager;
protected BagManager bagManager;
protected GameManager gameManager;
protected MarketManager marketManager;
protected IntegrationManager integrationManager;
protected CompetitionManager competitionManager;
protected StorageManager storageManager;
protected PlaceholderManager placeholderManager;
protected StatisticsManager statisticsManager;
protected TotemManager totemManager;
protected HookManager hookManager;
public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
private static BukkitCustomFishingPlugin instance;
protected EventManager eventManager;
protected ConfigManager configManager;
public BukkitCustomFishingPlugin() {
instance = this;
}
public static BukkitCustomFishingPlugin get() {
return getInstance();
}
public static BukkitCustomFishingPlugin getInstance() {
if (instance == null) {
throw new IllegalArgumentException("Plugin not initialized");
}
return instance;
}
public VersionManager getVersionManager() {
return versionManager;
public EventManager getEventManager() {
return eventManager;
}
public RequirementManager getRequirementManager() {
return requirementManager;
@Override
public ConfigManager getConfigManager() {
return configManager;
}
public ActionManager getActionManager() {
return actionManager;
}
public GameManager getGameManager() {
return gameManager;
}
public BlockManager getBlockManager() {
return blockManager;
}
public EntityManager getEntityManager() {
return entityManager;
}
public ItemManager getItemManager() {
return itemManager;
}
public EffectManager getEffectManager() {
return effectManager;
}
public MarketManager getMarketManager() {
return marketManager;
}
public FishingManager getFishingManager() {
return fishingManager;
}
public AdventureManager getAdventure() {
return adventure;
}
public BagManager getBagManager() {
return bagManager;
}
public LootManager getLootManager() {
return lootManager;
}
public StorageManager getStorageManager() {
return storageManager;
}
public TotemManager getTotemManager() {
return totemManager;
}
public HookManager getHookManager() {
return hookManager;
}
public IntegrationManager getIntegrationManager() {
return integrationManager;
}
public StatisticsManager getStatisticsManager() {
return statisticsManager;
}
public PlaceholderManager getPlaceholderManager() {
return placeholderManager;
}
public CompetitionManager getCompetitionManager() {
return competitionManager;
}
public abstract void reload();
public abstract YamlConfiguration getConfig(String file);
public abstract boolean isHookedPluginEnabled(String plugin);
public abstract void debug(String message);
}

View File

@@ -1,106 +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.api.data;
import com.google.gson.annotations.SerializedName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PlayerData {
@SerializedName("name")
protected String name;
@SerializedName("stats")
protected StatisticData statisticsData;
@SerializedName("bag")
protected InventoryData bagData;
@SerializedName("trade")
protected EarningData earningData;
public static PlayerData LOCKED = empty();
public static Builder builder() {
return new Builder();
}
public static PlayerData empty() {
return new Builder()
.setBagData(InventoryData.empty())
.setEarningData(EarningData.empty())
.setStats(StatisticData.empty())
.build();
}
public static class Builder {
private final PlayerData playerData;
public Builder() {
this.playerData = new PlayerData();
}
@NotNull
public Builder setName(@Nullable String name) {
this.playerData.name = name;
return this;
}
@NotNull
public Builder setStats(@Nullable StatisticData statisticsData) {
this.playerData.statisticsData = statisticsData;
return this;
}
@NotNull
public Builder setBagData(@Nullable InventoryData inventoryData) {
this.playerData.bagData = inventoryData;
return this;
}
@NotNull
public Builder setEarningData(@Nullable EarningData earningData) {
this.playerData.earningData = earningData;
return this;
}
@NotNull
public PlayerData build() {
return this.playerData;
}
}
public StatisticData getStatistics() {
return statisticsData;
}
public InventoryData getBagData() {
return bagData;
}
public EarningData getEarningData() {
return earningData;
}
public String getName() {
return name;
}
public boolean isLocked() {
return this == LOCKED;
}
}

View File

@@ -1,30 +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.api.data.user;
import org.bukkit.entity.Player;
public interface OnlineUser extends OfflineUser {
/**
* Get the bukkit player
*
* @return player
*/
Player getPlayer();
}

View File

@@ -1,60 +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.api.event;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class CompetitionEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
private final State state;
private final FishingCompetition competition;
public CompetitionEvent(State state, FishingCompetition competition) {
super(true);
this.state = state;
this.competition = competition;
}
public State getState() {
return state;
}
public FishingCompetition getCompetition() {
return competition;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public static enum State {
END,
STOP,
START
}
}

View File

@@ -1,47 +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.api.event;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class CustomFishingReloadEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
private final BukkitCustomFishingPlugin plugin;
public CustomFishingReloadEvent(BukkitCustomFishingPlugin plugin) {
this.plugin = plugin;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public BukkitCustomFishingPlugin getPluginInstance() {
return plugin;
}
}

View File

@@ -1,105 +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.api.event;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a fishing hook lands in either lava or water.
*/
public class FishHookLandEvent extends PlayerEvent {
private static final HandlerList handlerList = new HandlerList();
private final Target target;
private final FishHook fishHook;
private final Effect effect;
private final boolean isFirst;
/**
* Constructs a new FishHookLandEvent.
*
* @param who The player who triggered the event.
* @param target The target where the fishing hook has landed (LAVA or WATER).
* @param hook The fishing hook entity.
* @param initialEffect The initial effect
*/
public FishHookLandEvent(@NotNull Player who, Target target, FishHook hook, boolean isFirst, Effect initialEffect) {
super(who);
this.target = target;
this.fishHook = hook;
this.effect = initialEffect;
this.isFirst = isFirst;
}
/**
* Gets the target where the fishing hook has landed.
*
* @return The target, which can be either LAVA or WATER.
*/
public Target getTarget() {
return target;
}
/**
* Gets the fish hook bukkit entity
*
* @return fish hook
*/
public FishHook getFishHook() {
return fishHook;
}
public static HandlerList getHandlerList() {
return handlerList;
}
/**
* Is the first try of one fishing catch
*
* @return is first try
*/
public boolean isFirst() {
return isFirst;
}
/**
* Get the fishing effect
* It's not advised to modify this value without checking "isFirst()" since this event can be trigger multiple times in one fishing catch
*
* @return fishing effect
*/
public Effect getEffect() {
return effect;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public enum Target {
LAVA,
WATER
}
}

View File

@@ -1,68 +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.api.event;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class FishingBagPreCollectEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final ItemStack itemStack;
private boolean isCancelled;
private final Inventory bag;
public FishingBagPreCollectEvent(@NotNull Player who, ItemStack itemStack, Inventory bag) {
super(who);
this.itemStack = itemStack;
this.isCancelled = false;
this.bag = bag;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
public ItemStack getItemStack() {
return itemStack;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
public Inventory getBagInventory() {
return bag;
}
}

View File

@@ -1,68 +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.api.event;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class FishingLootPreSpawnEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final Location location;
private final ItemStack itemStack;
private boolean isCancelled;
public FishingLootPreSpawnEvent(@NotNull Player who, Location location, ItemStack itemStack) {
super(who);
this.itemStack = itemStack;
this.location = location;
this.isCancelled = false;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
public Location getLocation() {
return location;
}
public ItemStack getItemStack() {
return itemStack;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
}

View File

@@ -1,68 +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.api.event;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
public class FishingLootSpawnEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final Location location;
private final Item item;
private boolean isCancelled;
public FishingLootSpawnEvent(@NotNull Player who, Location location, Item item) {
super(who);
this.item = item;
this.location = location;
this.isCancelled = false;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
public Location getLocation() {
return location;
}
public Item getItem() {
return item;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
}

View File

@@ -1,165 +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.api.event;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
/**
* This class represents an event that occurs when a player gets a result from fishing.
*/
public class FishingResultEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private boolean isCancelled;
private final Result result;
private final Loot loot;
private final FishHook fishHook;
private final Map<String, String> args;
/**
* Constructs a new FishingResultEvent.
*
* @param who The player who triggered the event.
* @param result The result of the fishing action (SUCCESS or FAILURE).
* @param loot The loot received from fishing.
* @param args A map of placeholders and their corresponding values.
*/
public FishingResultEvent(@NotNull Player who, Result result, FishHook fishHook, Loot loot, Map<String, String> args) {
super(who);
this.result = result;
this.loot = loot;
this.args = args;
this.fishHook = fishHook;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
/**
* Gets the value associated with a specific argument key.
* Usage example event.getArg("{x}")
*
* @param key The argument key enclosed in curly braces, e.g., "{amount}".
* @return The value associated with the argument key, or null if not found.
*/
public String getArg(String key) {
return args.get(key);
}
/**
* Set the value associated with a specific argument key.
* @param key key
* @param value value
* @return previous value
*/
@Nullable
public String setArg(String key, String value) {
return args.put(key, value);
}
/**
* Gets the result of the fishing action.
*
* @return The fishing result, which can be either SUCCESS or FAILURE.
*/
public Result getResult() {
return result;
}
/**
* Get the fish hook entity.
*
* @return fish hook
*/
public FishHook getFishHook() {
return fishHook;
}
/**
* Gets the loot received from fishing.
*
* @return The loot obtained from the fishing action.
*/
public Loot getLoot() {
return loot;
}
/**
* Gets the amount of loot received.
* This value is determined by the "multiple-loot" effect.
* If you want to get the amount of item spawned, listen to FishingLootSpawnEvent
*
* @return The amount of loot received, or 1 if the loot is block or entity
*/
public int getAmount() {
return Integer.parseInt(Optional.ofNullable(getArg("{amount}")).orElse("1"));
}
/**
* Set the loot amount (Only works for items)
*
* @param amount amount
*/
public void setAmount(int amount) {
setArg("{amount}", String.valueOf(amount));
}
/**
* Set the score to get in competition
*
* @param score score
*/
public void setScore(double score) {
setArg("{SCORE}", String.valueOf(score));
}
/**
* An enumeration representing possible fishing results (SUCCESS or FAILURE).
*/
public enum Result {
SUCCESS,
FAILURE
}
}

View File

@@ -1,97 +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.api.event;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a player fishes in lava.
*/
public class LavaFishingEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final State state;
private boolean isCancelled;
private final FishHook hook;
/**
* Constructs a new LavaFishingEvent.
*
* @param who The player who triggered the event.
* @param state The state of the fishing action (REEL_IN, CAUGHT_FISH, or BITE).
* @param hook The FishHook entity associated with the fishing action.
*/
public LavaFishingEvent(@NotNull Player who, State state, FishHook hook) {
super(who);
this.state = state;
this.isCancelled = false;
this.hook = hook;
}
/**
* Gets the state of the fishing action.
*
* @return The fishing state, which can be REEL_IN, CAUGHT_FISH, or BITE.
*/
public State getState() {
return state;
}
/**
* Gets the FishHook entity associated with the fishing action.
*
* @return The FishHook entity used in the fishing action.
*/
public FishHook getHook() {
return hook;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
/**
* An enumeration representing possible states of the fishing action (REEL_IN, CAUGHT_FISH, BITE).
*/
public enum State {
REEL_IN,
CAUGHT_FISH,
BITE
}
}

View File

@@ -1,103 +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.api.event;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a player casts a fishing rod.
*/
public class RodCastEvent extends PlayerEvent implements Cancellable {
private final Effect effect;
private boolean isCancelled;
private final PlayerFishEvent event;
private final FishingPreparation preparation;
private static final HandlerList handlerList = new HandlerList();
/**
* Constructs a new RodCastEvent.
*
* @param event The original PlayerFishEvent that triggered the rod cast.
* @param fishingPreparation The fishing preparation associated with the rod cast.
* @param effect The effect associated with the fishing rod cast.
*/
public RodCastEvent(PlayerFishEvent event, FishingPreparation fishingPreparation, Effect effect) {
super(event.getPlayer());
this.effect = effect;
this.event = event;
this.preparation = fishingPreparation;
}
@Override
public boolean isCancelled() {
return this.isCancelled;
}
/**
* Cancelling this event would not cancel the bukkit PlayerFishEvent
*
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
this.isCancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlerList;
}
/**
* Gets the fishing preparation associated with the rod cast.
*
* @return The FishingPreparation associated with the rod cast.
*/
public FishingPreparation getPreparation() {
return preparation;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
/**
* Gets the effect associated with the fishing rod cast.
*
* @return The Effect associated with the rod cast.
*/
public Effect getEffect() {
return effect;
}
/**
* Gets the original PlayerFishEvent that triggered the rod cast.
*
* @return The original PlayerFishEvent.
*/
public PlayerFishEvent getBukkitPlayerFishEvent() {
return event;
}
}

View File

@@ -1,87 +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.api.event;
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a player activates a totem.
*/
public class TotemActivateEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final Location coreLocation;
private boolean isCancelled;
private final TotemConfig config;
/**
* Constructs a new TotemActivateEvent.
*
* @param who The player who activated the totem.
* @param location The location of the totem's core.
* @param config The configuration of the totem being activated.
*/
public TotemActivateEvent(@NotNull Player who, Location location, TotemConfig config) {
super(who);
this.coreLocation = location;
this.config = config;
}
/**
* Gets the location of the totem's core.
*
* @return The location of the totem's core.
*/
public Location getCoreLocation() {
return coreLocation;
}
/**
* Gets the configuration of the totem being activated.
*
* @return The TotemConfig of the totem being activated.
*/
public TotemConfig getConfig() {
return config;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
}

View File

@@ -1,45 +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.api.manager;
import java.util.concurrent.CompletableFuture;
public interface VersionManager {
boolean isVersionNewerThan1_19();
boolean isVersionNewerThan1_19_4();
boolean isVersionNewerThan1_19_3();
CompletableFuture<Boolean> checkUpdate();
boolean isVersionNewerThan1_20();
boolean isNewerThan1_20_5();
boolean isSpigot();
public boolean hasRegionScheduler();
String getPluginVersion();
boolean isMojmap();
String getServerVersion();
}

View File

@@ -1,136 +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.api.mechanic;
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.effect.EffectModifier;
import org.bukkit.configuration.ConfigurationSection;
import java.util.HashMap;
import java.util.Map;
/**
* Represents global settings for actions related to fishing, loot, rods, and bait.
*/
public class GlobalSettings {
private static HashMap<ActionTrigger, Action[]> lootActions = new HashMap<>();
private static HashMap<ActionTrigger, Action[]> rodActions = new HashMap<>();
private static HashMap<ActionTrigger, Action[]> baitActions = new HashMap<>();
private static HashMap<ActionTrigger, Action[]> hookActions = new HashMap<>();
private static EffectModifier[] effectModifiers;
/**
* Loads global settings from a configuration section.
*
* @param section The configuration section to load settings from.
*/
public static void loadEvents(ConfigurationSection section) {
if (section == null) return;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection inner) {
HashMap<ActionTrigger, Action[]> map = BukkitCustomFishingPlugin.get().getActionManager().getActionMap(inner);
switch (entry.getKey()) {
case "loot" -> lootActions = map;
case "rod" -> rodActions = map;
case "bait" -> baitActions = map;
case "hook" -> hookActions = map;
}
}
}
}
public static EffectModifier[] getEffectModifiers() {
return effectModifiers;
}
public static void setEffects(EffectModifier[] modifiers) {
effectModifiers = modifiers;
}
/**
* Unloads global settings, clearing all action maps.
*/
public static void unload() {
lootActions.clear();
rodActions.clear();
baitActions.clear();
}
/**
* Triggers loot-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param playerContext The condition that triggered the actions.
*/
public static void triggerLootActions(ActionTrigger trigger, PlayerContext playerContext) {
Action[] actions = lootActions.get(trigger);
if (actions != null) {
for (Action action : actions) {
action.trigger(playerContext);
}
}
}
/**
* Triggers rod-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param playerContext The condition that triggered the actions.
*/
public static void triggerRodActions(ActionTrigger trigger, PlayerContext playerContext) {
Action[] actions = rodActions.get(trigger);
if (actions != null) {
for (Action action : actions) {
action.trigger(playerContext);
}
}
}
/**
* Triggers bait-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param playerContext The condition that triggered the actions.
*/
public static void triggerBaitActions(ActionTrigger trigger, PlayerContext playerContext) {
Action[] actions = baitActions.get(trigger);
if (actions != null) {
for (Action action : actions) {
action.trigger(playerContext);
}
}
}
/**
* Triggers hook-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param playerContext The condition that triggered the actions.
*/
public static void triggerHookActions(ActionTrigger trigger, PlayerContext playerContext) {
Action[] actions = hookActions.get(trigger);
if (actions != null) {
for (Action action : actions) {
action.trigger(playerContext);
}
}
}
}

View File

@@ -1,79 +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.api.mechanic;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
/**
* Represents a temporary state during fishing that includes an effect, preparation, and loot.
*/
public class TempFishingState {
private final Effect effect;
private final FishingPreparation preparation;
private Loot loot;
/**
* Creates a new instance of TempFishingState.
*
* @param effect The effect associated with this state.
* @param preparation The fishing preparation associated with this state.
* @param loot The loot associated with this state.
*/
public TempFishingState(Effect effect, FishingPreparation preparation, Loot loot) {
this.effect = effect;
this.preparation = preparation;
this.loot = loot;
}
/**
* Gets the effect associated with this fishing state.
*
* @return The effect.
*/
public Effect getEffect() {
return effect;
}
/**
* Gets the fishing preparation associated with this fishing state.
*
* @return The fishing preparation.
*/
public FishingPreparation getPreparation() {
return preparation;
}
/**
* Gets the loot associated with this fishing state.
*
* @return The loot.
*/
public Loot getLoot() {
return loot;
}
/**
* Set the loot associated with this fishing state.
*
*/
public void setLoot(Loot loot) {
this.loot = loot;
}
}

View File

@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
public interface ActionManager<T> {
@@ -122,7 +123,13 @@ public interface ActionManager<T> {
* @param actions The list of actions to trigger.
* @param context The context associated with the actions.
*/
static <T> void trigger(@NotNull Context<T> context, @Nullable Action<T>... actions) {
static <T> void trigger(@NotNull Context<T> context, @Nullable List<Action<T>> actions) {
if (actions != null)
for (Action<T> action : actions)
action.trigger(context);
}
static <T> void trigger(@NotNull Context<T> context, @Nullable Action<T>[] actions) {
if (actions != null)
for (Action<T> action : actions)
action.trigger(context);

View File

@@ -18,7 +18,6 @@
package net.momirealms.customfishing.api.mechanic.action;
public enum ActionTrigger {
SUCCESS,
FAILURE,
HOOK,

View File

@@ -1,104 +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.api.mechanic.bag;
import net.momirealms.customfishing.api.data.user.OfflineUser;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import java.util.List;
import java.util.UUID;
public interface BagManager {
/**
* Is bag mechanics enabled
*
* @return enabled or not
*/
boolean isEnabled();
/**
* Retrieves the online bag inventory associated with a player's UUID.
*
* @param uuid The UUID of the player for whom the bag inventory is retrieved.
* @return The online bag inventory if the player is online, or null if not found.
*/
Inventory getOnlineBagInventory(UUID uuid);
/**
* Get the rows of a player's fishing bag
*
* @param player player who owns the bag
* @return rows
*/
int getBagInventoryRows(Player player);
/**
* Initiates the process of editing the bag inventory of an offline player by an admin.
*
* @param admin The admin player performing the edit.
* @param userData The OfflineUser data of the player whose bag is being edited.
*/
void editOfflinePlayerBag(Player admin, OfflineUser userData);
/**
* Get the actions to perform when loot is automatically collected
*
* @return actions
*/
Action[] getCollectLootActions();
/**
* Get the actions to perform when bag is full
*
* @return actions
*/
Action[] getBagFullActions();
/**
* If bag can store fishing loots
*
* @return can store or not
*/
boolean doesBagStoreLoots();
/**
* Get the fishing bag's title
*
* @return title
*/
String getBagTitle();
/**
* Get a list of allowed items in bag
*
* @return whitelisted items
*/
List<Material> getBagWhiteListItems();
/**
* Get the requirements for automatically collecting loots
*
* @return requirements
*/
Requirement[] getCollectRequirements();
}

View File

@@ -1,52 +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.api.mechanic.bag;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class FishingBagHolder implements InventoryHolder {
private final UUID owner;
private Inventory inventory;
public FishingBagHolder(UUID owner) {
this.owner = owner;
}
@Override
public @NotNull Inventory getInventory() {
return inventory;
}
public void setItems(ItemStack[] itemStacks) {
this.inventory.setContents(itemStacks);
}
public UUID getOwner() {
return owner;
}
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
}

View File

@@ -1,103 +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.api.mechanic.block;
import java.util.List;
public class BlockConfig implements BlockSettings {
private String blockID;
private List<BlockDataModifier> dataModifierList;
private List<BlockStateModifier> stateModifierList;
private boolean persist;
private double horizontalVector;
private double verticalVector;
@Override
public String getBlockID() {
return blockID;
}
@Override
public List<BlockDataModifier> getDataModifier() {
return dataModifierList;
}
@Override
public List<BlockStateModifier> getStateModifierList() {
return stateModifierList;
}
@Override
public boolean isPersist() {
return persist;
}
@Override
public double getHorizontalVector() {
return horizontalVector;
}
@Override
public double getVerticalVector() {
return verticalVector;
}
public static class Builder {
private final BlockConfig config;
public Builder() {
this.config = new BlockConfig();
}
public Builder persist(boolean value) {
config.persist = value;
return this;
}
public Builder horizontalVector(double value) {
config.horizontalVector = value;
return this;
}
public Builder verticalVector(double value) {
config.verticalVector = value;
return this;
}
public Builder blockID(String value) {
config.blockID = value;
return this;
}
public Builder dataModifiers(List<BlockDataModifier> value) {
config.dataModifierList = value;
return this;
}
public Builder stateModifiers(List<BlockStateModifier> value) {
config.stateModifierList = value;
return this;
}
public BlockConfig build() {
return config;
}
}
}

View File

@@ -1,26 +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.api.mechanic.block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
public interface BlockDataModifier {
void apply(Player player, BlockData blockData);
}

View File

@@ -1,23 +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.api.mechanic.block;
public interface BlockDataModifierBuilder {
BlockDataModifier build(Object args);
}

View File

@@ -1,35 +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.api.mechanic.block;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface BlockLibrary {
String identification();
BlockData getBlockData(Player player, String id, List<BlockDataModifier> modifiers);
@Nullable
String getBlockID(Block block);
}

View File

@@ -1,102 +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.api.mechanic.block;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public interface BlockManager {
/**
* Registers a BlockLibrary instance.
* This method associates a BlockLibrary with its unique identification and adds it to the registry.
*
* @param blockLibrary The BlockLibrary instance to register.
* @return True if the registration was successful (the identification is not already registered), false otherwise.
*/
boolean registerBlockLibrary(BlockLibrary blockLibrary);
/**
* Unregisters a BlockLibrary instance by its identification.
* This method removes a BlockLibrary from the registry based on its unique identification.
*
* @param identification The unique identification of the BlockLibrary to unregister.
* @return True if the BlockLibrary was successfully unregistered, false if it was not found.
*/
boolean unregisterBlockLibrary(String identification);
/**
* Registers a BlockDataModifierBuilder for a specific type.
* This method associates a BlockDataModifierBuilder with its type and adds it to the registry.
*
* @param type The type of the BlockDataModifierBuilder to register.
* @param builder The BlockDataModifierBuilder instance to register.
* @return True if the registration was successful (the type is not already registered), false otherwise.
*/
boolean registerBlockDataModifierBuilder(String type, BlockDataModifierBuilder builder);
/**
* Registers a BlockStateModifierBuilder for a specific type.
* This method associates a BlockStateModifierBuilder with its type and adds it to the registry.
*
* @param type The type of the BlockStateModifierBuilder to register.
* @param builder The BlockStateModifierBuilder instance to register.
* @return True if the registration was successful (the type is not already registered), false otherwise.
*/
boolean registerBlockStateModifierBuilder(String type, BlockStateModifierBuilder builder);
/**
* Unregisters a BlockDataModifierBuilder with the specified type.
*
* @param type The type of the BlockDataModifierBuilder to unregister.
* @return True if the BlockDataModifierBuilder was successfully unregistered, false otherwise.
*/
boolean unregisterBlockDataModifierBuilder(String type);
/**
* Unregisters a BlockStateModifierBuilder with the specified type.
*
* @param type The type of the BlockStateModifierBuilder to unregister.
* @return True if the BlockStateModifierBuilder was successfully unregistered, false otherwise.
*/
boolean unregisterBlockStateModifierBuilder(String type);
/**
* Summons a falling block at a specified location based on the provided loot.
* This method spawns a falling block at the given hookLocation with specific properties determined by the loot.
*
* @param player The player who triggered the action.
* @param hookLocation The location where the hook is positioned.
* @param playerLocation The location of the player.
* @param loot The loot to be associated with the summoned block.
*/
void summonBlock(Player player, Location hookLocation, Location playerLocation, Loot loot);
/**
* Retrieves the block ID associated with a given Block instance using block detection order.
* This method iterates through the configured block detection order to find the block's ID
* by checking different BlockLibrary instances in the specified order.
*
* @param block The Block instance for which to retrieve the block ID.
* @return The block ID
*/
@NotNull String getAnyPluginBlockID(Block block);
}

View File

@@ -1,34 +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.api.mechanic.block;
import java.util.List;
public interface BlockSettings {
String getBlockID();
List<BlockDataModifier> getDataModifier();
List<BlockStateModifier> getStateModifierList();
boolean isPersist();
double getHorizontalVector();
double getVerticalVector();
}

View File

@@ -1,26 +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.api.mechanic.block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
public interface BlockStateModifier {
void apply(Player player, BlockState blockState);
}

View File

@@ -1,23 +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.api.mechanic.block;
public interface BlockStateModifierBuilder {
BlockStateModifier build(Object args);
}

View File

@@ -7,109 +7,101 @@ 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.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.misc.function.FormatFunction;
import net.momirealms.customfishing.api.mechanic.misc.function.ItemPropertyFunction;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.common.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
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.helper.AdventureHelper;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.util.ListUtils;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
public class BukkitConfigManager implements ConfigManager {
public abstract class ConfigManager implements ConfigLoader {
private final CustomFishingPlugin plugin;
private final HashMap<String, Node<FormatFunction>> formatFunctions = new HashMap<>();
private final HashMap<String, Node<ConfigParserFunction>> formatFunctions = new HashMap<>();
public BukkitConfigManager(CustomFishingPlugin plugin) {
public ConfigManager(CustomFishingPlugin plugin) {
this.plugin = plugin;
this.registerBuiltInItemProperties();
}
private void registerBuiltInItemProperties() {
this.registerItemFunction(arg -> {
MathValue<Player> mathValue = MathValue.auto(arg);
return (item, context) -> item.customModelData((int) mathValue.evaluate(context));
}, 4000, "custom-model-data");
this.registerItemFunction(arg -> {
TextValue<Player> textValue = TextValue.auto((String) arg);
return (item, context) -> {
item.displayName(AdventureHelper.miniMessageToJson(textValue.render(context)));
};
}, 3000, "display", "name");
this.registerItemFunction(arg -> {
List<String> list = ListUtils.toList(arg);
List<TextValue<Player>> lore = new ArrayList<>();
for (String text : list) {
lore.add(TextValue.auto(text));
}
return (item, context) -> {
item.lore(lore.stream()
.map(it -> AdventureHelper.miniMessageToJson(it.render(context)))
.toList());
};
}, 2000, "display", "lore");
this.registerItemFunction(arg -> {
boolean enable = (boolean) arg;
return (item, context) -> {
if (!enable) return;
item.setTag(context.arg(ContextKeys.ID), "CustomFishing", "id");
item.setTag(context.arg(ContextKeys.TYPE), "CustomFishing", "type");
};
}, 1000, "tag");
public void registerLootParser(Function<Object, Consumer<Loot.Builder>> function, String... nodes) {
registerNodeFunction(nodes, new LootParserFunction(function));
}
private void registerItemFunction(Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function, int priority, String... nodes) {
registerNodeFunction(nodes, new ItemPropertyFunction(priority, function));
public void registerBaseEffectParser(Function<Object, Consumer<LootBaseEffect.Builder>> function, String... nodes) {
registerNodeFunction(nodes, new BaseEffectParserFunction(function));
}
public void registerNodeFunction(String[] nodes, FormatFunction formatFunction) {
Map<String, Node<FormatFunction>> functionMap = formatFunctions;
public void registerItemParser(Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function, int priority, String... nodes) {
registerNodeFunction(nodes, new ItemParserFunction(priority, function));
}
public void registerEffectModifierParser(Function<Object, Consumer<Effect>> function, String... nodes) {
registerNodeFunction(nodes, new EffectModifierParserFunction(function));
}
public void unregisterNodeFunction(String... nodes) {
Map<String, Node<ConfigParserFunction>> functionMap = formatFunctions;
for (int i = 0; i < nodes.length; i++) {
if (functionMap.containsKey(nodes[i])) {
Node<FormatFunction> functionNode = functionMap.get(nodes[i]);
Node<ConfigParserFunction> functionNode = functionMap.get(nodes[i]);
if (i != nodes.length - 1) {
if (functionNode.nodeValue() != null) {
return;
} else {
functionMap = functionNode.getChildTree();
}
} else {
if (functionNode.nodeValue() != null) {
functionMap.remove(nodes[i]);
}
}
}
}
}
public void registerNodeFunction(String[] nodes, ConfigParserFunction configParserFunction) {
Map<String, Node<ConfigParserFunction>> functionMap = formatFunctions;
for (int i = 0; i < nodes.length; i++) {
if (functionMap.containsKey(nodes[i])) {
Node<ConfigParserFunction> functionNode = functionMap.get(nodes[i]);
if (functionNode.nodeValue() != null) {
throw new IllegalArgumentException("Format function '" + nodes[i] + "' already exists");
}
functionMap = functionNode.getChildTree();
} else {
if (i != nodes.length - 1) {
Node<FormatFunction> newNode = new Node<>();
Node<ConfigParserFunction> newNode = new Node<>();
functionMap.put(nodes[i], newNode);
functionMap = newNode.getChildTree();
} else {
functionMap.put(nodes[i], new Node<>(formatFunction));
functionMap.put(nodes[i], new Node<>(configParserFunction));
}
}
}
}
protected Path resolveConfig(String filePath) {
if (filePath == null || filePath.equals("")) {
if (filePath == null || filePath.isEmpty()) {
throw new IllegalArgumentException("ResourcePath cannot be null or empty");
}
filePath = filePath.replace('\\', '/');
Path configFile = plugin.getConfigDirectory().resolve(filePath);
// if the config doesn't exist, create it based on the template in the resources dir
if (!Files.exists(configFile)) {
try {
@@ -117,19 +109,15 @@ public class BukkitConfigManager implements ConfigManager {
} catch (IOException e) {
// ignore
}
try (InputStream is = plugin.getResourceStream(filePath)) {
if (is == null) {
throw new IllegalArgumentException("The embedded resource '" + filePath + "' cannot be found");
}
Files.copy(is, configFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return configFile;
}
@@ -157,7 +145,27 @@ public class BukkitConfigManager implements ConfigManager {
);
} catch (IOException e) {
plugin.getPluginLogger().severe("Failed to load config " + filePath, e);
return null;
throw new RuntimeException(e);
}
}
@Override
public YamlDocument loadData(File file) {
try {
return YamlDocument.create(file);
} catch (IOException e) {
plugin.getPluginLogger().severe("Failed to load config " + file, e);
throw new RuntimeException(e);
}
}
@Override
public YamlDocument loadData(File file, char routeSeparator) {
try {
return YamlDocument.create(file, GeneralSettings.builder().setRouteSeparator(routeSeparator).build());
} catch (IOException e) {
plugin.getPluginLogger().severe("Failed to load config " + file, e);
throw new RuntimeException(e);
}
}
}

View File

@@ -1,62 +0,0 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.misc.function.FormatFunction;
import net.momirealms.customfishing.api.mechanic.misc.function.ItemPropertyFunction;
import net.momirealms.customfishing.api.mechanic.misc.function.PriorityFunction;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
public class ItemConfig {
private final String id;
private final String material;
private final List<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
public ItemConfig(String id, Section section, Map<String, Node<FormatFunction>> functionMap) {
this.id = id;
this.material = section.getString("material");
analyze(section, functionMap);
}
private void analyze(Section section, Map<String, Node<FormatFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<FormatFunction> node = functionMap.get(key);
if (node == null) continue;
FormatFunction function = node.nodeValue();
if (function != null) {
if (function instanceof ItemPropertyFunction propertyFunction) {
BiConsumer<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(, result));
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public Key key() {
return Key.of("item", id);
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.tagConsumers(tagConsumers)
.build();
}
}

View File

@@ -0,0 +1,99 @@
package net.momirealms.customfishing.api.mechanic.config;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ItemLootConfig {
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<>();
public ItemLootConfig(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 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 -> {
}
}
continue;
}
if (entry.getValue() instanceof Section innerSection) {
analyze(innerSection, node.getChildTree());
}
}
}
public Key key() {
return Key.of("item", id);
}
public CustomFishingItem getItem() {
return CustomFishingItem.builder()
.material(material)
.tagConsumers(tagConsumers)
.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();
builder.id(id);
builder.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.context;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -39,8 +40,26 @@ public interface Context<T> {
*/
Map<ContextKeys<?>, Object> args();
/**
* Adds or updates an argument in the context.
* This method allows adding a new argument or updating the value of an existing argument.
*
* @param <C> the type of the value being added to the context.
* @param key the ContextKeys key representing the argument to be added or updated.
* @param value the value to be associated with the specified key.
* @return the current context instance, allowing for method chaining.
*/
<C> Context<T> arg(ContextKeys<C> key, C value);
/**
* Retrieves the value of a specific argument from the context.
* This method fetches the value associated with the specified ContextKeys key.
*
* @param <C> the type of the value being retrieved.
* @param key the ContextKeys key representing the argument to be retrieved.
* @return the value associated with the specified key, or null if the key does not exist.
*/
@Nullable
<C> C arg(ContextKeys<C> key);
/**

View File

@@ -30,6 +30,8 @@ public class ContextKeys<T> {
public static final ContextKeys<String> WORLD = of("world", String.class);
public static final ContextKeys<String> ID = of("id", String.class);
public static final ContextKeys<String> TYPE = of("type", String.class);
public static final ContextKeys<Float> SIZE = of("size", Float.class);
public static final ContextKeys<Double> PRICE = of("price", Double.class);
private final String key;
private final Class<T> type;

View File

@@ -1,36 +0,0 @@
package net.momirealms.customfishing.api.mechanic.effect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import org.bukkit.entity.Player;
import java.util.Map;
public class BaseEffect {
private final MathValue<Player> waitTime;
private final MathValue<Player> waitTimeMultiplier;
private final MathValue<Player> difficulty;
private final MathValue<Player> difficultyMultiplier;
private final MathValue<Player> gameTime;
private final MathValue<Player> gameTimeMultiplier;
public BaseEffect(MathValue<Player> waitTime, MathValue<Player> waitTimeMultiplier, MathValue<Player> difficulty, MathValue difficultyMultiplier, MathValue gameTime, MathValue gameTimeMultiplier) {
this.waitTime = waitTime;
this.waitTimeMultiplier = waitTimeMultiplier;
this.difficulty = difficulty;
this.difficultyMultiplier = difficultyMultiplier;
this.gameTime = gameTime;
this.gameTimeMultiplier = gameTimeMultiplier;
}
public Effect build(Player player, Map<String, String> values) {
return new FishingEffect(
waitTime.get(player, values),
waitTimeMultiplier.get(player, values),
difficulty.get(player, values),
difficultyMultiplier.get(player, values),
gameTime.get(player, values),
gameTimeMultiplier.get(player, values)
);
}
}

View File

@@ -21,41 +21,248 @@ import net.momirealms.customfishing.common.util.Pair;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
/**
* Represents an effect applied in the custom fishing mechanic.
*/
public interface Effect {
boolean allowLavaFishing();
/**
* Retrieves the properties of this effect.
*
* @return a map of effect properties and their values
*/
Map<EffectProperties<?>, Object> properties();
/**
* Sets the specified property to the given value.
*
* @param key the property key
* @param value the property value
* @param <C> the type of the property value
* @return the effect instance with the updated property
*/
<C> EffectImpl arg(EffectProperties<C> key, C value);
/**
* Retrieves the value of the specified property.
*
* @param key the property key
* @param <C> the type of the property value
* @return the value of the specified property
*/
<C> C arg(EffectProperties<C> key);
/**
* Gets the chance of multiple loots.
*
* @return the multiple loot chance
*/
double multipleLootChance();
/**
* Sets the chance of multiple loots.
*
* @param multipleLootChance the new multiple loot chance
* @return the effect instance with the updated multiple loot chance
*/
Effect multipleLootChance(double multipleLootChance);
/**
* Gets the size adder.
*
* @return the size adder
*/
double sizeAdder();
/**
* Sets the size adder.
*
* @param sizeAdder the new size adder
* @return the effect instance with the updated size adder
*/
Effect sizeAdder(double sizeAdder);
/**
* Gets the size multiplier.
*
* @return the size multiplier
*/
double sizeMultiplier();
/**
* Sets the size multiplier.
*
* @param sizeMultiplier the new size multiplier
* @return the effect instance with the updated size multiplier
*/
Effect sizeMultiplier(double sizeMultiplier);
/**
* Gets the score adder.
*
* @return the score adder
*/
double scoreAdder();
/**
* Sets the score adder.
*
* @param scoreAdder the new score adder
* @return the effect instance with the updated score adder
*/
Effect scoreAdder(double scoreAdder);
/**
* Gets the score multiplier.
*
* @return the score multiplier
*/
double scoreMultiplier();
/**
* Sets the score multiplier.
*
* @param scoreMultiplier the new score multiplier
* @return the effect instance with the updated score multiplier
*/
Effect scoreMultiplier(double scoreMultiplier);
/**
* Gets the wait time adder.
*
* @return the wait time adder
*/
double waitTimeAdder();
double getWaitTimeMultiplier();
/**
* Sets the wait time adder.
*
* @param waitTimeAdder the new wait time adder
* @return the effect instance with the updated wait time adder
*/
Effect waitTimeAdder(double waitTimeAdder);
/**
* Gets the wait time multiplier.
*
* @return the wait time multiplier
*/
double waitTimeMultiplier();
/**
* Sets the wait time multiplier.
*
* @param waitTimeMultiplier the new wait time multiplier
* @return the effect instance with the updated wait time multiplier
*/
Effect waitTimeMultiplier(double waitTimeMultiplier);
/**
* Gets the game time adder.
*
* @return the game time adder
*/
double gameTimeAdder();
/**
* Sets the game time adder.
*
* @param gameTimeAdder the new game time adder
* @return the effect instance with the updated game time adder
*/
Effect gameTimeAdder(double gameTimeAdder);
/**
* Gets the game time multiplier.
*
* @return the game time multiplier
*/
double gameTimeMultiplier();
/**
* Sets the game time multiplier.
*
* @param gameTimeMultiplier the new game time multiplier
* @return the effect instance with the updated game time multiplier
*/
Effect gameTimeMultiplier(double gameTimeMultiplier);
/**
* Gets the difficulty adder.
*
* @return the difficulty adder
*/
double difficultyAdder();
/**
* Sets the difficulty adder.
*
* @param difficultyAdder the new difficulty adder
* @return the effect instance with the updated difficulty adder
*/
Effect difficultyAdder(double difficultyAdder);
/**
* Gets the difficulty multiplier.
*
* @return the difficulty multiplier
*/
double difficultyMultiplier();
List<Pair<String, BiFunction<Player, Double, Double>>> weightModifier();
/**
* Sets the difficulty multiplier.
*
* @param difficultyMultiplier the new difficulty multiplier
* @return the effect instance with the updated difficulty multiplier
*/
Effect difficultyMultiplier(double difficultyMultiplier);
List<Pair<String, BiFunction<Player, Double, Double>>> weightModifierIgnored();
/**
* Gets the list of weight operations.
*
* @return the list of weight operations
*/
List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations();
void merge(Effect effect);
/**
* Adds the list of weight operations.
*
* @param weightOperations the list of weight operations to add
* @return the effect instance with the updated weight operations
*/
Effect weightOperations(List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations);
interface Builder {
/**
* Gets the list of weight operations that are conditions ignored.
*
* @return the list of weight operations that are conditions ignored
*/
List<Pair<String, BiFunction<Player, Double, Double>>> weightOperationsIgnored();
/**
* Adds the list of weight operations that are conditions ignored.
*
* @param weightOperations the list of weight operations that are conditions ignored
* @return the effect instance with the updated ignored weight operations
*/
Effect weightOperationsIgnored(List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations);
/**
* Combines this effect with another effect.
*
* @param effect the effect to combine with
*/
void combine(Effect effect);
/**
* Creates a new instance of {@link Effect}.
*
* @return a new {@link Effect} instance
*/
static Effect newInstance() {
return new EffectImpl();
}
}

View File

@@ -1,113 +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.api.mechanic.effect;
import net.kyori.adventure.key.Key;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class EffectCarrier {
private Key key;
private Requirement[] requirements;
private EffectModifier[] effect;
private Map<ActionTrigger, Action[]> actionMap;
private boolean persist;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final EffectCarrier item;
public Builder() {
this.item = new EffectCarrier();
}
public Builder persist(boolean persist) {
item.persist = persist;
return this;
}
public Builder key(Key key) {
item.key = key;
return this;
}
public Builder requirements(Requirement[] requirements) {
item.requirements = requirements;
return this;
}
public Builder effect(EffectModifier[] effect) {
item.effect = effect;
return this;
}
public Builder actionMap(Map<ActionTrigger, Action[]> actionMap) {
item.actionMap = actionMap;
return this;
}
public EffectCarrier build() {
return item;
}
}
public Key getKey() {
return key;
}
public Requirement[] getRequirements() {
return requirements;
}
public EffectModifier[] getEffectModifiers() {
return effect;
}
public Map<ActionTrigger, Action[]> getActionMap() {
return actionMap;
}
@Nullable
public Action[] getActions(ActionTrigger trigger) {
return actionMap.get(trigger);
}
public boolean isPersist() {
return persist;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isConditionMet(PlayerContext playerContext) {
if (requirements == null) return true;
for (Requirement requirement : requirements) {
if (!requirement.check(playerContext)) {
return false;
}
}
return true;
}
}

View File

@@ -1,4 +1,207 @@
package net.momirealms.customfishing.api.mechanic.effect;
public class EffectImpl {
import net.momirealms.customfishing.common.util.Pair;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
public class EffectImpl implements Effect {
private final HashMap<EffectProperties<?>, Object> properties = new HashMap<>();
private double multipleLootChance = 0;
private double sizeAdder = 0;
private double sizeMultiplier = 1;
private double scoreAdder = 0;
private double scoreMultiplier = 1;
private double gameTimeAdder = 0;
private double gameTimeMultiplier = 1;
private double waitTimeAdder = 0;
private double waitTimeMultiplier = 1;
private double difficultyAdder = 0;
private double difficultyMultiplier = 1;
private final List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations = new ArrayList<>();
private final List<Pair<String, BiFunction<Player, Double, Double>>> weightOperationsIgnored = new ArrayList<>();
@Override
public Map<EffectProperties<?>, Object> properties() {
return properties;
}
@Override
public <C> EffectImpl arg(EffectProperties<C> key, C value) {
properties.put(key, value);
return this;
}
@Override
@SuppressWarnings("unchecked")
public <C> C arg(EffectProperties<C> key) {
return (C) properties.get(key);
}
@Override
public double multipleLootChance() {
return multipleLootChance;
}
@Override
public Effect multipleLootChance(double multipleLootChance) {
this.multipleLootChance = multipleLootChance;
return this;
}
@Override
public double sizeAdder() {
return sizeAdder;
}
@Override
public Effect sizeAdder(double sizeAdder) {
this.sizeAdder = sizeAdder;
return this;
}
@Override
public double sizeMultiplier() {
return sizeMultiplier;
}
@Override
public Effect sizeMultiplier(double sizeMultiplier) {
this.sizeMultiplier = sizeMultiplier;
return this;
}
@Override
public double scoreAdder() {
return scoreAdder;
}
@Override
public Effect scoreAdder(double scoreAdder) {
this.scoreAdder = scoreAdder;
return this;
}
@Override
public double scoreMultiplier() {
return scoreMultiplier;
}
@Override
public Effect scoreMultiplier(double scoreMultiplier) {
this.scoreMultiplier = scoreMultiplier;
return this;
}
@Override
public double waitTimeAdder() {
return waitTimeAdder;
}
@Override
public Effect waitTimeAdder(double waitTimeAdder) {
this.waitTimeAdder = waitTimeAdder;
return this;
}
@Override
public double waitTimeMultiplier() {
return waitTimeMultiplier;
}
@Override
public Effect waitTimeMultiplier(double waitTimeMultiplier) {
this.waitTimeMultiplier = waitTimeMultiplier;
return this;
}
@Override
public double gameTimeAdder() {
return gameTimeAdder;
}
@Override
public Effect gameTimeAdder(double gameTimeAdder) {
this.gameTimeAdder = gameTimeAdder;
return this;
}
@Override
public double gameTimeMultiplier() {
return gameTimeMultiplier;
}
@Override
public Effect gameTimeMultiplier(double gameTimeMultiplier) {
this.gameTimeMultiplier = gameTimeMultiplier;
return this;
}
@Override
public double difficultyAdder() {
return difficultyAdder;
}
@Override
public Effect difficultyAdder(double difficultyAdder) {
this.difficultyAdder = difficultyAdder;
return this;
}
@Override
public double difficultyMultiplier() {
return difficultyMultiplier;
}
@Override
public Effect difficultyMultiplier(double difficultyMultiplier) {
this.difficultyMultiplier = difficultyMultiplier;
return this;
}
@Override
public List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations() {
return weightOperations;
}
@Override
public Effect weightOperations(List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations) {
this.weightOperations.addAll(weightOperations);
return this;
}
@Override
public List<Pair<String, BiFunction<Player, Double, Double>>> weightOperationsIgnored() {
return weightOperationsIgnored;
}
@Override
public Effect weightOperationsIgnored(List<Pair<String, BiFunction<Player, Double, Double>>> weightOperations) {
this.weightOperationsIgnored.addAll(weightOperations);
return this;
}
@Override
public void combine(Effect another) {
if (another == null) return;
this.scoreMultiplier += (another.scoreMultiplier() -1);
this.scoreAdder += another.scoreAdder();
this.sizeMultiplier += (another.sizeMultiplier() -1);
this.sizeAdder += another.sizeAdder();
this.difficultyMultiplier += (another.difficultyMultiplier() -1);
this.difficultyAdder += another.difficultyAdder();
this.gameTimeMultiplier += (another.gameTimeMultiplier() - 1);
this.gameTimeAdder += another.gameTimeAdder();
this.waitTimeAdder += (another.waitTimeAdder() -1);
this.waitTimeMultiplier += (another.waitTimeMultiplier() -1);
this.multipleLootChance += another.multipleLootChance();
this.weightOperations.addAll(another.weightOperations());
this.weightOperationsIgnored.addAll(another.weightOperationsIgnored());
this.properties.putAll(another.properties());
}
}

View File

@@ -1,111 +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.api.mechanic.effect;
import net.kyori.adventure.key.Key;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface EffectManager {
/**
* Registers an EffectCarrier with a unique Key.
*
* @param key The unique Key associated with the EffectCarrier.
* @param effect The EffectCarrier to be registered.
* @return True if the registration was successful, false if the Key already exists.
*/
boolean registerEffectCarrier(Key key, EffectCarrier effect);
/**
* Unregisters an EffectCarrier associated with the specified Key.
*
* @param key The unique Key of the EffectCarrier to unregister.
* @return True if the EffectCarrier was successfully unregistered, false if the Key does not exist.
*/
boolean unregisterEffectCarrier(Key key);
/**
* Checks if an EffectCarrier with the specified namespace and id exists.
*
* @param namespace The namespace of the EffectCarrier.
* @param id The unique identifier of the EffectCarrier.
* @return True if an EffectCarrier with the given namespace and id exists, false otherwise.
*/
boolean hasEffectCarrier(String namespace, String id);
/**
* Retrieves an EffectCarrier with the specified namespace and id.
*
* @param namespace The namespace of the EffectCarrier.
* @param id The unique identifier of the EffectCarrier.
* @return The EffectCarrier with the given namespace and id, or null if it doesn't exist.
*/
@Nullable EffectCarrier getEffectCarrier(String namespace, String id);
/**
* Parses a ConfigurationSection to create an EffectCarrier based on the specified key and configuration.
* <p>
* xxx_item: <- section
* effects:
* ...
* events:
* ...
*
* @param key The key that uniquely identifies the EffectCarrier.
* @param section The ConfigurationSection containing the EffectCarrier configuration.
* @return An EffectCarrier instance based on the key and configuration, or null if the section is null.
*/
EffectCarrier getEffectCarrierFromSection(Key key, ConfigurationSection section);
/**
* Retrieves the initial FishingEffect that represents no special effects.
*
* @return The initial FishingEffect.
*/
@NotNull FishingEffect getInitialEffect();
/**
* Parses a ConfigurationSection to retrieve an array of EffectModifiers.
* <p>
* effects: <- section
* effect_1:
* type: xxx
* value: xxx
*
* @param section The ConfigurationSection to parse.
* @return An array of EffectModifiers based on the values found in the section.
*/
@NotNull EffectModifier[] getEffectModifiers(ConfigurationSection section);
BaseEffect getBaseEffect(ConfigurationSection section);
/**
* Parses a ConfigurationSection to create an EffectModifier based on the specified type and configuration.
* <p>
* effects:
* effect_1: <- section
* type: xxx
* value: xxx
*
* @param section The ConfigurationSection containing the effect modifier configuration.
* @return An EffectModifier instance based on the type and configuration.
*/
@Nullable EffectModifier getEffectModifier(ConfigurationSection section);
}

View File

@@ -1,26 +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.api.mechanic.effect;
import net.momirealms.customfishing.api.mechanic.context.Context;
import org.bukkit.entity.Player;
public interface EffectModifier {
void modify(FishingEffect effect, Context<Player> playerContext);
}

View File

@@ -0,0 +1,63 @@
/*
* 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.api.mechanic.effect;
import java.util.Objects;
public class EffectProperties<T> {
public static final EffectProperties<Boolean> LAVA_FISHING = of("lava", Boolean.class);
public static final EffectProperties<Boolean> VOID_FISHING = of("void", Boolean.class);
private final String key;
private final Class<T> type;
private EffectProperties(String key, Class<T> type) {
this.key = key;
this.type = type;
}
public String key() {
return key;
}
public Class<T> type() {
return type;
}
public static <T> EffectProperties<T> of(String key, Class<T> type) {
return new EffectProperties<T>(key, type);
}
@Override
public final boolean equals(final Object other) {
if (this == other) {
return true;
} else if (other != null && this.getClass() == other.getClass()) {
EffectProperties<?> that = (EffectProperties) other;
return Objects.equals(this.key, that.key);
} else {
return false;
}
}
@Override
public final int hashCode() {
return Objects.hashCode(this.key);
}
}

View File

@@ -1,372 +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.api.mechanic.effect;
import net.momirealms.customfishing.api.common.Pair;
import java.util.ArrayList;
import java.util.List;
public class FishingEffect implements Effect {
private boolean lavaFishing = false;
private double multipleLootChance = 0;
private double waitTime = 0;
private double waitTimeMultiplier = 1;
private double size = 0;
private double sizeMultiplier = 1;
private double score = 0;
private double scoreMultiplier = 1;
private double difficulty = 0;
private double difficultyMultiplier = 1;
private double gameTime = 0;
private double gameTimeMultiplier = 1;
private final List<Pair<String, WeightModifier>> weightModifier = new ArrayList<>();
private final List<Pair<String, WeightModifier>> weightModifierIgnored = new ArrayList<>();
public FishingEffect(double waitTime, double waitTimeMultiplier, double difficulty, double difficultyMultiplier, double gameTime, double gameTimeMultiplier) {
this.waitTime = waitTime;
this.waitTimeMultiplier = waitTimeMultiplier;
this.difficulty = difficulty;
this.difficultyMultiplier = difficultyMultiplier;
this.gameTime = gameTime;
this.gameTimeMultiplier = gameTimeMultiplier;
}
public FishingEffect() {
}
/**
* Sets whether lava fishing is enabled.
*
* @param lavaFishing True if lava fishing is enabled, false otherwise.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setLavaFishing(boolean lavaFishing) {
this.lavaFishing = lavaFishing;
return this;
}
/**
* Sets the multiple loot chance.
*
* @param multipleLootChance The multiple loot chance value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setMultipleLootChance(double multipleLootChance) {
this.multipleLootChance = multipleLootChance;
return this;
}
/**
* Sets the size multiplier.
*
* @param sizeMultiplier The size multiplier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setSizeMultiplier(double sizeMultiplier) {
this.sizeMultiplier = sizeMultiplier;
return this;
}
/**
* Sets the size.
*
* @param size The size value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setSize(double size) {
this.size = size;
return this;
}
/**
* Sets the score multiplier.
*
* @param scoreMultiplier The score multiplier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setScoreMultiplier(double scoreMultiplier) {
this.scoreMultiplier = scoreMultiplier;
return this;
}
/**
* Sets the score
*
* @param score The score value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setScore(double score) {
this.score = score;
return this;
}
/**
* Sets the wait time multiplier.
*
* @param timeMultiplier The wait time multiplier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setWaitTimeMultiplier(double timeMultiplier) {
this.waitTimeMultiplier = timeMultiplier;
return this;
}
/**
* Sets the wait time.
*
* @param waitTime The wait time value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setWaitTime(double waitTime) {
this.waitTime = waitTime;
return this;
}
/**
* Sets the difficulty.
*
* @param difficulty The difficulty value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setDifficulty(double difficulty) {
this.difficulty = difficulty;
return this;
}
/**
* Sets the difficulty multiplier.
*
* @param difficultyMultiplier The difficulty multiplier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setDifficultyMultiplier(double difficultyMultiplier) {
this.difficultyMultiplier = difficultyMultiplier;
return this;
}
/**
* Sets the game time.
*
* @param gameTime The game time value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setGameTime(double gameTime) {
this.gameTime = gameTime;
return this;
}
/**
* Sets the game time multiplier.
*
* @param gameTimeMultiplier The game time multiplier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setGameTimeMultiplier(double gameTimeMultiplier) {
this.gameTimeMultiplier = gameTimeMultiplier;
return this;
}
/**
* Adds weight modifiers to the FishingEffect.
*
* @param weightModifier A list of pairs representing weight modifiers to add.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect addWeightModifier(List<Pair<String, WeightModifier>> weightModifier) {
this.weightModifier.addAll(weightModifier);
return this;
}
/**
* Adds ignored weight modifiers to the FishingEffect.
*
* @param weightModifierIgnored A list of pairs representing ignored weight modifiers to add.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect addWeightModifierIgnored(List<Pair<String, WeightModifier>> weightModifierIgnored) {
this.weightModifierIgnored.addAll(weightModifierIgnored);
return this;
}
/**
* Checks if lava fishing is enabled.
*
* @return True if lava fishing is enabled, false otherwise.
*/
@Override
public boolean allowLavaFishing() {
return lavaFishing;
}
/**
* Retrieves the multiple loot chance.
*
* @return The multiple loot chance value.
*/
@Override
public double multipleLootChance() {
return multipleLootChance;
}
/**
* Retrieves the size multiplier.
*
* @return The size multiplier value.
*/
@Override
public double sizeMultiplier() {
return sizeMultiplier;
}
/**
* Retrieves the size.
*
* @return The size value.
*/
@Override
public double sizeAdder() {
return size;
}
/**
* Retrieves the score multiplier.
*
* @return The score multiplier value.
*/
@Override
public double scoreMultiplier() {
return scoreMultiplier;
}
/**
* Retrieves the wait time multiplier.
*
* @return The wait time multiplier value.
*/
@Override
public double getWaitTimeMultiplier() {
return waitTimeMultiplier;
}
/**
* Retrieves the wait time.
*
* @return The wait time .
*/
@Override
public double waitTimeAdder() {
return waitTime;
}
/**
* Retrieves the game time.
*
* @return The game time value.
*/
@Override
public double gameTimeAdder() {
return gameTime;
}
/**
* Retrieves the game time multiplier.
*
* @return The game time value multiplier.
*/
@Override
public double gameTimeMultiplier() {
return gameTimeMultiplier;
}
/**
* Retrieves score modifier.
*
* @return The score value.
*/
@Override
public double scoreAdder() {
return score;
}
/**
* Retrieves the difficulty.
*
* @return The difficulty value.
*/
@Override
public double difficultyAdder() {
return difficulty;
}
/**
* Retrieves the difficulty multiplier.
*
* @return The difficulty multiplier value.
*/
@Override
public double difficultyMultiplier() {
return difficultyMultiplier;
}
/**
* Retrieves the list of weight modifiers.
*
* @return The list of weight modifiers.
*/
@Override
public List<Pair<String, WeightModifier>> weightModifier() {
return weightModifier;
}
/**
* Retrieves the list of weight modifiers ignoring conditions.
*
* @return The list of weight modifiers ignoring conditions.
*/
@Override
public List<Pair<String, WeightModifier>> weightModifierIgnored() {
return weightModifierIgnored;
}
/**
* Merges another Effect into this FishingEffect, combining their properties.
*
* @param another The Effect to merge into this FishingEffect.
*/
@Override
public void merge(Effect another) {
if (another == null) return;
if (another.allowLavaFishing()) this.lavaFishing = true;
this.scoreMultiplier += (another.scoreMultiplier() -1);
this.score += another.scoreAdder();
this.sizeMultiplier += (another.sizeMultiplier() -1);
this.size += another.sizeAdder();
this.difficultyMultiplier += (another.difficultyMultiplier() -1);
this.difficulty += another.difficultyAdder();
this.gameTimeMultiplier += (another.gameTimeMultiplier() - 1);
this.gameTime += another.gameTimeAdder();
this.waitTimeMultiplier += (another.getWaitTimeMultiplier() -1);
this.multipleLootChance += another.multipleLootChance();
this.weightModifierIgnored.addAll(another.weightModifierIgnored());
this.weightModifier.addAll(another.weightModifier());
}
}

View File

@@ -0,0 +1,129 @@
package net.momirealms.customfishing.api.mechanic.effect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import org.bukkit.entity.Player;
/**
* Represents the base effect applied to loot in the custom fishing mechanic.
*/
public interface LootBaseEffect {
MathValue<Player> DEFAULT_WAIT_TIME_ADDER = MathValue.plain(0);
MathValue<Player> DEFAULT_WAIT_TIME_MULTIPLIER = MathValue.plain(1);
MathValue<Player> DEFAULT_DIFFICULTY_ADDER = MathValue.plain(0);
MathValue<Player> DEFAULT_DIFFICULTY_MULTIPLIER = MathValue.plain(1);
MathValue<Player> DEFAULT_GAME_TIME_ADDER = MathValue.plain(0);
MathValue<Player> DEFAULT_GAME_TIME_MULTIPLIER = MathValue.plain(1);
/**
* Gets the adder value for wait time.
*
* @return the wait time adder value
*/
MathValue<Player> waitTimeAdder();
/**
* Gets the multiplier value for wait time.
*
* @return the wait time multiplier value
*/
MathValue<Player> waitTimeMultiplier();
/**
* Gets the adder value for difficulty.
*
* @return the difficulty adder value
*/
MathValue<Player> difficultyAdder();
/**
* Gets the multiplier value for difficulty.
*
* @return the difficulty multiplier value
*/
MathValue<Player> difficultyMultiplier();
/**
* Gets the adder value for game time.
*
* @return the game time adder value
*/
MathValue<Player> gameTimeAdder();
/**
* Gets the multiplier value for game time.
*
* @return the game time multiplier value
*/
MathValue<Player> gameTimeMultiplier();
/**
* Creates a new {@link Builder} instance for constructing {@link LootBaseEffect} objects.
*
* @return a new {@link Builder} instance
*/
static Builder builder() {
return new LootBaseEffectImpl.BuilderImpl();
}
/**
* Builder interface for constructing {@link LootBaseEffect} instances.
*/
interface Builder {
/**
* Sets the adder value for wait time.
*
* @param waitTimeAdder the wait time adder value
* @return the builder instance
*/
Builder waitTimeAdder(MathValue<Player> waitTimeAdder);
/**
* Sets the multiplier value for wait time.
*
* @param waitTimeMultiplier the wait time multiplier value
* @return the builder instance
*/
Builder waitTimeMultiplier(MathValue<Player> waitTimeMultiplier);
/**
* Sets the adder value for difficulty.
*
* @param difficultyAdder the difficulty adder value
* @return the builder instance
*/
Builder difficultyAdder(MathValue<Player> difficultyAdder);
/**
* Sets the multiplier value for difficulty.
*
* @param difficultyMultiplier the difficulty multiplier value
* @return the builder instance
*/
Builder difficultyMultiplier(MathValue<Player> difficultyMultiplier);
/**
* Sets the adder value for game time.
*
* @param gameTimeAdder the game time adder value
* @return the builder instance
*/
Builder gameTimeAdder(MathValue<Player> gameTimeAdder);
/**
* Sets the multiplier value for game time.
*
* @param gameTimeMultiplier the game time multiplier value
* @return the builder instance
*/
Builder gameTimeMultiplier(MathValue<Player> gameTimeMultiplier);
/**
* Builds and returns the {@link LootBaseEffect} instance.
*
* @return the built {@link LootBaseEffect} instance
*/
LootBaseEffect build();
}
}

View File

@@ -0,0 +1,103 @@
package net.momirealms.customfishing.api.mechanic.effect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import org.bukkit.entity.Player;
public class LootBaseEffectImpl implements LootBaseEffect {
private final MathValue<Player> waitTimeAdder;
private final MathValue<Player> waitTimeMultiplier;
private final MathValue<Player> difficultyAdder;
private final MathValue<Player> difficultyMultiplier;
private final MathValue<Player> gameTimeAdder;
private final MathValue<Player> gameTimeMultiplier;
public LootBaseEffectImpl(
MathValue<Player> waitTimeAdder,
MathValue<Player> waitTimeMultiplier,
MathValue<Player> difficultyAdder,
MathValue<Player> difficultyMultiplier,
MathValue<Player> gameTimeAdder,
MathValue<Player> gameTimeMultiplier
) {
this.waitTimeAdder = waitTimeAdder;
this.waitTimeMultiplier = waitTimeMultiplier;
this.difficultyAdder = difficultyAdder;
this.difficultyMultiplier = difficultyMultiplier;
this.gameTimeAdder = gameTimeAdder;
this.gameTimeMultiplier = gameTimeMultiplier;
}
@Override
public MathValue<Player> waitTimeAdder() {
return waitTimeAdder;
}
@Override
public MathValue<Player> waitTimeMultiplier() {
return waitTimeMultiplier;
}
@Override
public MathValue<Player> difficultyAdder() {
return difficultyAdder;
}
@Override
public MathValue<Player> difficultyMultiplier() {
return difficultyMultiplier;
}
@Override
public MathValue<Player> gameTimeAdder() {
return gameTimeAdder;
}
@Override
public MathValue<Player> gameTimeMultiplier() {
return gameTimeMultiplier;
}
public static class BuilderImpl implements Builder {
private MathValue<Player> waitTimeAdder = DEFAULT_WAIT_TIME_ADDER;
private MathValue<Player> waitTimeMultiplier = DEFAULT_WAIT_TIME_MULTIPLIER;
private MathValue<Player> difficultyAdder = DEFAULT_DIFFICULTY_ADDER;
private MathValue<Player> difficultyMultiplier = DEFAULT_DIFFICULTY_MULTIPLIER;
private MathValue<Player> gameTimeAdder = DEFAULT_GAME_TIME_ADDER;
private MathValue<Player> gameTimeMultiplier = DEFAULT_GAME_TIME_MULTIPLIER;
@Override
public Builder waitTimeAdder(MathValue<Player> waitTimeAdder) {
this.waitTimeAdder = waitTimeAdder;
return this;
}
@Override
public Builder waitTimeMultiplier(MathValue<Player> waitTimeMultiplier) {
this.waitTimeMultiplier = waitTimeMultiplier;
return this;
}
@Override
public Builder difficultyAdder(MathValue<Player> difficultyAdder) {
this.difficultyAdder = difficultyAdder;
return this;
}
@Override
public Builder difficultyMultiplier(MathValue<Player> difficultyMultiplier) {
this.difficultyMultiplier = difficultyMultiplier;
return this;
}
@Override
public Builder gameTimeAdder(MathValue<Player> gameTimeAdder) {
this.gameTimeAdder = gameTimeAdder;
return this;
}
@Override
public Builder gameTimeMultiplier(MathValue<Player> gameTimeMultiplier) {
this.gameTimeMultiplier = gameTimeMultiplier;
return this;
}
@Override
public LootBaseEffect build() {
return new LootBaseEffectImpl(waitTimeAdder, waitTimeMultiplier, difficultyAdder, difficultyMultiplier, gameTimeAdder, gameTimeMultiplier);
}
}
}

View File

@@ -19,7 +19,6 @@ package net.momirealms.customfishing.api.mechanic.entity;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
/**

View File

@@ -0,0 +1,103 @@
package net.momirealms.customfishing.api.mechanic.event;
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 org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.TreeMap;
/**
* The EventCarrier interface represents an object that carries events in the custom fishing system.
* It defines methods to trigger actions based on specific triggers and contexts.
*/
public interface EventCarrier {
/**
* Get the type of item
*
* @return type
*/
ItemType type();
/**
* Whether to disable global actions
*
* @return disable global actions or not
*/
boolean disableGlobalActions();
/**
* Triggers actions based on the given context and trigger.
*
* @param context the context of the event, typically containing information about the player involved.
* @param trigger the trigger that activates the actions.
*/
void trigger(Context<Player> context, ActionTrigger trigger);
/**
* Triggers actions based on the given context, trigger, and action occurrence times.
*
* @param context the context of the event, typically containing information about the player involved.
* @param trigger the trigger that activates the actions.
* @param previousTimes the number of times the action has been triggered before.
* @param afterTimes the number of times the action will be triggered after.
*/
void trigger(Context<Player> context, ActionTrigger trigger, int previousTimes, int afterTimes);
/**
* Creates a new Builder instance for constructing EventCarrier objects.
*
* @return a new Builder instance.
*/
static Builder builder() {
return new EventCarrierImpl.BuilderImpl();
}
/**
* The Builder interface provides a fluent API for constructing EventCarrier instances.
*/
interface Builder {
/**
* Sets the map of actions associated with their triggers.
*
* @param actionMap the map of actions associated with their triggers.
* @return the Builder instance.
*/
Builder actionMap(HashMap<ActionTrigger, Action<Player>[]> actionMap);
/**
* Sets the map of actions associated with their triggers and occurrence times.
*
* @param actionTimesMap the map of actions associated with their triggers and occurrence times.
* @return the Builder instance.
*/
Builder actionTimesMap(HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap);
/**
* Set the type of the item
*
* @param type type
* @return the Builder instance.
*/
Builder type(ItemType type);
/**
* Set whether to disable global events
*
* @param value disable or not
* @return the Builder instance.
*/
Builder disableGlobalActions(boolean value);
/**
* Builds and returns the EventCarrier instance.
*
* @return the constructed EventCarrier instance.
*/
EventCarrier build();
}
}

View File

@@ -0,0 +1,88 @@
package net.momirealms.customfishing.api.mechanic.event;
import net.momirealms.customfishing.api.mechanic.action.Action;
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 org.bukkit.entity.Player;
import java.util.*;
import static java.util.Objects.requireNonNull;
public class EventCarrierImpl implements EventCarrier {
private final HashMap<ActionTrigger, Action<Player>[]> actionMap;
private final HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap;
private final ItemType type;
private final boolean disableGlobalActions;
public EventCarrierImpl(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;
}
@Override
public ItemType type() {
return type;
}
@Override
public boolean disableGlobalActions() {
return disableGlobalActions;
}
@Override
public void trigger(Context<Player> context, ActionTrigger trigger) {
Optional.ofNullable(actionMap.get(trigger)).ifPresent(actions -> {
ActionManager.trigger(context, actions);
});
}
@Override
public void trigger(Context<Player> context, ActionTrigger trigger, int previousTimes, int afterTimes) {
Optional.ofNullable(actionTimesMap.get(trigger)).ifPresent(integerTreeMap -> {
for (Map.Entry<Integer, Action<Player>[]> entry : integerTreeMap.entrySet()) {
if (entry.getKey() <= previousTimes)
continue;
if (entry.getKey() > afterTimes)
return;
ActionManager.trigger(context, entry.getValue());
}
});
}
public static class BuilderImpl implements Builder {
private final HashMap<ActionTrigger, Action<Player>[]> actionMap = new HashMap<>();
private final HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap = new HashMap<>();
private ItemType type = null;
private boolean disableGlobalActions = false;
@Override
public Builder actionMap(HashMap<ActionTrigger, Action<Player>[]> actionMap) {
this.actionMap.putAll(actionMap);
return this;
}
@Override
public Builder actionTimesMap(HashMap<ActionTrigger, TreeMap<Integer, Action<Player>[]>> actionTimesMap) {
this.actionTimesMap.putAll(actionTimesMap);
return this;
}
@Override
public Builder type(ItemType type) {
this.type = type;
return this;
}
@Override
public Builder disableGlobalActions(boolean value) {
this.disableGlobalActions = value;
return this;
}
@Override
public EventCarrier build() {
return new EventCarrierImpl(requireNonNull(type), disableGlobalActions, actionMap, actionTimesMap);
}
}
}

View File

@@ -0,0 +1,66 @@
package net.momirealms.customfishing.api.mechanic.event;
import net.momirealms.customfishing.api.mechanic.action.Action;
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 org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
public interface EventManager {
Map<ItemType, Map<ActionTrigger, Action<Player>[]>> GLOBAL_ACTIONS = new HashMap<>();
Map<ItemType, Map<ActionTrigger, TreeMap<Integer, Action<Player>[]>>> GLOBAL_TIMES_ACTION = new HashMap<>();
Optional<EventCarrier> getEventCarrier(String id);
boolean registerEventCarrier(String id, EventCarrier carrier);
default void trigger(Context<Player> context, String id, ActionTrigger trigger) {
getEventCarrier(id).ifPresent(carrier -> trigger(context, carrier, trigger));
}
default void trigger(Context<Player> context, String id, ActionTrigger trigger, int previousTimes, int afterTimes) {
getEventCarrier(id).ifPresent(carrier -> trigger(context, carrier, trigger, previousTimes, afterTimes));
}
static void trigger(Context<Player> context, EventCarrier carrier, ActionTrigger trigger) {
if (!carrier.disableGlobalActions()) {
triggerGlobalActions(context, carrier.type(), trigger);
}
carrier.trigger(context, trigger);
}
static void trigger(Context<Player> context, EventCarrier carrier, ActionTrigger trigger, int previousTimes, int afterTimes) {
if (!carrier.disableGlobalActions()) {
triggerGlobalActions(context, carrier.type(), trigger, previousTimes, afterTimes);
}
carrier.trigger(context, trigger, previousTimes, afterTimes);
}
static void triggerGlobalActions(Context<Player> context, ItemType type, ActionTrigger trigger) {
Optional.ofNullable(GLOBAL_ACTIONS.get(type))
.flatMap(actionTriggerMap -> Optional.ofNullable(actionTriggerMap.get(trigger)))
.ifPresent(action -> ActionManager.trigger(context, action));
}
static void triggerGlobalActions(Context<Player> context, ItemType type, ActionTrigger trigger, int previousTimes, int afterTimes) {
Optional.ofNullable(GLOBAL_TIMES_ACTION.get(type))
.flatMap(actionTriggerMap -> Optional.ofNullable(actionTriggerMap.get(trigger)))
.ifPresent(integerTreeMap -> {
for (Map.Entry<Integer, Action<Player>[]> entry : integerTreeMap.entrySet()) {
if (entry.getKey() <= previousTimes)
continue;
if (entry.getKey() > afterTimes)
return;
ActionManager.trigger(context, entry.getValue());
}
});
}
}

View File

@@ -17,7 +17,6 @@
package net.momirealms.customfishing.api.mechanic.fishing;
import net.momirealms.customfishing.api.mechanic.TempFishingState;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.game.GameInstance;
import net.momirealms.customfishing.api.mechanic.game.GameSettings;

View File

@@ -18,8 +18,8 @@
package net.momirealms.customfishing.api.mechanic.game;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.fishing.FishingManager;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.fishing.FishingManager;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import org.bukkit.Material;
import org.bukkit.entity.FishHook;

View File

@@ -7,7 +7,6 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.TreeSet;
import java.util.function.BiConsumer;
public interface CustomFishingItem {

View File

@@ -0,0 +1,35 @@
package net.momirealms.customfishing.api.mechanic.item;
import java.util.Objects;
public class ItemType {
public static ItemType LOOT = of("loot");
private final String type;
public ItemType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public static ItemType of(String type) {
return new ItemType(type);
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
ItemType itemType = (ItemType) object;
return Objects.equals(type, itemType.type);
}
@Override
public int hashCode() {
return Objects.hashCode(type);
}
}

View File

@@ -17,67 +17,27 @@
package net.momirealms.customfishing.api.mechanic.loot;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.effect.BaseEffect;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
public interface Loot {
boolean DEFAULT_INSTANT_GAME = false;
boolean DEFAULT_DISABLE_GAME = false;
boolean DEFAULT_DISABLE_STATS = false;
boolean DEFAULT_SHOW_IN_FINDER = false;
LootType DEFAULT_TYPE = LootType.ITEM;
MathValue<Player> DEFAULT_SCORE = MathValue.plain(0);
/**
* Check if this loot has an instance game.
* Check if this loot triggers an instant game.
*
* @return True if it's an instance game, false otherwise.
* @return True if it triggers an instant game, false otherwise.
*/
boolean instanceGame();
/**
* Check if the loot disables global actions
*/
boolean disableGlobalAction();
/**
* Get the unique ID of this loot.
*
* @return The unique ID.
*/
String getID();
/**
* Get the type of this loot.
*
* @return The loot type.
*/
LootType getType();
/**
* Get the nickname of this loot.
*
* @return The nickname.
*/
@NotNull
String getNick();
StatisticsKeys getStatisticKey();
/**
* Check if this loot should be shown in the finder.
*
* @return True if it should be shown, false otherwise.
*/
boolean showInFinder();
/**
* Get the score of this loot.
*
* @return The score.
*/
double getScore();
boolean instantGame();
/**
* Check if games are disabled for this loot.
@@ -87,55 +47,176 @@ public interface Loot {
boolean disableGame();
/**
* Check if statistics are disabled for this loot.
* Check if statistics recording is disabled for this loot.
*
* @return True if statistics are disabled, false otherwise.
*/
boolean disableStats();
/**
* Get the loot group of this loot.
* Check if this loot should be displayed in the finder tool.
*
* @return The loot group.
* @return True if it should be shown in the finder, false otherwise.
*/
String[] getLootGroup();
boolean showInFinder();
/**
* Get the actions triggered by a specific action trigger.
* Get the unique identifier for this loot.
*
* @param actionTrigger The action trigger.
* @return The actions triggered by the given trigger.
* @return The unique ID of the loot.
*/
@Nullable
Action[] getActions(ActionTrigger actionTrigger);
String getID();
/**
* Trigger actions associated with a specific action trigger.
* Get the type of this loot.
*
* @param actionTrigger The action trigger.
* @param playerContext The condition under which the actions are triggered.
* @return The type of the loot.
*/
void triggerActions(ActionTrigger actionTrigger, PlayerContext playerContext);
LootType getType();
/**
* Get effects that bond to this loot
* Get the display nickname for this loot.
*
* @return effects
* @return The nickname of the loot.
*/
BaseEffect getBaseEffect();
@NotNull
String getNick();
/**
* Get the actions triggered by a specific number of successes.
* Get the statistics key associated with this loot.
*
* @param times The number of successes.
* @return The actions triggered by the specified number of successes.
* @return The statistics key for this loot.
*/
Action<Player>[] getRecordActions(int times);
StatisticsKeys getStatisticKey();
/**
* Get a map of actions triggered by different numbers of successes.
* Get the score value for this loot.
*
* @return A map of actions triggered by success times.
* @return The score associated with the loot.
*/
HashMap<Integer, Action<Player>[]> getRecordActionMap();
MathValue<Player> getScore();
/**
* Get the groups this loot belongs to.
*
* @return An array of group names.
*/
String[] lootGroup();
/**
* Get the base effect associated with this loot.
*
* @return The base effect for the loot.
*/
LootBaseEffect baseEffect();
/**
* Create a new builder for constructing a Loot instance.
*
* @return A new Loot builder.
*/
static Builder builder() {
return new LootImpl.BuilderImpl();
}
/**
* Builder interface for constructing instances of Loot.
*/
interface Builder {
/**
* Set the type of the loot.
*
* @param type The type of the loot.
* @return The builder instance.
*/
Builder type(LootType type);
/**
* Specify whether the loot triggers an instant game.
*
* @param instantGame True if it should trigger an instant game.
* @return The builder instance.
*/
Builder instantGame(boolean instantGame);
/**
* Specify whether games are disabled for this loot.
*
* @param disableGame True if games should be disabled.
* @return The builder instance.
*/
Builder disableGame(boolean disableGame);
/**
* Specify whether statistics recording is disabled for this loot.
*
* @param disableStatistics True if statistics should be disabled.
* @return The builder instance.
*/
Builder disableStatistics(boolean disableStatistics);
/**
* Specify whether the loot should be shown in the finder tool.
*
* @param showInFinder True if it should be shown in the finder.
* @return The builder instance.
*/
Builder showInFinder(boolean showInFinder);
/**
* Set the unique ID for the loot.
*
* @param id The unique identifier.
* @return The builder instance.
*/
Builder id(String id);
/**
* Set the nickname for the loot.
*
* @param nick The nickname.
* @return The builder instance.
*/
Builder nick(String nick);
/**
* Set the statistics key for the loot.
*
* @param statisticsKeys The statistics key.
* @return The builder instance.
*/
Builder statisticsKeys(StatisticsKeys statisticsKeys);
/**
* Set the score for the loot.
*
* @param score The score value.
* @return The builder instance.
*/
Builder score(MathValue<Player> score);
/**
* Set the groups that the loot belongs to.
*
* @param groups An array of group names.
* @return The builder instance.
*/
Builder groups(String[] groups);
/**
* Set the base effect for the loot.
*
* @param lootBaseEffect The base effect.
* @return The builder instance.
*/
Builder lootBaseEffect(LootBaseEffect lootBaseEffect);
/**
* Build and return the Loot instance.
*
* @return The constructed Loot instance.
*/
Loot build();
}
}

View File

@@ -0,0 +1,183 @@
package net.momirealms.customfishing.api.mechanic.loot;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import static java.util.Objects.requireNonNull;
public class LootImpl implements Loot {
private final LootType type;
private final boolean instantGame;
private final boolean disableGame;
private final boolean disableStatistics;
private final boolean showInFinder;
private final String id;
private final String nick;
private final StatisticsKeys statisticsKeys;
private final MathValue<Player> score;
private final String[] groups;
private final LootBaseEffect lootBaseEffect;
public LootImpl(LootType type, boolean instantGame, boolean disableGame, boolean disableStatistics, boolean showInFinder, String id, String nick, StatisticsKeys statisticsKeys, MathValue<Player> score, String[] groups, LootBaseEffect lootBaseEffect) {
this.type = type;
this.instantGame = instantGame;
this.disableGame = disableGame;
this.disableStatistics = disableStatistics;
this.showInFinder = showInFinder;
this.id = id;
this.nick = nick;
this.statisticsKeys = statisticsKeys;
this.score = score;
this.groups = groups;
this.lootBaseEffect = lootBaseEffect;
}
@Override
public boolean instantGame() {
return instantGame;
}
@Override
public String getID() {
return id;
}
@Override
public LootType getType() {
return type;
}
@NotNull
@Override
public String getNick() {
return nick;
}
@Override
public StatisticsKeys getStatisticKey() {
return statisticsKeys;
}
@Override
public boolean showInFinder() {
return showInFinder;
}
@Override
public MathValue<Player> getScore() {
return score;
}
@Override
public boolean disableGame() {
return disableGame;
}
@Override
public boolean disableStats() {
return disableStatistics;
}
@Override
public String[] lootGroup() {
return groups;
}
@Override
public LootBaseEffect baseEffect() {
return lootBaseEffect;
}
public static class BuilderImpl implements Builder {
private LootType type = DEFAULT_TYPE;
private boolean instantGame = DEFAULT_INSTANT_GAME;
private boolean disableGame = DEFAULT_DISABLE_GAME;
private boolean disableStatistics = DEFAULT_DISABLE_STATS;
private boolean showInFinder = DEFAULT_SHOW_IN_FINDER;
private String id = null;
private String nick = null;
private StatisticsKeys statisticsKeys = null;
private MathValue<Player> score = DEFAULT_SCORE;
private String[] groups = new String[0];
private LootBaseEffect lootBaseEffect = null;
@Override
public Builder type(LootType type) {
this.type = type;
return this;
}
@Override
public Builder instantGame(boolean instantGame) {
this.instantGame = instantGame;
return this;
}
@Override
public Builder disableGame(boolean disableGame) {
this.disableGame = disableGame;
return this;
}
@Override
public Builder disableStatistics(boolean disableStatistics) {
this.disableStatistics = disableStatistics;
return this;
}
@Override
public Builder showInFinder(boolean showInFinder) {
this.showInFinder = showInFinder;
return this;
}
@Override
public Builder id(String id) {
this.id = id;
return this;
}
@Override
public Builder nick(String nick) {
this.nick = nick;
return this;
}
@Override
public Builder statisticsKeys(StatisticsKeys statisticsKeys) {
this.statisticsKeys = statisticsKeys;
return this;
}
@Override
public Builder score(MathValue<Player> score) {
this.score = score;
return this;
}
@Override
public Builder groups(String[] groups) {
this.groups = groups;
return this;
}
@Override
public Builder lootBaseEffect(LootBaseEffect lootBaseEffect) {
this.lootBaseEffect = lootBaseEffect;
return this;
}
@Override
public Loot build() {
return new LootImpl(
type,
instantGame,
disableGame,
disableStatistics,
showInFinder,
requireNonNull(id),
Optional.ofNullable(nick).orElse(id),
Optional.ofNullable(statisticsKeys).orElse(new StatisticsKeys(id, id)),
score,
groups,
requireNonNull(lootBaseEffect)
);
}
}
}

View File

@@ -17,78 +17,31 @@
package net.momirealms.customfishing.api.mechanic.loot;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
public interface LootManager {
/**
* 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.
*/
@Nullable List<String> getLootGroup(String key);
void registerLoot(@NotNull Loot loot);
/**
* 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.
*/
@Nullable Loot getLoot(String key);
@NotNull
List<String> getGroupMembers(String key);
/**
* Retrieves a collection of all loot configuration keys.
*
* @return A collection of all loot configuration keys.
*/
Collection<String> getAllLootKeys();
@NotNull
Optional<Loot> getLoot(String key);
/**
* Retrieves a collection of all loot configurations.
*
* @return A collection of all loot configurations.
*/
Collection<Loot> getAllLoots();
HashMap<String, Double> getLootWithWeight(Context<Player> context);
/**
* 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.
*/
HashMap<String, Double> getLootWithWeight(PlayerContext playerContext);
Collection<String> getPossibleLootKeys(Context<Player> context);
/**
* 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.
*/
Collection<String> getPossibleLootKeys(PlayerContext playerContext);
@NotNull
Map<String, Double> getPossibleLootKeysWithWeight(Effect effect, Context<Player> context);
/**
* Get a map of possible loot keys with their corresponding weights, considering fishing effect and condition.
*
* @param initialEffect The effect to apply weight modifiers.
* @param playerContext The condition to determine possible loot.
* @return A map of loot keys and their weights.
*/
@NotNull Map<String, Double> getPossibleLootKeysWithWeight(Effect initialEffect, PlayerContext playerContext);
/**
* 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.
*/
@Nullable Loot getNextLoot(Effect effect, PlayerContext playerContext);
@Nullable
Loot getNextLoot(Effect effect, Context<Player> context);
}

View File

@@ -21,6 +21,5 @@ public enum LootType {
ITEM,
ENTITY,
BLOCK,
GLOBAL
BLOCK
}

View File

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

View File

@@ -1,4 +1,6 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
public interface FormatFunction {
public interface ConfigParserFunction {
ParserType type();
}

View File

@@ -0,0 +1,24 @@
package net.momirealms.customfishing.api.mechanic.misc.function;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import java.util.function.Consumer;
import java.util.function.Function;
public class EffectModifierParserFunction implements ConfigParserFunction {
private final Function<Object, Consumer<Effect>> function;
public EffectModifierParserFunction(Function<Object, Consumer<Effect>> function) {
this.function = function;
}
public Consumer<Effect> accept(Object object) {
return function.apply(object);
}
@Override
public ParserType type() {
return ParserType.EFFECT_MODIFIER;
}
}

View File

@@ -8,13 +8,14 @@ import org.bukkit.inventory.ItemStack;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class ItemPropertyFunction implements FormatFunction {
public class ItemParserFunction implements ConfigParserFunction {
private Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function;
private int priority;
private final Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function;
private final int priority;
public ItemPropertyFunction(int priority, Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function) {
public ItemParserFunction(int priority, Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> function) {
this.function = function;
this.priority = priority;
}
public BiConsumer<Item<ItemStack>, Context<Player>> accept(Object object) {
@@ -24,4 +25,9 @@ public class ItemPropertyFunction implements FormatFunction {
public int getPriority() {
return priority;
}
@Override
public ParserType type() {
return ParserType.ITEM;
}
}

View File

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

View File

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

View File

@@ -70,7 +70,11 @@ public interface MathValue<T> {
*/
static <T> MathValue<T> auto(Object o) {
if (o instanceof String s) {
return expression(s);
try {
return plain(Double.parseDouble(s));
} catch (NumberFormatException e) {
return expression(s);
}
} else if (o instanceof Number n) {
return plain(n.doubleValue());
}

View File

@@ -97,7 +97,7 @@ public interface RequirementManager<T> {
@Nullable
RequirementFactory<T> getRequirementFactory(@NotNull String type);
static <T> boolean isSatisfied(Context<T> context, @Nullable Requirement<T>... requirements) {
static <T> boolean isSatisfied(Context<T> context, @Nullable Requirement<T>[] requirements) {
if (requirements == null) return true;
for (Requirement<T> requirement : requirements) {
if (!requirement.isSatisfied(context)) {

View File

@@ -0,0 +1,133 @@
package net.momirealms.customfishing.api.mechanic.statistic;
import net.momirealms.customfishing.common.util.Pair;
import java.util.Map;
/**
* The FishingStatistics interface represents statistics related to fishing activities.
* It provides methods to retrieve and manipulate statistics such as the amount of fish caught and the maximum size of fish.
*/
public interface FishingStatistics {
/**
* Retrieves the total amount of fish caught.
*
* @return the total amount of fish caught.
*/
int amountOfFishCaught();
/**
* Sets the total amount of fish caught.
*
* @param amountOfFishCaught the new total amount of fish caught.
*/
void amountOfFishCaught(int amountOfFishCaught);
/**
* Retrieves the amount of fish caught with the specified ID.
*
* @param id the ID of the fish.
* @return the amount of fish caught with the specified ID. -1 if not exist.
*/
int getAmount(String id);
/**
* Adds the specified amount to the fish caught with the specified ID and returns the updated amount.
*
* @param id the ID of the fish.
* @param amount the amount to add.
* @return a Pair containing the previous amount and the updated amount.
*/
Pair<Integer, Integer> addAmount(String id, int amount);
/**
* Sets the amount of fish caught with the specified ID.
*
* @param id the ID of the fish.
* @param amount the new amount to set.
*/
void setAmount(String id, int amount);
/**
* Retrieves the maximum size of the fish with the specified ID.
*
* @param id the ID of the fish.
* @return the maximum size of the fish with the specified ID. -1f if not exist.
*/
float getMaxSize(String id);
/**
* Sets the maximum size of the fish with the specified ID.
*
* @param id the ID of the fish.
* @param maxSize the new maximum size to set.
*/
void setMaxSize(String id, float maxSize);
/**
* Updates the maximum size of the fish with the specified ID and returns true if successful, false otherwise.
*
* @param id the ID of the fish.
* @param newSize the new maximum size.
* @return true if the update is successful, false otherwise.
*/
boolean updateSize(String id, float newSize);
/**
* Resets the fishing statistics, clearing all recorded data.
*/
void reset();
/**
* Retrieves the map containing the amounts of fish caught.
*
* @return the map containing the amounts of fish caught.
*/
Map<String, Integer> getAmountMap();
/**
* Retrieves the map containing the maximum sizes of fish.
*
* @return the map containing the maximum sizes of fish.
*/
Map<String, Float> getSizeMap();
/**
* Creates a new Builder instance for constructing FishingStatistics objects.
*
* @return a new Builder instance.
*/
static Builder builder() {
return new FishingStatisticsImpl.BuilderImpl();
}
/**
* The Builder interface provides a fluent API for constructing FishingStatistics instances.
*/
interface Builder {
/**
* Sets the map containing the amounts of fish caught.
*
* @param amountMap the map containing the amounts of fish caught.
* @return the Builder instance.
*/
Builder amountMap(Map<String, Integer> amountMap);
/**
* Sets the map containing the maximum sizes of fish.
*
* @param sizeMap the map containing the maximum sizes of fish.
* @return the Builder instance.
*/
Builder sizeMap(Map<String, Float> sizeMap);
/**
* Builds and returns the FishingStatistics instance.
*
* @return the constructed FishingStatistics instance.
*/
FishingStatistics build();
}
}

View File

@@ -0,0 +1,109 @@
package net.momirealms.customfishing.api.mechanic.statistic;
import net.momirealms.customfishing.common.util.Pair;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class FishingStatisticsImpl implements FishingStatistics {
private int amountOfFishCaught;
private final Map<String, Integer> amountMap;
private final Map<String, Float> sizeMap;
public FishingStatisticsImpl(HashMap<String, Integer> amountMap, HashMap<String, Float> sizeMap) {
this.amountMap = Collections.synchronizedMap(amountMap);
this.sizeMap = Collections.synchronizedMap(sizeMap);
this.amountOfFishCaught = amountMap.values().stream().mapToInt(Integer::intValue).sum();
}
@Override
public int amountOfFishCaught() {
return amountOfFishCaught;
}
@Override
public void amountOfFishCaught(int amountOfFishCaught) {
this.amountOfFishCaught = amountOfFishCaught;
}
@Override
public int getAmount(String id) {
return amountMap.getOrDefault(id, -1);
}
@Override
public Pair<Integer, Integer> addAmount(String id, int amount) {
if (amount <= 0) return Pair.of(-1, -1);
int previous = amountMap.getOrDefault(id, 0);
amountMap.put(id, previous + amount);
amountOfFishCaught += amount;
return Pair.of(previous, previous + amount);
}
@Override
public void setAmount(String id, int amount) {
if (amount < 0) amount = 0;
int previous = amountMap.getOrDefault(id, 0);
int delta = amount - previous;
this.amountOfFishCaught += delta;
amountMap.put(id, amount);
}
@Override
public float getMaxSize(String id) {
return sizeMap.getOrDefault(id, -1f);
}
@Override
public void setMaxSize(String id, float maxSize) {
if (maxSize < 0) maxSize = 0;
sizeMap.put(id, maxSize);
}
@Override
public boolean updateSize(String id, float newSize) {
if (newSize <= 0) return false;
float previous = sizeMap.getOrDefault(id, 0f);
if (previous >= newSize) return false;
sizeMap.put(id, newSize);
return true;
}
@Override
public void reset() {
this.sizeMap.clear();
this.amountMap.clear();
this.amountOfFishCaught = 0;
}
@Override
public Map<String, Integer> getAmountMap() {
return amountMap;
}
@Override
public Map<String, Float> getSizeMap() {
return sizeMap;
}
public static class BuilderImpl implements Builder {
private final HashMap<String, Integer> amountMap = new HashMap<>();
private final HashMap<String, Float> sizeMap = new HashMap<>();
@Override
public Builder amountMap(Map<String, Integer> amountMap) {
this.amountMap.putAll(amountMap);
return this;
}
@Override
public Builder sizeMap(Map<String, Float> sizeMap) {
this.sizeMap.putAll(sizeMap);
return this;
}
@Override
public FishingStatistics build() {
return new FishingStatisticsImpl(amountMap, sizeMap);
}
}
}

View File

@@ -1,177 +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.api.mechanic.statistic;
import net.momirealms.customfishing.api.data.StatisticData;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a statistics system for tracking loot and catch amounts.
*/
public class Statistics {
private final ConcurrentHashMap<String, Integer> statisticMap;
private final ConcurrentHashMap<String, Float> sizeMap;
private int total;
/**
* Creates a new instance of Statistics based on provided statistic data.
*
* @param statisticData The initial statistic data.
*/
public Statistics(StatisticData statisticData) {
this.statisticMap = new ConcurrentHashMap<>(statisticData.amountMap);
this.sizeMap = new ConcurrentHashMap<>(statisticData.sizeMap);
this.total = statisticMap.values().stream().mapToInt(Integer::intValue).sum();
}
/**
* Adds an amount of loot to the statistics.
*
* @param loot The loot item.
* @param playerContext The condition associated with the loot.
* @param amount The amount of loot to add.
*/
public synchronized void addLootAmount(Loot loot, Context<Player> playerContext, int amount) {
if (amount < 1) {
return;
}
if (amount == 1) {
addSingleLootAmount(loot, playerContext);
return;
}
Integer previous = statisticMap.get(loot.getStatisticKey().amountKey());
if (previous == null) previous = 0;
int after = previous + amount;
statisticMap.put(loot.getStatisticKey().amountKey(), after);
total += amount;
doSuccessTimesAction(previous, after, playerContext, loot);
}
/**
* Performs actions associated with the success times of acquiring loot.
*
* @param previous The previous success times.
* @param after The updated success times.
* @param playerContext The condition associated with the loot.
* @param loot The loot item.
*/
private void doSuccessTimesAction(Integer previous, int after, Context<Player> playerContext, Loot loot) {
HashMap<Integer, Action<Player>[]> actionMap = loot.getRecordActionMap();
if (actionMap != null) {
for (Map.Entry<Integer, Action<Player>[]> entry : actionMap.entrySet()) {
if (entry.getKey() > previous && entry.getKey() <= after) {
for (Action<Player> action : entry.getValue()) {
action.trigger(playerContext);
}
}
}
}
}
public boolean setSizeIfHigher(String loot, float size) {
float previous = sizeMap.getOrDefault(loot, 0f);
if (previous >= size) return false;
sizeMap.put(loot, size);
return true;
}
/**
* Adds a single loot amount to the statistics.
*
* @param loot The loot item.
* @param playerContext The condition associated with the loot.
*/
private void addSingleLootAmount(Loot loot, Context<Player> playerContext) {
Integer previous = statisticMap.get(loot.getID());
if (previous == null) previous = 0;
int after = previous + 1;
statisticMap.put(loot.getID(), after);
total += 1;
Action<Player>[] actions = loot.getRecordActionMap().get(after);
if (actions != null)
for (Action<Player> action : actions) {
action.trigger(playerContext);
}
}
/**
* Gets the amount of a specific loot item in the statistics.
*
* @param key The key of the loot item.
* @return The amount of the specified loot item.
*/
public int getLootAmount(String key) {
return statisticMap.getOrDefault(key, 0);
}
public float getSizeRecord(String key) {
return sizeMap.getOrDefault(key, 0f);
}
/**
* Resets the statistics data.
*/
public void reset() {
statisticMap.clear();
total = 0;
}
/**
* Gets the statistic map containing loot item keys and their respective amounts.
*
* @return The statistic map.
*/
public Map<String, Integer> getStatisticMap() {
return statisticMap;
}
public ConcurrentHashMap<String, Float> getSizeMap() {
return sizeMap;
}
/**
* Sets data for a specific key in the statistics.
*
* @param key The key to set data for.
* @param value The value to set.
*/
public void setData(String key, int value) {
if (value <= 0) {
statisticMap.remove(key);
return;
}
statisticMap.put(key, value);
}
/**
* Gets the total catch amount across all loot items.
*
* @return The total catch amount.
*/
public int getTotalCatchAmount() {
return total;
}
}

View File

@@ -20,19 +20,9 @@ package net.momirealms.customfishing.api.mechanic.statistic;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
public interface StatisticsManager {
/**
* Get the statistics for a player with the given UUID.
*
* @param uuid The UUID of the player for whom statistics are retrieved.
* @return The player's statistics or null if the player is not found.
*/
@Nullable
Statistics getStatistics(UUID uuid);
/**
* Get a list of strings associated with a specific key in a category map.
*
@@ -40,5 +30,5 @@ public interface StatisticsManager {
* @return A list of strings associated with the key or null if the key is not found.
*/
@Nullable
List<String> getCategory(String key);
List<String> getCategoryMembers(String key);
}

View File

@@ -1,197 +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.api.mechanic.totem;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
import org.bukkit.Location;
/**
* This class represents the configuration for a totem.
* It defines various settings and properties for the totem.
*/
public class TotemConfig {
private String key;
private TotemModel[] totemModels;
private TotemParticle[] particleSettings;
private Requirement[] requirements;
private double radius;
private int duration;
/**
* Get the array of totem models that define the totem's pattern.
*
* @return An array of TotemModel objects.
*/
public TotemModel[] getTotemModels() {
return totemModels;
}
/**
* Get the array of requirements for totem activation.
*
* @return An array of Requirement objects.
*/
public Requirement[] getRequirements() {
return requirements;
}
/**
* Get the unique key associated with this totem configuration.
*
* @return The unique key as a string.
*/
public String getKey() {
return key;
}
/**
* Check if the provided location matches any of the totem model patterns.
*
* @param location The location to check.
* @return True if the location matches a totem model pattern, false otherwise.
*/
public boolean isRightPattern(Location location) {
for (TotemModel totemModel : totemModels) {
if (totemModel.isPatternSatisfied(location)) {
return true;
}
}
return false;
}
/**
* Get the array of particle settings for the totem's visual effects.
*
* @return An array of TotemParticle objects.
*/
public TotemParticle[] getParticleSettings() {
return particleSettings;
}
/**
* Get the activation radius of the totem.
*
* @return The activation radius as a double.
*/
public double getRadius() {
return radius;
}
/**
* Get the duration of the totem's effect when activated.
*
* @return The duration in seconds as an integer.
*/
public int getDuration() {
return duration;
}
/**
* Get the totem core associated with the first totem model.
* This is used for some internal functionality.
*
* @return An array of TotemBlock objects representing the totem core.
*/
public TotemBlock[] getTotemCore() {
return totemModels[0].getTotemCore();
}
public static Builder builder(String key) {
return new Builder(key);
}
/**
* This class represents a builder for creating instances of TotemConfig.
* It allows for the convenient construction of TotemConfig objects with various settings.
*/
public static class Builder {
private final TotemConfig config;
public Builder(String key) {
this.config = new TotemConfig();
this.config.key = key;
}
/**
* Sets the totem models for the TotemConfig being built.
*
* @param totemModels An array of TotemModel objects representing different totem models.
* @return The builder instance to allow for method chaining.
*/
public Builder setTotemModels(TotemModel[] totemModels) {
config.totemModels = totemModels;
return this;
}
/**
* Sets the particle settings for the TotemConfig being built.
*
* @param particleSettings An array of TotemParticle objects representing particle settings.
* @return The builder instance to allow for method chaining.
*/
public Builder setParticleSettings(TotemParticle[] particleSettings) {
config.particleSettings = particleSettings;
return this;
}
/**
* Sets the requirements for the TotemConfig being built.
*
* @param requirements An array of Requirement objects representing activation requirements.
* @return The builder instance to allow for method chaining.
*/
public Builder setRequirements(Requirement[] requirements) {
config.requirements = requirements;
return this;
}
/**
* Sets the radius for the TotemConfig being built.
*
* @param radius The activation radius for the totem.
* @return The builder instance to allow for method chaining.
*/
public Builder setRadius(double radius) {
config.radius = radius;
return this;
}
/**
* Sets the duration for the TotemConfig being built.
*
* @param duration The duration of the totem's effect.
* @return The builder instance to allow for method chaining.
*/
public Builder setDuration(int duration) {
config.duration = duration;
return this;
}
/**
* Builds and returns the finalized TotemConfig object.
*
* @return The constructed TotemConfig object.
*/
public TotemConfig build() {
return config;
}
}
}

View File

@@ -1,32 +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.api.mechanic.totem;
import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier;
import org.bukkit.Location;
public interface TotemManager {
/**
* Get the EffectCarrier associated with an activated totem located near the specified location.
*
* @param location The location to search for activated totems.
* @return The EffectCarrier associated with the nearest activated totem or null if none are found.
*/
EffectCarrier getTotemEffect(Location location);
}

View File

@@ -1,277 +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.api.mechanic.totem;
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
import org.apache.commons.lang3.SerializationUtils;
import org.bukkit.Axis;
import org.bukkit.Location;
import java.io.Serializable;
import java.util.StringJoiner;
/**
* This class represents a totem model used to define the pattern of a totem.
*/
public class TotemModel implements Serializable {
private int coreX;
private final int coreY;
private int coreZ;
// [Y][Z][X][alternative totem blocks]
private TotemBlock[][][][] model;
/**
* Constructs a TotemModel with the specified parameters.
*
* @param coreX X-coordinate of the totem's core within the model.
* @param coreY Y-coordinate of the totem's core within the model.
* @param coreZ Z-coordinate of the totem's core within the model.
* @param model 3D array representing the totem model's structure.
*/
public TotemModel(int coreX, int coreY, int coreZ, TotemBlock[][][][] model) {
this.coreX = coreX;
this.coreY = coreY;
this.coreZ = coreZ;
this.model = model;
}
/**
* Get the totem core as an array of TotemBlock objects.
*
* @return An array of TotemBlock objects representing the totem's core.
*/
public TotemBlock[] getTotemCore() {
return model[coreY][coreZ][coreX];
}
/**
* Get the X-coordinate of the totem's core within the model.
*
* @return The X-coordinate as an integer.
*/
public int getCoreX() {
return coreX;
}
/**
* Get the Y-coordinate of the totem's core within the model.
*
* @return The Y-coordinate as an integer.
*/
public int getCoreY() {
return coreY;
}
/**
* Get the Z-coordinate of the totem's core within the model.
*
* @return The Z-coordinate as an integer.
*/
public int getCoreZ() {
return coreZ;
}
/**
* Get the 3D array representing the totem model's structure.
*
* @return The 3D array of TotemBlock objects.
*/
public TotemBlock[][][][] getModel() {
return model;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (int h = 0; h < model.length; h++) {
stringBuilder.append("layer: ").append(h + 1).append("\n");
TotemBlock[][][] totemBlocks1 = model[h];
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
StringJoiner stringJoiner = new StringJoiner("||");
for (TotemBlock totemBlock : totemBlocks3) {
stringJoiner.add(totemBlock.toString());
}
stringBuilder.append(stringJoiner).append("\t");
}
stringBuilder.append("\n");
}
}
return stringBuilder.toString();
}
public TotemModel deepClone() {
return SerializationUtils.clone(this);
}
/**
* Rotate the totem model 90 degrees clockwise.
*
* @return The rotated TotemModel.
*/
public TotemModel rotate90() {
int tempX = this.coreX;
this.coreX = this.coreZ;
this.coreZ = this.model[0][0].length - 1 - tempX;
this.model = rotate90(model);
for (TotemBlock[][][] totemBlocks1 : model) {
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
for (TotemBlock totemBlock : totemBlocks3) {
totemBlock.rotate90();
}
}
}
}
return this;
}
/**
* Mirror the totem model horizontally.
*
* @return The mirrored TotemModel.
*/
public TotemModel mirrorHorizontally() {
mirrorHorizontally(model);
this.coreZ = model[0].length - this.coreZ - 1;
for (TotemBlock[][][] totemBlocks1 : model) {
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
for (TotemBlock totemBlock : totemBlocks3) {
totemBlock.mirror(Axis.X);
}
}
}
}
return this;
}
/**
* Mirror the totem model vertically.
*
* @return The mirrored TotemModel.
*/
public TotemModel mirrorVertically() {
mirrorVertically(model);
this.coreX = model[0][0].length - this.coreX - 1;
for (TotemBlock[][][] totemBlocks1 : model) {
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
for (TotemBlock totemBlock : totemBlocks3) {
totemBlock.mirror(Axis.Z);
}
}
}
}
return this;
}
/**
* Check if the provided location satisfies the pattern defined by the totem model.
*
* @param location The location to check.
* @return True if the location satisfies the pattern, false otherwise.
*/
public boolean isPatternSatisfied(Location location) {
Location startLoc = location.clone().subtract(0, coreY, 0);
int height = model.length;
int width = model[0].length;
int length = model[0][0].length;
for (int y = 0; y < height; y++) {
Location loc = startLoc.clone().add(-coreX, y, -coreZ);
for (int z = 0; z < width; z++) {
outer:
for (int x = 0; x < length; x++) {
for (TotemBlock totemBlock : model[y][z][x]) {
if (totemBlock.isRightBlock(loc.clone().add(x, 0, z).getBlock())) {
continue outer;
}
}
return false;
}
}
}
return true;
}
/**
* Rotate a 3D totem model 90 degrees clockwise.
*
* @param matrix The 3D totem model to rotate.
* @return The rotated 3D totem model.
*/
private static TotemBlock[][][][] rotate90(TotemBlock[][][][] matrix) {
int height = matrix.length;
int rows = matrix[0].length;
int cols = matrix[0][0].length;
TotemBlock[][][][] rotated = new TotemBlock[height][cols][rows][];
for (int h = 0; h < height; h++) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
rotated[h][c][rows - 1 - r] = matrix[h][r][c];
}
}
}
return rotated;
}
/**
* Mirror a 3D totem model horizontally.
*
* @param matrix The 3D totem model to mirror.
*/
private static void mirrorHorizontally(TotemBlock[][][][] matrix) {
int height = matrix.length;
int rows = matrix[0].length;
int cols = matrix[0][0].length;
for (int h = 0; h < height; h++) {
for (int i = 0; i < rows / 2; i++) {
for (int j = 0; j < cols; j++) {
TotemBlock[] temp = matrix[h][i][j];
matrix[h][i][j] = matrix[h][rows - i - 1][j];
matrix[h][rows - i - 1][j] = temp;
}
}
}
}
/**
* Mirror a 3D totem model vertically.
*
* @param matrix The 3D totem model to mirror.
*/
private static void mirrorVertically(TotemBlock[][][][] matrix) {
int height = matrix.length;
int rows = matrix[0].length;
int cols = matrix[0][0].length;
for (int h = 0; h < height; h++) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols / 2; j++) {
TotemBlock[] temp = matrix[h][i][j];
matrix[h][i][j] = matrix[h][i][cols - j - 1];
matrix[h][i][cols - j - 1] = temp;
}
}
}
}
}

View File

@@ -1,16 +0,0 @@
package net.momirealms.customfishing.api.mechanic.totem;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import org.bukkit.Location;
public interface TotemParticle {
/**
* Start the particle task at specified location
*
* @param location location
* @param radius totem radius
* @return cancellable task
*/
CancellableTask start(Location location, double radius);
}

View File

@@ -1,118 +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.api.mechanic.totem.block;
import net.momirealms.customfishing.api.mechanic.totem.block.property.TotemBlockProperty;
import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
import org.bukkit.Axis;
import org.bukkit.block.Block;
import java.io.Serializable;
import java.util.StringJoiner;
/**
* Represents a TotemBlock that defines conditions and properties for a specific block type in a totem structure.
*/
public class TotemBlock implements Serializable {
private final TypeCondition typeCondition;
private final TotemBlockProperty[] properties;
/**
* Initializes a TotemBlock with the specified TypeCondition and properties.
*
* @param typeCondition The TypeCondition that specifies the block type.
* @param properties An array of TotemBlockProperty objects representing additional block properties.
*/
public TotemBlock(TypeCondition typeCondition, TotemBlockProperty[] properties) {
this.typeCondition = typeCondition;
this.properties = properties;
}
/**
* Gets the TypeCondition associated with this TotemBlock.
*
* @return The TypeCondition defining the block type.
*/
public TypeCondition getTypeCondition() {
return typeCondition;
}
/**
* Gets an array of properties associated with this TotemBlock.
*
* @return An array of TotemBlockProperty objects representing block properties.
*/
public TotemBlockProperty[] getProperties() {
return properties;
}
/**
* Checks if a given Block satisfies the TypeCondition and properties of this TotemBlock.
*
* @param block The Block to be checked against the conditions and properties.
* @return `true` if the block satisfies all conditions and properties, otherwise `false`.
*/
public boolean isRightBlock(Block block) {
if (!typeCondition.isMet(block)) {
return false;
}
for (TotemBlockProperty property : properties) {
if (!property.isPropertyMet(block)) {
return false;
}
}
return true;
}
/**
* Rotates the properties of this TotemBlock by 90 degrees.
* This method should be called when the totem structure is rotated.
*/
public void rotate90() {
for (TotemBlockProperty property : properties) {
property.rotate90();
}
}
/**
* Mirrors the properties of this TotemBlock horizontally or vertically.
* This method should be called when the totem structure is mirrored.
*
* @param axis The Axis along which to mirror the properties (X or Z).
*/
public void mirror(Axis axis) {
for (TotemBlockProperty property : properties) {
property.mirror(axis);
}
}
/**
* Returns the raw text representation of this TotemBlock, including its TypeCondition and properties.
*
* @return The raw text representation of this TotemBlock.
*/
@Override
public String toString() {
StringJoiner stringJoiner = new StringJoiner(";");
for (TotemBlockProperty property : properties) {
stringJoiner.add(property.getRawText());
}
return typeCondition.getRawText() + "{" + stringJoiner + "}";
}
}

View File

@@ -1,71 +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.api.mechanic.totem.block.property;
import org.bukkit.Axis;
import org.bukkit.block.Block;
import org.bukkit.block.data.Orientable;
import java.io.Serializable;
import java.util.Locale;
public class AxisImpl implements TotemBlockProperty, Serializable {
private Axis axis;
public AxisImpl(Axis axis) {
this.axis = axis;
}
@Override
public TotemBlockProperty mirror(Axis axis) {
return this;
}
/**
* Rotates the block axis 90 degrees. (X -> Z, Z -> X)
* @return The rotated block axis.
*/
@Override
public TotemBlockProperty rotate90() {
if (this.axis == Axis.X) {
axis = Axis.Z;
} else if (this.axis == Axis.Z) {
axis = Axis.X;
}
return this;
}
/**
* Checks if the block has the property.
* @param block The block to check.
* @return True if the block has the property.
*/
@Override
public boolean isPropertyMet(Block block) {
if (block.getBlockData() instanceof Orientable orientable) {
return orientable.getAxis().equals(this.axis);
}
return false;
}
@Override
public String getRawText() {
return "axis=" + axis.name().toLowerCase(Locale.ENGLISH);
}
}

View File

@@ -1,86 +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.api.mechanic.totem.block.property;
import org.bukkit.Axis;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Directional;
import java.io.Serializable;
import java.util.Locale;
public class FaceImpl implements TotemBlockProperty, Serializable {
private BlockFace blockFace;
public FaceImpl(BlockFace blockFace) {
this.blockFace = blockFace;
}
/**
* Mirrors the block face if the axis is X or Z.
* @param axis The axis to mirror.
* @return The mirrored block face.
*/
@Override
public TotemBlockProperty mirror(Axis axis) {
if (axis == Axis.X) {
if (blockFace == BlockFace.SOUTH || blockFace == BlockFace.NORTH) {
return new FaceImpl(blockFace.getOppositeFace());
} else {
return this;
}
} else if (axis == Axis.Z) {
if (blockFace == BlockFace.EAST || blockFace == BlockFace.WEST) {
return new FaceImpl(blockFace.getOppositeFace());
} else {
return this;
}
}
return this;
}
@Override
public TotemBlockProperty rotate90() {
switch (blockFace) {
case UP, DOWN -> {
return this;
}
case EAST -> blockFace = BlockFace.SOUTH;
case SOUTH -> blockFace = BlockFace.WEST;
case WEST -> blockFace = BlockFace.NORTH;
case NORTH -> blockFace = BlockFace.EAST;
default -> throw new IllegalArgumentException("Unsupported block facing: " + blockFace);
}
return this;
}
@Override
public boolean isPropertyMet(Block block) {
if (block.getBlockData() instanceof Directional directional) {
return directional.getFacing().equals(this.blockFace);
}
return false;
}
@Override
public String getRawText() {
return "face=" + blockFace.name().toLowerCase(Locale.ENGLISH);
}
}

View File

@@ -1,74 +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.api.mechanic.totem.block.property;
import org.bukkit.Axis;
import org.bukkit.block.Block;
import org.bukkit.block.data.Bisected;
import java.io.Serializable;
import java.util.Locale;
public class HalfImpl implements TotemBlockProperty, Serializable {
private final Bisected.Half half;
public HalfImpl(Bisected.Half half) {
this.half = half;
}
/**
* half is not affected by mirroring.
* @param axis The axis to mirror.
* @return this
*/
@Override
public TotemBlockProperty mirror(Axis axis) {
return this;
}
/**
* half is not affected by rotation.
* @return this
*/
@Override
public TotemBlockProperty rotate90() {
return this;
}
/**
* Checks if the block's half is the same as the half of this property.
* @param block The block to check.
* @return true if the block's half is the same as the half of this property.
*/
@Override
public boolean isPropertyMet(Block block) {
if (block.getBlockData() instanceof Bisected bisected) {
return bisected.getHalf().equals(this.half);
}
return false;
}
/**
* Returns the raw text of the half property.
* @return The raw text of the half property.
*/
@Override
public String getRawText() {
return "half=" + half.name().toLowerCase(Locale.ENGLISH);
}
}

View File

@@ -1,50 +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.api.mechanic.totem.block.property;
import org.bukkit.Axis;
import org.bukkit.block.Block;
public interface TotemBlockProperty {
/**
* Mirrors the block face if the axis is X or Z.
* @param axis The axis to mirror.
* @return The mirrored block face.
*/
TotemBlockProperty mirror(Axis axis);
/**
* Rotates the block face 90 degrees.
* @return The rotated block face.
*/
TotemBlockProperty rotate90();
/**
* Checks if the block has the property.
* @param block The block to check.
* @return True if the block has the property.
*/
boolean isPropertyMet(Block block);
/**
* Gets the raw text of the property.
* @return The raw text of the property.
*/
String getRawText();
}

View File

@@ -1,56 +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.api.mechanic.totem.block.type;
import org.bukkit.block.Block;
import java.io.Serializable;
/**
* Represents a TypeCondition that checks if a Block's type name ends with a specified string.
*/
public class EndWithType implements TypeCondition, Serializable {
private final String end;
public EndWithType(String end) {
this.end = end;
}
/**
* Checks if the specified Block's type name ends with the configured ending string.
*
* @param type The Block to check.
* @return `true` if the Block's type name ends with the specified string, otherwise `false`.
*/
@Override
public boolean isMet(Block type) {
return type.getType().name().endsWith(end);
}
/**
* Gets the raw text representation of this TypeCondition.
* The raw text includes the asterisk (*) followed by the configured ending string.
*
* @return The raw text representation of this TypeCondition.
*/
@Override
public String getRawText() {
return "*" + end;
}
}

View File

@@ -1,56 +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.api.mechanic.totem.block.type;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import org.bukkit.block.Block;
import java.io.Serializable;
/**
* Represents a TypeCondition that checks if a Block's type matches a specified type string.
*/
public class EqualType implements TypeCondition, Serializable {
private final String type;
public EqualType(String type) {
this.type = type;
}
/**
* Checks if the specified Block's type matches the configured type string.
*
* @param type The Block to check.
* @return `true` if the Block's type matches the specified type string, otherwise `false`.
*/
@Override
public boolean isMet(Block type) {
return this.type.equals(BukkitCustomFishingPlugin.get().getBlockManager().getAnyPluginBlockID(type));
}
/**
* Gets the raw text representation of this TypeCondition, which is the configured type string.
*
* @return The raw text representation of this TypeCondition.
*/
@Override
public String getRawText() {
return type;
}
}

View File

@@ -1,55 +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.api.mechanic.totem.block.type;
import org.bukkit.block.Block;
import java.io.Serializable;
/**
* Represents a TypeCondition that checks if a Block's type starts with a specified prefix.
*/
public class StartWithType implements TypeCondition, Serializable {
private final String start;
public StartWithType(String start) {
this.start = start;
}
/**
* Checks if the specified Block's type starts with the configured prefix.
*
* @param type The Block to check.
* @return `true` if the Block's type starts with the specified prefix, otherwise `false`.
*/
@Override
public boolean isMet(Block type) {
return type.getType().name().startsWith(start);
}
/**
* Gets the raw text representation of this TypeCondition, which is the configured prefix followed by '*'.
*
* @return The raw text representation of this TypeCondition.
*/
@Override
public String getRawText() {
return start + "*";
}
}

View File

@@ -1,57 +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.api.mechanic.totem.block.type;
import org.bukkit.block.Block;
/**
* Represents a condition used to check the type of a Block.
*/
public interface TypeCondition {
/**
* Checks if the specified Block meets the condition.
*
* @param block The Block to check.
* @return `true` if the condition is met, otherwise `false`.
*/
boolean isMet(Block block);
/**
* Gets the raw text representation of this TypeCondition.
*
* @return The raw text representation of this TypeCondition.
*/
String getRawText();
/**
* Gets a TypeCondition based on its raw text representation.
*
* @param raw The raw text representation of the TypeCondition.
* @return A TypeCondition instance corresponding to the raw text.
*/
static TypeCondition getTypeCondition(String raw) {
if (raw.startsWith("*")) {
return new EndWithType(raw.substring(1));
} else if (raw.endsWith("*")) {
return new StartWithType(raw.substring(0, raw.length() -1));
} else {
return new EqualType(raw);
}
}
}

View File

@@ -15,9 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data;
package net.momirealms.customfishing.api.storage;
import net.momirealms.customfishing.api.data.user.OfflineUser;
import net.momirealms.customfishing.api.storage.data.PlayerData;
import net.momirealms.customfishing.api.storage.user.UserData;
import org.bukkit.OfflinePlayer;
import java.util.Collection;
import java.util.Optional;
@@ -25,7 +27,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public interface DataStorageInterface {
public interface DataStorageProvider {
/**
* Initialize the data resource
@@ -79,7 +81,7 @@ public interface DataStorageInterface {
* @param users A collection of OfflineUser objects representing players.
* @param unlock Whether to unlock the player data after updating.
*/
void updateManyPlayersData(Collection<? extends OfflineUser> users, boolean unlock);
void updateManyPlayersData(Collection<? extends UserData<OfflinePlayer>> users, boolean unlock);
/**
* Lock or unlock a player's data in the SQL database.
@@ -92,8 +94,7 @@ public interface DataStorageInterface {
/**
* Get a set of unique user UUIDs
*
* @param legacy Whether to include legacy data in the retrieval.
* @return A set of unique user UUIDs.
*/
Set<UUID> getUniqueUsers(boolean legacy);
Set<UUID> getUniqueUsers();
}

View File

@@ -15,12 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.manager;
package net.momirealms.customfishing.api.storage;
import net.momirealms.customfishing.api.data.DataStorageInterface;
import net.momirealms.customfishing.api.data.PlayerData;
import net.momirealms.customfishing.api.data.user.OfflineUser;
import net.momirealms.customfishing.api.data.user.OnlineUser;
import net.momirealms.customfishing.api.storage.data.PlayerData;
import net.momirealms.customfishing.api.storage.user.UserData;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,14 +43,15 @@ public interface StorageManager {
* @param uuid The UUID of the player.
* @return An OnlineUser instance if the player is online, or null if not.
*/
@Nullable OnlineUser getOnlineUser(UUID uuid);
@Nullable
UserData<? extends OfflinePlayer> getOnlineUser(UUID uuid);
/**
* Get all the online users
*
* @return online users
*/
Collection<OnlineUser> getOnlineUsers();
Collection<UserData<? extends OfflinePlayer>> getOnlineUsers();
/**
* Asynchronously retrieves an OfflineUser instance for the specified UUID.
@@ -62,33 +62,23 @@ public interface StorageManager {
* @param lock Whether to lock the data during retrieval.
* @return A CompletableFuture that resolves to an Optional containing the OfflineUser instance if found, or empty if not found or locked.
*/
CompletableFuture<Optional<OfflineUser>> getOfflineUser(UUID uuid, boolean lock);
/**
* If the offlineUser is locked with no data in it
* An user's data would be locked if he is playing on another server that connected
* to database. Modifying this data would actually do nothing.
*
* @param offlineUser offlineUser
* @return is locked or not
*/
boolean isLockedData(OfflineUser offlineUser);
CompletableFuture<Optional<UserData<? extends OfflinePlayer>>> getOfflineUser(UUID uuid, boolean lock);
/**
* Asynchronously saves user data for an OfflineUser.
*
* @param offlineUser The OfflineUser whose data needs to be saved.
* @param userData The OfflineUser whose data needs to be saved.
* @param unlock Whether to unlock the data after saving.
* @return A CompletableFuture that resolves to a boolean indicating the success of the data saving operation.
*/
CompletableFuture<Boolean> saveUserData(OfflineUser offlineUser, boolean unlock);
CompletableFuture<Boolean> saveUserData(UserData userData, boolean unlock);
/**
* Gets the data source used for data storage.
*
* @return The data source.
*/
DataStorageInterface getDataSource();
DataStorageProvider getDataSource();
/**
* Checks if Redis is enabled.

View File

@@ -15,10 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data;
package net.momirealms.customfishing.api.storage;
public enum StorageType {
JSON,
YAML,
H2,

View File

@@ -15,10 +15,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data;
package net.momirealms.customfishing.api.storage.data;
import com.google.gson.annotations.SerializedName;
/**
* The EarningData class holds data related to the earnings of a player from selling fish.
* It includes the total earnings and the date of the earnings record.
*/
public class EarningData {
@SerializedName("earnings")
@@ -26,11 +30,22 @@ public class EarningData {
@SerializedName("date")
public int date;
/**
* Constructs a new EarningData instance with specified earnings and date.
*
* @param earnings the total earnings from fishing.
* @param date the date of the earnings record.
*/
public EarningData(double earnings, int date) {
this.earnings = earnings;
this.date = date;
}
/**
* Creates an instance of EarningData with default values (zero earnings and date).
*
* @return a new instance of EarningData with default values.
*/
public static EarningData empty() {
return new EarningData(0d, 0);
}

View File

@@ -15,22 +15,36 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data;
package net.momirealms.customfishing.api.storage.data;
import com.google.gson.annotations.SerializedName;
/**
* The InventoryData class holds data related to a player's fishing bag.
* It includes a serialized representation of the inventory and the size of the inventory.
*/
public class InventoryData {
@SerializedName("inventory")
public String serialized;
@SerializedName("size")
public int size;
/**
* Creates an instance of InventoryData with default values (empty inventory and size of 9).
*
* @return a new instance of InventoryData with default values.
*/
public static InventoryData empty() {
return new InventoryData("", 9);
}
/**
* Constructs a new InventoryData instance with specified serialized inventory and size.
*
* @param serialized the serialized representation of the inventory.
* @param size the size of the inventory.
*/
public InventoryData(String serialized, int size) {
this.serialized = serialized;
this.size = size;

View File

@@ -0,0 +1,197 @@
/*
* 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.api.storage.data;
import com.google.gson.annotations.SerializedName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* The PlayerData class holds data related to a player.
* It includes the player's name, their fishing statistics, inventory data, and earnings data.
*/
public class PlayerData {
public static final String DEFAULT_NAME = "";
public static final StatisticData DEFAULT_STATISTICS = StatisticData.empty();
public static final InventoryData DEFAULT_BAG = InventoryData.empty();
public static final EarningData DEFAULT_EARNING = EarningData.empty();
@SerializedName("name")
protected String name;
@SerializedName("stats")
protected StatisticData statisticsData;
@SerializedName("bag")
protected InventoryData bagData;
@SerializedName("trade")
protected EarningData earningData;
/**
* Constructs a new PlayerData instance with specified values.
*
* @param name the name of the player.
* @param statisticsData the fishing statistics data.
* @param bagData the inventory data.
* @param earningData the earnings data.
*/
public PlayerData(String name, StatisticData statisticsData, InventoryData bagData, EarningData earningData) {
this.name = name;
this.statisticsData = statisticsData;
this.bagData = bagData;
this.earningData = earningData;
}
// A static instance representing a locked state of PlayerData.
public static PlayerData LOCKED = empty();
/**
* Creates a new Builder instance for constructing PlayerData objects.
*
* @return a new Builder instance.
*/
public static Builder builder() {
return new Builder();
}
/**
* Creates an instance of PlayerData with empty fields.
*
* @return a new instance of PlayerData with empty fields.
*/
public static PlayerData empty() {
return new Builder()
.bag(InventoryData.empty())
.earnings(EarningData.empty())
.stats(StatisticData.empty())
.build();
}
/**
* The Builder class provides a fluent API for constructing PlayerData instances.
*/
public static class Builder {
private String name = DEFAULT_NAME;
private StatisticData statisticsData = DEFAULT_STATISTICS;
private InventoryData bagData = DEFAULT_BAG;
private EarningData earningData = DEFAULT_EARNING;
/**
* Sets the name for the PlayerData instance.
*
* @param name the name of the player.
* @return the Builder instance.
*/
@NotNull
public Builder name(@Nullable String name) {
this.name = name;
return this;
}
/**
* Sets the statistics data for the PlayerData instance.
*
* @param statisticsData the fishing statistics data.
* @return the Builder instance.
*/
@NotNull
public Builder stats(@Nullable StatisticData statisticsData) {
this.statisticsData = statisticsData;
return this;
}
/**
* Sets the inventory data for the PlayerData instance.
*
* @param inventoryData the inventory data.
* @return the Builder instance.
*/
@NotNull
public Builder bag(@Nullable InventoryData inventoryData) {
this.bagData = inventoryData;
return this;
}
/**
* Sets the earnings data for the PlayerData instance.
*
* @param earningData the earnings data.
* @return the Builder instance.
*/
@NotNull
public Builder earnings(@Nullable EarningData earningData) {
this.earningData = earningData;
return this;
}
/**
* Builds and returns the PlayerData instance.
*
* @return the constructed PlayerData instance.
*/
@NotNull
public PlayerData build() {
return new PlayerData(name, statisticsData, bagData, earningData);
}
}
/**
* Gets the statistics data for the player.
*
* @return the fishing statistics data.
*/
public StatisticData getStatistics() {
return statisticsData;
}
/**
* Gets the bag data for the player.
*
* @return the bag data.
*/
public InventoryData getBagData() {
return bagData;
}
/**
* Gets the earnings data for the player.
*
* @return the earnings data.
*/
public EarningData getEarningData() {
return earningData;
}
/**
* Gets the name of the player.
*
* @return the player's name.
*/
public String getName() {
return name;
}
/**
* Checks if the PlayerData instance is in a locked state.
*
* @return true if the PlayerData instance is locked, false otherwise.
*/
public boolean isLocked() {
return this == LOCKED;
}
}

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data;
package net.momirealms.customfishing.api.storage.data;
import com.google.gson.annotations.SerializedName;
import org.jetbrains.annotations.NotNull;
@@ -23,6 +23,10 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
/**
* The StatisticData class stores fishing statistics including amounts and sizes
* of fish caught, represented as maps.
*/
public class StatisticData {
@SerializedName(value="amount", alternate={"map"})
@@ -31,16 +35,30 @@ public class StatisticData {
@SerializedName("size")
public Map<String, Float> sizeMap;
public StatisticData() {
/**
* Default constructor that initializes the sizeMap and amountMap as empty HashMaps.
*/
private StatisticData() {
this.sizeMap = new HashMap<>();
this.amountMap = new HashMap<>();
}
/**
* Parameterized constructor that initializes the sizeMap and amountMap with provided values.
*
* @param amount a map containing the amount of each type of fish caught.
* @param size a map containing the size of each type of fish caught.
*/
public StatisticData(@NotNull Map<String, Integer> amount, @NotNull Map<String, Float> size) {
this.amountMap = amount;
this.sizeMap = size;
}
/**
* Creates an instance of StatisticData with empty maps.
*
* @return a new instance of StatisticData with empty maps.
*/
public static StatisticData empty() {
return new StatisticData();
}

View File

@@ -15,16 +15,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.data.user;
package net.momirealms.customfishing.api.storage.user;
import net.momirealms.customfishing.api.data.EarningData;
import net.momirealms.customfishing.api.data.PlayerData;
import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder;
import net.momirealms.customfishing.api.mechanic.statistic.Statistics;
import net.momirealms.customfishing.api.storage.data.EarningData;
import net.momirealms.customfishing.api.storage.data.PlayerData;
import java.util.UUID;
public interface OfflineUser {
public interface UserData<O> {
/**
* Get the username
@@ -74,4 +72,11 @@ public interface OfflineUser {
* @return player data
*/
PlayerData getPlayerData();
/**
* Get the user
*
* @return user
*/
O getUser();
}

View File

@@ -2,9 +2,15 @@ package net.momirealms.customfishing.common.config;
import dev.dejvokep.boostedyaml.YamlDocument;
public interface ConfigManager {
import java.io.File;
public interface ConfigLoader {
YamlDocument loadConfig(String filePath);
YamlDocument loadConfig(String filePath, char routeSeparator);
YamlDocument loadData(File file);
YamlDocument loadData(File file, char routeSeparator);
}

View File

@@ -32,4 +32,9 @@ public class Node<T> {
public Node<T> getChild(String node) {
return childTree.get(node);
}
@Nullable
public Node<T> removeChild(String node) {
return childTree.remove(node);
}
}

View File

@@ -18,7 +18,7 @@ public class AdventureHelper {
private final MiniMessage miniMessage;
private final MiniMessage miniMessageStrict;
private final GsonComponentSerializer gsonComponentSerializer;
private final Cache<String, String> miniMessageToJsonCache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES)
private final Cache<String, String> miniMessageToJsonCache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
private AdventureHelper() {
this.miniMessage = MiniMessage.builder().build();

View File

@@ -1,7 +1,6 @@
package net.momirealms.customfishing.common.item;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public interface Item<I> {

View File

@@ -1,6 +1,6 @@
package net.momirealms.customfishing.common.plugin;
import net.momirealms.customfishing.common.config.ConfigManager;
import net.momirealms.customfishing.common.config.ConfigLoader;
import net.momirealms.customfishing.common.dependency.DependencyManager;
import net.momirealms.customfishing.common.locale.TranslationManager;
import net.momirealms.customfishing.common.plugin.classpath.ClassPathAppender;
@@ -30,7 +30,7 @@ public interface CustomFishingPlugin {
TranslationManager getTranslationManager();
ConfigManager getConfigManager();
ConfigLoader getConfigManager();
String getServerVersion();

View File

@@ -0,0 +1,55 @@
package net.momirealms.customfishing.common.util;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class RandomUtils {
private final Random random;
private RandomUtils() {
random = ThreadLocalRandom.current();
}
private static class SingletonHolder {
private static final RandomUtils INSTANCE = new RandomUtils();
}
private static RandomUtils getInstance() {
return SingletonHolder.INSTANCE;
}
public static int generateRandomInt(int min, int max) {
return getInstance().random.nextInt(max - min + 1) + min;
}
public static double generateRandomDouble(double min, double max) {
return min + (max - min) * getInstance().random.nextDouble();
}
public static boolean generateRandomBoolean() {
return getInstance().random.nextBoolean();
}
public static <T> T getRandomElementFromArray(T[] array) {
int index = getInstance().random.nextInt(array.length);
return array[index];
}
public static <T> T[] getRandomElementsFromArray(T[] array, int count) {
if (count > array.length) {
throw new IllegalArgumentException("Count cannot be greater than array length");
}
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[count];
for (int i = 0; i < count; i++) {
int index = getInstance().random.nextInt(array.length - i);
result[i] = array[index];
array[index] = array[array.length - i - 1];
}
return result;
}
}

View File

@@ -38,8 +38,6 @@ import net.momirealms.customfishing.mechanic.misc.CoolDownManager;
import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl;
import net.momirealms.customfishing.mechanic.statistic.StatisticsManagerImpl;
import net.momirealms.customfishing.mechanic.totem.TotemManagerImpl;
import net.momirealms.customfishing.setting.CFConfig;
import net.momirealms.customfishing.setting.CFLocale;
import net.momirealms.customfishing.storage.StorageManagerImpl;
import net.momirealms.customfishing.version.VersionManagerImpl;
import org.bstats.bukkit.Metrics;

View File

@@ -19,7 +19,6 @@ package net.momirealms.customfishing.bukkit.compatibility.papi;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.data.user.OnlineUser;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
@@ -87,7 +86,7 @@ public class CFPapi extends PlaceholderExpansion {
}
}
case "earnings" -> {
OnlineUser user;
OnlineUserData user;
if (split.length < 3) {
user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
} else {
@@ -103,7 +102,7 @@ public class CFPapi extends PlaceholderExpansion {
}
case "canearn" -> {
if (split.length < 3) {
OnlineUser user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
OnlineUserData user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (user == null)
return "";
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(player) - user.getEarningData().earnings);
@@ -113,7 +112,7 @@ public class CFPapi extends PlaceholderExpansion {
return "";
}
OnlineUser user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
OnlineUserData user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
if (user == null)
return "";
return String.format("%.2f", plugin.getMarketManager().getEarningLimit(another) - user.getEarningData().earnings);

View File

@@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.compatibility.papi;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.setting.CFLocale;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@@ -19,8 +19,6 @@ package net.momirealms.customfishing.bukkit.compatibility.papi;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.data.user.OnlineUser;
import net.momirealms.customfishing.api.mechanic.statistic.Statistics;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,7 +63,7 @@ public class StatisticsPapi extends PlaceholderExpansion {
@Override
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
OnlineUser onlineUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
OnlineUserData onlineUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (onlineUser == null) return "Data not loaded";
Statistics statistics = onlineUser.getStatistics();
String[] split = params.split("_", 2);

View File

@@ -65,7 +65,7 @@ public class BattlePassHook implements Listener {
.buildAndExecute();
// Group Fish Quest
String[] lootGroup = event.getLoot().getLootGroup();
String[] lootGroup = event.getLoot().lootGroup();
if (event.getLoot() != null && lootGroup != null)
for (String group : lootGroup) {
this.executionBuilder("group")

Some files were not shown because too many files have changed in this diff Show More