9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-31 04:46:36 +00:00

checkpoint - 21

This commit is contained in:
XiaoMoMi
2024-07-03 02:55:33 +08:00
parent 71de6ea626
commit f3d21e466d
46 changed files with 657 additions and 403 deletions

View File

@@ -205,5 +205,5 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin,
public abstract void enable();
public abstract void debug(String message);
public abstract void debug(Object message);
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.event;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a fishing hook lands in either lava or water.
*/
public class FishHookLandEvent extends PlayerEvent {
private static final HandlerList handlerList = new HandlerList();
private final Target target;
private final FishHook fishHook;
private final Effect effect;
private final boolean isFirst;
/**
* Constructs a new FishHookLandEvent.
*
* @param who The player who triggered the event.
* @param target The target where the fishing hook has landed (LAVA or WATER).
* @param hook The fishing hook entity.
* @param initialEffect The initial effect
*/
public FishHookLandEvent(@NotNull Player who, Target target, FishHook hook, boolean isFirst, Effect initialEffect) {
super(who);
this.target = target;
this.fishHook = hook;
this.effect = initialEffect;
this.isFirst = isFirst;
}
/**
* Gets the target where the fishing hook has landed.
*
* @return The target, which can be either LAVA or WATER.
*/
public Target getTarget() {
return target;
}
/**
* Gets the fish hook bukkit entity
*
* @return fish hook
*/
public FishHook getFishHook() {
return fishHook;
}
public static HandlerList getHandlerList() {
return handlerList;
}
/**
* Is the first try of one fishing catch
*
* @return is first try
*/
public boolean isFirst() {
return isFirst;
}
/**
* Get the fishing effect
* It's not advised to modify this value without checking "isFirst()" since this event can be trigger multiple times in one fishing catch
*
* @return fishing effect
*/
public Effect getEffect() {
return effect;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public enum Target {
LAVA,
WATER
}
}

View File

@@ -17,52 +17,46 @@
package net.momirealms.customfishing.api.event;
import org.bukkit.Location;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class FishingLootPreSpawnEvent extends PlayerEvent implements Cancellable {
public class FishingHookStateEvent extends PlayerEvent {
private static final HandlerList handlerList = new HandlerList();
private final Location location;
private final ItemStack itemStack;
private boolean isCancelled;
private final FishHook fishHook;
private final State state;
public FishingLootPreSpawnEvent(@NotNull Player who, Location location, ItemStack itemStack) {
public FishingHookStateEvent(@NotNull Player who, FishHook hook, State state) {
super(who);
this.itemStack = itemStack;
this.location = location;
this.isCancelled = false;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
public Location getLocation() {
return location;
}
public ItemStack getItemStack() {
return itemStack;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
this.fishHook = hook;
this.state = state;
}
public static HandlerList getHandlerList() {
return handlerList;
}
public FishHook getFishHook() {
return fishHook;
}
public State getState() {
return state;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public enum State {
BITE,
ESCAPE,
LURE,
LAND
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.api.event;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* This class represents an event that occurs when a player fishes in lava.
*/
public class LavaFishingEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final State state;
private boolean isCancelled;
private final FishHook hook;
/**
* Constructs a new LavaFishingEvent.
*
* @param who The player who triggered the event.
* @param state The state of the fishing action (REEL_IN, CAUGHT_FISH, or BITE).
* @param hook The FishHook entity associated with the fishing action.
*/
public LavaFishingEvent(@NotNull Player who, State state, FishHook hook) {
super(who);
this.state = state;
this.isCancelled = false;
this.hook = hook;
}
/**
* Gets the state of the fishing action.
*
* @return The fishing state, which can be REEL_IN, CAUGHT_FISH, or BITE.
*/
public State getState() {
return state;
}
/**
* Gets the FishHook entity associated with the fishing action.
*
* @return The FishHook entity used in the fishing action.
*/
public FishHook getHook() {
return hook;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
/**
* An enumeration representing possible states of the fishing action (REEL_IN, CAUGHT_FISH, BITE).
*/
public enum State {
REEL_IN,
CAUGHT_FISH,
BITE
}
}

View File

@@ -25,8 +25,11 @@ public enum ActionTrigger {
CAST,
BITE,
LAND,
LURE,
ESCAPE,
ACTIVATE,
TIMER,
INTERACT,
REEL,
NEW_SIZE_RECORD
}

View File

@@ -47,6 +47,15 @@ public final class CompetitionGoal {
}),
() -> Optional.ofNullable(StandardLocales.GOAL_MAX_SIZE).orElse("max_size")
);
public static final CompetitionGoal MIN_SIZE = new CompetitionGoal(
"min_size",
((rankingProvider, player, score) -> {
if (rankingProvider.getPlayerScore(player) > score) {
rankingProvider.setData(player, score);
}
}),
() -> Optional.ofNullable(StandardLocales.GOAL_MIN_SIZE).orElse("min_size")
);
public static final CompetitionGoal TOTAL_SIZE = new CompetitionGoal(
"total_size",
(RankingProvider::refreshData),

View File

@@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
@@ -101,7 +102,7 @@ public class BaitConfigParser {
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id)
.type(MechanicType.ROD);
.type(MechanicType.BAIT);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
@@ -119,6 +120,7 @@ public class BaitConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ITEM)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);

View File

@@ -7,6 +7,7 @@ import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import java.util.ArrayList;
@@ -85,6 +86,7 @@ public class BlockConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.BLOCK)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
@@ -95,7 +97,7 @@ public class BlockConfigParser {
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(MechanicType.LOOT);
.type(MechanicType.BLOCK);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}

View File

@@ -66,6 +66,7 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected boolean enableVoidFishing;
protected int voidMinTime;
protected int voidMaxTime;
protected int multipleLootSpawnDelay;
protected boolean restrictedSizeRange;
protected List<String> durabilityLore;
protected boolean allowMultipleTotemType;
@@ -160,6 +161,10 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.voidMaxTime;
}
public static int multipleLootSpawnDelay() {
return instance.multipleLootSpawnDelay;
}
public static boolean restrictedSizeRange() {
return instance.restrictedSizeRange;
}

View File

@@ -25,6 +25,7 @@ public class ConfigType {
public static final ConfigType ENTITY = of(
"entity",
(id, section, functions) -> {
MechanicType.register(id, MechanicType.ENTITY);
EntityConfigParser config = new EntityConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getEntityManager().registerEntity(config.getEntity());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());
@@ -35,6 +36,7 @@ public class ConfigType {
public static final ConfigType BLOCK = of(
"block",
(id, section, functions) -> {
MechanicType.register(id, MechanicType.BLOCK);
BlockConfigParser config = new BlockConfigParser(id, section, functions);
BukkitCustomFishingPlugin.getInstance().getBlockManager().registerBlock(config.getBlock());
BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot());

View File

@@ -4,11 +4,9 @@ import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.config.function.ConfigParserFunction;
import net.momirealms.customfishing.api.mechanic.config.function.EffectModifierParserFunction;
import net.momirealms.customfishing.api.mechanic.config.function.EventParserFunction;
import net.momirealms.customfishing.api.mechanic.config.function.TotemParserFunction;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
import net.momirealms.customfishing.common.config.node.Node;
import java.util.ArrayList;
@@ -58,7 +56,7 @@ public class EnchantConfigParser {
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(MechanicType.TOTEM);
.type(MechanicType.ENCHANT);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
@@ -68,7 +66,7 @@ public class EnchantConfigParser {
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id)
.type(MechanicType.TOTEM);
.type(MechanicType.ENCHANT);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}

View File

@@ -7,6 +7,7 @@ import net.momirealms.customfishing.api.mechanic.entity.EntityConfig;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import java.util.ArrayList;
@@ -85,6 +86,7 @@ public class EntityConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ENTITY)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);
@@ -95,7 +97,7 @@ public class EntityConfigParser {
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(MechanicType.LOOT);
.type(MechanicType.ENTITY);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}

View File

@@ -10,6 +10,7 @@ import net.momirealms.customfishing.api.mechanic.hook.HookConfig;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
@@ -108,7 +109,7 @@ public class HookConfigParser {
public EffectModifier getEffectModifier() {
EffectModifier.Builder builder = EffectModifier.builder()
.id(id)
.type(MechanicType.ROD);
.type(MechanicType.HOOK);
for (Consumer<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
@@ -135,6 +136,7 @@ public class HookConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ITEM)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);

View File

@@ -8,6 +8,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
@@ -92,6 +93,7 @@ public class ItemConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ITEM)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);

View File

@@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.Material;
@@ -120,6 +121,7 @@ public class RodConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ITEM)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);

View File

@@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.item.Item;
import org.bukkit.entity.Player;
@@ -91,7 +92,7 @@ public class UtilConfigParser {
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(MechanicType.BAIT);
.type(MechanicType.UTIL);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
@@ -118,6 +119,7 @@ public class UtilConfigParser {
public Loot getLoot() {
Loot.Builder builder = Loot.builder()
.id(id)
.type(LootType.ITEM)
.lootBaseEffect(getBaseEffect());
for (Consumer<Loot.Builder> consumer : lootBuilderConsumers) {
consumer.accept(builder);

View File

@@ -18,6 +18,7 @@
package net.momirealms.customfishing.api.mechanic.context;
import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import org.bukkit.Location;
import java.util.Objects;
@@ -30,6 +31,8 @@ public class ContextKeys<T> {
public static final ContextKeys<Integer> Z = of("z", Integer.class);
public static final ContextKeys<String> WORLD = of("world", String.class);
public static final ContextKeys<String> ID = of("id", String.class);
public static final ContextKeys<LootType> LOOT = of("loot", LootType.class);
public static final ContextKeys<String> NICK = of("nick", String.class);
public static final ContextKeys<Boolean> OPEN_WATER = of("open_water", Boolean.class);
public static final ContextKeys<String> TYPE = of("type", String.class);
public static final ContextKeys<Float> SIZE = of("SIZE", Float.class);
@@ -48,7 +51,9 @@ public class ContextKeys<T> {
public static final ContextKeys<String> SECOND = of("second", String.class);
public static final ContextKeys<Integer> SECONDS = of("seconds", Integer.class);
public static final ContextKeys<String> PLAYER = of("player", String.class);
public static final ContextKeys<String> SCORE = of("score", String.class);
public static final ContextKeys<String> SCORE_FORMATTED = of("score_formatted", String.class);
public static final ContextKeys<Double> SCORE = of("score", Double.class);
public static final ContextKeys<Double> CUSTOM_SCORE = of("custom_score", Double.class);
public static final ContextKeys<String> RANK = of("rank", String.class);
public static final ContextKeys<Location> HOOK_LOCATION = of("hook_location", Location.class);
public static final ContextKeys<Integer> HOOK_X = of("hook_x", Integer.class);

View File

@@ -1,34 +1,49 @@
package net.momirealms.customfishing.api.mechanic.fishing;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
import net.momirealms.customfishing.api.mechanic.fishing.hook.HookMechanic;
import net.momirealms.customfishing.api.mechanic.fishing.hook.LavaFishingMechanic;
import net.momirealms.customfishing.api.mechanic.fishing.hook.VanillaMechanic;
import net.momirealms.customfishing.api.mechanic.fishing.hook.VoidFishingMechanic;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.common.helper.AdventureHelper;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.customfishing.common.util.TriConsumer;
import net.momirealms.customfishing.common.util.TriFunction;
import org.bukkit.Statistic;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class CustomFishingHook {
private final BukkitCustomFishingPlugin plugin;
private final FishHook hook;
private final SchedulerTask task;
private final FishingGears gears;
private final Context<Player> context;
private Effect tempFinalEffect;
private HookMechanic hookMechanic;
private Loot nextLoot;
private Context<Player> context;
private static TriFunction<FishHook, Context<Player>, Effect, List<HookMechanic>> mechanicProviders = defaultMechanicProviders();
@@ -46,8 +61,10 @@ public class CustomFishingHook {
CustomFishingHook.mechanicProviders = mechanicProviders;
}
public CustomFishingHook(FishHook hook, FishingGears gears, Context<Player> context) {
public CustomFishingHook(BukkitCustomFishingPlugin plugin, FishHook hook, FishingGears gears, Context<Player> context) {
this.gears = gears;
this.gears.trigger(ActionTrigger.CAST, context);
this.plugin = plugin;
this.hook = hook;
// once it becomes a custom hook, the wait time is controlled by plugin
this.context = context;
@@ -59,10 +76,10 @@ public class CustomFishingHook {
}
}
List<HookMechanic> enabledMechanics = mechanicProviders.apply(hook, context, effect);
this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> {
this.task = plugin.getScheduler().sync().runRepeating(() -> {
// destroy if hook is invalid
if (!hook.isValid()) {
BukkitCustomFishingPlugin.getInstance().getFishingManager().destroy(hook.getOwnerUniqueId());
plugin.getFishingManager().destroy(hook.getOwnerUniqueId());
return;
}
if (this.hookMechanic != null) {
@@ -85,14 +102,25 @@ public class CustomFishingHook {
consumer.accept(tempEffect, context, 1);
}
}
context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation());
context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX());
context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY());
context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ());
// get the next loot
Loot loot = BukkitCustomFishingPlugin.getInstance().getLootManager().getNextLoot(effect, context);
Loot loot = plugin.getLootManager().getNextLoot(effect, context);
if (loot == null) {
BukkitCustomFishingPlugin.getInstance().debug("No loot available for player " + context.getHolder().getName());
plugin.debug("No loot available for player " + context.getHolder().getName());
return;
}
this.nextLoot = loot;
BukkitCustomFishingPlugin.getInstance().debug("Next loot: " + loot.id());
context.arg(ContextKeys.ID, loot.id());
context.arg(ContextKeys.NICK, loot.nick());
context.arg(ContextKeys.LOOT, loot.type());
plugin.debug("Next loot: " + loot.id());
// get its basic properties
Effect baseEffect = loot.baseEffect().toEffect(context);
tempEffect.combine(baseEffect);
@@ -104,6 +132,8 @@ public class CustomFishingHook {
}
// start the mechanic
mechanic.start(tempEffect);
this.tempFinalEffect = tempEffect;
}
}
}
@@ -134,15 +164,147 @@ public class CustomFishingHook {
public void onReelIn() {
if (hookMechanic != null) {
if (!hookMechanic.isHooked()) {
gears.trigger(ActionTrigger.REEL, context);
destroy();
System.out.println("fail");
} else {
System.out.println("succeed");
if (nextLoot.disableGame()) {
handleSuccessfulFishing();
destroy();
} else {
handleSuccessfulFishing();
destroy();
}
}
} else {
gears.trigger(ActionTrigger.REEL, context);
destroy();
}
}
public void onBite() {
gears.bite();
gears.trigger(ActionTrigger.BITE, context);
}
public void onLand() {
gears.trigger(ActionTrigger.LAND, context);
}
public void onEscape() {
gears.trigger(ActionTrigger.ESCAPE, context);
}
public void onLure() {
gears.trigger(ActionTrigger.LURE, context);
}
private void handleFailedFishing() {
// update the hook location
context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation());
context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX());
context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY());
context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ());
gears.trigger(ActionTrigger.FAILURE, context);
String id = context.arg(ContextKeys.ID);
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, MechanicType.getTypeByID(id), ActionTrigger.FAILURE);
}
private void handleSuccessfulFishing() {
// update the hook location
context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation());
context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX());
context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY());
context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ());
LootType lootType = context.arg(ContextKeys.LOOT);
Objects.requireNonNull(lootType, "Missing loot type");
Objects.requireNonNull(tempFinalEffect, "Missing final effects");
switch (lootType) {
case ITEM -> {
int amount = (int) tempFinalEffect.multipleLootChance();
amount += Math.random() < (tempFinalEffect.multipleLootChance() - amount) ? 2 : 1;
for (int i = 0; i < amount; i++) {
plugin.getScheduler().sync().runLater(() -> {
Item item = plugin.getItemManager().dropItemLoot(context, gears.getItem(FishingGears.GearType.ROD).stream().findAny().orElseThrow().right(), hook);
if (item != null) {
if (Objects.equals(context.arg(ContextKeys.NICK), "UNDEFINED")) {
ItemStack stack = item.getItemStack();
Optional<String> displayName = plugin.getItemManager().wrap(stack).displayName();
if (displayName.isPresent()) {
context.arg(ContextKeys.NICK, AdventureHelper.jsonToMiniMessage(displayName.get()));
} else {
context.arg(ContextKeys.NICK, "<lang:" + stack.getType().translationKey() + ">");
}
}
}
handleSuccess();
}, (long) ConfigManager.multipleLootSpawnDelay() * i, hook.getLocation());
}
}
case BLOCK -> {
BukkitCustomFishingPlugin.getInstance().getBlockManager().summonBlockLoot(context);
handleSuccess();
}
case ENTITY -> {
BukkitCustomFishingPlugin.getInstance().getEntityManager().summonEntityLoot(context);
handleSuccess();
}
}
gears.trigger(ActionTrigger.SUCCESS, context);
}
private void handleSuccess() {
FishingCompetition competition = BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getOnGoingCompetition();
if (competition != null && RequirementManager.isSatisfied(context, competition.getConfig().joinRequirements())) {
Double customScore = context.arg(ContextKeys.CUSTOM_SCORE);
if (customScore != null) {
competition.refreshData(context.getHolder(), customScore);
context.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", customScore));
context.arg(ContextKeys.SCORE, customScore);
} else {
double score = 0;
if (competition.getGoal() == CompetitionGoal.CATCH_AMOUNT) {
score = 1;
competition.refreshData(context.getHolder(), score);
} else if (competition.getGoal() == CompetitionGoal.MAX_SIZE || competition.getGoal() == CompetitionGoal.MIN_SIZE) {
Float size = context.arg(ContextKeys.SIZE);
if (size != null) {
competition.refreshData(context.getHolder(), size);
}
} else if (competition.getGoal() == CompetitionGoal.TOTAL_SCORE) {
score = nextLoot.score().evaluate(context);
if (score != 0) {
competition.refreshData(context.getHolder(), score);
}
}
context.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", score));
context.arg(ContextKeys.SCORE, score);
}
} else {
context.arg(ContextKeys.SCORE_FORMATTED, "0.0");
context.arg(ContextKeys.SCORE, 0d);
}
String id = context.arg(ContextKeys.ID);
Player player = context.getHolder();
MechanicType type = MechanicType.getTypeByID(id);
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.SUCCESS);
player.setStatistic(Statistic.FISH_CAUGHT, player.getStatistic(Statistic.FISH_CAUGHT) + 1);
if (!nextLoot.disableStats()) {
BukkitCustomFishingPlugin.getInstance().getStorageManager().getOnlineUser(player.getUniqueId()).ifPresent(
userData -> {
userData.statistics().addAmount(id, 1);
Optional.ofNullable(context.arg(ContextKeys.SIZE)).ifPresent(size -> {
if (userData.statistics().updateSize(id, size)) {
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.NEW_SIZE_RECORD);
}
});
}
);
}
}
}

View File

@@ -1,6 +1,7 @@
package net.momirealms.customfishing.api.mechanic.fishing;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
@@ -9,7 +10,10 @@ import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.api.storage.user.UserData;
import net.momirealms.customfishing.common.util.Pair;
import net.momirealms.customfishing.common.util.TriConsumer;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@@ -18,12 +22,24 @@ import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class FishingGears {
private static final Map<ActionTrigger, TriConsumer<GearType, Context<Player>, ItemStack>> triggers = new HashMap<>();
static {
triggers.put(ActionTrigger.CAST, ((type, context, itemStack) -> type.castFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.REEL, ((type, context, itemStack) -> type.reelFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.LAND, ((type, context, itemStack) -> type.landFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.ESCAPE, ((type, context, itemStack) -> type.escapeFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.LURE, ((type, context, itemStack) -> type.lureFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.SUCCESS, ((type, context, itemStack) -> type.successFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.FAILURE, ((type, context, itemStack) -> type.failureFunction.accept(context, itemStack)));
triggers.put(ActionTrigger.BITE, ((type, context, itemStack) -> type.biteFunction.accept(context, itemStack)));
}
private static BiConsumer<Context<Player>, FishingGears> fishingGearsConsumers = defaultFishingGearsConsumers();
private final HashMap<GearType, Collection<ItemStack>> gears = new HashMap<>();
private final HashMap<GearType, Collection<Pair<String, ItemStack>>> gears = new HashMap<>();
private final ArrayList<EffectModifier> modifiers = new ArrayList<>();
private boolean canFish = true;
@@ -39,42 +55,12 @@ public class FishingGears {
return canFish;
}
public void cast() {
for (Map.Entry<GearType, Collection<ItemStack>> entry : gears.entrySet()) {
for (ItemStack itemStack : entry.getValue()) {
entry.getKey().castFunction.accept(itemStack);
}
}
}
public void reel() {
for (Map.Entry<GearType, Collection<ItemStack>> entry : gears.entrySet()) {
for (ItemStack itemStack : entry.getValue()) {
entry.getKey().reelFunction.accept(itemStack);
}
}
}
public void succeed() {
for (Map.Entry<GearType, Collection<ItemStack>> entry : gears.entrySet()) {
for (ItemStack itemStack : entry.getValue()) {
entry.getKey().successFunction.accept(itemStack);
}
}
}
public void fail() {
for (Map.Entry<GearType, Collection<ItemStack>> entry : gears.entrySet()) {
for (ItemStack itemStack : entry.getValue()) {
entry.getKey().failureFunction.accept(itemStack);
}
}
}
public void bite() {
for (Map.Entry<GearType, Collection<ItemStack>> entry : gears.entrySet()) {
for (ItemStack itemStack : entry.getValue()) {
entry.getKey().biteFunction.accept(itemStack);
public void trigger(ActionTrigger trigger, Context<Player> context) {
for (Map.Entry<GearType, Collection<Pair<String, ItemStack>>> entry : gears.entrySet()) {
for (Pair<String, ItemStack> itemPair : entry.getValue()) {
BukkitCustomFishingPlugin.getInstance().debug(entry.getKey() + " | " + itemPair.left() + " | " + trigger);
triggers.get(trigger).accept(entry.getKey(), context, itemPair.right());
BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, itemPair.left(), entry.getKey().getType(), trigger);
}
}
}
@@ -85,7 +71,7 @@ public class FishingGears {
}
@NotNull
public Collection<ItemStack> getItem(GearType type) {
public Collection<Pair<String, ItemStack>> getItem(GearType type) {
return gears.getOrDefault(type, List.of());
}
@@ -98,7 +84,7 @@ public class FishingGears {
// set rod
boolean rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD;
String rodID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(rodOnMainHand ? mainHandItem : offHandItem);
fishingGears.gears.put(GearType.ROD, List.of(rodOnMainHand ? mainHandItem : offHandItem));
fishingGears.gears.put(GearType.ROD, List.of(Pair.of(rodID, rodOnMainHand ? mainHandItem : offHandItem)));
context.arg(ContextKeys.ROD, rodID);
BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(rodID, MechanicType.ROD).ifPresent(fishingGears.modifiers::add);
@@ -114,7 +100,7 @@ public class FishingGears {
String anotherItemID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(rodOnMainHand ? offHandItem : mainHandItem);
MechanicType type = MechanicType.getTypeByID(anotherItemID);
if (type == MechanicType.BAIT) {
fishingGears.gears.put(GearType.BAIT, List.of(rodOnMainHand ? offHandItem : mainHandItem));
fishingGears.gears.put(GearType.BAIT, List.of(Pair.of(anotherItemID, rodOnMainHand ? offHandItem : mainHandItem)));
context.arg(ContextKeys.BAIT, anotherItemID);
BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(anotherItemID, MechanicType.BAIT).ifPresent(fishingGears.modifiers::add);
hasBait = true;
@@ -133,7 +119,7 @@ public class FishingGears {
String bagItemID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(itemInBag);
MechanicType bagItemType = MechanicType.getTypeByID(bagItemID);
if (!hasBait && bagItemType == MechanicType.BAIT) {
fishingGears.gears.put(GearType.BAIT, List.of(itemInBag));
fishingGears.gears.put(GearType.BAIT, List.of(Pair.of(bagItemID, itemInBag)));
context.arg(ContextKeys.BAIT, bagItemID);
BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(bagItemID, MechanicType.BAIT).ifPresent(fishingGears.modifiers::add);
hasBait = true;
@@ -143,9 +129,9 @@ public class FishingGears {
}
}
if (!uniqueUtils.isEmpty()) {
ArrayList<ItemStack> utils = new ArrayList<>();
ArrayList<Pair<String, ItemStack>> utils = new ArrayList<>();
for (Map.Entry<String, ItemStack> entry : uniqueUtils.entrySet()) {
utils.add(entry.getValue());
utils.add(Pair.of(entry.getKey(), entry.getValue()));
BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(entry.getKey(), MechanicType.UTIL).ifPresent(fishingGears.modifiers::add);
}
fishingGears.gears.put(GearType.UTIL, utils);
@@ -178,70 +164,118 @@ public class FishingGears {
public static class GearType {
public static final GearType ROD = new GearType("rod",
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false)),
(itemStack -> {}));
public static final GearType ROD = new GearType(MechanicType.ROD,
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {
if (context.getHolder().getGameMode() != GameMode.CREATIVE)
BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false);
}),
((context, itemStack) -> {
if (context.getHolder().getGameMode() != GameMode.CREATIVE)
BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false);
}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {})
);
public static final GearType BAIT = new GearType("bait",
(itemStack -> itemStack.setAmount(itemStack.getAmount() - 1)),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}));
public static final GearType BAIT = new GearType(MechanicType.BAIT,
((context, itemStack) -> {
if (context.getHolder().getGameMode() != GameMode.CREATIVE)
itemStack.setAmount(itemStack.getAmount() - 1);
}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {})
);
public static final GearType HOOK = new GearType("hook",
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}));
public static final GearType HOOK = new GearType(MechanicType.HOOK,
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {})
);
public static final GearType UTIL = new GearType("util",
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}),
(itemStack -> {}));
public static final GearType UTIL = new GearType(MechanicType.UTIL,
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {}),
((context, itemStack) -> {})
);
private final String type;
private Consumer<ItemStack> castFunction;
private Consumer<ItemStack> reelFunction;
private Consumer<ItemStack> biteFunction;
private Consumer<ItemStack> successFunction;
private Consumer<ItemStack> failureFunction;
private final MechanicType type;
private BiConsumer<Context<Player>, ItemStack> castFunction;
private BiConsumer<Context<Player>, ItemStack> reelFunction;
private BiConsumer<Context<Player>, ItemStack> biteFunction;
private BiConsumer<Context<Player>, ItemStack> successFunction;
private BiConsumer<Context<Player>, ItemStack> failureFunction;
private BiConsumer<Context<Player>, ItemStack> lureFunction;
private BiConsumer<Context<Player>, ItemStack> escapeFunction;
private BiConsumer<Context<Player>, ItemStack> landFunction;
public GearType(String type, Consumer<ItemStack> castFunction, Consumer<ItemStack> reelFunction, Consumer<ItemStack> biteFunction, Consumer<ItemStack> successFunction, Consumer<ItemStack> failureFunction) {
public GearType(MechanicType type,
BiConsumer<Context<Player>, ItemStack> castFunction, BiConsumer<Context<Player>, ItemStack> reelFunction,
BiConsumer<Context<Player>, ItemStack> biteFunction, BiConsumer<Context<Player>, ItemStack> successFunction,
BiConsumer<Context<Player>, ItemStack> failureFunction, BiConsumer<Context<Player>, ItemStack> lureFunction,
BiConsumer<Context<Player>, ItemStack> escapeFunction, BiConsumer<Context<Player>, ItemStack> landFunction
) {
this.type = type;
this.castFunction = castFunction;
this.reelFunction = reelFunction;
this.biteFunction = biteFunction;
this.successFunction = successFunction;
this.failureFunction = failureFunction;
this.landFunction = landFunction;
this.lureFunction = lureFunction;
this.escapeFunction = escapeFunction;
}
public void castFunction(Consumer<ItemStack> castFunction) {
public void castFunction(BiConsumer<Context<Player>, ItemStack> castFunction) {
this.castFunction = castFunction;
}
public void reelFunction(Consumer<ItemStack> reelFunction) {
public void reelFunction(BiConsumer<Context<Player>, ItemStack> reelFunction) {
this.reelFunction = reelFunction;
}
public void biteFunction(Consumer<ItemStack> biteFunction) {
public void biteFunction(BiConsumer<Context<Player>, ItemStack> biteFunction) {
this.biteFunction = biteFunction;
}
public void successFunction(Consumer<ItemStack> successFunction) {
public void successFunction(BiConsumer<Context<Player>, ItemStack> successFunction) {
this.successFunction = successFunction;
}
public void failureFunction(Consumer<ItemStack> failureFunction) {
public void failureFunction(BiConsumer<Context<Player>, ItemStack> failureFunction) {
this.failureFunction = failureFunction;
}
public void escapeFunction(BiConsumer<Context<Player>, ItemStack> escapeFunction) {
this.escapeFunction = escapeFunction;
}
public void lureFunction(BiConsumer<Context<Player>, ItemStack> lureFunction) {
this.lureFunction = lureFunction;
}
public void landFunction(BiConsumer<Context<Player>, ItemStack> landFunction) {
this.landFunction = landFunction;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
@@ -257,6 +291,10 @@ public class FishingGears {
@Override
public String toString() {
return type.toString();
}
public MechanicType getType() {
return type;
}
}

View File

@@ -2,11 +2,13 @@ package net.momirealms.customfishing.api.mechanic.fishing.hook;
import io.papermc.paper.block.fluid.FluidData;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishingHookStateEvent;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectProperties;
import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.customfishing.common.util.RandomUtils;
import org.bukkit.*;
@@ -34,6 +36,7 @@ public class LavaFishingMechanic implements HookMechanic {
private float fishAngle;
private int currentState;
private int jumpTimer;
private boolean firstTime = true;
public LavaFishingMechanic(FishHook hook, Effect gearsEffect, Context<Player> context) {
this.hook = hook;
@@ -46,6 +49,9 @@ public class LavaFishingMechanic implements HookMechanic {
if (!(boolean) gearsEffect.properties().getOrDefault(EffectProperties.LAVA_FISHING, false)) {
return false;
}
if (hook.isInLava()) {
return true;
}
float lavaHeight = 0F;
FluidData fluidData = this.hook.getWorld().getFluidData(this.hook.getLocation());
if (fluidData.getFluidType() == Fluid.LAVA || fluidData.getFluidType() == Fluid.FLOWING_LAVA) {
@@ -56,6 +62,9 @@ public class LavaFishingMechanic implements HookMechanic {
@Override
public boolean shouldStop() {
if (hook.isInLava()) {
return false;
}
return hook.isOnGround() || (hook.getLocation().getBlock().getType() != Material.LAVA && hook.getLocation().getBlock().getRelative(BlockFace.DOWN).getType() != Material.LAVA);
}
@@ -66,6 +75,7 @@ public class LavaFishingMechanic implements HookMechanic {
@Override
public void start(Effect finalEffect) {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND));
this.setWaitTime(finalEffect);
this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> {
float lavaHeight = 0F;
@@ -79,7 +89,6 @@ public class LavaFishingMechanic implements HookMechanic {
this.jumpTimer++;
if (this.jumpTimer >= 4) {
this.jumpTimer = 0;
Vector previousVector = this.hook.getVelocity();
this.hook.setVelocity(new Vector(0,0.24,0));
}
}
@@ -91,7 +100,7 @@ public class LavaFishingMechanic implements HookMechanic {
this.currentState = 0;
}
} else {
if (this.hook.getY() % 1 <= lavaHeight) {
if (this.hook.getY() % 1 <= lavaHeight || this.hook.isInLava()) {
Vector previousVector = this.hook.getVelocity();
this.hook.setVelocity(new Vector(previousVector.getX() * 0.6, Math.min(0.1, Math.max(-0.1, previousVector.getY() + 0.1)), previousVector.getZ() * 0.6));
this.currentState = 1;
@@ -102,6 +111,10 @@ public class LavaFishingMechanic implements HookMechanic {
this.tempEntity = this.hook.getWorld().spawn(this.hook.getLocation().clone().subtract(0,1,0), ArmorStand.class);
this.setTempEntityProperties(this.tempEntity);
this.hook.setHookedEntity(this.tempEntity);
if (!firstTime) {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE));
}
firstTime = false;
}
}
float f;
@@ -132,6 +145,7 @@ public class LavaFishingMechanic implements HookMechanic {
this.nibble = RandomUtils.generateRandomInt(20, 40);
this.hooked = true;
hook.getWorld().playSound(hook.getLocation(), Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.25F, 1.0F + (RandomUtils.generateRandomFloat(0,1)-RandomUtils.generateRandomFloat(0,1)) * 0.4F);
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE));
if (this.tempEntity != null && this.tempEntity.isValid()) {
this.tempEntity.remove();
}
@@ -141,6 +155,7 @@ public class LavaFishingMechanic implements HookMechanic {
if (this.timeUntilLured <= 0) {
this.fishAngle = RandomUtils.generateRandomFloat(0F, 360F);
this.timeUntilHooked = RandomUtils.generateRandomInt(20, 80);
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LURE));
}
} else {
setWaitTime(finalEffect);
@@ -166,7 +181,7 @@ public class LavaFishingMechanic implements HookMechanic {
private void setWaitTime(Effect effect) {
int before = ThreadLocalRandom.current().nextInt(ConfigManager.lavaMaxTime() - ConfigManager.lavaMinTime() + 1) + ConfigManager.lavaMinTime();
int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
int after = Math.max(ConfigManager.lavaMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks");
this.timeUntilLured = after;
}

View File

@@ -1,11 +1,13 @@
package net.momirealms.customfishing.api.mechanic.fishing.hook;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishingHookStateEvent;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectProperties;
import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.sparrow.heart.SparrowHeart;
import org.bukkit.entity.FishHook;
@@ -42,6 +44,7 @@ public class VanillaMechanic implements HookMechanic {
@Override
public void start(Effect finalEffect) {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND));
setWaitTime(hook, finalEffect);
this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> {
if (isHooked) {
@@ -66,7 +69,7 @@ public class VanillaMechanic implements HookMechanic {
hook.setWaitTime(after);
} else {
int before = ThreadLocalRandom.current().nextInt(ConfigManager.waterMaxTime() - ConfigManager.waterMinTime() + 1) + ConfigManager.waterMinTime();
int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
int after = Math.max(ConfigManager.waterMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
hook.setWaitTime(after);
BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks");
}
@@ -82,4 +85,12 @@ public class VanillaMechanic implements HookMechanic {
public void destroy() {
if (this.task != null) this.task.cancel();
}
public void onBite() {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE));
}
public void onFailedAttempt() {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE));
}
}

View File

@@ -1,11 +1,13 @@
package net.momirealms.customfishing.api.mechanic.fishing.hook;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishingHookStateEvent;
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectProperties;
import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.customfishing.common.util.RandomUtils;
import org.bukkit.NamespacedKey;
@@ -59,6 +61,7 @@ public class VoidFishingMechanic implements HookMechanic {
@Override
public void start(Effect finalEffect) {
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND));
this.setWaitTime(finalEffect);
this.tempEntity = hook.getWorld().spawn(hook.getLocation().clone().subtract(0,1,0), ArmorStand.class);
this.setTempEntityProperties(this.tempEntity);
@@ -69,7 +72,6 @@ public class VoidFishingMechanic implements HookMechanic {
if (timer >= 16) timer = 0;
hook.getWorld().spawnParticle(Particle.END_ROD, hook.getX() + 0.5 * Math.cos(timer * 22.5D * 0.017453292F), hook.getY() - 0.15, hook.getZ() + 0.5 * Math.sin(timer * 22.5D * 0.017453292F), 0,0,0,0);
}
if (this.nibble > 0) {
--this.nibble;
if (this.nibble % 4 == 0) {
@@ -83,6 +85,7 @@ public class VoidFishingMechanic implements HookMechanic {
this.timeUntilLured = 0;
this.timeUntilHooked = 0;
this.hooked = false;
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE));
}
} else {
float f;
@@ -113,6 +116,7 @@ public class VoidFishingMechanic implements HookMechanic {
this.nibble = RandomUtils.generateRandomInt(20, 40);
this.hooked = true;
hook.getWorld().playSound(hook.getLocation(), Sound.ITEM_TRIDENT_THUNDER, 0.25F, 1.0F + (RandomUtils.generateRandomFloat(0,1)-RandomUtils.generateRandomFloat(0,1)) * 0.4F);
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE));
}
} else if (timeUntilLured > 0) {
timeUntilLured--;
@@ -130,11 +134,12 @@ public class VoidFishingMechanic implements HookMechanic {
d0 = hook.getX() + Math.sin(f1) * f2 * 0.1D;
d1 = hook.getY();
d2 = hook.getZ() + Math.cos(f1) * f2 * 0.1D;
hook.getWorld().spawnParticle(Particle.DRAGON_BREATH, d0, d1, d2, 2 + RandomUtils.generateRandomInt(0,2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D);
hook.getWorld().spawnParticle(Particle.DRAGON_BREATH, d0, d1, d2, 2 + RandomUtils.generateRandomInt(0,1), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D);
}
if (this.timeUntilLured <= 0) {
this.fishAngle = RandomUtils.generateRandomFloat(0F, 360F);
this.timeUntilHooked = RandomUtils.generateRandomInt(20, 80);
EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LURE));
}
} else {
setWaitTime(finalEffect);
@@ -160,7 +165,7 @@ public class VoidFishingMechanic implements HookMechanic {
private void setWaitTime(Effect effect) {
int before = ThreadLocalRandom.current().nextInt(ConfigManager.voidMaxTime() - ConfigManager.voidMinTime() + 1) + ConfigManager.voidMinTime();
int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
int after = Math.max(ConfigManager.voidMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder()));
BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks");
this.timeUntilLured = after;
}

View File

@@ -23,6 +23,7 @@ import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.common.item.ItemFactory;
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -56,7 +57,7 @@ public interface ItemManager extends Reloadable {
MechanicType getItemType(@NotNull String id);
@Nullable
Item dropItemLoot(@NotNull Context<Player> context);
Item dropItemLoot(@NotNull Context<Player> context, ItemStack rod, FishHook hook);
void decreaseDurability(ItemStack itemStack, int amount, boolean incorrectUsage);
@@ -65,4 +66,6 @@ public interface ItemManager extends Reloadable {
ItemProvider[] getItemProviders();
Collection<String> getItemIDs();
net.momirealms.customfishing.common.item.Item<ItemStack> wrap(ItemStack itemStack);
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.customfishing.api.mechanic.item;
import net.kyori.adventure.util.Index;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -17,6 +18,8 @@ public class MechanicType {
public static final MechanicType BAIT = of("bait");
public static final MechanicType HOOK = of("hook");
public static final MechanicType TOTEM = of("totem");
public static final MechanicType ENTITY = of("entity");
public static final MechanicType BLOCK = of("block");
public static final MechanicType ENCHANT = of("enchant");
private final String type;
@@ -29,10 +32,20 @@ public class MechanicType {
return type;
}
public static MechanicType of(String type) {
private static MechanicType of(String type) {
return new MechanicType(type);
}
public static MechanicType[] values() {
return new MechanicType[]{LOOT, ROD, UTIL, BAIT, HOOK, TOTEM, ENCHANT, ENTITY, BLOCK};
}
private static final Index<String, MechanicType> INDEX = Index.create(MechanicType::getType, values());
public static Index<String, MechanicType> index() {
return INDEX;
}
@ApiStatus.Internal
public static void register(String id, MechanicType type) {
MechanicType previous = types.put(id, type);

View File

@@ -102,7 +102,7 @@ public class LootImpl implements Loot {
private boolean disableStatistics = DEFAULT_DISABLE_STATS;
private boolean showInFinder = DEFAULT_SHOW_IN_FINDER;
private String id = null;
private String nick = null;
private String nick = "UNDEFINED";
private StatisticsKeys statisticsKeys = null;
private MathValue<Player> score = DEFAULT_SCORE;
private String[] groups = new String[0];

View File

@@ -21,5 +21,10 @@ public enum LootType {
ITEM,
ENTITY,
BLOCK
BLOCK;
@Override
public String toString() {
return name();
}
}

View File

@@ -58,6 +58,10 @@ public interface MathValue<T> {
return new PlainMathValueImpl<>(value);
}
static <T> MathValue<T> ranged(String value) {
return new RangedMathValueImpl<>(value);
}
/**
* Automatically creates a MathValue based on the given object.
* If the object is a String, it is treated as a mathematical expression.
@@ -70,6 +74,9 @@ public interface MathValue<T> {
*/
static <T> MathValue<T> auto(Object o) {
if (o instanceof String s) {
if (s.contains("~")) {
return ranged(s);
}
try {
return plain(Double.parseDouble(s));
} catch (NumberFormatException e) {

View File

@@ -0,0 +1,31 @@
package net.momirealms.customfishing.api.mechanic.misc.value;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.common.util.RandomUtils;
public class RangedMathValueImpl<T> implements MathValue<T> {
private final double min;
private final double max;
public RangedMathValueImpl(String value) {
String[] split = value.split("~");
if (split.length != 2) {
throw new IllegalArgumentException("Correct ranged format `a~b`");
}
double min = Double.parseDouble(split[0]);
double max = Double.parseDouble(split[1]);
if (min > max) {
double temp = max;
max = min;
min = temp;
}
this.min = min;
this.max = max;
}
@Override
public double evaluate(Context<T> context) {
return RandomUtils.generateRandomDouble(min, max);
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.util;
import org.bukkit.Bukkit;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
public class EventUtils {
public static void fireAndForget(Event event) {
Bukkit.getPluginManager().callEvent(event);
}
public static boolean fireAndCheckCancel(Event event) {
if (!(event instanceof Cancellable cancellable))
throw new IllegalArgumentException("Only cancellable events are allowed here");
Bukkit.getPluginManager().callEvent(event);
return cancellable.isCancelled();
}
}