Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to catch entities with fishing #301

Merged
merged 5 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import dev.aurelium.auraskills.api.user.SkillsUser;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Called when AuraSkills drops extra loot from mechanics like Fishing, Luck, and custom loot tables.
Expand All @@ -22,6 +25,7 @@ public class LootDropEvent extends Event implements Cancellable {
private Location location;
private final Cause cause;
private boolean toInventory;
private Entity entity;
private boolean cancelled = false;

public LootDropEvent(Player player, SkillsUser user, ItemStack item, Location location, Cause cause, boolean toInventory) {
Expand All @@ -33,6 +37,26 @@ public LootDropEvent(Player player, SkillsUser user, ItemStack item, Location lo
this.toInventory = toInventory;
}

public LootDropEvent(Player player, SkillsUser user, Entity entity, Location location, Cause cause) {
this.player = player;
this.user = user;
this.location = location;
this.cause = cause;
this.toInventory = false;
this.entity = entity;
// Let's not break things and make the item not nullable still
this.item = new ItemStack(Material.AIR);
}

/**
* Gets the spawned entity if the loot was an entity.
*
* @return the entity
*/
public @Nullable Entity getEntity() {
return entity;
}

/**
* Gets the player that caused the loot drop.
*
Expand All @@ -53,6 +77,7 @@ public SkillsUser getUser() {

/**
* Gets the item that will be dropped by the event.
* If the drop is an entity, this will be AIR.
*
* @return the item
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.aurelium.auraskills.bukkit.AuraSkills;
import dev.aurelium.auraskills.bukkit.damage.DamageHandler;
import dev.aurelium.auraskills.bukkit.damage.DamageResult;
import dev.aurelium.auraskills.bukkit.hooks.mythicmobs.loot.MythicEntityLootParser;
import dev.aurelium.auraskills.common.hooks.Hook;
import dev.aurelium.auraskills.api.damage.DamageType;
import io.lumine.mythic.api.adapters.AbstractEntity;
Expand All @@ -30,6 +31,10 @@ public MythicMobsHook(AuraSkills plugin, ConfigurationNode config) {
super(plugin, config);
this.plugin = plugin;
this.damageHandler = new DamageHandler();

// Wait for loot manager to be created, but add parser before it is loaded
plugin.getScheduler().executeSync(() ->
plugin.getLootTableManager().getLootManager().registerCustomEntityParser(new MythicEntityLootParser()));
}

@EventHandler(priority = EventPriority.HIGH)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.aurelium.auraskills.bukkit.hooks.mythicmobs.loot;

import dev.aurelium.auraskills.bukkit.loot.entity.EntityProperties;
import dev.aurelium.auraskills.bukkit.loot.entity.EntitySupplier;
import dev.aurelium.auraskills.bukkit.loot.parser.CustomEntityParser;
import org.spongepowered.configurate.ConfigurationNode;

public class MythicEntityLootParser implements CustomEntityParser {

@Override
public EntitySupplier getEntitySupplier(ConfigurationNode config) {
return new MythicEntitySupplier(EntityProperties.fromConfig(config));
}

@Override
public boolean shouldUseParser(ConfigurationNode config) {
return config.node("entity").getString("").startsWith("mythicmobs:");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.aurelium.auraskills.bukkit.hooks.mythicmobs.loot;

import dev.aurelium.auraskills.bukkit.AuraSkills;
import dev.aurelium.auraskills.bukkit.loot.entity.EntityProperties;
import dev.aurelium.auraskills.bukkit.loot.entity.EntitySupplier;
import io.lumine.mythic.bukkit.BukkitAdapter;
import io.lumine.mythic.bukkit.MythicBukkit;
import io.lumine.mythic.core.mobs.ActiveMob;
import org.bukkit.Location;
import org.bukkit.entity.Entity;

public class MythicEntitySupplier extends EntitySupplier {
Archy-X marked this conversation as resolved.
Show resolved Hide resolved

public MythicEntitySupplier(EntityProperties entityProperties) {
super(entityProperties);
}

@Override
public Entity spawnEntity(AuraSkills plugin, Location location) {
ActiveMob activeMob;

if (getEntityProperties().level() != null) {
activeMob = MythicBukkit.inst().getMobManager().spawnMob(getEntityProperties().entityId(), location, getEntityProperties().level());
} else {
activeMob = MythicBukkit.inst().getMobManager().spawnMob(getEntityProperties().entityId(), location);
}

return BukkitAdapter.adapt(activeMob.getEntity());
}

@Override
public void removeEntity(Entity entity) {
MythicBukkit.inst().getMobManager().getActiveMob(entity.getUniqueId()).ifPresent(ActiveMob::remove);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.aurelium.auraskills.api.loot.*;
import dev.aurelium.auraskills.api.registry.NamespacedId;
import dev.aurelium.auraskills.bukkit.loot.parser.CommandLootParser;
import dev.aurelium.auraskills.bukkit.loot.parser.EntityLootParser;
import dev.aurelium.auraskills.bukkit.loot.parser.ItemLootParser;
import dev.aurelium.auraskills.bukkit.loot.parser.LootParsingContextImpl;
import dev.aurelium.auraskills.bukkit.util.VersionUtils;
Expand Down Expand Up @@ -70,6 +71,9 @@ public LootTable loadLootTable(NamespacedId id, File file, ConfigurationNode con
// Command loot
else if (lootType.equalsIgnoreCase("command")) {
loot = new CommandLootParser().parse(context, lootNode);
// Entity loot, mainly for fishing
} else if (lootType.equalsIgnoreCase("entity")) {
loot = new EntityLootParser(manager).parse(context, lootNode);
} else {
// Parse custom loot registered from API
LootParser customParser = manager.getCustomLootParsers().get(lootType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.aurelium.auraskills.api.loot.LootParser;
import dev.aurelium.auraskills.bukkit.AuraSkills;
import dev.aurelium.auraskills.bukkit.loot.context.ContextProvider;
import dev.aurelium.auraskills.bukkit.loot.parser.CustomEntityParser;
import dev.aurelium.auraskills.bukkit.loot.parser.CustomItemParser;
import org.jetbrains.annotations.Nullable;

Expand All @@ -16,6 +17,7 @@ public class LootManager {
private final Set<String> lootOptionKeys;
private final Set<String> poolOptionKeys;
private final List<CustomItemParser> customItemParsers;
private final List<CustomEntityParser> customEntityParsers;
private final Map<String, LootParser> customLootParsers;

public LootManager(AuraSkills plugin) {
Expand All @@ -24,6 +26,7 @@ public LootManager(AuraSkills plugin) {
this.contextProviders = new HashMap<>();
this.lootOptionKeys = new HashSet<>();
this.poolOptionKeys = new HashSet<>();
this.customEntityParsers = new ArrayList<>();
this.customItemParsers = new ArrayList<>();
this.customLootParsers = new HashMap<>();
}
Expand Down Expand Up @@ -77,10 +80,18 @@ public List<CustomItemParser> getCustomItemParsers() {
return customItemParsers;
}

public List<CustomEntityParser> getCustomEntityParsers() {
return customEntityParsers;
}

public void registerCustomItemParser(CustomItemParser customItemParser) {
customItemParsers.add(customItemParser);
}

public void registerCustomEntityParser(CustomEntityParser customEntityParser) {
customEntityParsers.add(customEntityParser);
}

public Map<String, LootParser> getCustomLootParsers() {
return customLootParsers;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import dev.aurelium.auraskills.bukkit.AuraSkills;
import dev.aurelium.auraskills.bukkit.loot.context.MobContextProvider;
import dev.aurelium.auraskills.bukkit.loot.context.SourceContextProvider;
import dev.aurelium.auraskills.bukkit.loot.entity.VanillaEntityParser;
import dev.aurelium.auraskills.bukkit.util.ItemUtils;
import dev.aurelium.auraskills.common.api.ApiAuraSkills;
import dev.aurelium.auraskills.common.config.ConfigurateLoader;
Expand Down Expand Up @@ -44,6 +45,7 @@ public void initLootManager() {
lootManager.registerContextProvider(new SourceContextProvider(plugin));
lootManager.registerContextProvider(new MobContextProvider());
lootManager.registerCustomItemParser(new ItemKeyParser(plugin));
lootManager.registerCustomEntityParser(new VanillaEntityParser());
lootManager.addLootOptionKeys("xp");
lootManager.addPoolOptionKeys("chance_per_luck", "require_open_water");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dev.aurelium.auraskills.bukkit.loot.entity;

import org.spongepowered.configurate.ConfigurationNode;

public record EntityProperties(String entityId,
String name,
Integer level,
Archy-X marked this conversation as resolved.
Show resolved Hide resolved
Double health,
Double damage,
Float horizontalVelocity,
Float verticalVelocity) {

public static EntityProperties fromConfig(ConfigurationNode config) {
String[] id = config.node("entity").getString("").split(":");

return new EntityProperties(
id.length > 1 ? id[1] : id[0],
config.node("name").getString(),
config.node("level").empty() ? null : config.node("level").getInt(),
config.node("health").empty() ? null : config.node("health").getDouble(),
config.node("damage").empty() ? null : config.node("damage").getDouble(),
config.node("velocity", "horizontal").empty() ? null : config.node("velocity", "horizontal").getFloat(),
config.node("velocity", "vertical").empty() ? null : config.node("velocity", "vertical").getFloat()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.aurelium.auraskills.bukkit.loot.entity;

import dev.aurelium.auraskills.bukkit.AuraSkills;
import org.bukkit.Location;
import org.bukkit.entity.Entity;

public abstract class EntitySupplier {
Archy-X marked this conversation as resolved.
Show resolved Hide resolved

private final EntityProperties entityProperties;

public EntitySupplier(EntityProperties entityProperties) {
this.entityProperties = entityProperties;
}

public abstract Entity spawnEntity(AuraSkills plugin, Location location);
Archy-X marked this conversation as resolved.
Show resolved Hide resolved

public abstract void removeEntity(Entity entity);

public EntityProperties getEntityProperties() {
return entityProperties;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.aurelium.auraskills.bukkit.loot.entity;

import dev.aurelium.auraskills.bukkit.loot.parser.CustomEntityParser;
import org.spongepowered.configurate.ConfigurationNode;

public class VanillaEntityParser implements CustomEntityParser {
Archy-X marked this conversation as resolved.
Show resolved Hide resolved

@Override
public EntitySupplier getEntitySupplier(ConfigurationNode config) {
return new VanillaEntitySupplier(EntityProperties.fromConfig(config));
}

@Override
public boolean shouldUseParser(ConfigurationNode config) {
String entity = config.node("entity").getString();

if (entity == null) return false;

// If it has a colon, it's a custom entity
// But if it starts with minecraft:, it's a vanilla entity stated explicitly
return !entity.contains(":") || entity.startsWith("minecraft:");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package dev.aurelium.auraskills.bukkit.loot.entity;

import dev.aurelium.auraskills.bukkit.AuraSkills;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.metadata.FixedMetadataValue;

public class VanillaEntitySupplier extends EntitySupplier {

public VanillaEntitySupplier(EntityProperties entityProperties) {
super(entityProperties);
}

@Override
public Entity spawnEntity(AuraSkills plugin, Location location) {
World world = location.getWorld();
if (world == null) return null;

Entity entity = world.spawnEntity(location, EntityType.valueOf(getEntityProperties().entityId().toUpperCase()));

if (entity instanceof LivingEntity livingEntity) {
if (getEntityProperties().health() != null) {
AttributeInstance attribute = livingEntity.getAttribute(Attribute.GENERIC_MAX_HEALTH);
if (attribute != null) {
attribute.setBaseValue(getEntityProperties().health());
livingEntity.setHealth(Math.min(getEntityProperties().health(), attribute.getValue()));
}
}
if (getEntityProperties().damage() != null) {
AttributeInstance attribute = livingEntity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE);
if (attribute != null) {
attribute.setBaseValue(getEntityProperties().damage());
}
}
}

if (getEntityProperties().name() != null) {
entity.setCustomName(plugin.getMessageProvider().applyFormatting(getEntityProperties().name()));
entity.setCustomNameVisible(true);
}

if (getEntityProperties().level() != null) {
entity.setMetadata("auraskills_level", new FixedMetadataValue(plugin, getEntityProperties().level()));
}

return entity;
}

@Override
public void removeEntity(Entity entity) {
entity.remove();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import dev.aurelium.auraskills.api.loot.LootTable;
import dev.aurelium.auraskills.bukkit.loot.context.SourceContext;
import dev.aurelium.auraskills.bukkit.loot.type.CommandLoot;
import dev.aurelium.auraskills.bukkit.loot.type.EntityLoot;
import dev.aurelium.auraskills.bukkit.loot.type.ItemLoot;
import dev.aurelium.auraskills.bukkit.source.FishingLeveler;
import dev.aurelium.auraskills.bukkit.util.VersionUtils;
Expand Down Expand Up @@ -103,6 +104,8 @@ public void onFish(PlayerFishEvent event) {
giveFishingItemLoot(player, itemLoot, event, source, skill, cause, table);
} else if (selectedLoot instanceof CommandLoot commandLoot) {
giveCommandLoot(player, commandLoot, source, skill);
} else if (selectedLoot instanceof EntityLoot entityLoot) {
giveFishingEntityLoot(player, entityLoot, event, source, skill, cause);
}
break; // Stop iterating pools
}
Expand Down
Loading
Loading