9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-27 10:59:13 +00:00

events and actions

This commit is contained in:
XiaoMoMi
2023-09-09 03:29:37 +08:00
parent f56169c56e
commit 7f9cc4f2c0
31 changed files with 713 additions and 307 deletions

View File

@@ -26,6 +26,7 @@ import net.momirealms.customfishing.adventure.AdventureManagerImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.manager.CommandManager;
import net.momirealms.customfishing.command.sub.CompetitionCommand;
import net.momirealms.customfishing.command.sub.DebugCommand;
import net.momirealms.customfishing.command.sub.FishingBagCommand;
import net.momirealms.customfishing.command.sub.ItemCommand;
import net.momirealms.customfishing.setting.Locale;
@@ -47,7 +48,8 @@ public class CommandManagerImpl implements CommandManager {
.withSubcommands(
getReloadCommand(),
CompetitionCommand.INSTANCE.getCompetitionCommand(),
ItemCommand.INSTANCE.getItemCommand()
ItemCommand.INSTANCE.getItemCommand(),
DebugCommand.INSTANCE.getDebugCommand()
)
.register();

View File

@@ -0,0 +1,117 @@
package net.momirealms.customfishing.command.sub;
import dev.jorel.commandapi.CommandAPICommand;
import dev.jorel.commandapi.IStringTooltip;
import dev.jorel.commandapi.StringTooltip;
import dev.jorel.commandapi.arguments.ArgumentSuggestions;
import dev.jorel.commandapi.arguments.BooleanArgument;
import net.momirealms.biomeapi.BiomeAPI;
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.integration.SeasonInterface;
import net.momirealms.customfishing.api.manager.AdventureManager;
import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class DebugCommand {
public static DebugCommand INSTANCE = new DebugCommand();
public CommandAPICommand getDebugCommand() {
return new CommandAPICommand("debug")
.withSubcommands(
getLootChanceCommand(),
getBiomeCommand(),
getSeasonCommand()
);
}
public CommandAPICommand getBiomeCommand() {
return new CommandAPICommand("biome")
.executesPlayer((player, arg) -> {
AdventureManagerImpl.getInstance().sendMessage(player, BiomeAPI.getBiome(player.getLocation()));
});
}
public CommandAPICommand getSeasonCommand() {
return new CommandAPICommand("season")
.executesPlayer((player, arg) -> {
SeasonInterface seasonInterface = CustomFishingPlugin.get().getIntegrationManager().getSeasonInterface();
if (seasonInterface == null) {
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "NO SEASON PLUGIN");
return;
}
AdventureManagerImpl.getInstance().sendMessage(player, seasonInterface.getSeason(player.getLocation().getWorld()));
});
}
public CommandAPICommand getLootChanceCommand() {
return new CommandAPICommand("loot-chance")
.withArguments(new BooleanArgument("lava fishing").replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(info ->
new IStringTooltip[] {
StringTooltip.ofString("true", "loots in lava"),
StringTooltip.ofString("false", "loots in water")
})))
.executesPlayer((player, arg) -> {
Effect initialEffect = CustomFishingPlugin.get().getEffectManager().getInitialEffect();
FishingPreparation fishingPreparation = new FishingPreparation(player, CustomFishingPlugin.get());
boolean inLava = (boolean) arg.getOrDefault("lava fishing", false);
fishingPreparation.insertArg("{lava}", String.valueOf(inLava));
fishingPreparation.mergeEffect(initialEffect);
//TODO apply totems
var map = CustomFishingPlugin.get().getFishingManager().getPossibleLootKeysWithWeight(initialEffect, fishingPreparation);
List<LootWithWeight> loots = new ArrayList<>();
double sum = 0;
for (Map.Entry<String, Double> entry : map.entrySet()) {
double weight = entry.getValue();
String loot = entry.getKey();
if (weight <= 0) continue;
loots.add(new LootWithWeight(loot, weight));
sum += weight;
}
LootWithWeight[] lootArray = loots.toArray(new LootWithWeight[0]);
quickSort(lootArray, 0,lootArray.length - 1);
AdventureManager adventureManager = AdventureManagerImpl.getInstance();
adventureManager.sendMessage(player, "<red>---------- results ---------");
for (LootWithWeight loot : lootArray) {
adventureManager.sendMessage(player, "<hover:show_text:'<blue>GET'><click:run_command:/cfishing items loot get "+ loot.key() + ">" +loot.key() + "</click></hover>: <gold>" + String.format("%.2f", loot.weight()*100/sum) + "% <gray>(" + String.format("%.2f", loot.weight()) + ")");
}
adventureManager.sendMessage(player, "<red>----------- end -----------");
});
}
public record LootWithWeight(String key, double weight) {
}
public static void quickSort(LootWithWeight[] loot, int low, int high) {
if (low < high) {
int pi = partition(loot, low, high);
quickSort(loot, low, pi - 1);
quickSort(loot, pi + 1, high);
}
}
public static int partition(LootWithWeight[] loot, int low, int high) {
double pivot = loot[high].weight();
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
if (loot[j].weight() > pivot) {
i++;
swap(loot, i, j);
}
}
swap(loot, i + 1, high);
return i + 1;
}
public static void swap(LootWithWeight[] loot, int i, int j) {
LootWithWeight temp = loot[i];
loot[i] = loot[j];
loot[j] = temp;
}
}

View File

@@ -24,6 +24,10 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -32,7 +36,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class PlaceholderManagerImpl implements PlaceholderManager {
public class PlaceholderManagerImpl implements PlaceholderManager, Listener {
private static PlaceholderManagerImpl instance;
private final CustomFishingPlugin plugin;
@@ -59,18 +63,25 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
public void load() {
if (competitionPapi != null) competitionPapi.load();
if (statisticsPapi != null) statisticsPapi.load();
Bukkit.getPluginManager().registerEvents(this, plugin);
loadCustomPlaceholders();
}
public void unload() {
if (competitionPapi != null) competitionPapi.unload();
if (statisticsPapi != null) statisticsPapi.unload();
HandlerList.unregisterAll(this);
}
public void disable() {
this.customPlaceholderMap.clear();
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
cachedPlaceholders.remove(event.getPlayer().getUniqueId());
}
public void loadCustomPlaceholders() {
YamlConfiguration config = plugin.getConfig("config.yml");
ConfigurationSection section = config.getConfigurationSection("other-settings.placeholder-register");

View File

@@ -23,16 +23,21 @@ import net.momirealms.customfishing.adventure.AdventureManagerImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.common.Pair;
import net.momirealms.customfishing.api.manager.ActionManager;
import net.momirealms.customfishing.api.mechanic.GlobalSettings;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionExpansion;
import net.momirealms.customfishing.api.mechanic.action.ActionFactory;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl;
import net.momirealms.customfishing.util.ArmorStandUtils;
import net.momirealms.customfishing.util.ClassUtils;
import net.momirealms.customfishing.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
@@ -73,20 +78,30 @@ public class ActionManagerImpl implements ActionManager {
this.registerDelayedAction();
this.registerConditionalAction();
this.registerPriorityAction();
this.registerLevelAction();
this.registerHologramAction();
this.registerFakeItemAction();
}
public void load() {
this.loadExpansions();
this.loadGlobalEventActions();
}
public void unload() {
GlobalSettings.unload();
}
public void disable() {
unload();
this.actionBuilderMap.clear();
}
private void loadGlobalEventActions() {
YamlConfiguration config = plugin.getConfig("config.yml");
GlobalSettings.load(config.getConfigurationSection("mechanics.global-events"));
}
@Override
public boolean registerAction(String type, ActionFactory actionFactory) {
if (this.actionBuilderMap.containsKey(type)) return false;
@@ -104,6 +119,21 @@ public class ActionManagerImpl implements ActionManager {
return getActionBuilder(section.getString("type")).build(section.get("value"), section.getDouble("chance", 1d));
}
@Override
public HashMap<ActionTrigger, Action[]> getActionMap(ConfigurationSection section) {
HashMap<ActionTrigger, Action[]> actionMap = new HashMap<>();
if (section == null) return actionMap;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection innerSection) {
actionMap.put(
ActionTrigger.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)),
getActions(innerSection)
);
}
}
return actionMap;
}
@Nullable
@Override
public Action[] getActions(ConfigurationSection section) {
@@ -247,6 +277,62 @@ public class ActionManagerImpl implements ActionManager {
});
}
private void registerHologramAction() {
registerAction("hologram", (args, chance) -> {
if (args instanceof ConfigurationSection section) {
String text = section.getString("text", "");
int duration = section.getInt("duration", 20);
boolean position = section.getString("position", "hook").equals("hook");
double x = section.getDouble("x");
double y = section.getDouble("y");
double z = section.getDouble("z");
return condition -> {
if (Math.random() > chance) return;
Player player = condition.getPlayer();
Location location = position ? condition.getLocation() : player.getLocation();
ArmorStandUtils.sendHologram(
condition.getPlayer(),
location.clone().add(x, y, z),
AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
PlaceholderManagerImpl.getInstance().parse(player, text, condition.getArgs())
),
duration
);
};
} else {
LogUtils.warn("Illegal value format found at action: hologram");
return null;
}
});
}
private void registerFakeItemAction() {
registerAction("fake-item", (args, chance) -> {
if (args instanceof ConfigurationSection section) {
String[] itemSplit = section.getString("item", "").split(":", 2);
int duration = section.getInt("duration", 20);
boolean position = section.getString("position", "hook").equals("hook");
double x = section.getDouble("x");
double y = section.getDouble("y");
double z = section.getDouble("z");
return condition -> {
if (Math.random() > chance) return;
Player player = condition.getPlayer();
Location location = position ? condition.getLocation() : player.getLocation();
ArmorStandUtils.sendFakeItem(
condition.getPlayer(),
location.clone().add(x, y, z),
plugin.getItemManager().build(player, itemSplit[0], itemSplit[1], condition.getArgs()),
duration
);
};
} else {
LogUtils.warn("Illegal value format found at action: hologram");
return null;
}
});
}
private void registerChainAction() {
registerAction("chain", (args, chance) -> {
List<Action> actions = new ArrayList<>();
@@ -357,6 +443,17 @@ public class ActionManagerImpl implements ActionManager {
});
}
private void registerLevelAction() {
registerAction("level", (args, chance) -> {
int level = (int) args;
return condition -> {
if (Math.random() > chance) return;
Player player = condition.getPlayer();
player.setLevel(Math.max(0, player.getLevel() + level));
};
});
}
@SuppressWarnings("all")
private void registerSoundAction() {
registerAction("sound", (args, chance) -> {
@@ -452,6 +549,7 @@ public class ActionManagerImpl implements ActionManager {
});
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void loadExpansions() {
File expansionFolder = new File(plugin.getDataFolder(), EXPANSION_FOLDER);
if (!expansionFolder.exists())

View File

@@ -82,9 +82,10 @@ public class Competition implements FishingCompetition {
this.actionBarManager.load();
}
Action[] actions = config.getStartActions();
if (actions != null) {
Condition condition = new Condition();
Condition condition = new Condition(null, null, new HashMap<>());
for (Action action : actions) {
action.trigger(condition);
}
@@ -171,7 +172,7 @@ public class Competition implements FishingCompetition {
// do end actions
Action[] actions = config.getEndActions();
if (actions != null) {
Condition condition = new Condition(new HashMap<>(publicPlaceholders));
Condition condition = new Condition(null, null, new HashMap<>(publicPlaceholders));
for (Action action : actions) {
action.trigger(condition);
}

View File

@@ -108,6 +108,7 @@ public class EffectManagerImpl implements EffectManager {
.key(key)
.requirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), true))
.effect(getEffectFromSection(section.getConfigurationSection("effects")))
.actionMap(plugin.getActionManager().getActionMap(section.getConfigurationSection("events")))
.build();
}

View File

@@ -26,13 +26,13 @@ import net.momirealms.customfishing.api.event.LavaFishingEvent;
import net.momirealms.customfishing.api.event.RodCastEvent;
import net.momirealms.customfishing.api.manager.FishingManager;
import net.momirealms.customfishing.api.manager.RequirementManager;
import net.momirealms.customfishing.api.mechanic.GlobalSettings;
import net.momirealms.customfishing.api.mechanic.TempFishingState;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier;
import net.momirealms.customfishing.api.mechanic.game.GameConfig;
import net.momirealms.customfishing.api.mechanic.game.GameInstance;
import net.momirealms.customfishing.api.mechanic.game.GameSettings;
@@ -41,7 +41,6 @@ import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.Modifier;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.api.util.WeightUtils;
import net.momirealms.customfishing.mechanic.loot.LootManagerImpl;
import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl;
import net.momirealms.customfishing.setting.Config;
import org.bukkit.Bukkit;
@@ -56,12 +55,10 @@ import org.bukkit.event.inventory.InventoryPickupItemEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class FishingManagerImpl implements Listener, FishingManager {
@@ -202,6 +199,19 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
@EventHandler
public void onConsumeItem(PlayerItemConsumeEvent event) {
if (event.isCancelled()) return;
ItemStack itemStack = event.getItem();
String id = plugin.getItemManager().getAnyItemID(itemStack);
Loot loot = plugin.getLootManager().getLoot(id);
if (loot != null) {
Condition condition = new Condition(event.getPlayer());
GlobalSettings.triggerLootActions(ActionTrigger.CONSUME, condition);
loot.triggerActions(ActionTrigger.CONSUME, condition);
}
}
@Override
public boolean removeHook(UUID uuid) {
FishHook hook = hookCacheMap.remove(uuid);
@@ -248,16 +258,11 @@ public class FishingManagerImpl implements Listener, FishingManager {
fishingPreparation.mergeEffect(initialEffect);
// Apply enchants
for (String enchant : plugin.getIntegrationManager().getEnchantments(fishingPreparation.getRodItemStack())) {
EffectCarrier enchantEffect = plugin.getEffectManager().getEffect("enchant", enchant);
if (enchantEffect != null && enchantEffect.isConditionMet(fishingPreparation)) {
initialEffect.merge(enchantEffect.getEffect());
}
}
//TODO Apply totem effects
// Call custom event
RodCastEvent rodCastEvent = new RodCastEvent(event, initialEffect);
RodCastEvent rodCastEvent = new RodCastEvent(event, fishingPreparation, initialEffect);
Bukkit.getPluginManager().callEvent(rodCastEvent);
if (rodCastEvent.isCancelled()) {
return;
@@ -271,15 +276,15 @@ public class FishingManagerImpl implements Listener, FishingManager {
// Reduce amount & Send animation
var baitItem = fishingPreparation.getBaitItemStack();
if (baitItem != null) {
if (Config.enableBaitAnimation) {
ItemStack cloned = baitItem.clone();
cloned.setAmount(1);
new BaitAnimationTask(plugin, player, fishHook, cloned);
}
ItemStack cloned = baitItem.clone();
cloned.setAmount(1);
new BaitAnimationTask(plugin, player, fishHook, cloned);
baitItem.setAmount(baitItem.getAmount() - 1);
}
// Arrange hook check task
this.hookCheckMap.put(player.getUniqueId(), new HookCheckTimerTask(this, fishHook, fishingPreparation, initialEffect));
// trigger actions
fishingPreparation.triggerActions(ActionTrigger.CAST);
}
private void onCaughtEntity(PlayerFishEvent event) {
@@ -343,6 +348,8 @@ public class FishingManagerImpl implements Listener, FishingManager {
// put vanilla loot in map
this.vanillaLootMap.put(uuid, item.getItemStack());
}
loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation());
temp.getPreparation().triggerActions(ActionTrigger.HOOK);
if (!loot.disableGame()) {
// start the game if the loot has a game
event.setCancelled(true);
@@ -379,12 +386,12 @@ public class FishingManagerImpl implements Listener, FishingManager {
if (temp != null) {
var loot = temp.getLoot();
Action[] actions = loot.getActions(ActionTrigger.HOOK);
if (actions != null)
for (Action action : actions)
action.trigger(temp.getPreparation());
loot.triggerActions(ActionTrigger.BITE, temp.getPreparation());
temp.getPreparation().triggerActions(ActionTrigger.BITE);
if (loot.instanceGame() && !loot.disableGame()) {
loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation());
temp.getPreparation().triggerActions(ActionTrigger.HOOK);
startFishingGame(player, loot, temp.getEffect());
}
}
@@ -414,9 +421,12 @@ public class FishingManagerImpl implements Listener, FishingManager {
var temp = this.tempFishingStateMap.get(uuid);
if (temp != null ) {
if (!temp.getLoot().disableGame()) {
Loot loot = temp.getLoot();
loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation());
temp.getPreparation().triggerActions(ActionTrigger.HOOK);
if (!loot.disableGame()) {
event.setCancelled(true);
startFishingGame(player, temp.getLoot(), temp.getEffect());
startFishingGame(player, loot, temp.getEffect());
} else {
success(temp, event.getHook());
}
@@ -454,7 +464,15 @@ public class FishingManagerImpl implements Listener, FishingManager {
gamingPlayer.cancel();
gamingPlayerMap.remove(uuid);
plugin.getScheduler().runTaskSync(fishHook::remove, fishHook.getLocation());
plugin.getScheduler().runTaskSync(() -> {
fishHook.remove();
ItemStack rod = tempFishingState.getPreparation().getRodItemStack();
PlayerItemDamageEvent damageEvent = new PlayerItemDamageEvent(player, rod, 1);
Bukkit.getPluginManager().callEvent(damageEvent);
if (damageEvent.isCancelled()) {
return;
}
}, fishHook.getLocation());
}
public void fail(TempFishingState state, FishHook hook) {
@@ -482,15 +500,10 @@ public class FishingManagerImpl implements Listener, FishingManager {
return;
}
Action[] globalActions = LootManagerImpl.GlobalSetting.globalLootProperties.getActions(ActionTrigger.FAILURE);
if (globalActions != null)
for (Action action : globalActions)
action.trigger(fishingPreparation);
GlobalSettings.triggerLootActions(ActionTrigger.FAILURE, fishingPreparation);
loot.triggerActions(ActionTrigger.FAILURE, fishingPreparation);
fishingPreparation.triggerActions(ActionTrigger.FAILURE);
Action[] actions = loot.getActions(ActionTrigger.FAILURE);
if (actions != null)
for (Action action : actions)
action.trigger(fishingPreparation);
}, hook.getLocation());
}
@@ -579,28 +592,35 @@ public class FishingManagerImpl implements Listener, FishingManager {
fishingPreparation.insertArg("{score}","-1");
}
Action[] globalActions = LootManagerImpl.GlobalSetting.globalLootProperties.getActions(ActionTrigger.SUCCESS);
if (globalActions != null)
for (Action action : globalActions)
action.trigger(fishingPreparation);
Action[] actions = loot.getActions(ActionTrigger.SUCCESS);
if (actions != null)
for (Action action : actions)
action.trigger(fishingPreparation);
// events and actions
GlobalSettings.triggerLootActions(ActionTrigger.SUCCESS, fishingPreparation);
loot.triggerActions(ActionTrigger.SUCCESS, fishingPreparation);
fishingPreparation.triggerActions(ActionTrigger.SUCCESS);
player.setStatistic(
Statistic.FISH_CAUGHT,
player.getStatistic(Statistic.FISH_CAUGHT) + 1
);
if (!loot.disableStats())
Optional.ofNullable(
plugin.getStatisticsManager()
.getStatistics(player.getUniqueId())
).ifPresent(it -> it.addLootAmount(loot, fishingPreparation, 1));
}
@Nullable
public Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation) {
HashMap<String, Double> lootWithWeight = plugin.getRequirementManager().getLootWithWeight(fishingPreparation);
@Override
public Collection<String> getPossibleLootKeys (FishingPreparation fishingPreparation) {
return plugin.getRequirementManager().getLootWithWeight(fishingPreparation).keySet();
}
@NotNull
@Override
public Map<String, Double> getPossibleLootKeysWithWeight(Effect initialEffect, FishingPreparation fishingPreparation) {
Map<String, Double> lootWithWeight = plugin.getRequirementManager().getLootWithWeight(fishingPreparation);
if (lootWithWeight.size() == 0) {
LogUtils.warn(String.format("No Loot found at %s for Player %s!", fishingPreparation.getPlayer().getLocation(), fishingPreparation.getPlayer().getName()));
return null;
return new HashMap<>();
}
Player player = fishingPreparation.getPlayer();
@@ -608,8 +628,13 @@ public class FishingManagerImpl implements Listener, FishingManager {
double previous = lootWithWeight.getOrDefault(pair.left(), 0d);
lootWithWeight.put(pair.left(), pair.right().modify(player, previous));
}
return lootWithWeight;
}
String key = WeightUtils.getRandom(lootWithWeight);
@Override
@Nullable
public Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation) {
String key = WeightUtils.getRandom(getPossibleLootKeysWithWeight(initialEffect, fishingPreparation));
Loot loot = plugin.getLootManager().getLoot(key);
if (loot == null) {
LogUtils.warn(String.format("Loot %s doesn't exist!", key));

View File

@@ -21,14 +21,15 @@ import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.event.FishHookLandEvent;
import net.momirealms.customfishing.api.event.LavaFishingEvent;
import net.momirealms.customfishing.api.mechanic.TempFishingState;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.scheduler.CancellableTask;
import net.momirealms.customfishing.setting.Config;
import net.momirealms.customfishing.util.ArmorStandUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -59,6 +60,7 @@ public class HookCheckTimerTask implements Runnable {
private boolean reserve;
private int jumpTimer;
private Entity hookedEntity;
private Loot loot;
public HookCheckTimerTask(
FishingManagerImpl manager,
@@ -94,14 +96,11 @@ public class HookCheckTimerTask implements Runnable {
return;
}
if (firstTime) {
this.fishingPreparation.insertArg("in-lava", "true");
if (Config.enableSplashAnimation)
ArmorStandUtils.sendAnimationToPlayer(
fishingPreparation.getPlayer(),
fishHook.getLocation(),
CustomFishingPlugin.get().getItemManager().build(null, "util", Config.lavaSplashItem),
Config.splashAnimationTime
);
this.fishingPreparation.setLocation(fishHook.getLocation());
this.fishingPreparation.insertArg("{lava}", "true");
this.fishingPreparation.triggerActions(ActionTrigger.LAND);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.LAVA);
Bukkit.getPluginManager().callEvent(event);
firstTime = false;
this.setTempState();
}
@@ -127,16 +126,13 @@ public class HookCheckTimerTask implements Runnable {
return;
}
if (fishHook.isInWater()) {
this.fishingPreparation.setLocation(fishHook.getLocation());
this.fishingPreparation.insertArg("{lava}", "false");
this.fishingPreparation.triggerActions(ActionTrigger.LAND);
FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER);
Bukkit.getPluginManager().callEvent(event);
// if the hook is in water
// then cancel the task
this.fishingPreparation.insertArg("in-lava", "false");
if (Config.enableSplashAnimation)
ArmorStandUtils.sendAnimationToPlayer(
fishingPreparation.getPlayer(),
fishHook.getLocation(),
CustomFishingPlugin.get().getItemManager().build(null, "util", Config.waterSplashItem),
Config.splashAnimationTime
);
this.destroy();
this.setTempState();
return;
@@ -161,6 +157,7 @@ public class HookCheckTimerTask implements Runnable {
Loot nextLoot = manager.getNextLoot(initialEffect, fishingPreparation);
if (nextLoot == null)
return;
this.loot = nextLoot;
fishingPreparation.insertArg("{nick}", nextLoot.getNick());
fishingPreparation.insertArg("{loot}", nextLoot.getID());
CustomFishingPlugin.get().getScheduler().runTaskAsync(() -> manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState(
@@ -198,6 +195,9 @@ public class HookCheckTimerTask implements Runnable {
return;
}
this.loot.triggerActions(ActionTrigger.BITE, fishingPreparation);
this.fishingPreparation.triggerActions(ActionTrigger.BITE);
this.fishHooked = true;
this.removeTempEntity();

View File

@@ -104,6 +104,7 @@ public class GameManagerImpl implements GameManager {
@Override
@Nullable
public GameConfig getGameConfig(String key) {
if (key == null) return null;
return gameConfigMap.get(key);
}

View File

@@ -20,7 +20,6 @@ package net.momirealms.customfishing.mechanic.loot;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.manager.LootManager;
import net.momirealms.customfishing.api.mechanic.action.Action;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.loot.CFLoot;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType;
@@ -40,16 +39,6 @@ public class LootManagerImpl implements LootManager {
private final HashMap<String, Loot> lootMap;
private final HashMap<String, List<String>> lootGroupMap;
public static class GlobalSetting {
public static CFLoot globalLootProperties;
public static boolean disableStats;
public static boolean disableGames;
public static boolean instantGame;
public static boolean showInFinder;
public static String gameGroup;
public static String[] lootGroup;
}
public LootManagerImpl(CustomFishingPlugin plugin) {
this.plugin = plugin;
this.lootMap = new HashMap<>();
@@ -57,7 +46,6 @@ public class LootManagerImpl implements LootManager {
}
public void load() {
this.loadGlobalLootProperties();
this.loadLootsFromPluginFolder();
}
@@ -95,11 +83,6 @@ public class LootManagerImpl implements LootManager {
}
}
@Override
public Loot getGlobalLootProperties() {
return GlobalSetting.globalLootProperties;
}
@Nullable
@Override
public List<String> getLootGroup(String key) {
@@ -112,21 +95,6 @@ public class LootManagerImpl implements LootManager {
return lootMap.get(key);
}
private void loadGlobalLootProperties() {
YamlConfiguration config = plugin.getConfig("config.yml");
GlobalSetting.globalLootProperties = getSingleSectionItem(
Objects.requireNonNull(config.getConfigurationSection("mechanics.global-loot-properties")),
"GLOBAL",
"global"
);
GlobalSetting.disableStats = GlobalSetting.globalLootProperties.disableStats();
GlobalSetting.disableGames = GlobalSetting.globalLootProperties.disableGame();
GlobalSetting.instantGame = GlobalSetting.globalLootProperties.instanceGame();
GlobalSetting.showInFinder = GlobalSetting.globalLootProperties.showInFinder();
GlobalSetting.lootGroup = GlobalSetting.globalLootProperties.getLootGroup();
GlobalSetting.gameGroup = GlobalSetting.globalLootProperties.getGameConfigKey();
}
private void loadSingleFile(File file, String namespace) {
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file);
for (Map.Entry<String, Object> entry : yaml.getValues(false).entrySet()) {
@@ -154,33 +122,18 @@ public class LootManagerImpl implements LootManager {
private CFLoot getSingleSectionItem(ConfigurationSection section, String namespace, String key) {
return new CFLoot.Builder(key, LootType.valueOf(namespace.toUpperCase(Locale.ENGLISH)))
.disableStats(section.getBoolean("disable-stat", GlobalSetting.disableStats))
.disableGames(section.getBoolean("disable-game", GlobalSetting.disableGames))
.instantGame(section.getBoolean("instant-game", GlobalSetting.instantGame))
.showInFinder(section.getBoolean("show-in-fishfinder", GlobalSetting.showInFinder))
.gameConfig(section.getString("game-group", GlobalSetting.gameGroup))
.lootGroup(ConfigUtils.stringListArgs(Optional.ofNullable(section.get("loot-group")).orElse(GlobalSetting.lootGroup)).toArray(new String[0]))
.disableStats(section.getBoolean("disable-stat", false))
.disableGames(section.getBoolean("disable-game", false))
.instantGame(section.getBoolean("instant-game", false))
.showInFinder(section.getBoolean("show-in-fishfinder", true))
.gameConfig(section.getString("game-group"))
.lootGroup(ConfigUtils.stringListArgs(section.get("loot-group")).toArray(new String[0]))
.nick(section.getString("nick", section.getString("display.name", key)))
.addActions(getActionMap(section.getConfigurationSection("events")))
.addActions(plugin.getActionManager().getActionMap(section.getConfigurationSection("events")))
.addTimesActions(getTimesActionMap(section.getConfigurationSection("events.success-times")))
.build();
}
private HashMap<ActionTrigger, Action[]> getActionMap(ConfigurationSection section) {
HashMap<ActionTrigger, Action[]> actionMap = new HashMap<>();
if (section == null) return actionMap;
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection innerSection) {
actionMap.put(
ActionTrigger.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)),
plugin.getActionManager().getActions(innerSection)
);
}
}
return actionMap;
}
private HashMap<Integer, Action[]> getTimesActionMap(ConfigurationSection section) {
HashMap<Integer, Action[]> actionMap = new HashMap<>();
if (section == null) return actionMap;

View File

@@ -117,6 +117,8 @@ public class RequirementManagerImpl implements RequirementManager {
this.registerCompareRequirement();
this.registerAndRequirement();
this.registerOrRequirement();
this.registerLevelRequirement();
this.registerRandomRequirement();
}
public ConditionalLoots getConditionalLoots(ConfigurationSection section) {
@@ -302,7 +304,7 @@ public class RequirementManagerImpl implements RequirementManager {
registerRequirement("in-lava", (args, actions, advanced) -> {
boolean inLava = (boolean) args;
return condition -> {
String current = condition.getArgs().get("in-lava");
String current = condition.getArgs().get("{lava}");
if (current.equals(String.valueOf(inLava)))
return true;
if (advanced) triggerActions(actions, condition);
@@ -311,6 +313,31 @@ public class RequirementManagerImpl implements RequirementManager {
});
}
private void registerLevelRequirement() {
registerRequirement("level", (args, actions, advanced) -> {
int level = (int) args;
return condition -> {
int current = condition.getPlayer().getLevel();
if (current >= level)
return true;
if (advanced) triggerActions(actions, condition);
return false;
};
});
}
private void registerRandomRequirement() {
registerRequirement("random", (args, actions, advanced) -> {
double random = ConfigUtils.getDoubleValue(args);
return condition -> {
if (Math.random() < random)
return true;
if (advanced) triggerActions(actions, condition);
return false;
};
});
}
private void registerBiomeRequirement() {
registerRequirement("biome", (args, actions, advanced) -> {
HashSet<String> biomes = new HashSet<>(ConfigUtils.stringListArgs(args));

View File

@@ -68,13 +68,6 @@ public class Config {
public static String bagTitle;
public static List<Material> bagWhiteListItems;
// Animation
public static boolean enableBaitAnimation;
public static boolean enableSplashAnimation;
public static int splashAnimationTime;
public static String lavaSplashItem;
public static String waterSplashItem;
// Lava fishing
public static int lavaMinTime;
public static int lavaMaxTime;
@@ -88,9 +81,10 @@ public class Config {
public static boolean redisRanking;
public static int placeholderLimit;
//
// Data save interval
public static int dataSaveInterval;
// Legacy color code support
public static boolean legacyColorSupport;
public static void load() {
@@ -108,7 +102,7 @@ public class Config {
.builder()
.setVersioning(new BasicVersioning("config-version"))
.addIgnoredRoute(configVersion, "mechanics.mechanic-requirements", '.')
.addIgnoredRoute(configVersion, "mechanics.global-loot-properties", '.')
.addIgnoredRoute(configVersion, "mechanics.global-events", '.')
.build()
);
loadSettings(CustomFishingPlugin.getInstance().getConfig("config.yml"));
@@ -139,12 +133,6 @@ public class Config {
lavaMinTime = config.getInt("mechanics.lava-fishing.min-wait-time", 100);
lavaMaxTime = config.getInt("mechanics.lava-fishing.max-wait-time", 600);
enableSplashAnimation = config.getBoolean("mechanics.animation.splash.enable", true);
enableBaitAnimation = config.getBoolean("mechanics.animation.bait.enable", true);
waterSplashItem = config.getString("mechanics.animation.splash.water");
lavaSplashItem = config.getString("mechanics.animation.splash.lava");
splashAnimationTime = config.getInt("mechanics.animation.splash.duration");
vanillaMechanicIfNoLoot = config.getBoolean("mechanics.vanilla-mechanic-if-no-loot.enable", false);
noLootActions = CustomFishingPlugin.get().getActionManager().getActions(config.getConfigurationSection("mechanics.vanilla-mechanic-if-no-loot.actions"));

View File

@@ -21,7 +21,7 @@ import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.*;
import com.google.common.collect.Lists;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customfishing.CustomFishingPluginImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
@@ -73,14 +73,14 @@ public class ArmorStandUtils {
metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList);
}
public static PacketContainer getMetaPacket(int id, String text) {
public static PacketContainer getMetaPacket(int id, Component component) {
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
metaPacket.getIntegers().write(0, id);
if (CustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_R2()) {
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(text);
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(component);
setValueList(metaPacket, wrappedDataWatcher);
} else {
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(text).getWatchableObjects());
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(component).getWatchableObjects());
}
return metaPacket;
}
@@ -95,11 +95,11 @@ public class ArmorStandUtils {
return wrappedDataWatcher;
}
public static WrappedDataWatcher createDataWatcher(String text) {
public static WrappedDataWatcher createDataWatcher(Component component) {
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class);
WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class);
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(text))).getHandle()));
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)).getHandle()));
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), true);
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, serializer2), (byte) 0x01);
byte flag = 0x20;
@@ -116,11 +116,18 @@ public class ArmorStandUtils {
return equipPacket;
}
public static void sendAnimationToPlayer(Player player, Location location, ItemStack itemStack, int time) {
public static void sendFakeItem(Player player, Location location, ItemStack itemStack, int time) {
int id = new Random().nextInt(Integer.MAX_VALUE);
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getMetaPacket(id));
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getEquipPacket(id, itemStack));
CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), time * 50L, TimeUnit.MILLISECONDS);
}
public static void sendHologram(Player player, Location location, Component component, int time) {
int id = new Random().nextInt(Integer.MAX_VALUE);
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getMetaPacket(id, component));
CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), time * 50L, TimeUnit.MILLISECONDS);
}
}

View File

@@ -21,14 +21,10 @@ mechanics:
value:
- blacklist_world
# Global loot properties
global-loot-properties:
show-in-fishfinder: true
disable-stat: false
disable-game: false
instant-game: false
prevent-grabbing: false
events:
# global event settings
global-events:
bait: {}
loot:
success:
title_action:
type: random-title
@@ -60,7 +56,37 @@ mechanics:
stay: 30
fade-out: 10
chance: 1.0
rod:
land:
priority_action:
type: priority
value:
priority_1:
conditions:
in-lava: true
actions:
fake_item_action:
type: fake-item
value:
duration: 35
position: hook
item: util:lava_effect
y: 0
x: 0
z: 0
priority_2:
conditions:
in-lava: false
actions:
fake_item_action:
type: fake-item
value:
duration: 35
position: hook
item: util:water_effect
y: 0
x: 0
z: 0
# Fishing bag is where players can store their baits, utils and rods (Fish optional)
fishing-bag:
# Enable
@@ -79,16 +105,6 @@ mechanics:
min-wait-time: 100
max-wait-time: 600
# Animation settings
animation:
splash:
enable: true
water: water_effect
lava: lava_effect
duration: 25
bait:
enable: true
# Competition settings
competition:
# Use redis for cross server data synchronization

View File

@@ -11,7 +11,7 @@ rubbish:
disable-game: true
instant-game: false
prevent-grabbing: false
action:
events:
success:
mending:
type: mending
@@ -27,7 +27,7 @@ tuna_fish:
- <gray>Tuna is a kind of healthy food.
- '<white>size: {size}cm'
custom-model-data: 50001
action:
events:
success:
action_mending:
type: mending
@@ -47,7 +47,7 @@ tuna_fish_silver_star:
- <gray>Tuna is a kind of healthy food.
- '<white>size: {size}cm'
custom-model-data: 50002
action:
events:
success:
action_mending:
type: mending
@@ -67,7 +67,7 @@ tuna_fish_golden_star:
- <gray>Tuna is a kind of healthy food.
- '<white>size: {size}cm'
custom-model-data: 50003
action:
events:
success:
action_mending:
type: mending
@@ -90,7 +90,7 @@ pike_fish:
- <gray>water and inland freshwater lakes
- '<white>size: {size}cm'
custom-model-data: 50004
action:
events:
success:
action_mending:
type: mending
@@ -113,7 +113,7 @@ pike_fish_silver_star:
- <gray>water and inland freshwater lakes
- '<white>size: {size}cm'
custom-model-data: 50005
action:
events:
success:
action_mending:
type: mending
@@ -136,7 +136,7 @@ pike_fish_golden_star:
- <gray>water and inland freshwater lakes
- '<white>size: {size}cm'
custom-model-data: 50006
action:
events:
success:
action_mending:
type: mending
@@ -158,7 +158,7 @@ gold_fish:
price:
base: 70
custom-model-data: 50007
action:
events:
success:
action_mending:
type: mending
@@ -177,7 +177,7 @@ gold_fish_silver_star:
price:
base: 80
custom-model-data: 50008
action:
events:
success:
action_mending:
type: mending
@@ -196,7 +196,7 @@ gold_fish_golden_star:
price:
base: 100
custom-model-data: 50009
action:
events:
success:
action_mending:
type: mending
@@ -212,7 +212,7 @@ perch_fish:
- <gray>foraging at dusk and early morning
- '<white>size: {size}cm'
custom-model-data: 50010
action:
events:
success:
action_mending:
type: mending
@@ -233,7 +233,7 @@ perch_fish_silver_star:
- <gray>foraging at dusk and early morning
- '<white>size: {size}cm'
custom-model-data: 50011
action:
events:
success:
action_mending:
type: mending
@@ -254,7 +254,7 @@ perch_fish_golden_star:
- <gray>foraging at dusk and early morning
- '<white>size: {size}cm'
custom-model-data: 50012
action:
events:
success:
action_mending:
type: mending
@@ -275,7 +275,7 @@ mullet_fish:
- <gray>to treat spleen and stomach weakness
- '<white>size: {size}cm'
custom-model-data: 50013
action:
events:
success:
action_mending:
type: mending
@@ -296,7 +296,7 @@ mullet_fish_silver_star:
- <gray>to treat spleen and stomach weakness
- '<white>size: {size}cm'
custom-model-data: 50014
action:
events:
success:
action_mending:
type: mending
@@ -317,7 +317,7 @@ mullet_fish_golden_star:
- <gray>to treat spleen and stomach weakness
- '<white>size: {size}cm'
custom-model-data: 50015
action:
events:
success:
action_mending:
type: mending
@@ -338,7 +338,7 @@ sardine_fish:
- <gray>Therefore, sardine are also called "smart food"
- '<white>size: {size}cm'
custom-model-data: 50016
action:
events:
success:
action_mending:
type: mending
@@ -358,7 +358,7 @@ sardine_fish_silver_star:
- <gray>Therefore, sardine are also called "smart food"
- '<white>size: {size}cm'
custom-model-data: 50017
action:
events:
success:
action_mending:
type: mending
@@ -378,7 +378,7 @@ sardine_fish_golden_star:
- <gray>Therefore, sardine are also called "smart food"
- '<white>size: {size}cm'
custom-model-data: 50018
action:
events:
success:
action_mending:
type: mending
@@ -398,7 +398,7 @@ carp_fish:
- <gray>One of the most common edible fish
- '<white>size: {size}cm'
custom-model-data: 50019
action:
events:
success:
action_mending:
type: mending
@@ -417,7 +417,7 @@ carp_fish_silver_star:
- <gray>One of the most common edible fish
- '<white>size: {size}cm'
custom-model-data: 50020
action:
events:
success:
action_mending:
type: mending
@@ -436,7 +436,7 @@ carp_fish_golden_star:
- <gray>One of the most common edible fish
- '<white>size: {size}cm'
custom-model-data: 50021
action:
events:
success:
action_mending:
type: mending
@@ -456,7 +456,7 @@ cat_fish:
- <gray>sharp jaw teeth, short intestine and stomach
- '<white>size: {size}cm'
custom-model-data: 50022
action:
events:
success:
action_mending:
type: mending
@@ -476,7 +476,7 @@ cat_fish_silver_star:
- <gray>sharp jaw teeth, short intestine and stomach
- '<white>size: {size}cm'
custom-model-data: 50023
action:
events:
success:
action_mending:
type: mending
@@ -496,7 +496,7 @@ cat_fish_golden_star:
- <gray>sharp jaw teeth, short intestine and stomach
- '<white>size: {size}cm'
custom-model-data: 50024
action:
events:
success:
action_mending:
type: mending
@@ -517,7 +517,7 @@ octopus:
- <gray>People often use pots to catch octopus
- '<white>size: {size}cm'
custom-model-data: 50025
action:
events:
success:
action_mending:
type: mending
@@ -537,7 +537,7 @@ octopus_silver_star:
- <gray>People often use pots to catch octopus
- '<white>size: {size}cm'
custom-model-data: 50026
action:
events:
success:
action_mending:
type: mending
@@ -557,7 +557,7 @@ octopus_golden_star:
- <gray>People often use pots to catch octopus
- '<white>size: {size}cm'
custom-model-data: 50027
action:
events:
success:
action_mending:
type: mending
@@ -577,7 +577,7 @@ sunfish:
- <gray>It only has one huge head
- '<white>size: {size}cm'
custom-model-data: 50028
action:
events:
success:
action_mending:
type: mending
@@ -596,7 +596,7 @@ sunfish_silver_star:
- <gray>It only has one huge head
- '<white>size: {size}cm'
custom-model-data: 50029
action:
events:
success:
action_mending:
type: mending
@@ -615,7 +615,7 @@ sunfish_golden_star:
- <gray>It only has one huge head
- '<white>size: {size}cm'
custom-model-data: 50030
action:
events:
success:
action_mending:
type: mending
@@ -635,7 +635,7 @@ red_snapper_fish:
- <gray>with a male as the "head of the family"
- '<white>size: {size}cm'
custom-model-data: 50031
action:
events:
success:
action_mending:
type: mending
@@ -656,7 +656,7 @@ red_snapper_fish_silver_star:
- <gray>with a male as the "head of the family"
- '<white>size: {size}cm'
custom-model-data: 50032
action:
events:
success:
action_mending:
type: mending
@@ -677,7 +677,7 @@ red_snapper_fish_golden_star:
- <gray>with a male as the "head of the family"
- '<white>size: {size}cm'
custom-model-data: 50033
action:
events:
success:
action_mending:
type: mending
@@ -697,7 +697,7 @@ salmon_void_fish:
lore:
- <gray>A fish from the hell
custom-model-data: 50034
action:
events:
success:
action_mending:
type: mending
@@ -714,7 +714,7 @@ salmon_void_fish_silver_star:
lore:
- <gray>A fish from the hell
custom-model-data: 50035
action:
events:
success:
action_mending:
type: mending
@@ -732,7 +732,7 @@ salmon_void_fish_golden_star:
- <gray>A fish from the hell
group: gold
custom-model-data: 50036
action:
events:
success:
action_mending:
type: mending
@@ -751,7 +751,7 @@ woodskip_fish:
- <gray>live in pools deep in the forest
- '<white>size: {size}cm'
custom-model-data: 50037
action:
events:
success:
action_mending:
type: mending
@@ -771,7 +771,7 @@ woodskip_fish_silver_star:
- <gray>live in pools deep in the forest
- '<white>size: {size}cm'
custom-model-data: 50038
action:
events:
success:
action_mending:
type: mending
@@ -791,7 +791,7 @@ woodskip_fish_golden_star:
- <gray>live in pools deep in the forest
- '<white>size: {size}cm'
custom-model-data: 50039
action:
events:
success:
action_mending:
type: mending
@@ -812,7 +812,7 @@ sturgeon_fish:
- <gray>population. Females can live up to 150 years
- '<white>size: {size}cm'
custom-model-data: 50040
action:
events:
success:
action_mending:
type: mending
@@ -832,7 +832,7 @@ sturgeon_fish_silver_star:
- <gray>population. Females can live up to 150 years
- '<white>size: {size}cm'
custom-model-data: 50041
action:
events:
success:
action_mending:
type: mending
@@ -852,7 +852,7 @@ sturgeon_fish_golden_star:
- <gray>population. Females can live up to 150 years
- '<white>size: {size}cm'
custom-model-data: 50042
action:
events:
success:
action_mending:
type: mending

View File

@@ -5,7 +5,7 @@
######################################
rainbow_1:
game-type: accurate_click
title: '<#B22222>RED!'
title: '<#fd4036>RED!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -24,7 +24,7 @@ rainbow_1:
7: 0
rainbow_2:
game-type: accurate_click
title: '<#FFA500>ORANGE!'
title: '<#ffa449>ORANGE!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -43,7 +43,7 @@ rainbow_2:
7: 0
rainbow_3:
game-type: accurate_click
title: '<#FFFF00>YELLOW!'
title: '<#ffca4c>YELLOW!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -62,7 +62,7 @@ rainbow_3:
7: 0
rainbow_4:
game-type: accurate_click
title: '<GREEN>GREEN!'
title: '<#34f250>GREEN!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -81,7 +81,7 @@ rainbow_4:
7: 0
rainbow_5:
game-type: accurate_click
title: '<#00FFFF>AQUA!'
title: '<#34f2d5>AQUA!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -100,7 +100,7 @@ rainbow_5:
7: 0
rainbow_6:
game-type: accurate_click
title: '<#1E90FF>BLUE!'
title: '<#34f2d5>BLUE!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -119,7 +119,7 @@ rainbow_6:
7: 0
rainbow_7:
game-type: accurate_click
title: '<#9400D3>PURPLE!'
title: '<#c96cff>PURPLE!'
subtitle:
font: 'customfishing:default'
bar: '뀋'
@@ -583,10 +583,4 @@ tension_game:
- '<font:customfishing:icons>뀖</font>'
- '<font:customfishing:icons>뀗</font>'
- '<font:customfishing:icons>뀘</font>'
- '<font:customfishing:icons>뀙</font>'
######################################
# Burst #
# When the fish is hooked, you need #
# to click quickly in limited time #
######################################
- '<font:customfishing:icons>뀙</font>'

View File

@@ -1,3 +1,9 @@
# Vanilla fishing rod properties
FISHING_ROD:
tag: false
material: fishing_rod
# Custom rods
wooden_rod:
material: fishing_rod
display: