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

[Rewrite] Custom Mobs #78

Merged
merged 11 commits into from
Aug 6, 2024
4 changes: 3 additions & 1 deletion src/main/java/me/gallowsdove/foxymachines/FoxyMachines.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import me.gallowsdove.foxymachines.abstracts.AbstractWand;
import me.gallowsdove.foxymachines.abstracts.CustomBoss;
import me.gallowsdove.foxymachines.commands.KillallCommand;
import me.gallowsdove.foxymachines.commands.ListallCommand;
import me.gallowsdove.foxymachines.commands.QuestCommand;
import me.gallowsdove.foxymachines.commands.SacrificialAltarCommand;
import me.gallowsdove.foxymachines.commands.SummonCommand;
Expand Down Expand Up @@ -36,6 +37,7 @@ public FoxyMachines() {
public void enable() {
instance = this;

Events.registerListener(new ChunkLoadListener());
Events.registerListener(new ChunkLoaderListener());
Events.registerListener(new BoostedRailListener());
Events.registerListener(new BerryBushListener());
Expand Down Expand Up @@ -67,7 +69,7 @@ public void enable() {
new Metrics(this, 10568);

getAddonCommand().addSub(new KillallCommand()).addSub((new QuestCommand())).
addSub(new SacrificialAltarCommand()).addSub(new SummonCommand());
addSub(new SacrificialAltarCommand()).addSub(new SummonCommand()).addSub(new ListallCommand());
}

@SneakyThrows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public abstract class CustomBoss extends CustomMob {

private final Set<DamageCause> resistances;

public CustomBoss(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health, @Nonnull DamageCause... resistances) {
protected CustomBoss(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health, @Nonnull DamageCause... resistances) {
super(id, name, type, health);
this.resistances = Set.of(resistances);
}
Expand Down Expand Up @@ -60,20 +60,28 @@ public void onSpawn(@Nonnull LivingEntity spawned) {

@Override
@OverridingMethodsMustInvokeSuper
public final void onHit(@Nonnull EntityDamageEvent e) {
this.onBossDamaged(e);
public void onMobTick(@Nonnull LivingEntity mob, int tick) {
if (tick == 100) {
onBossPattern(mob);
}
}

@Override
@OverridingMethodsMustInvokeSuper
public final void onHit(@Nonnull EntityDamageEvent event) {
this.onBossDamaged(event);

if (!e.isCancelled() && e.getEntity() instanceof LivingEntity entity) {
if (!event.isCancelled() && event.getEntity() instanceof LivingEntity entity) {
BossBar bossbar = getBossBarForEntity(entity);

if (entity.isInsideVehicle() && entity.getVehicle() instanceof LivingEntity vehicle) {
double finalHealth = entity.getHealth() + vehicle.getHealth() - e.getFinalDamage();
double finalHealth = entity.getHealth() + vehicle.getHealth() - event.getFinalDamage();
if (finalHealth > 0) {
bossbar.setProgress(Math.min(finalHealth / (entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue() +
vehicle.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue()), 1));
}
} else {
double finalHealth = entity.getHealth() - e.getFinalDamage();
double finalHealth = entity.getHealth() - event.getFinalDamage();
if (finalHealth > 0) {
bossbar.setProgress(Math.min(finalHealth / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue(), 1));
}
Expand All @@ -90,8 +98,10 @@ protected void onBossDamaged(@Nonnull EntityDamageEvent e) {

@Override
@OverridingMethodsMustInvokeSuper
public void onDeath(@Nonnull EntityDeathEvent e) {
BossBar bossbar = getBossBarForEntity(e.getEntity());
public void onDeath(@Nonnull EntityDeathEvent event) {
super.onDeath(event);

BossBar bossbar = getBossBarForEntity(event.getEntity());
bossbar.setVisible(false);
bossbar.removeAll();
}
Expand Down
119 changes: 79 additions & 40 deletions src/main/java/me/gallowsdove/foxymachines/abstracts/CustomMob.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.github.thebusybiscuit.slimefun4.libraries.dough.common.ChatColors;
import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
Expand All @@ -24,27 +25,35 @@

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

public abstract class CustomMob {

public static final Map<String, CustomMob> MOBS = new HashMap<>();
public static final Map<CustomMob, Set<UUID>> MOB_CACHE = new HashMap<>();

@Nullable
public static CustomMob getByID(@Nonnull String id) {
public static CustomMob getById(@Nonnull String id) {
return MOBS.get(id);
}

@Nullable
public static CustomMob getByEntity(@Nonnull Entity entity) {
String id = PersistentDataAPI.getString(entity, CustomMob.KEY);
return id == null ? null : getByID(id);
return id == null ? null : getById(id);
}

private static final NamespacedKey KEY = new NamespacedKey(FoxyMachines.getInstance(), "mob");

@Getter
@Nonnull
private final String id;
@Nonnull
Expand All @@ -54,7 +63,8 @@ public static CustomMob getByEntity(@Nonnull Entity entity) {
private final EntityType type;
private final int health;

public CustomMob(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health) {
@ParametersAreNonnullByDefault
protected CustomMob(String id, String name, EntityType type, int health) {
Validate.notNull(this.id = id);
Validate.notNull(this.name = ChatColors.color(name));
Validate.notNull(this.type = type);
Expand All @@ -78,6 +88,7 @@ public final LivingEntity spawn(@Nonnull Location loc) {
entity.setRemoveWhenFarAway(true);

onSpawn(entity);
cacheEntity(entity);

return entity;
}
Expand All @@ -88,98 +99,126 @@ protected void onSpawn(@Nonnull LivingEntity spawned) { }

public void onMobTick(@Nonnull LivingEntity mob, int tick) { }

protected void onHit(@Nonnull EntityDamageEvent e) { }
protected void onHit(@Nonnull EntityDamageEvent event) { }

protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { }
protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { }

protected void onInteract(@Nonnull PlayerInteractEntityEvent e) { }
protected void onInteract(@Nonnull PlayerInteractEntityEvent event) { }

protected void onTarget(@Nonnull EntityTargetEvent e) { }
protected void onTarget(@Nonnull EntityTargetEvent event) { }

protected void onDeath(@Nonnull EntityDeathEvent e) { }
@OverridingMethodsMustInvokeSuper
protected void onDeath(@Nonnull EntityDeathEvent event) {
uncacheEntity(event.getEntity());
}

protected void onCastSpell(EntitySpellCastEvent e) { }
protected void onCastSpell(@Nonnull EntitySpellCastEvent event) { }

protected void onDamage(EntityDamageEvent e) { }
protected void onDamage(@Nonnull EntityDamageEvent event) { }

protected Vector getSpawnOffset() {
return new Vector();
}

public void cacheEntity(@Nonnull Entity entity) {
cacheEntity(entity.getUniqueId());
}

public void cacheEntity(@Nonnull UUID uuid) {
Set<UUID> entities = MOB_CACHE.getOrDefault(this, new HashSet<>());
entities.add(uuid);
MOB_CACHE.put(this, entities);
}

public void uncacheEntity(@Nonnull Entity entity) {
uncacheEntity(entity.getUniqueId());
}

public void uncacheEntity(@Nonnull UUID uuid) {
Set<UUID> entities = MOB_CACHE.getOrDefault(this, new HashSet<>());
entities.remove(uuid);
MOB_CACHE.put(this, entities);
}

public static void debug() {
Bukkit.broadcastMessage("CACHE:");
for (Map.Entry<CustomMob, Set<UUID>> entry : CustomMob.MOB_CACHE.entrySet()) {
Bukkit.broadcastMessage(entry.getKey().getId() + " (" + entry.getValue().size() + ")\n" + entry.getValue().stream().map(UUID::toString).collect(Collectors.joining("\n")));
}
}

static {
Events.registerListener(new Listener() {

@EventHandler
public void onTarget(@Nonnull EntityTargetEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getEntity());
public void onTarget(@Nonnull EntityTargetEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getEntity());
if (customMob != null) {
customMob.onTarget(e);
customMob.onTarget(event);
}
}

@EventHandler
public void onInteract(@Nonnull PlayerInteractEntityEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getRightClicked());
public void onInteract(@Nonnull PlayerInteractEntityEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getRightClicked());
if (customMob != null) {
customMob.onInteract(e);
customMob.onInteract(event);
}
}

@EventHandler
public void onHit(@Nonnull EntityDamageByEntityEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getDamager());
public void onHit(@Nonnull EntityDamageByEntityEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getDamager());
if (customMob != null) {
customMob.onAttack(e);
customMob.onAttack(event);
}
}

@EventHandler
public void onDamaged(@Nonnull EntityDamageEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getEntity());
public void onDamaged(@Nonnull EntityDamageEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getEntity());
if (customMob != null) {
customMob.onHit(e);
customMob.onHit(event);
}
}

@EventHandler
public void onDeath(@Nonnull EntityDeathEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getEntity());
public void onDeath(@Nonnull EntityDeathEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getEntity());
if (customMob != null) {
customMob.onDeath(e);
customMob.onDeath(event);
}
}

@EventHandler
public void onSpellCast(@Nonnull EntitySpellCastEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getEntity());
public void onSpellCast(@Nonnull EntitySpellCastEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getEntity());
if (customMob != null) {
customMob.onCastSpell(e);
customMob.onCastSpell(event);
}
}

@EventHandler
public void onDamage(@Nonnull EntityDamageEvent e) {
CustomMob customMob = CustomMob.getByEntity(e.getEntity());
public void onDamage(@Nonnull EntityDamageEvent event) {
CustomMob customMob = CustomMob.getByEntity(event.getEntity());
if (customMob != null) {
customMob.onDamage(e);
customMob.onDamage(event);
}
}

@EventHandler(ignoreCancelled = true)
private void onNametagEvent(PlayerInteractEntityEvent e) {
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
private void onNametagEvent(PlayerInteractEntityEvent event) {
ItemStack item = event.getPlayer().getInventory().getItemInMainHand();

if (item.getType() == Material.NAME_TAG) {
if (CustomMob.getByEntity(e.getRightClicked()) != null) {
e.setCancelled(true);
}
if (item.getType() == Material.NAME_TAG && CustomMob.getByEntity(event.getRightClicked()) != null) {
event.setCancelled(true);
}
}

@EventHandler(ignoreCancelled = true)
private void onCombust(EntityCombustEvent e) {
if (CustomMob.getByEntity(e.getEntity()) != null) {
e.setCancelled(true);
private void onCombust(EntityCombustEvent event) {
if (CustomMob.getByEntity(event.getEntity()) != null) {
event.setCancelled(true);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,48 @@
import io.github.mooy1.infinitylib.commands.SubCommand;
import me.gallowsdove.foxymachines.abstracts.CustomBoss;
import me.gallowsdove.foxymachines.abstracts.CustomMob;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public class KillallCommand extends SubCommand {
public KillallCommand() {
super("killall", "Kills all Custom Mobs from FoxyMachines.", "foxymachines.admin");
super("killall", "Kills all Custom Mobs from FoxyMachines in your current World.", "foxymachines.admin");
}

@Override
protected void execute(@Nonnull CommandSender commandSender, @Nonnull String[] args) {
if (!(commandSender instanceof Player p)) {
protected void execute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (!(sender instanceof Player player)) {
return;
}

if (args.length != 0) {
commandSender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy killall");
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy killall");
return;
}

for (LivingEntity entity : p.getWorld().getLivingEntities()) {
CustomMob mob = CustomMob.getByEntity(entity);
if (mob != null) {
entity.remove();
int count = 0;
for (Set<UUID> uuids : CustomMob.MOB_CACHE.values()) {
for (UUID uuid : uuids) {
Entity entity = Bukkit.getEntity(uuid);
if (entity instanceof LivingEntity && entity.getWorld().equals(player.getWorld())) {
entity.remove();
count++;
}
}
}

CustomBoss.removeBossBars();

player.sendMessage("Killed %s Entities".formatted(count));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package me.gallowsdove.foxymachines.commands;

import io.github.mooy1.infinitylib.commands.SubCommand;
import me.gallowsdove.foxymachines.abstracts.CustomMob;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

import javax.annotation.Nonnull;
import java.util.List;

public class ListallCommand extends SubCommand {
public ListallCommand() {
super("listall", "Lists all Custom Mobs from FoxyMachines", "foxymachines.admin");
}

@Override
protected void execute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (args.length != 0) {
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy listall");
return;
}

CustomMob.debug();
}

@Override
protected void complete(@Nonnull CommandSender commandSender, @Nonnull String[] strings, @Nonnull List<String> list) { }
}
Loading
Loading