9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-31 12:56:43 +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

@@ -18,8 +18,10 @@
package net.momirealms.customfishing.compatibility.season;
import net.momirealms.customcrops.api.CustomCropsAPI;
import net.momirealms.customcrops.api.object.CCWorldSeason;
import net.momirealms.customfishing.api.integration.SeasonInterface;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
@@ -31,8 +33,11 @@ public class CustomCropsSeasonImpl implements SeasonInterface {
customCropsAPI = CustomCropsAPI.getInstance();
}
@NotNull
@Override
public String getSeason(World world) {
return Objects.requireNonNull(customCropsAPI.getSeason(world.getName())).getSeason();
CCWorldSeason season = customCropsAPI.getSeason(world.getName());
if (season == null) return "disabled";
return season.getSeason();
}
}

View File

@@ -20,9 +20,11 @@ package net.momirealms.customfishing.compatibility.season;
import me.casperge.realisticseasons.api.SeasonsAPI;
import net.momirealms.customfishing.api.integration.SeasonInterface;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
public class RealisticSeasonsImpl implements SeasonInterface {
@NotNull
@Override
public String getSeason(World world) {
return switch (SeasonsAPI.getInstance().getSeason(world)) {

View File

@@ -27,6 +27,7 @@ import net.momirealms.customfishing.api.scheduler.CancellableTask;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.setting.CFLocale;
import net.momirealms.customfishing.storage.method.database.nosql.RedisManager;
import net.momirealms.customfishing.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.boss.BarColor;
import org.bukkit.configuration.ConfigurationSection;
@@ -155,7 +156,7 @@ public class CompetitionManagerImpl implements CompetitionManager {
CompetitionConfig competitionConfig = builder.build();
List<Pair<Integer, Integer>> timePairs = section.getStringList("start-time")
.stream().map(this::getTimePair).toList();
.stream().map(ConfigUtils::splitStringIntegerArgs).toList();
List<Integer> weekdays = section.getIntegerList("start-weekday");
if (weekdays.size() == 0) {
weekdays.addAll(List.of(1,2,3,4,5,6,7));
@@ -171,6 +172,12 @@ public class CompetitionManagerImpl implements CompetitionManager {
}
}
/**
* Gets prize actions from a configuration section.
*
* @param section The configuration section containing prize actions.
* @return A HashMap where keys are action names and values are arrays of Action objects.
*/
public HashMap<String, Action[]> getPrizeActions(ConfigurationSection section) {
HashMap<String, Action[]> map = new HashMap<>();
if (section == null) return map;
@@ -182,11 +189,9 @@ public class CompetitionManagerImpl implements CompetitionManager {
return map;
}
public Pair<Integer, Integer> getTimePair(String time) {
String[] split = time.split(":");
return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
}
/**
* Checks the timer for the next competition and starts it if necessary.
*/
public void timerCheck() {
LocalDateTime now = LocalDateTime.now();
CompetitionSchedule competitionSchedule = new CompetitionSchedule(

View File

@@ -31,22 +31,47 @@ public class CompetitionSchedule {
this.second = second;
}
/**
* Gets the weekday associated with this time schedule.
*
* @return The weekday value (e.g., 1 for Monday, 2 for Tuesday, etc.).
*/
public int getWeekday() {
return weekday;
}
/**
* Gets the hour of the day associated with this time schedule.
*
* @return The hour value (0-23).
*/
public int getHour() {
return hour;
}
/**
* Gets the minute of the hour associated with this time schedule.
*
* @return The minute value (0-59).
*/
public int getMinute() {
return minute;
}
/**
* Gets the second of the minute associated with this time schedule.
*
* @return The second value (0-59).
*/
public int getSecond() {
return second;
}
/**
* Calculates the total number of seconds represented by this time schedule.
*
* @return The total number of seconds.
*/
public int getTotalSeconds() {
return second +
minute * 60 +
@@ -54,6 +79,12 @@ public class CompetitionSchedule {
weekday * 24 * 60 * 60;
}
/**
* Calculates the time difference (delta) in seconds between this time schedule and a given total seconds value.
*
* @param totalSeconds The total seconds value to compare against.
* @return The time difference in seconds.
*/
public int getTimeDelta(int totalSeconds) {
int thisSeconds = getTotalSeconds();
if (thisSeconds >= totalSeconds) {

View File

@@ -43,6 +43,9 @@ public class ActionBarManager implements Listener {
this.competition = competition;
}
/**
* Loads the ActionBar manager, registering events and showing ActionBar messages to online players.
*/
public void load() {
Bukkit.getPluginManager().registerEvents(this, CustomFishingPlugin.getInstance());
if (actionBarConfig.isShowToAll()) {
@@ -56,6 +59,9 @@ public class ActionBarManager implements Listener {
}
}
/**
* Unloads the ActionBar manager, unregistering events and hiding ActionBar messages for all players.
*/
public void unload() {
HandlerList.unregisterAll(this);
for (ActionBarSender ActionBarSender : senderMap.values()) {
@@ -64,6 +70,11 @@ public class ActionBarManager implements Listener {
senderMap.clear();
}
/**
* Handles the PlayerQuitEvent to hide ActionBar messages for a player when they quit the game.
*
* @param event The PlayerQuitEvent.
*/
@EventHandler
public void onQuit(PlayerQuitEvent event) {
final Player player = event.getPlayer();
@@ -74,6 +85,11 @@ public class ActionBarManager implements Listener {
}
}
/**
* Handles the PlayerJoinEvent to show ActionBar messages to players when they join the game.
*
* @param event The PlayerJoinEvent.
*/
@EventHandler
public void onJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
@@ -90,6 +106,11 @@ public class ActionBarManager implements Listener {
}, 200, TimeUnit.MILLISECONDS);
}
/**
* Shows an ActionBar message to a specific player.
*
* @param player The player to show the ActionBar message to.
*/
public void showActionBarTo(Player player) {
ActionBarSender sender = senderMap.get(player.getUniqueId());
if (sender == null) {

View File

@@ -29,6 +29,9 @@ import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
/**
* Manages and updates ActionBar messages for a specific player in a competition context.
*/
public class ActionBarSender {
private final Player player;
@@ -42,6 +45,13 @@ public class ActionBarSender {
private final Competition competition;
private final HashMap<String, String> privatePlaceholders;
/**
* Creates a new ActionBarSender instance for a player.
*
* @param player The player to manage ActionBar messages for.
* @param config The configuration for ActionBar messages.
* @param competition The competition associated with this ActionBarSender.
*/
public ActionBarSender(Player player, ActionBarConfig config, Competition competition) {
this.player = player;
this.config = config;
@@ -59,6 +69,9 @@ public class ActionBarSender {
}
}
/**
* Updates private placeholders used in ActionBar messages.
*/
@SuppressWarnings("DuplicatedCode")
private void updatePrivatePlaceholders() {
this.privatePlaceholders.put("{score}", String.format("%.2f", competition.getRanking().getPlayerScore(player.getName())));
@@ -67,6 +80,9 @@ public class ActionBarSender {
this.privatePlaceholders.putAll(competition.getCachedPlaceholders());
}
/**
* Shows the ActionBar message to the player.
*/
public void show() {
this.isShown = true;
senderTask = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> {
@@ -90,16 +106,29 @@ public class ActionBarSender {
}, 50, 50, TimeUnit.MILLISECONDS);
}
/**
* Hides the ActionBar message from the player.
*/
public void hide() {
if (senderTask != null && !senderTask.isCancelled())
senderTask.cancel();
this.isShown = false;
}
/**
* Checks if the ActionBar message is currently visible to the player.
*
* @return True if the ActionBar message is visible, false otherwise.
*/
public boolean isVisible() {
return this.isShown;
}
/**
* Gets the ActionBar configuration.
*
* @return The ActionBar configuration.
*/
public ActionBarConfig getConfig() {
return config;
}

View File

@@ -43,6 +43,9 @@ public class BossBarManager implements Listener {
this.competition = competition;
}
/**
* Loads the boss bar manager, registering events and showing boss bars to online players.
*/
public void load() {
Bukkit.getPluginManager().registerEvents(this, CustomFishingPlugin.getInstance());
if (bossBarConfig.isShowToAll()) {
@@ -56,6 +59,9 @@ public class BossBarManager implements Listener {
}
}
/**
* Unloads the boss bar manager, unregistering events and hiding boss bars for all players.
*/
public void unload() {
HandlerList.unregisterAll(this);
for (BossBarSender bossBarSender : senderMap.values()) {
@@ -64,6 +70,11 @@ public class BossBarManager implements Listener {
senderMap.clear();
}
/**
* Handles the PlayerQuitEvent to hide the boss bar for a player when they quit the game.
*
* @param event The PlayerQuitEvent.
*/
@EventHandler
public void onQuit(PlayerQuitEvent event) {
final Player player = event.getPlayer();
@@ -74,6 +85,11 @@ public class BossBarManager implements Listener {
}
}
/**
* Handles the PlayerJoinEvent to show boss bars to players when they join the game.
*
* @param event The PlayerJoinEvent.
*/
@EventHandler
public void onJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
@@ -90,6 +106,11 @@ public class BossBarManager implements Listener {
}, 200, TimeUnit.MILLISECONDS);
}
/**
* Shows a boss bar to a specific player.
*
* @param player The player to show the boss bar to.
*/
public void showBossBarTo(Player player) {
BossBarSender sender = senderMap.get(player.getUniqueId());
if (sender == null) {

View File

@@ -40,6 +40,9 @@ import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* Manages and updates boss bars for a specific player in a competition context.
*/
public class BossBarSender {
private final Player player;
@@ -54,6 +57,13 @@ public class BossBarSender {
private final Competition competition;
private final HashMap<String, String> privatePlaceholders;
/**
* Creates a new BossBarSender instance for a player.
*
* @param player The player to manage the boss bar for.
* @param config The configuration for the boss bar.
* @param competition The competition associated with this boss bar.
*/
public BossBarSender(Player player, BossBarConfig config, Competition competition) {
this.player = player;
this.uuid = UUID.randomUUID();
@@ -72,6 +82,9 @@ public class BossBarSender {
}
}
/**
* Updates private placeholders used in boss bar messages.
*/
@SuppressWarnings("DuplicatedCode")
private void updatePrivatePlaceholders() {
this.privatePlaceholders.put("{score}", String.format("%.2f", competition.getRanking().getPlayerScore(player.getName())));
@@ -80,6 +93,9 @@ public class BossBarSender {
this.privatePlaceholders.putAll(competition.getCachedPlaceholders());
}
/**
* Shows the boss bar to the player.
*/
public void show() {
this.isShown = true;
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getCreatePacket());
@@ -103,14 +119,27 @@ public class BossBarSender {
}, 50, 50, TimeUnit.MILLISECONDS);
}
/**
* Checks if the boss bar is currently visible to the player.
*
* @return True if the boss bar is visible, false otherwise.
*/
public boolean isVisible() {
return this.isShown;
}
/**
* Gets the boss bar configuration.
*
* @return The boss bar configuration.
*/
public BossBarConfig getConfig() {
return config;
}
/**
* Hides the boss bar from the player.
*/
public void hide() {
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getRemovePacket());
if (senderTask != null && !senderTask.isCancelled()) senderTask.cancel();

View File

@@ -23,6 +23,9 @@ import net.momirealms.customfishing.api.mechanic.competition.Ranking;
import java.util.*;
/**
* Implementation of the Ranking interface that manages the ranking of competition players locally.
*/
public class LocalRankingImpl implements Ranking {
private final Set<CompetitionPlayer> competitionPlayers;
@@ -31,19 +34,38 @@ public class LocalRankingImpl implements Ranking {
competitionPlayers = Collections.synchronizedSet(new TreeSet<>());
}
/**
* Adds a competition player to the ranking.
*
* @param competitionPlayer The CompetitionPlayer to add.
*/
public void addPlayer(CompetitionPlayer competitionPlayer) {
competitionPlayers.add(competitionPlayer);
}
/**
* Removes a competition player from the ranking.
*
* @param competitionPlayer The CompetitionPlayer to remove.
*/
public void removePlayer(CompetitionPlayer competitionPlayer) {
competitionPlayers.removeIf(e -> e.equals(competitionPlayer));
}
/**
* Clears the list of competition players.
*/
@Override
public void clear() {
competitionPlayers.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.
*/
@Override
public CompetitionPlayer getCompetitionPlayer(String player) {
for (CompetitionPlayer competitionPlayer : competitionPlayers) {
@@ -54,6 +76,11 @@ public class LocalRankingImpl implements Ranking {
return null;
}
/**
* Returns an iterator for iterating over pairs of player names and scores.
*
* @return An iterator for pairs of player names and scores.
*/
@Override
public Iterator<Pair<String, Double>> getIterator() {
List<Pair<String, Double>> players = new ArrayList<>();
@@ -63,11 +90,22 @@ public class LocalRankingImpl implements Ranking {
return players.iterator();
}
/**
* Returns the number of competition players.
*
* @return The number of competition players.
*/
@Override
public int getSize() {
return competitionPlayers.size();
}
/**
* 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.
*/
@Override
public int getPlayerRank(String player) {
int index = 1;
@@ -81,6 +119,12 @@ public class LocalRankingImpl implements Ranking {
return -1;
}
/**
* 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.
*/
@Override
public double getPlayerScore(String player) {
for (CompetitionPlayer competitionPlayer : competitionPlayers) {
@@ -91,6 +135,12 @@ public class LocalRankingImpl implements Ranking {
return 0;
}
/**
* Returns the name of a player at a given index.
*
* @param i The index of the player to retrieve.
* @return The name of the player at the specified index, or null if not found.
*/
@Override
public String getPlayerAt(int i) {
int index = 1;
@@ -103,6 +153,12 @@ public class LocalRankingImpl implements Ranking {
return null;
}
/**
* Returns the score of a player at a given index.
*
* @param i The index of the player to retrieve.
* @return The score of the player at the specified index, or 0 if not found.
*/
@Override
public double getScoreAt(int i) {
int index = 1;
@@ -115,6 +171,12 @@ public class LocalRankingImpl implements Ranking {
return 0f;
}
/**
* 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.
*/
@Override
public void refreshData(String player, double score) {
CompetitionPlayer competitionPlayer = getCompetitionPlayer(player);
@@ -128,6 +190,12 @@ public class LocalRankingImpl implements Ranking {
}
}
/**
* 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.
*/
@Override
public void setData(String player, double score) {
CompetitionPlayer competitionPlayer = getCompetitionPlayer(player);

View File

@@ -29,6 +29,9 @@ import java.util.List;
public class RedisRankingImpl implements Ranking {
/**
* Clears the ranking data by removing all players and scores.
*/
@Override
public void clear() {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -36,6 +39,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Retrieves a competition player by their name from the Redis ranking.
*
* @param player The name of the player to retrieve.
* @return The CompetitionPlayer object if found, or null if not found.
*/
@Override
public CompetitionPlayer getCompetitionPlayer(String player) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -45,6 +54,11 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns an iterator for iterating over pairs of player names and scores in descending order.
*
* @return An iterator for pairs of player names and scores.
*/
@Override
public Iterator<Pair<String, Double>> getIterator() {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -53,6 +67,11 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns the number of players in the Redis ranking.
*
* @return The number of players in the ranking.
*/
@Override
public int getSize() {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -61,6 +80,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns the rank of a player based on their name in descending order (1-based).
*
* @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.
*/
@Override
public int getPlayerRank(String player) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -71,6 +96,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns the score of a player based on their name from the Redis ranking.
*
* @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.
*/
@Override
public double getPlayerScore(String player) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -81,6 +112,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Refreshes the data for a player in the Redis ranking 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.
*/
@Override
public void refreshData(String player, double score) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -88,6 +125,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Sets the data for a player in the Redis ranking, 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.
*/
@Override
public void setData(String player, double score) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -95,6 +138,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns the name of the player at a given rank in descending order.
*
* @param rank The rank of the player to retrieve (1-based).
* @return The name of the player at the specified rank, or null if not found.
*/
@Override
public String getPlayerAt(int rank) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {
@@ -104,6 +153,12 @@ public class RedisRankingImpl implements Ranking {
}
}
/**
* Returns the score of the player at a given rank in descending order.
*
* @param rank The rank of the player to retrieve (1-based).
* @return The score of the player at the specified rank, or 0 if not found.
*/
@Override
public double getScoreAt(int rank) {
try (Jedis jedis = RedisManager.getInstance().getJedis()) {

View File

@@ -84,6 +84,9 @@ public class EntityManagerImpl implements EntityManager {
return entityLibraryMap.remove(identification) != null;
}
/**
* Load configuration files for entity properties.
*/
@SuppressWarnings("DuplicatedCode")
private void loadConfig() {
Deque<File> fileDeque = new ArrayDeque<>();
@@ -109,6 +112,11 @@ public class EntityManagerImpl implements EntityManager {
}
}
/**
* Load a single entity configuration file.
*
* @param file The YAML file to load.
*/
private void loadSingleFile(File file) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {

View File

@@ -28,6 +28,9 @@ import org.bukkit.inventory.ItemStack;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* A task responsible for animating bait when it's attached to a fishing hook.
*/
public class BaitAnimationTask implements Runnable {
private final CancellableTask cancellableTask;
@@ -35,6 +38,14 @@ public class BaitAnimationTask implements Runnable {
private final Player player;
private final FishHook fishHook;
/**
* Constructs a new BaitAnimationTask.
*
* @param plugin The CustomFishingPlugin instance.
* @param player The player who cast the fishing rod.
* @param fishHook The FishHook entity.
* @param baitItem The bait ItemStack.
*/
public BaitAnimationTask(CustomFishingPlugin plugin, Player player, FishHook fishHook, ItemStack baitItem) {
this.player = player;
this.fishHook = fishHook;
@@ -46,7 +57,7 @@ public class BaitAnimationTask implements Runnable {
@Override
public void run() {
if ( fishHook == null
if ( fishHook == null
|| fishHook.isOnGround()
|| fishHook.isInLava()
|| fishHook.isInWater()
@@ -59,6 +70,9 @@ public class BaitAnimationTask implements Runnable {
}
}
/**
* Cancels the bait animation and cleans up resources.
*/
private void cancelAnimation() {
cancellableTask.cancel();
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getDestroyPacket(entityID));

View File

@@ -244,6 +244,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
/**
* Handle the event when the fishing hook lands on the ground.
*
* @param event The PlayerFishEvent that occurred.
*/
private void onInGround(PlayerFishEvent event) {
final Player player = event.getPlayer();
FishHook hook = event.getHook();
@@ -262,6 +267,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
/**
* Handle the event when a player casts a fishing rod.
*
* @param event The PlayerFishEvent that occurred.
*/
public void onCastRod(PlayerFishEvent event) {
var player = event.getPlayer();
var fishingPreparation = new FishingPreparation(player, plugin);
@@ -312,6 +322,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
fishingPreparation.triggerActions(ActionTrigger.CAST);
}
/**
* Handle the event when a player catches an entity.
*
* @param event The PlayerFishEvent that occurred.
*/
private void onCaughtEntity(PlayerFishEvent event) {
final Player player = event.getPlayer();
final UUID uuid = player.getUniqueId();
@@ -361,6 +376,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
/**
* Handle the event when a player catches a fish.
*
* @param event The PlayerFishEvent that occurred.
*/
private void onCaughtFish(PlayerFishEvent event) {
final Player player = event.getPlayer();
final UUID uuid = player.getUniqueId();
@@ -405,6 +425,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
/**
* Handle the event when a player receives a bite on their fishing hook.
*
* @param event The PlayerFishEvent that occurred.
*/
private void onBite(PlayerFishEvent event) {
final Player player = event.getPlayer();
final UUID uuid = player.getUniqueId();
@@ -432,6 +457,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
/**
* Handle the event when a player reels in their fishing line.
*
* @param event The PlayerFishEvent that occurred.
*/
private void onReelIn(PlayerFishEvent event) {
final Player player = event.getPlayer();
final UUID uuid = player.getUniqueId();
@@ -559,6 +589,12 @@ public class FishingManagerImpl implements Listener, FishingManager {
ItemUtils.decreaseHookDurability(fishingPreparation.getRodItemStack(), 1, true);
}
/**
* Handle the success of a fishing attempt, including spawning loot, calling events, and executing success actions.
*
* @param state The temporary fishing state containing information about the loot and effect.
* @param hook The FishHook entity associated with the fishing attempt.
*/
public void success(TempFishingState state, FishHook hook) {
var loot = state.getLoot();
var effect = state.getEffect();
@@ -617,6 +653,14 @@ public class FishingManagerImpl implements Listener, FishingManager {
doSuccessActions(loot, effect, fishingPreparation, player);
}
/**
* Execute success-related actions after a successful fishing attempt, including updating competition data, triggering events and actions, and updating player statistics.
*
* @param loot The loot that was successfully caught.
* @param effect The effect applied during fishing.
* @param fishingPreparation The fishing preparation containing preparation data.
* @param player The player who successfully caught the loot.
*/
private void doSuccessActions(Loot loot, Effect effect, FishingPreparation fishingPreparation, Player player) {
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
if (competition != null) {

View File

@@ -46,6 +46,9 @@ import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* A task responsible for checking the state of a fishing hook and handling lava fishing mechanics.
*/
public class HookCheckTimerTask implements Runnable {
private final FishingManagerImpl manager;
@@ -62,6 +65,14 @@ public class HookCheckTimerTask implements Runnable {
private Entity hookedEntity;
private Loot loot;
/**
* Constructs a new HookCheckTimerTask.
*
* @param manager The FishingManagerImpl instance.
* @param fishHook The FishHook entity being checked.
* @param fishingPreparation The FishingPreparation instance.
* @param initialEffect The initial fishing effect.
*/
public HookCheckTimerTask(
FishingManagerImpl manager,
FishHook fishHook,
@@ -99,7 +110,7 @@ public class HookCheckTimerTask implements Runnable {
this.fishingPreparation.setLocation(fishHook.getLocation());
this.fishingPreparation.insertArg("{lava}", "true");
this.fishingPreparation.triggerActions(ActionTrigger.LAND);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.LAVA);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.LAVA, fishHook);
Bukkit.getPluginManager().callEvent(event);
firstTime = false;
this.setTempState();
@@ -130,7 +141,7 @@ public class HookCheckTimerTask implements Runnable {
this.fishingPreparation.insertArg("{lava}", "false");
this.fishingPreparation.insertArg("{open-water}", String.valueOf(fishHook.isInOpenWater()));
this.fishingPreparation.triggerActions(ActionTrigger.LAND);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER, fishHook);
Bukkit.getPluginManager().callEvent(event);
// if the hook is in water
// then cancel the task
@@ -140,6 +151,9 @@ public class HookCheckTimerTask implements Runnable {
}
}
/**
* Destroys the task and associated entities.
*/
public void destroy() {
this.cancelSubTask();
this.removeTempEntity();
@@ -147,6 +161,9 @@ public class HookCheckTimerTask implements Runnable {
this.manager.removeHookCheckTask(fishingPreparation.getPlayer());
}
/**
* Cancels the lava fishing subtask if it's active.
*/
public void cancelSubTask() {
if (lavaFishingTask != null && !lavaFishingTask.isCancelled()) {
lavaFishingTask.cancel();
@@ -154,6 +171,9 @@ public class HookCheckTimerTask implements Runnable {
}
}
/**
* Sets temporary state and prepares for the next loot.
*/
private void setTempState() {
Loot nextLoot = CustomFishingPlugin.get().getLootManager().getNextLoot(initialEffect, fishingPreparation);
if (nextLoot == null)
@@ -171,11 +191,17 @@ public class HookCheckTimerTask implements Runnable {
)));
}
/**
* Removes the temporary hooked entity.
*/
public void removeTempEntity() {
if (hookedEntity != null && !hookedEntity.isDead())
hookedEntity.remove();
}
/**
* Starts the lava fishing mechanic.
*/
private void startLavaFishingMechanic() {
// get random time
int random = ThreadLocalRandom.current().nextInt(CFConfig.lavaMinTime, CFConfig.lavaMaxTime);
@@ -191,6 +217,9 @@ public class HookCheckTimerTask implements Runnable {
);
}
/**
* Handles the hook state of the fish hook.
*/
public void getHooked() {
LavaFishingEvent lavaFishingEvent = new LavaFishingEvent(fishingPreparation.getPlayer(), LavaFishingEvent.State.BITE, fishHook);
Bukkit.getPluginManager().callEvent(lavaFishingEvent);
@@ -240,6 +269,11 @@ public class HookCheckTimerTask implements Runnable {
fishHook.setHookedEntity(hookedEntity);
}
/**
* Checks if the fish hook is currently hooked.
*
* @return True if the fish hook is hooked, false otherwise.
*/
public boolean isFishHooked() {
return fishHooked;
}

View File

@@ -24,6 +24,9 @@ import org.bukkit.Particle;
import java.util.concurrent.TimeUnit;
/**
* A task responsible for creating a lava effect animation between two points.
*/
public class LavaEffectTask implements Runnable {
private final Location startLoc;
@@ -33,9 +36,16 @@ public class LavaEffectTask implements Runnable {
private final CancellableTask lavaTask;
private final HookCheckTimerTask hookCheckTimerTask;
public LavaEffectTask(HookCheckTimerTask hookCheckTimerTask, Location loc, int delay) {
/**
* Constructs a new LavaEffectTask.
*
* @param hookCheckTimerTask The HookCheckTimerTask instance.
* @param location The starting location for the lava effect.
* @param delay The delay before starting the task.
*/
public LavaEffectTask(HookCheckTimerTask hookCheckTimerTask, Location location, int delay) {
this.hookCheckTimerTask = hookCheckTimerTask;
this.startLoc = loc.clone().add(0,0.3,0);
this.startLoc = location.clone().add(0,0.3,0);
this.endLoc = this.startLoc.clone().add((Math.random() * 16 - 8), startLoc.getY(), (Math.random() * 16 - 8));
this.controlLoc = new Location(
startLoc.getWorld(),
@@ -60,11 +70,19 @@ public class LavaEffectTask implements Runnable {
}
}
/**
* Cancels the lava effect task.
*/
public void cancel() {
if (lavaTask != null && !lavaTask.isCancelled())
lavaTask.cancel();
}
/**
* Checks if the lava effect task is cancelled.
*
* @return True if the task is cancelled, false otherwise.
*/
public boolean isCancelled() {
return lavaTask.isCancelled();
}

View File

@@ -39,6 +39,7 @@ import net.momirealms.customfishing.compatibility.item.CustomFishingItemImpl;
import net.momirealms.customfishing.compatibility.item.VanillaItemImpl;
import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl;
import net.momirealms.customfishing.setting.CFConfig;
import net.momirealms.customfishing.util.ConfigUtils;
import net.momirealms.customfishing.util.ItemUtils;
import net.momirealms.customfishing.util.NBTUtils;
import org.bukkit.Bukkit;
@@ -116,6 +117,10 @@ public class ItemManagerImpl implements ItemManager, Listener {
this.itemLibraryMap.clear();
}
/**
* Loads items from the plugin folder.
* This method scans various item types (item, bait, rod, util, hook) in the plugin's content folder and loads their configurations.
*/
@SuppressWarnings("DuplicatedCode")
public void loadItemsFromPluginFolder() {
Deque<File> fileDeque = new ArrayDeque<>();
@@ -141,6 +146,12 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
/**
* Loads a single item configuration file.
*
* @param file The YAML configuration file to load.
* @param namespace The namespace of the item type (item, bait, rod, util, hook).
*/
private void loadSingleFile(File file, String namespace) {
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file);
for (Map.Entry<String, Object> entry : yaml.getValues(false).entrySet()) {
@@ -304,16 +315,16 @@ public class ItemManagerImpl implements ItemManager, Listener {
itemCFBuilder
.amount(section.getInt("amount", 1))
.stackable(section.getBoolean("stackable", true))
.size(getSizePair(section.getString("size")))
.size(ConfigUtils.getSizePair(section.getString("size")))
.price((float) section.getDouble("price.base"), (float) section.getDouble("price.bonus"))
.customModelData(section.getInt("custom-model-data"))
.nbt(section.getConfigurationSection("nbt"))
.maxDurability(section.getInt("max-durability"))
.itemFlag(section.getStringList("item-flags").stream().map(flag -> ItemFlag.valueOf(flag.toUpperCase())).toList())
.enchantment(getEnchantmentPair(section.getConfigurationSection("enchantments")), false)
.enchantment(getEnchantmentPair(section.getConfigurationSection("stored-enchantments")), true)
.randomEnchantments(getEnchantmentTuple(section.getConfigurationSection("random-enchantments")), false)
.randomEnchantments(getEnchantmentTuple(section.getConfigurationSection("random-stored-enchantments")), true)
.enchantment(ConfigUtils.getEnchantmentPair(section.getConfigurationSection("enchantments")), false)
.enchantment(ConfigUtils.getEnchantmentPair(section.getConfigurationSection("stored-enchantments")), true)
.randomEnchantments(ConfigUtils.getEnchantmentTuple(section.getConfigurationSection("random-enchantments")), false)
.randomEnchantments(ConfigUtils.getEnchantmentTuple(section.getConfigurationSection("random-stored-enchantments")), true)
.tag(section.getBoolean("tag", true), type, id)
.randomDamage(section.getBoolean("random-durability", false))
.unbreakable(section.getBoolean("unbreakable", false))
@@ -445,42 +456,6 @@ public class ItemManagerImpl implements ItemManager, Listener {
ItemUtils.setDurability(itemStack, amount, updateLore);
}
@NotNull
private List<Pair<String, Short>> getEnchantmentPair(ConfigurationSection section) {
List<Pair<String, Short>> list = new ArrayList<>();
if (section == null) return list;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof Integer integer) {
list.add(Pair.of(entry.getKey(), Short.valueOf(String.valueOf(integer))));
}
}
return list;
}
@NotNull
private List<Tuple<Double, String, Short>> getEnchantmentTuple(ConfigurationSection section) {
List<Tuple<Double, String, Short>> list = new ArrayList<>();
if (section == null) return list;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection inner) {
Tuple<Double, String, Short> tuple = Tuple.of(
inner.getDouble("chance"),
inner.getString("enchant"),
Short.valueOf(String.valueOf(inner.getInt("level")))
);
list.add(tuple);
}
}
return list;
}
@Nullable
private Pair<Float, Float> getSizePair(String size) {
if (size == null) return null;
String[] split = size.split("~", 2);
return Pair.of(Float.parseFloat(split[0]), Float.parseFloat(split[1]));
}
public static class CFBuilder implements ItemBuilder {
private final String library;
@@ -763,6 +738,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
/**
* Handles item pickup by players.
*
* @param event The PlayerAttemptPickupItemEvent.
*/
@EventHandler
public void onPickUp(PlayerAttemptPickupItemEvent event) {
if (event.isCancelled()) return;
@@ -777,6 +757,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
/**
* Handles item movement in inventories.
*
* @param event The InventoryPickupItemEvent.
*/
@EventHandler
public void onMove(InventoryPickupItemEvent event) {
if (event.isCancelled()) return;
@@ -787,7 +772,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
/**
* Handles item consumption by players.
*
* @param event The PlayerItemConsumeEvent.
*/
@EventHandler
public void onConsumeItem(PlayerItemConsumeEvent event) {
if (event.isCancelled()) return;
@@ -801,6 +790,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
/**
* Handles the repair of custom items in an anvil.
*
* @param event The PrepareAnvilEvent.
*/
@EventHandler
public void onRepairItem(PrepareAnvilEvent event) {
ItemStack result = event.getInventory().getResult();
@@ -816,6 +810,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
event.setResult(nbtItem.getItem());
}
/**
* Handles the mending of custom items.
*
* @param event The PlayerItemMendEvent.
*/
@EventHandler
public void onMending(PlayerItemMendEvent event) {
if (event.isCancelled()) return;
@@ -827,6 +826,11 @@ public class ItemManagerImpl implements ItemManager, Listener {
ItemUtils.increaseDurability(itemStack, event.getRepairAmount(), true);
}
/**
* Handles interactions with custom utility items.
*
* @param event The PlayerInteractEvent.
*/
@EventHandler
public void onInteractWithUtils(PlayerInteractEvent event) {
if (event.useItemInHand() == Event.Result.DENY)

View File

@@ -254,7 +254,6 @@ public class LootManagerImpl implements LootManager {
.disableGames(section.getBoolean("disable-game", false))
.instantGame(section.getBoolean("instant-game", false))
.showInFinder(section.getBoolean("show-in-fishfinder", true))
.gameConfig(section.getString("game"))
.score(section.getDouble("score"))
.lootGroup(ConfigUtils.stringListArgs(section.get("group")).toArray(new String[0]))
.nick(section.getString("nick", section.getString("display.name", key)))

View File

@@ -22,8 +22,10 @@ import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
import net.momirealms.customfishing.mechanic.totem.particle.ParticleSetting;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import org.bukkit.Location;
import java.util.ArrayList;
@@ -44,7 +46,7 @@ public class ActivatedTotem {
this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
this.totemConfig = config;
this.effectCarrier = CustomFishingPlugin.get().getEffectManager().getEffectCarrier("totem", config.getKey());
for (ParticleSetting particleSetting : config.getParticleSettings()) {
for (TotemParticle particleSetting : config.getParticleSettings()) {
this.subTasks.add(particleSetting.start(coreLocation, config.getRadius()));
}
}

View File

@@ -20,18 +20,21 @@ package net.momirealms.customfishing.mechanic.totem;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.common.SimpleLocation;
import net.momirealms.customfishing.api.event.TotemActivateEvent;
import net.momirealms.customfishing.api.manager.TotemManager;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier;
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
import net.momirealms.customfishing.api.mechanic.totem.TotemModel;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import net.momirealms.customfishing.mechanic.totem.block.TotemBlock;
import net.momirealms.customfishing.mechanic.totem.block.property.AxisImpl;
import net.momirealms.customfishing.mechanic.totem.block.property.FaceImpl;
import net.momirealms.customfishing.mechanic.totem.block.property.HalfImpl;
import net.momirealms.customfishing.mechanic.totem.block.property.TotemBlockProperty;
import net.momirealms.customfishing.mechanic.totem.block.type.TypeCondition;
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
import net.momirealms.customfishing.api.mechanic.totem.block.property.AxisImpl;
import net.momirealms.customfishing.api.mechanic.totem.block.property.FaceImpl;
import net.momirealms.customfishing.api.mechanic.totem.block.property.HalfImpl;
import net.momirealms.customfishing.api.mechanic.totem.block.property.TotemBlockProperty;
import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
import net.momirealms.customfishing.mechanic.totem.particle.DustParticleSetting;
import net.momirealms.customfishing.mechanic.totem.particle.ParticleSetting;
import net.momirealms.customfishing.util.LocationUtils;
@@ -165,6 +168,13 @@ public class TotemManagerImpl implements TotemManager, Listener {
Condition condition = new Condition(block.getLocation(), event.getPlayer(), new HashMap<>());
if (!carrier.isConditionMet(condition))
return;
TotemActivateEvent totemActivateEvent = new TotemActivateEvent(event.getPlayer(), block.getLocation(), config);
Bukkit.getPluginManager().callEvent(totemActivateEvent);
if (totemActivateEvent.isCancelled()) {
return;
}
Action[] actions = carrier.getActionMap().get(ActionTrigger.ACTIVATE);
if (actions != null)
for (Action action : actions) {
@@ -331,7 +341,7 @@ public class TotemManagerImpl implements TotemManager, Listener {
TotemModel originalModel = parseModel(section);
List<TotemModel> modelList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
originalModel = originalModel.clone().rotate90();
originalModel = originalModel.deepClone().rotate90();
modelList.add(originalModel);
if (i % 2 == 0) {
modelList.add(originalModel.mirrorVertically());

View File

@@ -19,6 +19,7 @@ package net.momirealms.customfishing.mechanic.totem.particle;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
@@ -29,7 +30,7 @@ import org.bukkit.World;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ParticleSetting {
public class ParticleSetting implements TotemParticle {
protected final Expression expressionHorizontal;
protected final Expression expressionVertical;

View File

@@ -75,7 +75,7 @@ public class StorageManagerImpl implements StorageManager, Listener {
private RedisManager redisManager;
private String uniqueID;
private CancellableTask timerSaveTask;
private Gson gson;
private final Gson gson;
public StorageManagerImpl(CustomFishingPluginImpl plugin) {
this.plugin = plugin;

View File

@@ -18,18 +18,23 @@
package net.momirealms.customfishing.util;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.common.Tuple;
import net.momirealms.customfishing.api.mechanic.loot.WeightModifier;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Utility class for configuration-related operations.
@@ -97,6 +102,19 @@ public class ConfigUtils {
return 0;
}
/**
* Parses a string representing a size range and returns a pair of floats.
*
* @param size The size string in the format "min~max".
* @return A pair of floats representing the minimum and maximum size.
*/
@Nullable
public static Pair<Float, Float> getSizePair(String size) {
if (size == null) return null;
String[] split = size.split("~", 2);
return Pair.of(Float.parseFloat(split[0]), Float.parseFloat(split[1]));
}
/**
* Converts a list of strings in the format "key:value" into a list of Pairs with keys and WeightModifiers.
*
@@ -113,6 +131,47 @@ public class ConfigUtils {
return result;
}
/**
* Retrieves a list of enchantment pairs from a configuration section.
*
* @param section The configuration section to extract enchantment data from.
* @return A list of enchantment pairs.
*/
@NotNull
public static List<Pair<String, Short>> getEnchantmentPair(ConfigurationSection section) {
List<Pair<String, Short>> list = new ArrayList<>();
if (section == null) return list;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof Integer integer) {
list.add(Pair.of(entry.getKey(), Short.valueOf(String.valueOf(integer))));
}
}
return list;
}
/**
* Retrieves a list of enchantment tuples from a configuration section.
*
* @param section The configuration section to extract enchantment data from.
* @return A list of enchantment tuples.
*/
@NotNull
public static List<Tuple<Double, String, Short>> getEnchantmentTuple(ConfigurationSection section) {
List<Tuple<Double, String, Short>> list = new ArrayList<>();
if (section == null) return list;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection inner) {
Tuple<Double, String, Short> tuple = Tuple.of(
inner.getDouble("chance"),
inner.getString("enchant"),
Short.valueOf(String.valueOf(inner.getInt("level")))
);
list.add(tuple);
}
}
return list;
}
/**
* Reads data from a YAML configuration file and creates it if it doesn't exist.
*