9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-30 20:39:18 +00:00
This commit is contained in:
XiaoMoMi
2023-09-21 22:27:03 +08:00
parent e503eac3f9
commit 95374d221e
69 changed files with 2873 additions and 116 deletions

View File

@@ -27,20 +27,73 @@ import java.util.concurrent.CompletableFuture;
public interface DataStorageInterface {
/**
* Initialize the data resource
*/
void initialize();
/**
* Close the data resource
*/
void disable();
/**
* Get the storage data source type
*
* @return {@link StorageType}
*/
StorageType getStorageType();
/**
* Retrieve a player's data
*
* @param uuid The UUID of the player.
* @param lock Whether to lock the player data during retrieval.
* @return A CompletableFuture containing the optional player data.
*/
CompletableFuture<Optional<PlayerData>> getPlayerData(UUID uuid, boolean lock);
/**
* Update a player's data
*
* @param uuid The UUID of the player.
* @param playerData The player data to update.
* @param unlock Whether to unlock the player data after updating.
* @return A CompletableFuture indicating the success of the update.
*/
CompletableFuture<Boolean> updatePlayerData(UUID uuid, PlayerData playerData, boolean unlock);
/**
* Update or insert a player's data into the SQL database.
*
* @param uuid The UUID of the player.
* @param playerData The player data to update or insert.
* @param unlock Whether to unlock the player data after updating or inserting.
* @return A CompletableFuture indicating the success of the operation.
*/
CompletableFuture<Boolean> updateOrInsertPlayerData(UUID uuid, PlayerData playerData, boolean unlock);
/**
* Update data for multiple players
*
* @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);
/**
* Lock or unlock a player's data in the SQL database.
*
* @param uuid The UUID of the player.
* @param lock Whether to lock or unlock the player data.
*/
void lockOrUnlockPlayerData(UUID uuid, boolean lock);
/**
* 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);
}

View File

@@ -23,5 +23,11 @@ import java.util.concurrent.CompletableFuture;
public interface LegacyDataStorageInterface extends DataStorageInterface {
/**
* Retrieve legacy player data from the SQL database.
*
* @param uuid The UUID of the player.
* @return A CompletableFuture containing the optional legacy player data.
*/
CompletableFuture<Optional<PlayerData>> getLegacyPlayerData(UUID uuid);
}

View File

@@ -34,6 +34,10 @@ public class PlayerData {
public static PlayerData LOCKED = empty();
public static Builder builder() {
return new Builder();
}
public static PlayerData empty() {
return new Builder()
.setBagData(InventoryData.empty())

View File

@@ -22,20 +22,57 @@ import net.momirealms.customfishing.api.data.PlayerData;
import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder;
import net.momirealms.customfishing.api.mechanic.statistic.Statistics;
import java.io.Serializable;
import java.util.UUID;
public interface OfflineUser {
/**
* Get the username
*
* @return user name
*/
String getName();
/**
* Get the user's uuid
*
* @return uuid
*/
UUID getUUID();
/**
* Get the fishing bag holder
*
* @return fishing bag holder
*/
FishingBagHolder getHolder();
/**
* Get the player's earning data
*
* @return earning data
*/
EarningData getEarningData();
/**
* Get the player's statistics
*
* @return statistics
*/
Statistics getStatistics();
/**
* If the user is online on current server
*
* @return online or not
*/
boolean isOnline();
/**
* Get the data in another minimized format that can be saved
*
* @return player data
*/
PlayerData getPlayerData();
}

View File

@@ -20,5 +20,11 @@ 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

@@ -17,25 +17,52 @@
package net.momirealms.customfishing.api.event;
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;
public FishHookLandEvent(@NotNull Player who, Target target) {
/**
* 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.
*/
public FishHookLandEvent(@NotNull Player who, Target target, FishHook hook) {
super(who);
this.target = target;
this.fishHook = hook;
}
/**
* 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;
}

View File

@@ -27,6 +27,9 @@ import org.jetbrains.annotations.NotNull;
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();
@@ -35,6 +38,14 @@ public class FishingResultEvent extends PlayerEvent implements Cancellable {
private final Loot loot;
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, Loot loot, Map<String, String> args) {
super(who);
this.result = result;
@@ -62,22 +73,47 @@ public class FishingResultEvent extends PlayerEvent implements Cancellable {
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 + "}");
return args.get(key);
}
/**
* Gets the result of the fishing action.
*
* @return The fishing result, which can be either SUCCESS or FAILURE.
*/
public Result getResult() {
return result;
}
/**
* 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
*
* @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"));
}
/**
* An enumeration representing possible fishing results (SUCCESS or FAILURE).
*/
public enum Result {
SUCCESS,
FAILURE

View File

@@ -24,6 +24,9 @@ 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();
@@ -31,6 +34,13 @@ public class LavaFishingEvent extends PlayerEvent implements Cancellable {
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;
@@ -38,10 +48,20 @@ public class LavaFishingEvent extends PlayerEvent implements Cancellable {
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;
}
@@ -66,6 +86,9 @@ public class LavaFishingEvent extends PlayerEvent implements Cancellable {
isCancelled = cancel;
}
/**
* An enumeration representing possible states of the fishing action (REEL_IN, CAUGHT_FISH, BITE).
*/
public enum State {
REEL_IN,
CAUGHT_FISH,

View File

@@ -25,6 +25,9 @@ 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;
@@ -33,6 +36,13 @@ public class RodCastEvent extends PlayerEvent implements Cancellable {
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;
@@ -45,6 +55,11 @@ public class RodCastEvent extends PlayerEvent implements Cancellable {
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;
@@ -54,6 +69,11 @@ public class RodCastEvent extends PlayerEvent implements Cancellable {
return handlerList;
}
/**
* Gets the fishing preparation associated with the rod cast.
*
* @return The FishingPreparation associated with the rod cast.
*/
public FishingPreparation getPreparation() {
return preparation;
}
@@ -64,10 +84,20 @@ public class RodCastEvent extends PlayerEvent implements Cancellable {
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

@@ -17,5 +17,71 @@
package net.momirealms.customfishing.api.event;
public class TotemActivateEvent {
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

@@ -22,5 +22,14 @@ import org.bukkit.inventory.ItemStack;
import java.util.List;
public interface EnchantmentInterface {
/**
* Get a list of enchantments with level for itemStack
* format: plugin:enchantment:level
* example: minecraft:sharpness:5
*
* @param itemStack itemStack
* @return enchantment list
*/
List<String> getEnchants(ItemStack itemStack);
}

View File

@@ -21,6 +21,21 @@ import org.bukkit.entity.Player;
public interface LevelInterface {
/**
* Add exp to a certain skill or job
*
* @param player player
* @param target the skill or job, for instance "Fishing" "fisherman"
* @param amount the exp amount
*/
void addXp(Player player, String target, double amount);
/**
* Get a player's skill or job's level
*
* @param player player
* @param target the skill or job, for instance "Fishing" "fisherman"
* @return level
*/
int getLevel(Player player, String target);
}

View File

@@ -18,8 +18,15 @@
package net.momirealms.customfishing.api.integration;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
public interface SeasonInterface {
String getSeason(World world);
/**
* Get a world's season
*
* @param world world
* @return spring, summer, autumn, winter or disabled
*/
@NotNull String getSeason(World world);
}

View File

@@ -26,12 +26,21 @@ 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 {
public static HashMap<ActionTrigger, Action[]> lootActions = new HashMap<>();
public static HashMap<ActionTrigger, Action[]> rodActions = new HashMap<>();
public static HashMap<ActionTrigger, Action[]> baitActions = new HashMap<>();
public static HashMap<ActionTrigger, Action[]> hookActions = new HashMap<>();
/**
* Loads global settings from a configuration section.
*
* @param section The configuration section to load settings from.
*/
public static void load(ConfigurationSection section) {
if (section == null) return;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
@@ -41,17 +50,27 @@ public class GlobalSettings {
case "loot" -> lootActions = map;
case "rod" -> rodActions = map;
case "bait" -> baitActions = map;
case "hook" -> hookActions = map;
}
}
}
}
/**
* 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 condition The condition that triggered the actions.
*/
public static void triggerLootActions(ActionTrigger trigger, Condition condition) {
Action[] actions = lootActions.get(trigger);
if (actions != null) {
@@ -61,6 +80,12 @@ public class GlobalSettings {
}
}
/**
* Triggers rod-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param condition The condition that triggered the actions.
*/
public static void triggerRodActions(ActionTrigger trigger, Condition condition) {
Action[] actions = rodActions.get(trigger);
if (actions != null) {
@@ -70,6 +95,12 @@ public class GlobalSettings {
}
}
/**
* Triggers bait-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param condition The condition that triggered the actions.
*/
public static void triggerBaitActions(ActionTrigger trigger, Condition condition) {
Action[] actions = baitActions.get(trigger);
if (actions != null) {
@@ -78,4 +109,19 @@ public class GlobalSettings {
}
}
}
/**
* Triggers hook-related actions for a specific trigger and condition.
*
* @param trigger The trigger to activate actions for.
* @param condition The condition that triggered the actions.
*/
public static void triggerHookActions(ActionTrigger trigger, Condition condition) {
Action[] actions = hookActions.get(trigger);
if (actions != null) {
for (Action action : actions) {
action.trigger(condition);
}
}
}
}

View File

@@ -21,27 +21,60 @@ import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation;
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 final Loot loot;
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

@@ -24,24 +24,79 @@ import java.util.Iterator;
public interface Ranking {
/**
* Clears the list of competition players.
*/
void clear();
/**
* Retrieves a competition player by their name.
*
* @param player The name of the player to retrieve.
* @return The CompetitionPlayer object if found, or null if not found.
*/
CompetitionPlayer getCompetitionPlayer(String player);
/**
* Returns an iterator for iterating over pairs of player names and scores.
*
* @return An iterator for pairs of player names and scores.
*/
Iterator<Pair<String, Double>> getIterator();
/**
* Returns the number of competition players.
*
* @return The number of competition players.
*/
int getSize();
/**
* Returns the rank of a player based on their name.
*
* @param player The name of the player to get the rank for.
* @return The rank of the player, or -1 if the player is not found.
*/
int getPlayerRank(String player);
/**
* Returns the score of a player based on their name.
*
* @param player The name of the player to get the score for.
* @return The score of the player, or 0 if the player is not found.
*/
double getPlayerScore(String player);
/**
* Refreshes the data for a player by adding a score to their existing score or creating a new player.
*
* @param player The name of the player to update or create.
* @param score The score to add to the player's existing score or set as their initial score.
*/
void refreshData(String player, double score);
/**
* Sets the data for a player, updating their score or creating a new player.
*
* @param player The name of the player to update or create.
* @param score The score to set for the player.
*/
void setData(String player, double score);
/**
* Returns the name of a player at a given index.
*
* @param rank The index of the player to retrieve.
* @return The name of the player at the specified index, or null if not found.
*/
@Nullable
String getPlayerAt(int rank);
/**
* Returns the score of a player at a given index.
*
* @param rank The index of the player to retrieve.
* @return The score of the player at the specified index, or 0 if not found.
*/
double getScoreAt(int rank);
}

View File

@@ -25,20 +25,41 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a condition with associated data
*/
public class Condition {
protected Location location;
protected final Player player;
protected final @NotNull Map<String, String> args;
/**
* Creates a new Condition object based on a player's location.
*
* @param player The player associated with this condition.
*/
public Condition(@NotNull Player player) {
this(player.getLocation(), player, new HashMap<>());
}
/**
* Creates a new Condition object with specified arguments.
*
* @param player The player associated with this condition.
* @param args A map of arguments associated with this condition.
*/
public Condition(@NotNull Player player, @NotNull Map<String, String> args) {
this(player.getLocation(), player, args);
}
/**
* Creates a new Condition object with a specific location, player, and arguments.
*
* @param location The location associated with this condition.
* @param player The player associated with this condition.
* @param args A map of arguments associated with this condition.
*/
public Condition(Location location, Player player, @NotNull Map<String, String> args) {
this.location = location;
this.player = player;
@@ -53,6 +74,11 @@ public class Condition {
}
}
/**
* Sets the location associated with this condition.
*
* @param location The new location to set.
*/
public void setLocation(@NotNull Location location) {
this.location = location;
this.args.put("{x}", String.valueOf(location.getX()));
@@ -61,28 +87,61 @@ public class Condition {
this.args.put("{world}", location.getWorld().getName());
}
/**
* Gets the location associated with this condition.
*
* @return The location associated with this condition.
*/
public Location getLocation() {
return location;
}
/**
* Gets the player associated with this condition.
*
* @return The player associated with this condition.
*/
public Player getPlayer() {
return player;
}
/**
* Gets the map of arguments associated with this condition.
*
* @return A map of arguments associated with this condition.
*/
@NotNull
public Map<String, String> getArgs() {
return args;
}
/**
* Gets the value of a specific argument by its key.
*
* @param key The key of the argument to retrieve.
* @return The value of the argument or null if not found.
*/
@Nullable
public String getArg(String key) {
return args.get(key);
}
/**
* Inserts or updates an argument with the specified key and value.
*
* @param key The key of the argument to insert or update.
* @param value The value to set for the argument.
*/
public void insertArg(String key, String value) {
args.put(key, value);
}
/**
* Deletes an argument with the specified key.
*
* @param key The key of the argument to delete.
* @return The value of the deleted argument or null if not found.
*/
public String delArg(String key) {
return args.remove(key);
}

View File

@@ -125,20 +125,40 @@ public class FishingPreparation extends Condition {
}
}
/**
* Retrieves the ItemStack representing the fishing rod.
*
* @return The ItemStack representing the fishing rod.
*/
@NotNull
public ItemStack getRodItemStack() {
return rodItemStack;
}
/**
* Retrieves the ItemStack representing the bait (if available).
*
* @return The ItemStack representing the bait, or null if no bait is set.
*/
@Nullable
public ItemStack getBaitItemStack() {
return baitItemStack;
}
/**
* Checks if player meet the requirements for fishing gears
*
* @return True if can fish, false otherwise.
*/
public boolean canFish() {
return this.canFish;
}
/**
* Merges a FishingEffect into this fishing rod, applying effect modifiers.
*
* @param effect The FishingEffect to merge into this rod.
*/
public void mergeEffect(FishingEffect effect) {
for (EffectCarrier effectCarrier : effects) {
for (EffectModifier modifier : effectCarrier.getEffectModifiers()) {
@@ -147,8 +167,15 @@ public class FishingPreparation extends Condition {
}
}
/**
* Triggers actions associated with a specific action trigger.
*
* @param actionTrigger The action trigger that initiates the actions.
*/
public void triggerActions(ActionTrigger actionTrigger) {
GlobalSettings.triggerRodActions(actionTrigger, this);
GlobalSettings.triggerBaitActions(actionTrigger, this);
GlobalSettings.triggerHookActions(actionTrigger, this);
for (EffectCarrier effectCarrier : effects) {
Action[] actions = effectCarrier.getActions(actionTrigger);
if (actions != null)

View File

@@ -42,5 +42,5 @@ public interface Effect {
List<Pair<String, WeightModifier>> getWeightModifierIgnored();
void merge(Effect bonus);
void merge(Effect effect);
}

View File

@@ -35,96 +35,200 @@ public class FishingEffect implements Effect {
private final List<Pair<String, WeightModifier>> weightModifier = new ArrayList<>();
private final List<Pair<String, WeightModifier>> weightModifierIgnored = new ArrayList<>();
/**
* 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 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 hook time modifier.
*
* @param timeModifier The hook time modifier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setHookTimeModifier(double timeModifier) {
this.hookTimeModifier = timeModifier;
return this;
}
/**
* Sets the difficulty modifier.
*
* @param difficultyModifier The difficulty modifier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setDifficultyModifier(double difficultyModifier) {
this.difficultyModifier = difficultyModifier;
return this;
}
/**
* Sets the game time modifier.
*
* @param gameTimeModifier The game time modifier value to set.
* @return The FishingEffect instance for method chaining.
*/
public FishingEffect setGameTimeModifier(double gameTimeModifier) {
this.gameTimeModifier = gameTimeModifier;
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 canLavaFishing() {
return lavaFishing;
}
/**
* Retrieves the multiple loot chance.
*
* @return The multiple loot chance value.
*/
@Override
public double getMultipleLootChance() {
return multipleLootChance;
}
/**
* Retrieves the size multiplier.
*
* @return The size multiplier value.
*/
@Override
public double getSizeMultiplier() {
return sizeMultiplier;
}
/**
* Retrieves the score multiplier.
*
* @return The score multiplier value.
*/
@Override
public double getScoreMultiplier() {
return scoreMultiplier;
}
/**
* Retrieves the hook time modifier.
*
* @return The hook time modifier value.
*/
@Override
public double getHookTimeModifier() {
return hookTimeModifier;
}
/**
* Retrieves the game time modifier.
*
* @return The game time modifier value.
*/
@Override
public double getGameTimeModifier() {
return gameTimeModifier;
}
/**
* Retrieves the difficulty modifier.
*
* @return The difficulty modifier value.
*/
@Override
public double getDifficultyModifier() {
return difficultyModifier;
}
/**
* Retrieves the list of weight modifiers.
*
* @return The list of weight modifiers.
*/
@Override
public List<Pair<String, WeightModifier>> getWeightModifier() {
return weightModifier;
}
/**
* Retrieves the list of weight modifiers ignoring conditions.
*
* @return The list of weight modifiers ignoring conditions.
*/
@Override
public List<Pair<String, WeightModifier>> getWeightModifierIgnored() {
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;
@@ -139,6 +243,13 @@ public class FishingEffect implements Effect {
this.weightModifier.addAll(another.getWeightModifier());
}
public static Builder builder() {
return new Builder();
}
/**
* Builder class for creating instances of the {@link FishingEffect} class with customizable properties.
*/
public static class Builder {
private final FishingEffect effect;
@@ -147,51 +258,110 @@ public class FishingEffect implements Effect {
this.effect = new FishingEffect();
}
/**
* Adds weight modifiers to the FishingEffect.
*
* @param modifier A list of pairs representing weight modifiers.
* @return The Builder instance for method chaining.
*/
public Builder addWeightModifier(List<Pair<String, WeightModifier>> modifier) {
effect.weightModifier.addAll(modifier);
return this;
}
/**
* Adds weight modifiers ignoring conditions to the FishingEffect.
*
* @param modifier A list of pairs representing ignoring conditions weight modifiers.
* @return The Builder instance for method chaining.
*/
public Builder addWeightModifierIgnored(List<Pair<String, WeightModifier>> modifier) {
effect.weightModifierIgnored.addAll(modifier);
return this;
}
/**
* Sets the multiple loot chance for the FishingEffect.
*
* @param multipleLootChance The multiple loot chance value to set.
* @return The Builder instance for method chaining.
*/
public Builder multipleLootChance(double multipleLootChance) {
effect.multipleLootChance = multipleLootChance;
return this;
}
/**
* Sets the difficulty modifier for the FishingEffect.
*
* @param difficultyModifier The difficulty modifier value to set.
* @return The Builder instance for method chaining.
*/
public Builder difficultyModifier(double difficultyModifier) {
effect.difficultyModifier = difficultyModifier;
return this;
}
/**
* Sets the size multiplier for the FishingEffect.
*
* @param sizeMultiplier The size multiplier value to set.
* @return The Builder instance for method chaining.
*/
public Builder sizeMultiplier(double sizeMultiplier) {
effect.sizeMultiplier = sizeMultiplier;
return this;
}
/**
* Sets the time modifier for the FishingEffect.
*
* @param timeModifier The time modifier value to set.
* @return The Builder instance for method chaining.
*/
public Builder timeModifier(double timeModifier) {
effect.hookTimeModifier = timeModifier;
return this;
}
/**
* Sets the score multiplier for the FishingEffect.
*
* @param scoreMultiplier The score multiplier value to set.
* @return The Builder instance for method chaining.
*/
public Builder scoreMultiplier(double scoreMultiplier) {
effect.scoreMultiplier = scoreMultiplier;
return this;
}
/**
* Sets the game time modifier for the FishingEffect.
*
* @param gameTimeModifier The game time modifier value to set.
* @return The Builder instance for method chaining.
*/
public Builder gameTimeModifier(double gameTimeModifier) {
effect.gameTimeModifier = gameTimeModifier;
return this;
}
/**
* Sets whether lava fishing is enabled for the FishingEffect.
*
* @param lavaFishing True if lava fishing is enabled, false otherwise.
* @return The Builder instance for method chaining.
*/
public Builder lavaFishing(boolean lavaFishing) {
effect.lavaFishing = lavaFishing;
return this;
}
/**
* Builds and returns the finalized FishingEffect instance.
*
* @return The created FishingEffect instance.
*/
public FishingEffect build() {
return effect;
}

View File

@@ -28,7 +28,6 @@ public class CFLoot implements Loot {
private final String id;
private final LootType type;
private String gameConfig;
private final HashMap<ActionTrigger, Action[]> actionMap;
private final HashMap<Integer, Action[]> successTimesActionMap;
private String nick;
@@ -46,10 +45,13 @@ public class CFLoot implements Loot {
this.successTimesActionMap = new HashMap<>();
}
public static CFLoot of(String id, LootType type) {
return new CFLoot(id, type);
public static Builder builder(String id, LootType type) {
return new Builder(id, type);
}
/**
* Builder class for CFLoot.
*/
public static class Builder {
private final CFLoot loot;
@@ -58,121 +60,246 @@ public class CFLoot implements Loot {
this.loot = new CFLoot(id, type);
}
/**
* Set the nickname for this loot.
*
* @param nick The nickname.
* @return The builder.
*/
public Builder nick(String nick) {
this.loot.nick = nick;
return this;
}
/**
* Set whether this loot should be shown in the finder.
*
* @param show True if it should be shown, false otherwise.
* @return The builder.
*/
public Builder showInFinder(boolean show) {
this.loot.showInFinder = show;
return this;
}
/**
* Set whether this loot should have an instance game.
*
* @param instant True if it should be an instance game, false otherwise.
* @return The builder.
*/
public Builder instantGame(boolean instant) {
this.loot.instanceGame = instant;
return this;
}
public Builder gameConfig(String gameConfig) {
this.loot.gameConfig = gameConfig;
return this;
}
/**
* Set whether games are disabled for this loot.
*
* @param disable True if games are disabled, false otherwise.
* @return The builder.
*/
public Builder disableGames(boolean disable) {
this.loot.disableGame = disable;
return this;
}
/**
* Set whether statistics are disabled for this loot.
*
* @param disable True if statistics are disabled, false otherwise.
* @return The builder.
*/
public Builder disableStats(boolean disable) {
this.loot.disableStats = disable;
return this;
}
/**
* Set the score for this loot.
*
* @param score The score.
* @return The builder.
*/
public Builder score(double score) {
this.loot.score = score;
return this;
}
/**
* Set the loot group for this loot.
*
* @param groups The loot group.
* @return The builder.
*/
public Builder lootGroup(String[] groups) {
this.loot.lootGroup = groups;
return this;
}
/**
* Add actions triggered by a specific trigger.
*
* @param trigger The trigger for the actions.
* @param actions The actions to add.
* @return The builder.
*/
public Builder addActions(ActionTrigger trigger, Action[] actions) {
this.loot.actionMap.put(trigger, actions);
return this;
}
/**
* Add actions triggered by multiple triggers.
*
* @param actionMap A map of triggers to actions.
* @return The builder.
*/
public Builder addActions(HashMap<ActionTrigger, Action[]> actionMap) {
this.loot.actionMap.putAll(actionMap);
return this;
}
/**
* Add actions triggered by the number of successes.
*
* @param times The number of successes for triggering the actions.
* @param actions The actions to add.
* @return The builder.
*/
public Builder addTimesActions(int times, Action[] actions) {
this.loot.successTimesActionMap.put(times, actions);
return this;
}
/**
* Add actions triggered by multiple numbers of successes.
*
* @param actionMap A map of numbers of successes to actions.
* @return The builder.
*/
public Builder addTimesActions(HashMap<Integer, Action[]> actionMap) {
this.loot.successTimesActionMap.putAll(actionMap);
return this;
}
/**
* Build the CFLoot object.
*
* @return The built CFLoot object.
*/
public CFLoot build() {
return loot;
}
}
/**
* Check if this loot has an instance game.
*
* @return True if it's an instance game, false otherwise.
*/
@Override
public boolean instanceGame() {
return this.instanceGame;
}
/**
* Get the unique ID of this loot.
*
* @return The unique ID.
*/
@Override
public String getID() {
return this.id;
}
/**
* Get the type of this loot.
*
* @return The loot type.
*/
@Override
public LootType getType() {
return this.type;
}
/**
* Get the nickname of this loot.
*
* @return The nickname.
*/
@Override
public @NotNull String getNick() {
return this.nick;
}
/**
* Check if this loot should be shown in the finder.
*
* @return True if it should be shown, false otherwise.
*/
@Override
public boolean showInFinder() {
return this.showInFinder;
}
/**
* Get the score of this loot.
*
* @return The score.
*/
@Override
public double getScore() {
return this.score;
}
/**
* Check if games are disabled for this loot.
*
* @return True if games are disabled, false otherwise.
*/
@Override
public boolean disableGame() {
return this.disableGame;
}
/**
* Check if statistics are disabled for this loot.
*
* @return True if statistics are disabled, false otherwise.
*/
@Override
public boolean disableStats() {
return this.disableStats;
}
/**
* Get the loot group of this loot.
*
* @return The loot group.
*/
@Override
public String[] getLootGroup() {
return lootGroup;
}
/**
* Get the actions triggered by a specific action trigger.
*
* @param actionTrigger The action trigger.
* @return The actions triggered by the given trigger.
*/
@Override
public Action[] getActions(ActionTrigger actionTrigger) {
return actionMap.get(actionTrigger);
}
/**
* Trigger actions associated with a specific action trigger.
*
* @param actionTrigger The action trigger.
* @param condition The condition under which the actions are triggered.
*/
@Override
public void triggerActions(ActionTrigger actionTrigger, Condition condition) {
Action[] actions = getActions(actionTrigger);
@@ -183,11 +310,22 @@ public class CFLoot implements Loot {
}
}
/**
* Get the actions triggered by a specific number of successes.
*
* @param times The number of successes.
* @return The actions triggered by the specified number of successes.
*/
@Override
public Action[] getSuccessTimesActions(int times) {
return successTimesActionMap.get(times);
}
/**
* Get a map of actions triggered by different numbers of successes.
*
* @return A map of actions triggered by success times.
*/
@Override
public HashMap<Integer, Action[]> getSuccessTimesActionMap() {
return successTimesActionMap;

View File

@@ -26,67 +26,98 @@ import java.util.HashMap;
public interface Loot {
/**
* Check if this loot has an instance game.
*
* @return True if it's an instance game, false otherwise.
*/
boolean instanceGame();
/**
* get the loot id
* @return id
* Get the unique ID of this loot.
*
* @return The unique ID.
*/
String getID();
/**
* get the loot type
* @return type
* Get the type of this loot.
*
* @return The loot type.
*/
LootType getType();
/**
* nick would be display.name or key name if not set (MiniMessage format)
* @return nick
* Get the nickname of this loot.
*
* @return The nickname.
*/
@NotNull
String getNick();
/**
* if the loot can be seen from the finder
* @return show in finder or not
* Check if this loot should be shown in the finder.
*
* @return True if it should be shown, false otherwise.
*/
boolean showInFinder();
/**
* get the score in competition
* @return score
* Get the score of this loot.
*
* @return The score.
*/
double getScore();
/**
* if the game is disabled
* @return disabled or not
* Check if games are disabled for this loot.
*
* @return True if games are disabled, false otherwise.
*/
boolean disableGame();
/**
* if the statistics is disabled
* @return disabled or not
* Check if statistics are disabled for this loot.
*
* @return True if statistics are disabled, false otherwise.
*/
boolean disableStats();
/**
* Get the loot group of this loot.
*
* @return The loot group.
*/
String[] getLootGroup();
/**
* get actions triggered by certain events
* @return actions
* Get the actions triggered by a specific action trigger.
*
* @param actionTrigger The action trigger.
* @return The actions triggered by the given trigger.
*/
Action[] getActions(ActionTrigger actionTrigger);
/**
* Trigger actions associated with a specific action trigger.
*
* @param actionTrigger The action trigger.
* @param condition The condition under which the actions are triggered.
*/
void triggerActions(ActionTrigger actionTrigger, Condition condition);
/**
* get actions when succeeding in fishing for certain times
* @param times times
* @return actions
* Get the actions triggered by a specific number of successes.
*
* @param times The number of successes.
* @return The actions triggered by the specified number of successes.
*/
Action[] getSuccessTimesActions(int times);
/**
* Get a map of actions triggered by different numbers of successes.
*
* @return A map of actions triggered by success times.
*/
HashMap<Integer, Action[]> getSuccessTimesActionMap();
}

View File

@@ -20,5 +20,6 @@ package net.momirealms.customfishing.api.mechanic.loot;
import org.bukkit.entity.Player;
public interface WeightModifier {
double modify(Player player, double weight);
}

View File

@@ -21,14 +21,28 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.jetbrains.annotations.NotNull;
/**
* Represents a holder for the Market GUI inventory.
* This class is used to associate the Market GUI's inventory with an object.
*/
public class MarketGUIHolder implements InventoryHolder {
private Inventory inventory;
/**
* Sets the inventory associated with this holder.
*
* @param inventory The inventory to associate with this holder.
*/
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
/**
* Retrieves the inventory associated with this holder.
*
* @return The associated inventory.
*/
@Override
public @NotNull Inventory getInventory() {
return inventory;

View File

@@ -21,5 +21,11 @@ import net.momirealms.customfishing.api.mechanic.condition.Condition;
public interface Requirement {
/**
* Is condition met the requirement
*
* @param condition condition
* @return meet or not
*/
boolean isConditionMet(Condition condition);
}

View File

@@ -17,13 +17,37 @@
package net.momirealms.customfishing.api.mechanic.requirement;
/**
* An abstract class representing a requirement expansion
* Requirement expansions are used to define custom requirements for various functionalities.
*/
public abstract class RequirementExpansion {
/**
* Get the version of this requirement expansion.
*
* @return The version of the expansion.
*/
public abstract String getVersion();
/**
* Get the author of this requirement expansion.
*
* @return The author of the expansion.
*/
public abstract String getAuthor();
/**
* Get the type of requirement provided by this expansion.
*
* @return The type of requirement.
*/
public abstract String getRequirementType();
/**
* Get the factory for creating requirements defined by this expansion.
*
* @return The requirement factory.
*/
public abstract RequirementFactory getRequirementFactory();
}

View File

@@ -21,10 +21,27 @@ import net.momirealms.customfishing.api.mechanic.action.Action;
import java.util.List;
/**
* An interface for a requirement factory that builds requirements.
*/
public interface RequirementFactory {
Requirement build(Object args, List<Action> notMetActions, boolean checkAction);
/**
* Build a requirement with the given arguments, not met actions, and check action flag.
*
* @param args The arguments used to build the requirement.
* @param notMetActions Actions to be triggered when the requirement is not met (can be null).
* @param advanced Flag indicating whether to check the action when building the requirement.
* @return The built requirement.
*/
Requirement build(Object args, List<Action> notMetActions, boolean advanced);
/**
* Build a requirement with the given arguments.
*
* @param args The arguments used to build the requirement.
* @return The built requirement.
*/
default Requirement build(Object args) {
return build(args, null, false);
}

View File

@@ -17,7 +17,6 @@
package net.momirealms.customfishing.api.mechanic.statistic;
import com.google.gson.annotations.SerializedName;
import net.momirealms.customfishing.api.data.StatisticData;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
@@ -27,17 +26,31 @@ 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 {
@SerializedName("statistic_map")
private final ConcurrentHashMap<String, Integer> statisticMap;
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.statisticMap);
this.total = statisticMap.values().stream().mapToInt(Integer::intValue).sum();
}
/**
* Adds an amount of loot to the statistics.
*
* @param loot The loot item.
* @param condition The condition associated with the loot.
* @param amount The amount of loot to add.
*/
public synchronized void addLootAmount(Loot loot, Condition condition, int amount) {
if (amount == 1) {
addSingleLootAmount(loot, condition);
@@ -51,6 +64,14 @@ public class Statistics {
doSuccessTimesAction(previous, after, condition, loot);
}
/**
* Performs actions associated with the success times of acquiring loot.
*
* @param previous The previous success times.
* @param after The updated success times.
* @param condition The condition associated with the loot.
* @param loot The loot item.
*/
private void doSuccessTimesAction(Integer previous, int after, Condition condition, Loot loot) {
HashMap<Integer, Action[]> actionMap = loot.getSuccessTimesActionMap();
if (actionMap != null) {
@@ -64,6 +85,12 @@ public class Statistics {
}
}
/**
* Adds a single loot amount to the statistics.
*
* @param loot The loot item.
* @param condition The condition associated with the loot.
*/
private void addSingleLootAmount(Loot loot, Condition condition) {
Integer previous = statisticMap.get(loot.getID());
if (previous == null) previous = 0;
@@ -77,20 +104,40 @@ public class Statistics {
}
}
/**
* 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) {
Integer amount = statisticMap.get(key);
return amount == null ? 0 : amount;
}
/**
* 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;
}
/**
* 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);
@@ -99,6 +146,11 @@ public class Statistics {
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

@@ -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.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

@@ -0,0 +1,277 @@
/*
* 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

@@ -0,0 +1,16 @@
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

@@ -0,0 +1,118 @@
/*
* 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

@@ -0,0 +1,71 @@
/*
* 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

@@ -0,0 +1,86 @@
/*
* 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

@@ -0,0 +1,74 @@
/*
* 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

@@ -0,0 +1,50 @@
/*
* 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

@@ -0,0 +1,56 @@
/*
* 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

@@ -0,0 +1,56 @@
/*
* 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.CustomFishingPlugin;
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(CustomFishingPlugin.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

@@ -0,0 +1,55 @@
/*
* 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

@@ -0,0 +1,57 @@
/*
* 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

@@ -19,7 +19,15 @@ package net.momirealms.customfishing.api.scheduler;
public interface CancellableTask {
/**
* Cancel the task
*/
void cancel();
/**
* Get if the task is cancelled or not
*
* @return cancelled or not
*/
boolean isCancelled();
}

View File

@@ -23,17 +23,71 @@ import java.util.concurrent.TimeUnit;
public interface Scheduler {
/**
* Runs a task synchronously on the main server thread or region thread.
*
* @param runnable The task to run.
* @param location The location associated with the task.
*/
void runTaskSync(Runnable runnable, Location location);
/**
* Runs a task synchronously with a specified delay and period.
*
* @param runnable The task to run.
* @param location The location associated with the task.
* @param delayTicks The delay in ticks before the first execution.
* @param periodTicks The period between subsequent executions in ticks.
* @return A CancellableTask for managing the scheduled task.
*/
CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delayTicks, long periodTicks);
/**
* Runs a task asynchronously with a specified delay.
*
* @param runnable The task to run.
* @param delay The delay before the task execution.
* @param timeUnit The time unit for the delay.
* @return A CancellableTask for managing the scheduled task.
*/
CancellableTask runTaskAsyncLater(Runnable runnable, long delay, TimeUnit timeUnit);
/**
* Runs a task asynchronously.
*
* @param runnable The task to run.
*/
void runTaskAsync(Runnable runnable);
/**
* Runs a task synchronously with a specified delay.
*
* @param runnable The task to run.
* @param location The location associated with the task.
* @param delay The delay before the task execution.
* @param timeUnit The time unit for the delay.
* @return A CancellableTask for managing the scheduled task.
*/
CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay, TimeUnit timeUnit);
/**
* Runs a task synchronously with a specified delay in ticks.
*
* @param runnable The task to run.
* @param location The location associated with the task.
* @param delayTicks The delay in ticks before the task execution.
* @return A CancellableTask for managing the scheduled task.
*/
CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delayTicks);
/**
* Runs a task asynchronously with a specified delay and period.
*
* @param runnable The task to run.
* @param delay The delay before the first execution.
* @param period The period between subsequent executions.
* @param timeUnit The time unit for the delay and period.
* @return A CancellableTask for managing the scheduled task.
*/
CancellableTask runTaskAsyncTimer(Runnable runnable, long delay, long period, TimeUnit timeUnit);
}

View File

@@ -17,8 +17,22 @@
package net.momirealms.customfishing.api.util;
/**
* Utility class for working with fonts in text.
*/
public class FontUtils {
private FontUtils() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
/**
* Surrounds the given text with a specified font tag.
*
* @param text The text to be surrounded with the font tag.
* @param font The font to use in the font tag.
* @return The input text surrounded by the font tag.
*/
public static String surroundWithFont(String text, String font) {
return "<font:" + font + ">" + text + "</font>";
}

View File

@@ -35,8 +35,23 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Utility class for working with Bukkit Inventories and item stacks.
*/
public class InventoryUtils {
private InventoryUtils() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
/**
* Create a custom inventory with a specified size and title component.
*
* @param inventoryHolder The holder of the inventory.
* @param size The size of the inventory.
* @param component The title component of the inventory.
* @return The created Inventory instance.
*/
public static Inventory createInventory(InventoryHolder inventoryHolder, int size, Component component) {
try {
boolean isSpigot = CustomFishingPlugin.get().getVersionManager().isSpigot();
@@ -58,6 +73,14 @@ public class InventoryUtils {
}
}
/**
* Create a custom inventory with a specified type and title component.
*
* @param inventoryHolder The holder of the inventory.
* @param type The type of the inventory.
* @param component The title component of the inventory.
* @return The created Inventory instance.
*/
public static Inventory createInventory(InventoryHolder inventoryHolder, InventoryType type, Component component) {
try {
boolean isSpigot = CustomFishingPlugin.get().getVersionManager().isSpigot();
@@ -79,6 +102,12 @@ public class InventoryUtils {
}
}
/**
* Serialize an array of ItemStacks to a Base64-encoded string.
*
* @param contents The ItemStack array to serialize.
* @return The Base64-encoded string representing the serialized ItemStacks.
*/
public static @NotNull String stacksToBase64(ItemStack[] contents) {
if (contents.length == 0) {
return "";
@@ -101,9 +130,10 @@ public class InventoryUtils {
}
/**
* Get itemStacks from base64
* @param base64 base64
* @return itemStacks
* Deserialize an ItemStack array from a Base64-encoded string.
*
* @param base64 The Base64-encoded string representing the serialized ItemStacks.
* @return An array of ItemStacks deserialized from the input string.
*/
@Nullable
public static ItemStack[] getInventoryItems(String base64) {

View File

@@ -22,30 +22,59 @@ import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
/**
* Utility class for logging messages with various log levels.
*/
public final class LogUtils {
public static void info(@NotNull String s) {
CustomFishingPlugin.getInstance().getLogger().info(s);
/**
* Log an informational message.
*
* @param message The message to log.
*/
public static void info(@NotNull String message) {
CustomFishingPlugin.getInstance().getLogger().info(message);
}
public static void warn(@NotNull String s) {
CustomFishingPlugin.getInstance().getLogger().warning(s);
/**
* Log a warning message.
*
* @param message The message to log.
*/
public static void warn(@NotNull String message) {
CustomFishingPlugin.getInstance().getLogger().warning(message);
}
public static void severe(@NotNull String s) {
CustomFishingPlugin.getInstance().getLogger().severe(s);
/**
* Log a severe error message.
*
* @param message The message to log.
*/
public static void severe(@NotNull String message) {
CustomFishingPlugin.getInstance().getLogger().severe(message);
}
public static void warn(@NotNull String s, Throwable t) {
CustomFishingPlugin.getInstance().getLogger().log(Level.WARNING, s, t);
/**
* Log a warning message with a throwable exception.
*
* @param message The message to log.
* @param throwable The throwable exception to log.
*/
public static void warn(@NotNull String message, Throwable throwable) {
CustomFishingPlugin.getInstance().getLogger().log(Level.WARNING, message, throwable);
}
public static void severe(@NotNull String s, Throwable t) {
CustomFishingPlugin.getInstance().getLogger().log(Level.SEVERE, s, t);
/**
* Log a severe error message with a throwable exception.
*
* @param message The message to log.
* @param throwable The throwable exception to log.
*/
public static void severe(@NotNull String message, Throwable throwable) {
CustomFishingPlugin.getInstance().getLogger().log(Level.SEVERE, message, throwable);
}
private LogUtils() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
}

View File

@@ -19,8 +19,16 @@ package net.momirealms.customfishing.api.util;
import org.bukkit.configuration.ConfigurationSection;
/**
* Utility class for generating offset characters based on a font configuration.
*/
@SuppressWarnings("DuplicatedCode")
public class OffsetUtils {
private OffsetUtils() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
private static String font;
private static String negative_1;
private static String negative_2;
@@ -39,6 +47,11 @@ public class OffsetUtils {
private static String positive_64;
private static String positive_128;
/**
* Load font configuration from a given section.
*
* @param section The configuration section containing font settings.
*/
public static void loadConfig(ConfigurationSection section) {
if (section != null) {
font = section.getString("font", "customfishing:offset_chars");
@@ -61,6 +74,12 @@ public class OffsetUtils {
}
}
/**
* Get the shortest negative offset characters for a given number.
*
* @param n The number for which to generate offset characters.
* @return Offset characters as a string.
*/
public static String getShortestNegChars(int n) {
StringBuilder stringBuilder = new StringBuilder();
while (n >= 128) {
@@ -97,6 +116,12 @@ public class OffsetUtils {
return stringBuilder.toString();
}
/**
* Get the shortest positive offset characters for a given number.
*
* @param n The number for which to generate offset characters.
* @return Offset characters as a string.
*/
public static String getShortestPosChars(int n) {
StringBuilder stringBuilder = new StringBuilder();
while (n >= 128) {
@@ -133,6 +158,13 @@ public class OffsetUtils {
return stringBuilder.toString();
}
/**
* Get offset characters for a given number. This method selects between positive and negative
* offset characters based on the sign of the number.
*
* @param n The number for which to generate offset characters.
* @return Offset characters as a string.
*/
public static String getOffsetChars(int n) {
if (n > 0) {
return "<font:" + font + ">" + getShortestPosChars(n) + "</font>";

View File

@@ -24,8 +24,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* Utility class for selecting random items based on weights.
*/
public class WeightUtils {
/**
* Get a random item from a list of pairs, each associated with a weight.
*
* @param pairs A list of pairs where the left element is the item and the right element is its weight.
* @param <T> The type of items in the list.
* @return A randomly selected item from the list, or null if no item was selected.
*/
public static <T> T getRandom(List<Pair<T, Double>> pairs) {
List<T> available = new ArrayList<>();
double[] weights = new double[pairs.size()];
@@ -40,6 +50,13 @@ public class WeightUtils {
return getRandom(weights, available, index);
}
/**
* Get a random item from a map where each entry is associated with a weight.
*
* @param map A map where each entry's key is an item, and the value is its weight.
* @param <T> The type of items in the map.
* @return A randomly selected item from the map, or null if no item was selected.
*/
public static <T> T getRandom(Map<T, Double> map) {
List<T> available = new ArrayList<>();
double[] weights = new double[map.size()];
@@ -54,6 +71,15 @@ public class WeightUtils {
return getRandom(weights, available, index);
}
/**
* Get a random item from a list of items with associated weights.
*
* @param weights An array of weights corresponding to the available items.
* @param available A list of available items.
* @param effectiveSize The effective size of the array and list after filtering out items with non-positive weights.
* @param <T> The type of items.
* @return A randomly selected item from the list, or null if no item was selected.
*/
private static <T> T getRandom(double[] weights, List<T> available, int effectiveSize) {
double total = Arrays.stream(weights).sum();
double[] weightRatios = new double[effectiveSize];