Implemented lava fishing

This commit is contained in:
Teriuihi 2023-09-27 23:27:43 +02:00
parent 49fdb5a602
commit c971e11d9f
6 changed files with 290 additions and 67 deletions

View File

@ -5,7 +5,7 @@ import com.alttd.fishingevent.config.Config;
import com.alttd.fishingevent.config.Fishes;
import com.alttd.fishingevent.config.Messages;
import com.alttd.fishingevent.config.NPCLocationConfig;
import com.alttd.fishingevent.fish_generator.WaterFishGenerator;
import com.alttd.fishingevent.fish_generator.FishGenerator;
import com.alttd.fishingevent.gui.GUIListener;
import com.alttd.fishingevent.listeners.CatchFish;
import com.alttd.fishingevent.npc.NPCManager;
@ -63,7 +63,7 @@ public final class FishingEvent extends JavaPlugin {
}
private void registerEvents(@NotNull PluginManager pluginManager) {
pluginManager.registerEvents(new CatchFish(logger, new WaterFishGenerator(Fishes.FISH.RARITY_WATER_FISH_MAP, new RarityManager(Config.RARITY.RARITY_SET), logger), PointsManagement.getInstance()), this);
pluginManager.registerEvents(new CatchFish(this, logger, new FishGenerator(Fishes.FISH.RARITY_WATER_FISH_MAP, new RarityManager(Config.RARITY.RARITY_SET), logger), PointsManagement.getInstance()), this);
pluginManager.registerEvents(new GUIListener(), this);
}

View File

@ -1,13 +1,45 @@
package com.alttd.fishingevent.fish_generator;
import com.alttd.fishingevent.fish.Fish;
import com.alttd.fishingevent.objects.FishType;
import com.alttd.fishingevent.objects.*;
import com.alttd.fishingevent.util.Logger;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
public interface FishGenerator {
public class FishGenerator {
Optional<Fish> getFish(ItemStack fishingRod, FishType fishType);
private final HashMap<Rarity, List<Fish>> possibleFishMap;
private final RandomListItem<Fish> randomListItem = new RandomListItem<>();
private final RarityManager rarityManager;
private final Logger logger;
public FishGenerator(HashMap<Rarity, List<Fish>> possibleFishMap, RarityManager rarityManager, Logger logger) {
this.possibleFishMap = possibleFishMap;
this.rarityManager = rarityManager;
this.logger = logger;
}
public Optional<Fish> getFish(ItemStack fishingRod, FishType fishType) {
if (!fishingRod.getType().equals(Material.FISHING_ROD))
return Optional.empty();
int luckLevel = fishingRod.getEnchantmentLevel(Enchantment.LUCK);
int maxChanceRange = rarityManager.getMaxChanceRange(fishType);
int rarityValue = CustomRandom.generateNumber(0, maxChanceRange, luckLevel + 1);
Optional<Rarity> optionalRarity = rarityManager.getRarityFromNumber(fishType, rarityValue);
if (optionalRarity.isEmpty())
return Optional.empty();
Rarity rarity = optionalRarity.get();
List<Fish> fish = possibleFishMap.get(rarity);
if (fish == null) {
logger.warning("Empty fish map for rarity [%]", rarity.toString());
return Optional.empty();
}
return randomListItem.getRandomObject(fish);
}
}

View File

@ -1,46 +0,0 @@
package com.alttd.fishingevent.fish_generator;
import com.alttd.fishingevent.fish.Fish;
import com.alttd.fishingevent.objects.*;
import com.alttd.fishingevent.util.Logger;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
public class WaterFishGenerator implements FishGenerator {
private final HashMap<Rarity, List<Fish>> possibleFishMap;
private final RandomListItem<Fish> randomListItem = new RandomListItem<>();
private final RarityManager rarityManager;
private final Logger logger;
public WaterFishGenerator(HashMap<Rarity, List<Fish>> possibleFishMap, RarityManager rarityManager, Logger logger) {
this.possibleFishMap = possibleFishMap;
this.rarityManager = rarityManager;
this.logger = logger;
}
@Override
public Optional<Fish> getFish(ItemStack fishingRod, FishType fishType) {
if (!fishingRod.getType().equals(Material.FISHING_ROD))
return Optional.empty();
int luckLevel = fishingRod.getEnchantmentLevel(Enchantment.LUCK);
int maxChanceRange = rarityManager.getMaxChanceRange(fishType);
int rarityValue = CustomRandom.generateNumber(0, maxChanceRange, luckLevel + 1);
Optional<Rarity> optionalRarity = rarityManager.getRarityFromNumber(fishType, rarityValue);
if (optionalRarity.isEmpty())
return Optional.empty();
Rarity rarity = optionalRarity.get();
List<Fish> fish = possibleFishMap.get(rarity);
if (fish == null) {
logger.warning("Empty fish map for rarity [%]", rarity.toString());
return Optional.empty();
}
return randomListItem.getRandomObject(fish);
}
}

View File

@ -1,13 +1,20 @@
package com.alttd.fishingevent.listeners;
import com.alttd.fishingevent.FishingEvent;
import com.alttd.fishingevent.config.Messages;
import com.alttd.fishingevent.fish.Fish;
import com.alttd.fishingevent.fish_generator.FishGenerator;
import com.alttd.fishingevent.objects.CaughtFishData;
import com.alttd.fishingevent.objects.FishType;
import com.alttd.fishingevent.points.PointsManagement;
import com.alttd.fishingevent.scoreboard.ScoreboardManager;
import com.alttd.fishingevent.timer.EventManager;
import com.alttd.fishingevent.util.Logger;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.title.Title;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -18,8 +25,10 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Optional;
import java.util.*;
public class CatchFish implements Listener {
@ -27,8 +36,11 @@ public class CatchFish implements Listener {
private final FishGenerator waterFishGenerator;
private final PointsManagement pointsManagement;
private final EventManager eventManager = EventManager.getInstance();
private final FishingEvent fishingEvent;
private final HashMap<UUID, LavaFishing> activeLavaFishers = new HashMap<>();
public CatchFish(Logger logger, FishGenerator waterFishGenerator, PointsManagement pointsManagement) {
public CatchFish(FishingEvent fishingEvent, Logger logger, FishGenerator waterFishGenerator, PointsManagement pointsManagement) {
this.fishingEvent = fishingEvent;
this.logger = logger;
this.waterFishGenerator = waterFishGenerator;
this.pointsManagement = pointsManagement;
@ -41,25 +53,67 @@ public class CatchFish implements Listener {
event.setCancelled(true);
return;
}
Player player = event.getPlayer();
if (fishingRodBroken(player)) {
player.showTitle(Title.title(Component.empty(), MiniMessage.miniMessage().deserialize("<red>Your rod is too damaged to fish</red>")));
event.setCancelled(true);
return;
}
if (event.getState().equals(PlayerFishEvent.State.FISHING)) {
//if fishing rod in lava continue else return
new BukkitRunnable() {
@Override
public void run() {
if (event.getHook().getLocation().getBlock().getType().equals(Material.LAVA)) {
player.showTitle(Title.title(Component.empty(), MiniMessage.miniMessage().deserialize("<gold>You are now fishing in lava...</gold>"))); //TODO move to config
LavaFishing lavaFishing = new LavaFishing(1, 1, player, logger, event.getHook().getLocation());
activeLavaFishers.put(player.getUniqueId(), lavaFishing);
lavaFishing.runTaskTimerAsynchronously(fishingEvent, 1, 1);
logger.debug("in lava above");
} else
logger.debug("Not in lava");
// logger.debug("% might have caught a lava fish", event.getPlayer().getName());
// handleLavaFishCaught(event);
}
}.runTaskLater(fishingEvent, 50);
} else if (event.getState().equals(PlayerFishEvent.State.CAUGHT_FISH)) {
if (event.getCaught() == null) {
logger.debug("% caught a water fish but it was null", event.getPlayer().getName());
logger.debug("% caught a water fish but it was null", player.getName());
return;
}
logger.debug("% caught a water fish", event.getPlayer().getName());
logger.debug("% caught a water fish", player.getName());
handleFishCaught(event);
} else if (event.getState().equals(PlayerFishEvent.State.IN_GROUND)) {
logger.debug("% reeled in fishing rod that was in the ground", event.getPlayer().getName());
logger.debug("% reeled in fishing rod that was in the ground", player.getName());
handleLavaFishCaught(event);
} else {
logger.debug("Registered different fish state [%]", event.getState().toString());
}
}
private boolean fishingRodBroken(Player player) {
Optional<ItemStack> optionalFishingROd = getFishingRod(player);
if (optionalFishingROd.isEmpty()) {
logger.warning("No fishing rod found for %", player.getName());
return true;
}
ItemStack fishingRod = optionalFishingROd.get();
if (fishingRod.getItemMeta() instanceof Damageable damageable) {
int damage = damageable.getDamage();
return damage >= 63;
}
return false;
}
private Optional<ItemStack> getFishingRod(Player player) {
return Arrays.stream(player.getInventory().getStorageContents())
.filter(Objects::nonNull)
.filter(itemStack -> itemStack.getType().equals(Material.FISHING_ROD))
.findFirst();
}
private void handleLavaFish(PlayerFishEvent event) {
Location location = event.getHook().getLocation();
Block block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() + 1, location.getBlockZ());
@ -69,7 +123,32 @@ public class CatchFish implements Listener {
}
private void handleLavaFishCaught(PlayerFishEvent event) {
Player player = event.getPlayer();
LavaFishing lavaFishing = activeLavaFishers.get(player.getUniqueId());
if (lavaFishing == null) {
logger.debug("Reeled in but was not lava fishing");
return;
}
activeLavaFishers.remove(player.getUniqueId());
lavaFishing.cancel();
if (!lavaFishing.canCatchFish()) {
logger.debug("Reeled in in lava but too early");
return;
}
Optional<CaughtFishData> optionalFishData = getFishData(event, player, FishType.LAVA);
if (optionalFishData.isEmpty())
return;
CaughtFishData caughtFishData = optionalFishData.get();
player.getInventory().addItem(caughtFishData.fishItem()).values()
.forEach(item -> player.getWorld().dropItem(player.getLocation(), item).setOwner(player.getUniqueId()));
player.updateInventory();
ScoreboardManager.getInstance().updateScoreboard(player, caughtFishData.length(), caughtFishData.fish());
player.showTitle(Title.title(Component.empty(), MiniMessage.miniMessage().deserialize("<green>You caught a <rarity> <name> fish <gold><length> cm</gold></green>", //TODO move to config
TagResolver.resolver(
Placeholder.component("rarity", caughtFishData.fish().getRarity().displayName()),
Placeholder.component("name", caughtFishData.fish().fishName()),
Placeholder.parsed("length", String.valueOf(caughtFishData.length()))
))));
}
private void handleFishCaught(PlayerFishEvent event) {
@ -82,13 +161,33 @@ public class CatchFish implements Listener {
logger.debug(String.valueOf(item.getItemStack().getType()));
Player player = event.getPlayer();
Optional<CaughtFishData> optionalFishData = getFishData(event, player, FishType.WATER);
if (optionalFishData.isEmpty())
return;
CaughtFishData caughtFishData = optionalFishData.get();
item.setItemStack(caughtFishData.fishItem());
logger.debug(String.valueOf(item.getItemStack().getType()));
item.setOwner(player.getUniqueId());
logger.debug("[%] caught a [%] with length [%] and rarity [%] for [%] points",
player.getName(), caughtFishData.fish().normalFishName(), String.format("%.2f", caughtFishData.length()),
caughtFishData.fish().getRarity().displayNameString(), String.valueOf(caughtFishData.pointsValue()));
ScoreboardManager.getInstance().updateScoreboard(player, caughtFishData.length(), caughtFishData.fish());
player.showTitle(Title.title(Component.empty(), MiniMessage.miniMessage().deserialize("<green>You caught a <rarity> <name> fish <gold><length> cm</gold></green>", //TODO move to config
TagResolver.resolver(
Placeholder.component("rarity", caughtFishData.fish().getRarity().displayName()),
Placeholder.component("name", caughtFishData.fish().fishName()),
Placeholder.parsed("length", String.valueOf(caughtFishData.length()))
))));
}
private Optional<CaughtFishData> getFishData(PlayerFishEvent event, Player player, FishType fishType) {
ItemStack activeItem = player.getInventory().getItemInMainHand();
if (!activeItem.getType().equals(Material.FISHING_ROD))
activeItem = player.getInventory().getItemInOffHand();
Optional<Fish> optionalFish = waterFishGenerator.getFish(activeItem, FishType.WATER);
Optional<Fish> optionalFish = waterFishGenerator.getFish(activeItem, fishType);
if (optionalFish.isEmpty()) {
logger.warning("Unable to get water fish for %", event.getPlayer().getName());
return;
return Optional.empty();
}
Fish fish = optionalFish.get();
@ -98,14 +197,8 @@ public class CatchFish implements Listener {
if (fishItem.isEmpty()) {
player.sendMiniMessage(Messages.OTHER_ERRORS.UNABLE_TO_CREATE_FISH, null);
event.setCancelled(true);
return;
return Optional.empty();
}
item.setItemStack(fishItem.get());
logger.debug(String.valueOf(item.getItemStack().getType()));
item.setOwner(player.getUniqueId());
logger.debug("[%] caught a [%] with length [%] and rarity [%] for [%] points",
player.getName(), fish.normalFishName(), String.format("%.2f", length),
fish.getRarity().displayNameString(), String.valueOf(pointsValue));
ScoreboardManager.getInstance().updateScoreboard(player, length, fish);
return Optional.of(new CaughtFishData(fish, fishItem.get(), length, pointsValue));
}
}

View File

@ -0,0 +1,137 @@
package com.alttd.fishingevent.listeners;
import com.alttd.fishingevent.util.Logger;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Random;
public class LavaFishing extends BukkitRunnable {
private int timeUntilHooked;
private int timeUntilLured;
private final int lure;
private final int fireProtection;
private final int minWaitTime = 100;
private final int maxWaitTime = 600;
private boolean isBiting;
private int timeUntilHookDamage;
private boolean shouldDamageHook;
private final Random random = new Random();
private final Player player;
private final Logger logger;
private final Location hookLocation;
public LavaFishing(int lure, int fireProtection, Player player, Logger logger, Location hookLocation) {
this.lure = lure;
this.fireProtection = Math.min(5, fireProtection);
this.player = player;
this.logger = logger;
this.hookLocation = hookLocation;
this.shouldDamageHook = fireProtection >= 5;
resetTimeUntilHookDamage();
resetTimeUntilLured();
}
private void resetTimeUntilLured() {
isBiting = false;
this.timeUntilLured = random.nextInt(minWaitTime, maxWaitTime);
this.timeUntilLured = Math.max(timeUntilLured - this.lure * 100, minWaitTime);
}
private void damageHook() {
if (!shouldDamageHook)
return;
if (timeUntilHookDamage > 0) {
timeUntilHookDamage--;
return;
}
resetTimeUntilHookDamage();
PlayerInventory inventory = player.getInventory();
int fishingRodSlot = findFishingRodSlot(inventory);
if (fishingRodSlot < 0) {
logger.warning("Unable to find fishing rod slot");
return;
}
ItemStack item = inventory.getItem(fishingRodSlot);
if (item == null) {
logger.warning("Unable to find fishing rod");
return;
}
if (item.getItemMeta() instanceof Damageable damageable) {
int damage = damageable.getDamage();
damageable.setDamage(Math.min(++damage, 63));
item.setItemMeta(damageable);
} else {
logger.warning("This item can't be damaged");
}
}
private int findFishingRodSlot(Inventory inventory) {
ItemStack[] contents = inventory.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack item = contents[i];
if (item != null && item.getType().equals(Material.FISHING_ROD)) {
return i;
}
}
return -1;
}
private void resetTimeUntilHookDamage() {
timeUntilHookDamage = random.nextInt(fireProtection, 5 + fireProtection);
}
private void spawnLavaParticles() {
// Customize the particle effect
Particle particle = Particle.LAVA;
int count = 10; // Number of particles to spawn
double offsetX = 0.2; // X-axis offset
double offsetY = 1.0; // Y-axis offset (positive value for upward direction)
double offsetZ = 0.2; // Z-axis offset
double extra = 0.1; // Extra random offset
// Spawn the lava particles
hookLocation.getWorld().spawnParticle(particle, hookLocation, count, offsetX, offsetY, offsetZ, extra);
}
@Override
public void run() {
damageHook();
if (!isBiting && timeUntilLured > 0) {
timeUntilLured--;
if (timeUntilLured % 5 == 0)
logger.debug("Time until lured: %", String.valueOf(timeUntilLured));
return;
}
if (!isBiting) {
isBiting = true;
this.timeUntilHooked = random.nextInt(20, 60);
spawnLavaParticles();
logger.debug("Fish on hook in lava");
return;
}
if (this.timeUntilHooked > 0) {
this.timeUntilHooked--;
if (timeUntilHooked % 5 == 0)
logger.debug("Time until hooked: %", String.valueOf(timeUntilLured));
if (this.timeUntilHooked % 5 == 0)
spawnLavaParticles();
return;
}
resetTimeUntilLured();
}
public boolean canCatchFish() {
return isBiting;
}
}

View File

@ -0,0 +1,7 @@
package com.alttd.fishingevent.objects;
import com.alttd.fishingevent.fish.Fish;
import org.bukkit.inventory.ItemStack;
public record CaughtFishData(Fish fish, ItemStack fishItem, double length, int pointsValue) {
}