Skip to content

Commit

Permalink
First implementation of every default trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
rainbowdashlabs committed Aug 18, 2023
1 parent 32bad60 commit 7b0dd73
Show file tree
Hide file tree
Showing 27 changed files with 866 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public class Configuration extends JacksonConfig<ConfigFile> {
// TODO: Register default mobs on creation
public static final ConfigKey<MobRegistry> MOBS = ConfigKey.of("mobs", Path.of("mobs.yml"), MobRegistry.class, MobRegistry::new);
public static final ConfigKey<ItemRegistry> ITEMS = ConfigKey.of("mobs", Path.of("mobs.yml"), ItemRegistry.class, ItemRegistry::new);
public static final ConfigKey<ItemRegistry> ITEMS = ConfigKey.of("items", Path.of("items.yml"), ItemRegistry.class, ItemRegistry::new);
public static final ConfigKey<GlobalDrops> GLOBAL_DROPS = ConfigKey.of("Global Drops", Path.of("global_drops.yml"), GlobalDrops.class, GlobalDrops::defaultDrops);

public Configuration(@NotNull Plugin plugin) {
Expand Down
75 changes: 75 additions & 0 deletions core/src/main/java/de/eldoria/bloodnight/mobs/DamageHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package de.eldoria.bloodnight.mobs;

import de.eldoria.bloodnight.util.MobTags;
import org.bukkit.EntityEffect;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;

import java.util.Optional;
import java.util.UUID;

/**
* This class handles damage events for custom mobs with extensions.
* It listens for entity damage events and performs necessary actions based on the type of damage and the entity involved.
*/
public class DamageHandler implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onExtensionDamage(EntityDamageEvent event) {
if (MobTags.isExtension(event.getEntity())) handleExtensionDamage(event);
}

@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBaseDamage(EntityDamageEvent event) {
if (MobTags.isExtended(event.getEntity())) handleBaseDamage(event);
}

private void handleExtensionDamage(EntityDamageEvent event) {
Entity entity = event.getEntity();
Optional<UUID> baseId = MobTags.getBase(entity);
if (baseId.isEmpty()) return;
if (!(entity instanceof LivingEntity extension)) return;
// Forward damage from extension over to base mob
if (!(entity.getServer().getEntity(baseId.get()) instanceof LivingEntity base)) return;

if (event instanceof EntityDamageByEntityEvent byEntity) {
base.damage(event.getDamage(), byEntity.getDamager());
} else {
base.damage(event.getDamage());
}
event.setCancelled(true);
// Sync damage from base to extension
extension.setHealth(base.getHealth());
entity.playEffect(EntityEffect.HURT);
}

private void handleBaseDamage(EntityDamageEvent event) {
Entity entity = event.getEntity();
Optional<UUID> extensionId = MobTags.getExtension(entity);
if (!(entity instanceof LivingEntity base)) return;

if (extensionId.isEmpty()) return;
if (!(entity.getServer().getEntity(extensionId.get()) instanceof LivingEntity extension)) return;

// We assume that the damage won't change anymore
extension.setHealth(base.getHealth() - event.getFinalDamage());
extension.playEffect(EntityEffect.HURT);
}

@EventHandler(priority = EventPriority.HIGHEST)
public void onEntityDeath(EntityDeathEvent event) {
var entity = event.getEntity();
if (!MobTags.isCustomMob(entity)) return;
Optional<UUID> extensionId = MobTags.getExtension(entity);
if (extensionId.isEmpty()) return;
// Kill extension when the base dies.
if (entity.getServer().getEntity(extensionId.get()) instanceof LivingEntity extension) {
extension.damage(extension.getHealth());
}
}
}
2 changes: 2 additions & 0 deletions core/src/main/java/de/eldoria/bloodnight/mobs/MobSpawner.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ void handleSpawnedMob(Entity entity) {
List<CustomMob> matching = configuration.mobs().getMatching(active, entity.getType());
if(matching.isEmpty()) return;
if (worldSettings.mobSettings().spawning().spawnPercentage() < ThreadLocalRandom.current().nextInt(100)) return;
// TODO: This doesnt factor in the spawn percentage of matching active mobs itself.
CustomMob customMob = matching.get(ThreadLocalRandom.current().nextInt(matching.size()));
// TODO Building the mob with changed attributes, equipment, extensions etc is missing.
coordinator.register(entity, customMob);
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package de.eldoria.bloodnight.mobs.dispatcher.impl;

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.mobs.dispatcher.TriggerDispatcher;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.impl.events.damage.OnDamageByEntityNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.damage.OnDamageByPlayerNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.damage.OnDamageNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.damage.OnDeathNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.damage.OnHitNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.kill.OnEntityKillNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.kill.OnKillNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.kill.OnPlayerKillNode;
import de.eldoria.bloodnight.util.MobTags;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;

/**
* A {@link TriggerDispatcher} which only handles kills of entities
*/
public class DamageDispatcher extends TriggerDispatcher {
public DamageDispatcher(MobCoordinator coordinator) {
super(coordinator);
}

/**
* This handler is purely for observing dealt damage to entities to notice who killed it.
*
* @param event damage event
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
public void onKill(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity living)) return;
// Check whether entity will be killed.
if (event.getFinalDamage() >= living.getHealth()) {
trigger(event.getDamager(), TriggerData.forNode(OnKillNode.class, event));
if (event.getEntity() instanceof Player) {
trigger(event.getDamager(), TriggerData.forNode(OnPlayerKillNode.class, event));
} else {
trigger(event.getDamager(), TriggerData.forNode(OnEntityKillNode.class, event));
}
}
}

@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
public void onDamage(EntityDamageEvent event) {
// We do not care about non CustomMob damage here
if (!MobTags.isCustomMob(event.getEntity())) return;
// Damage to extensions is handled somewhere else
if (MobTags.isExtension(event.getEntity())) return;

if (event instanceof EntityDamageByEntityEvent byEntity) {
if (byEntity.getDamager().getType() == EntityType.PLAYER) {
trigger(event.getEntity(), TriggerData.forNode(OnDamageByPlayerNode.class, byEntity));
} else {
trigger(event.getEntity(), TriggerData.forNode(OnDamageByEntityNode.class, byEntity));
}
} else {
trigger(event.getEntity(), TriggerData.forNode(OnDamageNode.class, event));
}
}

@EventHandler
public void onHit(EntityDamageByEntityEvent event) {
trigger(event.getDamager(), TriggerData.forNode(OnHitNode.class, event));
}

@EventHandler(priority = EventPriority.HIGH)
public void onEntityDeath(EntityDeathEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnDeathNode.class, event));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package de.eldoria.bloodnight.mobs.dispatcher.impl;

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.mobs.dispatcher.TriggerDispatcher;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.impl.events.explosion.OnExplosionNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.explosion.OnExplosionPrimeNode;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;

public class ExplosionDispatcher extends TriggerDispatcher {
public ExplosionDispatcher(MobCoordinator coordinator) {
super(coordinator);
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onExplosionPrime(ExplosionPrimeEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnExplosionPrimeNode.class, event));
}

@EventHandler
public void onExplosionEvent(EntityExplodeEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnExplosionNode.class, event));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.eldoria.bloodnight.mobs.dispatcher.impl;

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.mobs.dispatcher.TriggerDispatcher;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.impl.events.projectile.OnProjectileHit;
import de.eldoria.bloodnight.nodes.trigger.impl.events.projectile.OnProjectileShoot;
import de.eldoria.eldoutilities.entities.projectiles.ProjectileSender;
import de.eldoria.eldoutilities.entities.projectiles.ProjectileUtil;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;

public class ProjectileDispatcher extends TriggerDispatcher {
public ProjectileDispatcher(MobCoordinator coordinator) {
super(coordinator);
}

@EventHandler
public void onProjectileShoot(ProjectileLaunchEvent event) {
ProjectileSender projectileSource = ProjectileUtil.getProjectileSource(event.getEntity());
if (projectileSource.isEntity()) {
trigger(projectileSource.getEntity(), TriggerData.forNode(OnProjectileShoot.class, event));
}
}

@EventHandler
public void onProjectileHit(ProjectileHitEvent event) {
ProjectileSender projectileSource = ProjectileUtil.getProjectileSource(event.getEntity());
if (projectileSource.isEntity()) {
trigger(event.getEntity(), TriggerData.forNode(OnProjectileHit.class, event));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package de.eldoria.bloodnight.mobs.dispatcher.impl;

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.mobs.dispatcher.TriggerDispatcher;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.TriggerNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnTargetChangeNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnTeleportNode;
import de.eldoria.bloodnight.util.MobTags;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
import org.bukkit.event.entity.EntityTeleportEvent;

/**
* This class listens to events, wraps their data into a {@link TriggerData} and trigger corresponding {@link TriggerNode}.
* This class only covers predefined trigger nodes.
* Custom nodes will need to create their own trigger dispatcher.
*/
public class StandardTriggerDispatcher extends TriggerDispatcher {

public StandardTriggerDispatcher(MobCoordinator coordinator) {
super(coordinator);
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onTeleport(EntityTeleportEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnTeleportNode.class, event));
}

@EventHandler
public void onTargetEvent(EntityTargetLivingEntityEvent event) {
if (event.getTarget() != null && MobTags.isCustomMob(event.getTarget())) {
event.setCancelled(true);
return;
}

if (!MobTags.isCustomMob(event.getEntity())) {
return;
}

// Block that custom mobs target something else than players.
// Otherwise, they will probably kill each other.
if (event.getTarget() != null && event.getTarget().getType() != EntityType.PLAYER) {
event.setCancelled(true);
return;
}
trigger(event.getEntity(), TriggerData.forNode(OnTargetChangeNode.class, event));
}
}
Loading

0 comments on commit 7b0dd73

Please sign in to comment.