mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-10 17:31:26 +01:00
Implement new push / knockback events
This commit is contained in:
parent
ff736ebd4b
commit
9704f1493c
@ -1,5 +1,6 @@
|
||||
package net.citizensnpcs;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -19,6 +20,7 @@ import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.EntityBlockFormEvent;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
@ -58,7 +60,9 @@ import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicates;
|
||||
@ -84,7 +88,9 @@ import net.citizensnpcs.api.event.NPCDamageEntityEvent;
|
||||
import net.citizensnpcs.api.event.NPCDamageEvent;
|
||||
import net.citizensnpcs.api.event.NPCDeathEvent;
|
||||
import net.citizensnpcs.api.event.NPCDespawnEvent;
|
||||
import net.citizensnpcs.api.event.NPCKnockbackEvent;
|
||||
import net.citizensnpcs.api.event.NPCLeftClickEvent;
|
||||
import net.citizensnpcs.api.event.NPCPushEvent;
|
||||
import net.citizensnpcs.api.event.NPCRemoveEvent;
|
||||
import net.citizensnpcs.api.event.NPCRightClickEvent;
|
||||
import net.citizensnpcs.api.event.NPCSeenByPlayerEvent;
|
||||
@ -98,6 +104,7 @@ import net.citizensnpcs.api.trait.trait.Owner;
|
||||
import net.citizensnpcs.api.trait.trait.PlayerFilter;
|
||||
import net.citizensnpcs.api.util.Messaging;
|
||||
import net.citizensnpcs.editor.Editor;
|
||||
import net.citizensnpcs.npc.ai.NPCHolder;
|
||||
import net.citizensnpcs.npc.skin.SkinUpdateTracker;
|
||||
import net.citizensnpcs.trait.ClickRedirectTrait;
|
||||
import net.citizensnpcs.trait.CommandTrait;
|
||||
@ -150,6 +157,26 @@ public class EventListen implements Listener {
|
||||
}, CitizensAPI.getPlugin());
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
|
||||
Class<?> kbc = null;
|
||||
try {
|
||||
kbc = Class.forName("com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent");
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
if (kbc != null) {
|
||||
registerKnockbackEvent(kbc);
|
||||
}
|
||||
|
||||
Class<?> pbeac = null;
|
||||
try {
|
||||
pbeac = Class.forName("io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent");
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
if (pbeac != null) {
|
||||
registerPushEvent(pbeac);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCreationEvent(CommandSenderCreateNPCEvent event) {
|
||||
@ -665,6 +692,68 @@ public class EventListen implements Listener {
|
||||
CitizensAPI.getLocationLookup().onWorldUnload(event);
|
||||
}
|
||||
|
||||
private void registerKnockbackEvent(Class<?> kbc) {
|
||||
try {
|
||||
HandlerList handlers = (HandlerList) kbc.getMethod("getHandlerList").invoke(null);
|
||||
Method getEntity = kbc.getMethod("getEntity");
|
||||
Method getHitBy = kbc.getMethod("getHitBy");
|
||||
Method getKnockbackStrength = kbc.getMethod("getKnockbackStrength");
|
||||
Method getAcceleration = kbc.getMethod("getAcceleration");
|
||||
handlers.register(new RegisteredListener(new Listener() {
|
||||
}, (listener, event) -> {
|
||||
if (NPCKnockbackEvent.getHandlerList().getRegisteredListeners().length == 0)
|
||||
return;
|
||||
try {
|
||||
Entity entity = (Entity) getEntity.invoke(event);
|
||||
if (!(entity instanceof NPCHolder))
|
||||
return;
|
||||
NPC npc = ((NPCHolder) entity).getNPC();
|
||||
Entity hitBy = (Entity) getHitBy.invoke(event);
|
||||
float strength = (float) getKnockbackStrength.invoke(event);
|
||||
Vector vector = (Vector) getAcceleration.invoke(event);
|
||||
NPCKnockbackEvent kb = new NPCKnockbackEvent(npc, strength, vector, hitBy);
|
||||
Bukkit.getPluginManager().callEvent(kb);
|
||||
((Cancellable) event).setCancelled(kb.isCancelled());
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}, EventPriority.NORMAL, CitizensAPI.getPlugin(), true));
|
||||
} catch (Throwable ex) {
|
||||
Messaging.severe("Error registering knockback event forwarder");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPushEvent(Class<?> clazz) {
|
||||
try {
|
||||
HandlerList handlers = (HandlerList) clazz.getMethod("getHandlerList").invoke(null);
|
||||
Method getEntity = clazz.getMethod("getEntity");
|
||||
Method getPushedBy = clazz.getMethod("getPushedBy");
|
||||
Method getAcceleration = clazz.getMethod("getAcceleration");
|
||||
handlers.register(new RegisteredListener(new Listener() {
|
||||
}, (listener, event) -> {
|
||||
if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0)
|
||||
return;
|
||||
try {
|
||||
Entity entity = (Entity) getEntity.invoke(event);
|
||||
if (!(entity instanceof NPCHolder))
|
||||
return;
|
||||
NPC npc = ((NPCHolder) entity).getNPC();
|
||||
Entity pushedBy = (Entity) getPushedBy.invoke(event);
|
||||
Vector vector = (Vector) getAcceleration.invoke(event);
|
||||
NPCPushEvent push = new NPCPushEvent(npc, vector, pushedBy);
|
||||
Bukkit.getPluginManager().callEvent(push);
|
||||
((Cancellable) event).setCancelled(push.isCancelled());
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}, EventPriority.NORMAL, CitizensAPI.getPlugin(), true));
|
||||
} catch (Throwable ex) {
|
||||
Messaging.severe("Error registering push event forwarder");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void respawnAllFromCoord(ChunkCoord coord, Event event) {
|
||||
List<NPC> ids = Lists.newArrayList(toRespawn.get(coord));
|
||||
if (ids.size() > 0) {
|
||||
|
@ -680,7 +680,7 @@ public class NPCCommands {
|
||||
if (!sender.hasPermission("citizens.npc.create.*") && !sender.hasPermission("citizens.npc.createall")
|
||||
&& !sender.hasPermission("citizens.npc.create." + type.name().toLowerCase().replace("_", "")))
|
||||
throw new NoPermissionsException();
|
||||
|
||||
|
||||
if ((at != null || registryName != null || traits != null || templateName != null)
|
||||
&& !sender.hasPermission("citizens.npc.admin"))
|
||||
throw new NoPermissionsException();
|
||||
@ -764,8 +764,6 @@ public class NPCCommands {
|
||||
}
|
||||
|
||||
if (at != null) {
|
||||
if (!sender.hasPermission("citizens.npc.create-at-location"))
|
||||
throw new NoPermissionsException();
|
||||
spawnLoc = at;
|
||||
spawnLoc.getChunk().load();
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ import java.util.stream.Collectors;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.entity.Enderman;
|
||||
@ -107,7 +109,24 @@ public class NMS {
|
||||
|
||||
public static void callKnockbackEvent(NPC npc, float strength, double dx, double dz,
|
||||
Consumer<NPCKnockbackEvent> cb) {
|
||||
NPCKnockbackEvent event = new NPCKnockbackEvent(npc, strength, dx, dz);
|
||||
if (SUPPORT_KNOCKBACK_RESISTANCE && npc.getEntity() instanceof LivingEntity) {
|
||||
try {
|
||||
AttributeInstance attribute = ((LivingEntity) npc.getEntity())
|
||||
.getAttribute(Attribute.GENERIC_KNOCKBACK_RESISTANCE);
|
||||
if (attribute != null) {
|
||||
strength *= 1 - attribute.getValue();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
SUPPORT_KNOCKBACK_RESISTANCE = false;
|
||||
}
|
||||
}
|
||||
Vector vector = npc.getEntity().getVelocity();
|
||||
Vector impulse = new Vector(dx, 0, dz).normalize().multiply(strength);
|
||||
Vector delta = new Vector(vector.getX() / 2 - impulse.getX() - vector.getX(),
|
||||
-vector.getY()
|
||||
+ (npc.getEntity().isOnGround() ? Math.min(0.4, vector.getY() / 2 + strength) : vector.getY()),
|
||||
vector.getZ() / 2 - impulse.getZ() - vector.getZ());
|
||||
NPCKnockbackEvent event = new NPCKnockbackEvent(npc, strength, delta, null);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (!event.isCancelled()) {
|
||||
cb.accept(event);
|
||||
@ -853,6 +872,7 @@ public class NMS {
|
||||
private static Method GET_MODULE;
|
||||
private static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||
private static Field MODIFIERS_FIELD;
|
||||
private static boolean SUPPORT_KNOCKBACK_RESISTANCE = true;
|
||||
private static Object UNSAFE;
|
||||
private static MethodHandle UNSAFE_FIELD_OFFSET;
|
||||
private static MethodHandle UNSAFE_PUT_BOOLEAN;
|
||||
|
@ -91,7 +91,7 @@ public class Util {
|
||||
// when another entity collides, this method is called to push the NPC so we prevent it from
|
||||
// doing anything if the event is cancelled.
|
||||
Vector vector = new Vector(x, y, z);
|
||||
NPCPushEvent event = new NPCPushEvent(npc, vector);
|
||||
NPCPushEvent event = new NPCPushEvent(npc, vector, null);
|
||||
event.setCancelled(!allowed);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
return !event.isCancelled() ? event.getCollisionVector() : null;
|
||||
|
@ -18,7 +18,6 @@ import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.event.NPCKnockbackEvent;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPC.NPCUpdate;
|
||||
import net.citizensnpcs.api.trait.trait.Inventory;
|
||||
@ -273,12 +272,8 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
|
||||
|
||||
@Override
|
||||
public void knockback(double strength, double dx, double dz) {
|
||||
NPCKnockbackEvent event = new NPCKnockbackEvent(npc, strength, dx, dz);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
Vector kb = event.getKnockbackVector();
|
||||
if (!event.isCancelled()) {
|
||||
super.knockback(event.getStrength(), kb.getX(), kb.getZ());
|
||||
}
|
||||
NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(),
|
||||
evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ()));
|
||||
}
|
||||
|
||||
private void moveOnCurrentHeading() {
|
||||
|
@ -18,7 +18,6 @@ import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.event.NPCKnockbackEvent;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPC.NPCUpdate;
|
||||
import net.citizensnpcs.api.trait.trait.Inventory;
|
||||
@ -268,12 +267,8 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
|
||||
|
||||
@Override
|
||||
public void knockback(double strength, double dx, double dz) {
|
||||
NPCKnockbackEvent event = new NPCKnockbackEvent(npc, strength, dx, dz);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
Vector kb = event.getKnockbackVector();
|
||||
if (!event.isCancelled()) {
|
||||
super.knockback(event.getStrength(), kb.getX(), kb.getZ());
|
||||
}
|
||||
NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(),
|
||||
evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ()));
|
||||
}
|
||||
|
||||
private void moveOnCurrentHeading() {
|
||||
|
Loading…
Reference in New Issue
Block a user