Skip to content

Commit

Permalink
Continue implementing node dispatching
Browse files Browse the repository at this point in the history
  • Loading branch information
rainbowdashlabs committed Aug 13, 2023
1 parent 99f0f0b commit 8d018fd
Show file tree
Hide file tree
Showing 19 changed files with 293 additions and 15 deletions.
7 changes: 7 additions & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
`java-library`
}

dependencies{
api(project(":nodes"))
}
1 change: 1 addition & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ plugins{

dependencies{
api(project(":nodes"))
api(project(":api"))
api(libs.bundles.eldoria.utilities)
}
7 changes: 7 additions & 0 deletions core/src/main/java/de/eldoria/bloodnight/mob/CustomMob.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
import de.eldoria.bloodnight.mob.meta.MobDrops;
import de.eldoria.bloodnight.mob.meta.Equipment;
import de.eldoria.bloodnight.mob.meta.Extension;
import de.eldoria.bloodnight.nodes.container.ContainerMeta;
import de.eldoria.bloodnight.nodes.container.NodeContainer;
import org.bukkit.entity.Entity;

public record CustomMob(String id, Equipment equipment, Attributes attributes, NodeContainer nodes, MobDrops mobDrops,
Extension extension) {
public CustomMob copy(Entity entity, Entity extension) {
NodeContainer copy = nodes.copy();
copy.inject(new ContainerMeta(entity, extension));
return new CustomMob(id, equipment, attributes, copy, mobDrops, this.extension);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.eldoria.bloodnight.mob.meta;

import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;

public record Attributes(String displayName,
Expand All @@ -9,6 +10,8 @@ public record Attributes(String displayName,
ValueModifier damageModifier, double damage) {
public boolean isAssignable(EntityType type) {
if(exactType) return type == entityType;
return entityType.getEntityClass().isAssignableFrom(type.getEntityClass());
Class<? extends Entity> thisClass = entityType.getEntityClass();
Class<? extends Entity> thatClass = type.getEntityClass();
return thisClass != null && thatClass != null && thisClass.isAssignableFrom(thatClass);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
import java.util.HashMap;
import java.util.Map;

/**
* Class which holds all custom mobs.
* Responsible for dispatching event triggers to the correct custom mob.
*/
public class MobCoordinator {
/**
* Maps which references the {@link Entity#getEntityId()} and holds the custom mob assigned to id.
*/
private final Map<Integer, CustomMob> mobs = new HashMap<>();

/**
Expand All @@ -22,7 +29,16 @@ public void trigger(Entity entity, TriggerData<?> trigger) {
customMob.nodes().dispatch(trigger);
}

/**
* Registers the custom mob on the provided entity.
* Will create a copy of the custom mob using {@link CustomMob#copy(Entity, Entity)}
* If this mob is already registered, it will be changed to the new custom mob.
*
* @param entity the entity to assign the mob to
* @param customMob the custom mob assigned to the entity.
*/
public void register(Entity entity, CustomMob customMob) {

// TODO spawn and register extension
mobs.put(entity.getEntityId(), customMob.copy(entity, null));
}
}
36 changes: 35 additions & 1 deletion core/src/main/java/de/eldoria/bloodnight/mobs/MobRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.eldoria.bloodnight.mob.CustomMob;
import de.eldoria.bloodnight.mob.meta.Attributes;
import de.eldoria.bloodnight.mobs.exceptions.MobIdAlreadyTakenException;
import de.eldoria.bloodnight.util.Checks;
import org.bukkit.entity.EntityType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -24,11 +26,43 @@ public MobRegistry() {
this.mobs = new HashMap<>();
}

/**
* Registers a new {@link CustomMob} at the registry.
*
* @param mob the mob to be registered.
* @throws MobIdAlreadyTakenException when the id is already taken.
*/
public void add(CustomMob mob) {
check(mob);
if (mobs.containsKey(mob.id())) throw new MobIdAlreadyTakenException(mob, get(mob.id()));
mobs.put(mob.id(), mob);
}


/**
* Returns the {@link CustomMob} associated with the given id.
*
* @param id the id of the mob to be retrieved.
* @return the {@link CustomMob} associated with the given id, or null if no mob is found.
*/
public CustomMob get(String id) {
return mobs.get(id);
}

/**
* Gets all matching {@link CustomMob}s, depending on the result of calling {@link Attributes#isAssignable(EntityType)}.
*
* @param active a set containing the ids of active mobs that should be checked
* @param type the type of the entity
* @return an immutable list containing all mobs that are matching. May be empty.
*/
public List<CustomMob> getMatching(Set<String> active, EntityType type) {
return active.stream().map(mobs::get).filter(mob -> mob.attributes().isAssignable(type)).toList();
}

private void check(CustomMob mob) {
Checks.notNull(mob, "Mob can not be null");
Checks.notNull(mob.id(), "Mob id can not be null");
Checks.lowerCase(mob.id(), "Mob id must be lower case.");
}
}

This file was deleted.

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

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.TriggerNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnDeathNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnExplosionPrimeNode;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
* 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 DefaultTriggerDispatcher extends TriggerDispatcher {

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

@EventHandler
public void onDeath(EntityDeathEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnDeathNode.class, event));
}

@EventHandler
public void onExplosionPrime(ExplosionPrimeEvent event) {
trigger(event.getEntity(), TriggerData.forNode(OnExplosionPrimeNode.class, event));
}

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

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnDeathNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnEntityKillNode;
import de.eldoria.bloodnight.nodes.trigger.impl.events.OnPlayerKillNode;
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.EntityDeathEvent;

public class KillDispatcher extends TriggerDispatcher {
public KillDispatcher(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 onEntityDamageDelegate(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity living)) return;
// Check if entity will be killed.
if (event.getFinalDamage() >= living.getHealth()) {
if (event.getEntity() instanceof Player) {
trigger(event.getDamager(), TriggerData.forNode(OnPlayerKillNode.class, event));
} else {
trigger(event.getDamager(), TriggerData.forNode(OnEntityKillNode.class, event));
}
}
}

@EventHandler
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,22 @@
package de.eldoria.bloodnight.mobs.dispatcher;

import de.eldoria.bloodnight.mobs.MobCoordinator;
import de.eldoria.bloodnight.nodes.dispatching.TriggerData;
import org.bukkit.entity.Entity;
import org.bukkit.event.Listener;

/**
* Basic Trigger dispatcher.
* Holds a {@link MobCoordinator} and provides delegates to the core functionality.
*/
public class TriggerDispatcher implements Listener {
private final MobCoordinator coordinator;

public TriggerDispatcher(MobCoordinator coordinator) {
this.coordinator = coordinator;
}

public void trigger(Entity entity, TriggerData<?> trigger) {
coordinator.trigger(entity, trigger);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.eldoria.bloodnight.mobs.exceptions;

import de.eldoria.bloodnight.mob.CustomMob;

/**
* Exception thrown when trying to register a CustomMob with an id that is already taken by another CustomMob.
*/
public class MobIdAlreadyTakenException extends RuntimeException {
private final CustomMob newMob;
private final CustomMob currentMob;

public MobIdAlreadyTakenException(CustomMob newMob, CustomMob currentMob) {
super("Could not register %s. The id %s is already taken by %s".formatted(newMob.getClass().getName(), newMob.id(), currentMob.getClass().getName()));
this.newMob = newMob;
this.currentMob = currentMob;
}

public CustomMob newMob() {
return newMob;
}

public CustomMob currentMob() {
return currentMob;
}
}
19 changes: 19 additions & 0 deletions core/src/main/java/de/eldoria/bloodnight/util/MobTags.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
package de.eldoria.bloodnight.util;

import de.eldoria.bloodnight.mob.CustomMob;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.persistence.PersistentDataType;

public class MobTags {
/**
* Marks that an {@link Entity} is a {@link CustomMob}.
* This tag is solely for existence checks and should use a {@link PersistentDataType#BYTE}.
* The value of the byte doesn't matter.
* If this tag is set on the mob with the BYTE type, it is always considered a custom mob.
*/
public static final NamespacedKey CUSTOM_MOB = new NamespacedKey("bloodnight", "custom_mob");
/**
* Marks that a mob is an extension of a custom mob.
* This tag should use a {@link PersistentDataType#INTEGER} containing the {@link Entity#getEntityId()} of the entity that the mob has, that is extended.
*/
public static final NamespacedKey EXTENDS = new NamespacedKey("bloodnight", "extends");
/**
* Marks that a mob is extended and has another mob attached to it.
* This tag should use a {@link PersistentDataType#INTEGER} containing the {@link Entity#getEntityId()} of the entity that extends this mob.
*/
public static final NamespacedKey EXTENDED = new NamespacedKey("bloodnight", "extended");
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@Input(name = Fields.VALUE, type = DataType.BOOLEAN)
@Execution(Fields.TRUE)
@Execution(Fields.FALSE)
@Meta(name = "Branch", description = "calling other node depending on the evaluated boolean value.")
@Meta(name = "Branch", description = "Calling other nodes depending on the evaluated boolean value.")
public class BranchNode extends ControlFlowNode<BranchNode> {

public BranchNode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,24 @@

import de.eldoria.bloodnight.nodes.trigger.TriggerNode;

/**
* This class holds the trigger data for a {@link TriggerNode}.
*
* @param triggerNodeClass the class of the node to be triggered
* @param data the data required by the trigger node
* @param <V> the type of the data required by the trigger node
*/
public record TriggerData<V>(Class<? extends TriggerNode<?, V>> triggerNodeClass, V data) {

/**
* Creates a new TriggerData instance for the specified TriggerNode class using the provided data.
*
* @param triggerNodeClass The class of the TriggerNode.
* @param data The data to be associated with the TriggerNode.
* @param <V> The type of the data.
* @return A new TriggerData instance.
*/
public static <V> TriggerData<V> forNode(Class<? extends TriggerNode<?, V>> triggerNodeClass, V data) {
return new TriggerData<>(triggerNodeClass, data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@

import java.util.Map;

@Output(name = OnKillNode.Outputs.KILLED_ENTITY, type = DataType.ENTITY)
@Output(name = OnKillNode.Outputs.CANCELABLE_EVENT, type = DataType.CANCELABLE_EVENT)
@Output(name = OnEntityKillNode.Outputs.KILLED_ENTITY, type = DataType.ENTITY)
@Output(name = OnEntityKillNode.Outputs.CANCELABLE_EVENT, type = DataType.CANCELABLE_EVENT)
@Meta(name = "On entity kill", description = "A trigger, that's called when an entity got killed by this mob.", category = Categories.EVENT)
public class OnKillNode extends CancelableEventTriggerNode<OnKillNode, EntityDamageByEntityEvent> {
public class OnEntityKillNode extends CancelableEventTriggerNode<OnEntityKillNode, EntityDamageByEntityEvent> {

@JsonCreator
public OnKillNode(@JsonProperty("input") Map<String, Edge> input, @JsonProperty("meta") EditorMeta meta) {
public OnEntityKillNode(@JsonProperty("input") Map<String, Edge> input, @JsonProperty("meta") EditorMeta meta) {
super(input, meta);
}

Expand Down
Loading

0 comments on commit 8d018fd

Please sign in to comment.