Call events using EventDispatcher

This commit is contained in:
TheMode 2021-06-04 03:48:51 +02:00
parent 5d3bae3d7f
commit 8b255651ab
39 changed files with 194 additions and 179 deletions

View File

@ -8,6 +8,8 @@ import net.minestom.server.data.DataType;
import net.minestom.server.data.SerializableData;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.Player;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventNode;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.exception.ExceptionManager;
import net.minestom.server.extensions.Extension;
@ -124,6 +126,7 @@ public final class MinecraftServer {
private static ExtensionManager extensionManager;
private static final GlobalEventHandler GLOBAL_EVENT_HANDLER = new GlobalEventHandler();
private static final EventNode<Event> GLOBAL_EVENT_NODE = EventNode.all();
private static UpdateManager updateManager;
private static MinecraftServer minecraftServer;
@ -303,6 +306,10 @@ public final class MinecraftServer {
return GLOBAL_EVENT_HANDLER;
}
public static @NotNull EventNode<Event> getGlobalEventNode() {
return GLOBAL_EVENT_NODE;
}
/**
* Gets the manager handling all incoming packets
*

View File

@ -11,6 +11,7 @@ import net.minestom.server.command.builder.parser.ArgumentQueryResult;
import net.minestom.server.command.builder.parser.CommandParser;
import net.minestom.server.command.builder.parser.CommandQueryResult;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerCommandEvent;
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
import net.minestom.server.utils.ArrayUtils;
@ -104,7 +105,7 @@ public final class CommandManager {
Player player = (Player) sender;
PlayerCommandEvent playerCommandEvent = new PlayerCommandEvent(player, command);
player.callEvent(PlayerCommandEvent.class, playerCommandEvent);
EventDispatcher.call(playerCommandEvent);
if (playerCommandEvent.isCancelled())
return CommandResult.of(CommandResult.Type.CANCELLED, command);

View File

@ -18,6 +18,7 @@ import net.minestom.server.data.DataContainer;
import net.minestom.server.entity.metadata.EntityMeta;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.*;
import net.minestom.server.event.handler.EventHandler;
import net.minestom.server.instance.Chunk;
@ -645,7 +646,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
update(time);
ticks++;
callEvent(EntityTickEvent.class, tickEvent); // reuse tickEvent to avoid recreating it each tick
EventDispatcher.call(tickEvent); // reuse tickEvent to avoid recreating it each tick
// remove expired effects
if (!effects.isEmpty()) {
@ -655,10 +656,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
if (time >= timedPotion.getStartingTime() + potionTime) {
// Send the packet that the potion should no longer be applied
timedPotion.getPotion().sendRemovePacket(this);
callEvent(EntityPotionRemoveEvent.class, new EntityPotionRemoveEvent(
this,
timedPotion.getPotion()
));
EventDispatcher.call(new EntityPotionRemoveEvent(this, timedPotion.getPotion()));
return true;
}
return false;
@ -916,8 +914,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
refreshCurrentChunk(instance.getChunkAt(position.getX(), position.getZ()));
instance.UNSAFE_addEntity(this);
spawn();
EntitySpawnEvent entitySpawnEvent = new EntitySpawnEvent(this, instance);
callEvent(EntitySpawnEvent.class, entitySpawnEvent);
EventDispatcher.call(new EntitySpawnEvent(this, instance));
}
/**
@ -950,7 +947,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
*/
public void setVelocity(@NotNull Vector velocity) {
EntityVelocityEvent entityVelocityEvent = new EntityVelocityEvent(this, velocity);
callCancellableEvent(EntityVelocityEvent.class, entityVelocityEvent, () -> {
EventDispatcher.callCancellable(entityVelocityEvent, () -> {
this.velocity.copy(entityVelocityEvent.getVelocity());
sendPacketToViewersAndSelf(getVelocityPacket());
});
@ -1464,7 +1461,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
removeEffect(potion.getEffect());
this.effects.add(new TimedPotion(potion, System.currentTimeMillis()));
potion.sendAddPacket(this);
callEvent(EntityPotionAddEvent.class, new EntityPotionAddEvent(this, potion));
EventDispatcher.call(new EntityPotionAddEvent(this, potion));
}
/**
@ -1476,10 +1473,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
this.effects.removeIf(timedPotion -> {
if (timedPotion.getPotion().getEffect() == effect) {
timedPotion.getPotion().sendRemovePacket(this);
callEvent(EntityPotionRemoveEvent.class, new EntityPotionRemoveEvent(
this,
timedPotion.getPotion()
));
EventDispatcher.call(new EntityPotionRemoveEvent(this, timedPotion.getPotion()));
return true;
}
return false;
@ -1492,10 +1486,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
public void clearEffects() {
for (TimedPotion timedPotion : effects) {
timedPotion.getPotion().sendRemovePacket(this);
callEvent(EntityPotionRemoveEvent.class, new EntityPotionRemoveEvent(
this,
timedPotion.getPotion()
));
EventDispatcher.call(new EntityPotionRemoveEvent(this, timedPotion.getPotion()));
}
this.effects.clear();
}

View File

@ -6,6 +6,7 @@ import net.minestom.server.entity.ai.EntityAI;
import net.minestom.server.entity.ai.EntityAIGroup;
import net.minestom.server.entity.pathfinding.NavigableEntity;
import net.minestom.server.entity.pathfinding.Navigator;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.Position;
@ -146,7 +147,7 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
if (swingHand)
swingMainHand();
EntityAttackEvent attackEvent = new EntityAttackEvent(this, target);
callEvent(EntityAttackEvent.class, attackEvent);
EventDispatcher.call(attackEvent);
}
/**

View File

@ -1,5 +1,6 @@
package net.minestom.server.entity;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityItemMergeEvent;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
@ -112,7 +113,7 @@ public class ItemEntity extends ObjectEntity {
final ItemStack result = stackingRule.apply(itemStack, totalAmount);
EntityItemMergeEvent entityItemMergeEvent = new EntityItemMergeEvent(this, itemEntity, result);
callCancellableEvent(EntityItemMergeEvent.class, entityItemMergeEvent, () -> {
EventDispatcher.callCancellable(entityItemMergeEvent, () -> {
setItemStack(entityItemMergeEvent.getResult());
itemEntity.remove();
});

View File

@ -7,6 +7,7 @@ import net.minestom.server.attribute.Attributes;
import net.minestom.server.collision.BoundingBox;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.metadata.LivingEntityMeta;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityDamageEvent;
import net.minestom.server.event.entity.EntityDeathEvent;
import net.minestom.server.event.entity.EntityFireEvent;
@ -17,7 +18,10 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.inventory.EquipmentHandler;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.packet.server.play.CollectItemPacket;
import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
import net.minestom.server.network.packet.server.play.EntityPropertiesPacket;
import net.minestom.server.network.packet.server.play.SoundEffectPacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.SoundEvent;
@ -193,7 +197,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
private ItemStack getEquipmentItem(@NotNull ItemStack itemStack, @NotNull EquipmentSlot slot) {
EntityEquipEvent entityEquipEvent = new EntityEquipEvent(this, itemStack, slot);
callEvent(EntityEquipEvent.class, entityEquipEvent);
EventDispatcher.call(entityEquipEvent);
return entityEquipEvent.getEquippedItem();
}
@ -232,7 +236,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
if (itemEntity.shouldRemove() || itemEntity.isRemoveScheduled())
continue;
PickupItemEvent pickupItemEvent = new PickupItemEvent(this, itemEntity);
callCancellableEvent(PickupItemEvent.class, pickupItemEvent, () -> {
EventDispatcher.callCancellable(pickupItemEvent, () -> {
final ItemStack item = itemEntity.getItemStack();
CollectItemPacket collectItemPacket = new CollectItemPacket();
@ -305,7 +309,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
}
EntityDeathEvent entityDeathEvent = new EntityDeathEvent(this);
callEvent(EntityDeathEvent.class, entityDeathEvent);
EventDispatcher.call(entityDeathEvent);
}
/**
@ -329,7 +333,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
// Do not start fire event if the fire needs to be removed (< 0 duration)
if (duration > 0) {
callCancellableEvent(EntityFireEvent.class, entityFireEvent, () -> {
EventDispatcher.callCancellable(entityFireEvent, () -> {
final long fireTime = entityFireEvent.getFireTime(TimeUnit.MILLISECOND);
setOnFire(true);
fireExtinguishTime = System.currentTimeMillis() + fireTime;
@ -354,7 +358,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
}
EntityDamageEvent entityDamageEvent = new EntityDamageEvent(this, type, value);
callCancellableEvent(EntityDamageEvent.class, entityDamageEvent, () -> {
EventDispatcher.callCancellable(entityDamageEvent, () -> {
// Set the last damage type since the event is not cancelled
this.lastDamageSource = entityDamageEvent.getDamageType();
@ -602,7 +606,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
public void setFlyingWithElytra(boolean isFlying) {
this.entityMeta.setFlyingWithElytra(isFlying);
}
/**
* Used to change the {@code isDead} internal field.
*

View File

@ -30,6 +30,7 @@ import net.minestom.server.effects.Effects;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.fakeplayer.FakePlayer;
import net.minestom.server.entity.vehicle.PlayerVehicleInformation;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.inventory.InventoryOpenEvent;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.ItemUpdateStateEvent;
@ -38,14 +39,14 @@ import net.minestom.server.event.player.*;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.message.ChatMessageType;
import net.minestom.server.message.ChatPosition;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.WrittenBookMeta;
import net.minestom.server.listener.PlayerDiggingListener;
import net.minestom.server.message.ChatMessageType;
import net.minestom.server.message.ChatPosition;
import net.minestom.server.message.Messenger;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.ConnectionState;
@ -250,7 +251,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// Add player to list with spawning skin
PlayerSkinInitEvent skinInitEvent = new PlayerSkinInitEvent(this, skin);
callEvent(PlayerSkinInitEvent.class, skinInitEvent);
EventDispatcher.call(skinInitEvent);
this.skin = skinInitEvent.getSkin();
// FIXME: when using Geyser, this line remove the skin of the client
playerConnection.sendPacket(getAddPlayerToList());
@ -296,7 +297,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
TagsPacket tags = TagsPacket.getRequiredTagsPacket();
UpdateTagListEvent event = new UpdateTagListEvent(tags);
callEvent(UpdateTagListEvent.class, event);
EventDispatcher.call(event);
this.playerConnection.sendPacket(tags);
}
@ -388,7 +389,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
continue;
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
callCancellableEvent(PickupExperienceEvent.class, pickupExperienceEvent, () -> {
EventDispatcher.callCancellable(pickupExperienceEvent, () -> {
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
entity.remove();
});
@ -414,7 +415,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
if (isFood) {
PlayerEatEvent playerEatEvent = new PlayerEatEvent(this, foodItem, eatingHand);
callEvent(PlayerEatEvent.class, playerEatEvent);
EventDispatcher.call(playerEatEvent);
}
refreshEating(null);
@ -422,7 +423,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
// Tick event
callEvent(PlayerTickEvent.class, playerTickEvent);
EventDispatcher.call(playerTickEvent);
}
@Override
@ -452,7 +453,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// Call player death event
PlayerDeathEvent playerDeathEvent = new PlayerDeathEvent(this, deathText, chatMessage);
callEvent(PlayerDeathEvent.class, playerDeathEvent);
EventDispatcher.call(playerDeathEvent);
deathText = playerDeathEvent.getDeathText();
chatMessage = playerDeathEvent.getChatMessage();
@ -489,7 +490,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
respawnPacket.isFlat = levelFlat;
getPlayerConnection().sendPacket(respawnPacket);
PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(this);
callEvent(PlayerRespawnEvent.class, respawnEvent);
EventDispatcher.call(respawnEvent);
refreshIsDead(false);
// Runnable called when teleportation is successful (after loading and sending necessary chunk)
@ -511,7 +512,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
if (isRemoved())
return;
callEvent(PlayerDisconnectEvent.class, new PlayerDisconnectEvent(this));
EventDispatcher.call(new PlayerDisconnectEvent(this));
super.remove();
this.packets.clear();
@ -669,7 +670,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent(this, instance, firstSpawn);
callEvent(PlayerSpawnEvent.class, spawnEvent);
EventDispatcher.call(spawnEvent);
}
/**
@ -1333,7 +1334,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
ItemDropEvent itemDropEvent = new ItemDropEvent(this, item);
callEvent(ItemDropEvent.class, itemDropEvent);
EventDispatcher.call(itemDropEvent);
return !itemDropEvent.isCancelled();
}
@ -1860,7 +1861,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
InventoryOpenEvent inventoryOpenEvent = new InventoryOpenEvent(inventory, this);
callCancellableEvent(InventoryOpenEvent.class, inventoryOpenEvent, () -> {
EventDispatcher.callCancellable(inventoryOpenEvent, () -> {
Inventory openInventory = getOpenInventory();
if (openInventory != null) {
openInventory.removeViewer(this);
@ -2227,9 +2228,9 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
public void refreshOnGround(boolean onGround) {
this.onGround = onGround;
if(this.onGround && this.isFlyingWithElytra()) {
if (this.onGround && this.isFlyingWithElytra()) {
this.setFlyingWithElytra(false);
this.callEvent(PlayerStopFlyingWithElytraEvent.class, new PlayerStopFlyingWithElytraEvent(this));
EventDispatcher.call(new PlayerStopFlyingWithElytraEvent(this));
}
}
@ -2302,7 +2303,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
return null;
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(this, hand, updatedItem);
callEvent(ItemUpdateStateEvent.class, itemUpdateStateEvent);
EventDispatcher.call(itemUpdateStateEvent);
return itemUpdateStateEvent;
}
@ -2676,7 +2677,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*
* @param locale the player locale
* @param viewDistance the player view distance
* @param chatMessageType the chat messages the player wishes to receive
* @param chatMessageType the chat messages the player wishes to receive
* @param chatColors if chat colors should be displayed
* @param displayedSkinParts the player displayed skin parts
* @param mainHand the player main hand

View File

@ -1,6 +1,7 @@
package net.minestom.server.entity.type.decoration;
import net.minestom.server.entity.*;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.item.EntityEquipEvent;
import net.minestom.server.inventory.EquipmentHandler;
import net.minestom.server.item.ItemStack;
@ -237,7 +238,7 @@ public class EntityArmorStand extends ObjectEntity implements EquipmentHandler {
private ItemStack getEquipmentItem(@NotNull ItemStack itemStack, @NotNull EquipmentSlot slot) {
EntityEquipEvent entityEquipEvent = new EntityEquipEvent(this, itemStack, slot);
callEvent(EntityEquipEvent.class, entityEquipEvent);
EventDispatcher.call(entityEquipEvent);
return entityEquipEvent.getEquippedItem();
}
}

View File

@ -4,6 +4,7 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.metadata.ProjectileMeta;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.entity.EntityShootEvent;
import net.minestom.server.instance.Chunk;
@ -71,14 +72,14 @@ public class EntityProjectile extends Entity {
}
public void shoot(Position to, double power, double spread) {
EntityShootEvent event = new EntityShootEvent(this.shooter, this, to, power, spread);
this.shooter.callEvent(EntityShootEvent.class, event);
if (event.isCancelled()) {
EntityShootEvent shootEvent = new EntityShootEvent(this.shooter, this, to, power, spread);
EventDispatcher.call(shootEvent);
if (shootEvent.isCancelled()) {
remove();
return;
}
Position from = this.shooter.getPosition().clone().add(0D, this.shooter.getEyeHeight(), 0D);
shoot(from, to, event.getPower(), event.getSpread());
shoot(from, to, shootEvent.getPower(), shootEvent.getSpread());
}
private void shoot(@NotNull Position from, @NotNull Position to, double power, double spread) {
@ -193,7 +194,7 @@ public class EntityProjectile extends Entity {
if (victimOptional.isPresent()) {
LivingEntity victim = (LivingEntity) victimOptional.get();
victim.setArrowCount(victim.getArrowCount() + 1);
callEvent(EntityAttackEvent.class, new EntityAttackEvent(this, victim));
EventDispatcher.call(new EntityAttackEvent(this, victim));
remove();
return super.onGround;
}

View File

@ -0,0 +1,15 @@
package net.minestom.server.event;
import net.minestom.server.MinecraftServer;
import org.jetbrains.annotations.NotNull;
public class EventDispatcher {
public static void call(@NotNull Event event) {
MinecraftServer.getGlobalEventNode().call(event);
}
public static void callCancellable(@NotNull CancellableEvent event, @NotNull Runnable successCallback) {
MinecraftServer.getGlobalEventNode().callCancellable(event, successCallback);
}
}

View File

@ -58,6 +58,7 @@ public class EventNode<T extends Event> {
protected final EventFilter<T, ?> filter;
protected final BiPredicate<T, Object> predicate;
protected final Class<T> eventType;
private volatile String name = "unknown";
// Tree data
@ -69,6 +70,7 @@ public class EventNode<T extends Event> {
protected EventNode(EventFilter<T, ?> filter, BiPredicate<T, Object> predicate) {
this.filter = filter;
this.predicate = predicate;
this.eventType = filter.getEventType();
}
/**
@ -84,7 +86,7 @@ public class EventNode<T extends Event> {
public void call(@NotNull T event) {
final var eventClass = event.getClass();
if (!filter.getEventType().isAssignableFrom(eventClass)) {
if (!eventType.isAssignableFrom(eventClass)) {
// Invalid event type
return;
}
@ -121,6 +123,29 @@ public class EventNode<T extends Event> {
this.children.forEach(eventNode -> eventNode.call(event));
}
public void callCancellable(@NotNull T event, @NotNull Runnable successCallback) {
call(event);
if (!(event instanceof CancellableEvent) || !((CancellableEvent) event).isCancelled()) {
successCallback.run();
}
}
public @Nullable EventNode<? super T> getParent() {
return parent;
}
public @NotNull Set<@NotNull EventNode<T>> getChildren() {
return Collections.unmodifiableSet(children);
}
public <E extends T> @NotNull EventNode<E> findChild(@NotNull String name, Class<E> eventType) {
return null;
}
public @NotNull EventNode<T> findChild(@NotNull String name) {
return findChild(name, eventType);
}
public EventNode<T> addChild(@NotNull EventNode<? extends T> child) {
synchronized (GLOBAL_CHILD_LOCK) {
Check.stateCondition(child.parent != null, "Node already has a parent");
@ -210,14 +235,6 @@ public class EventNode<T extends Event> {
return this;
}
public @Nullable EventNode<? super T> getParent() {
return parent;
}
public @NotNull Set<@NotNull EventNode<T>> getChildren() {
return Collections.unmodifiableSet(children);
}
private void increaseListenerCount(Class<? extends T> eventClass, int count) {
final int current = childEventMap.getInt(eventClass);
final int result = current + count;

View File

@ -1,14 +1,10 @@
package net.minestom.server.event.handler;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Entity;
import net.minestom.server.event.CancellableEvent;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.extensions.IExtensionObserver;
import net.minestom.server.extras.selfmodification.MinestomRootClassLoader;
import net.minestom.server.instance.Instance;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@ -48,7 +44,7 @@ public interface EventHandler extends IExtensionObserver {
*/
default <E extends Event> boolean addEventCallback(@NotNull Class<E> eventClass, @NotNull EventCallback<E> eventCallback) {
String extensionSource = MinestomRootClassLoader.findExtensionObjectOwner(eventCallback);
if(extensionSource != null) {
if (extensionSource != null) {
MinecraftServer.getExtensionManager().getExtension(extensionSource).observe(this);
getExtensionCallbacks(extensionSource).add(eventCallback);
}
@ -68,7 +64,7 @@ public interface EventHandler extends IExtensionObserver {
default <E extends Event> boolean removeEventCallback(@NotNull Class<E> eventClass, @NotNull EventCallback<E> eventCallback) {
Collection<EventCallback> callbacks = getEventCallbacks(eventClass);
String extensionSource = MinestomRootClassLoader.findExtensionObjectOwner(eventCallback);
if(extensionSource != null) {
if (extensionSource != null) {
getExtensionCallbacks(extensionSource).remove(eventCallback);
}
@ -97,72 +93,18 @@ public interface EventHandler extends IExtensionObserver {
return getEventCallbacksMap().values().stream().flatMap(Collection::stream);
}
/**
* Calls the specified {@link Event} with all the assigned {@link EventCallback}.
* <p>
* Events are always called in the current thread.
*
* @param eventClass the event class
* @param event the event object
* @param <E> the event type
*/
default <E extends Event> void callEvent(@NotNull Class<E> eventClass, @NotNull E event) {
try {
// Global listeners
if (!(this instanceof GlobalEventHandler)) {
final GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
runEvent(globalEventHandler.getEventCallbacks(eventClass), event);
}
// Local listeners
final Collection<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
runEvent(eventCallbacks, event);
// Call the same event for the current entity instance
if (this instanceof Entity) {
final Instance instance = ((Entity) this).getInstance();
if (instance != null) {
runEvent(instance.getEventCallbacks(eventClass), event);
}
}
} catch (Exception exception) {
MinecraftServer.getExceptionManager().handleException(exception);
}
}
/**
* Calls a {@link CancellableEvent} and execute {@code successCallback} if the {@link Event} is not cancelled.
* <p>
* Does call {@link #callEvent(Class, Event)} internally.
*
* @param eventClass the event class
* @param event the event object
* @param successCallback the callback called when the event is not cancelled
* @param <E> the event type
* @see #callEvent(Class, Event)
*/
default <E extends Event & CancellableEvent> void callCancellableEvent(@NotNull Class<E> eventClass,
@NotNull E event,
@NotNull Runnable successCallback) {
callEvent(eventClass, event);
if (!event.isCancelled()) {
successCallback.run();
}
}
/**
* Remove all event callbacks owned by the given extension
*
* @param extension the extension to remove callbacks from
*/
default void removeCallbacksOwnedByExtension(String extension) {
Collection<EventCallback<?>> extensionCallbacks = getExtensionCallbacks(extension);
for(EventCallback<?> callback : extensionCallbacks) {
for (EventCallback<?> callback : extensionCallbacks) {
// try to remove this callback from all callback collections
// we do this because we do not have information about the event class at this point
for(Collection<EventCallback> eventCallbacks : getEventCallbacksMap().values()) {
for (Collection<EventCallback> eventCallbacks : getEventCallbacksMap().values()) {
eventCallbacks.remove(callback);
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.extras.lan;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.server.ServerListPingEvent;
import net.minestom.server.timer.Task;
import net.minestom.server.utils.NetworkUtils;
@ -25,6 +26,7 @@ import static net.minestom.server.ping.ServerListPingType.OPEN_TO_LAN;
* Instead it simply sends the packets needed to trick the Minecraft client into thinking
* that this is a single-player world that has been opened to LANfor it to be displayed on
* the bottom of the server list.
*
* @see <a href="https://wiki.vg/Server_List_Ping#Ping_via_LAN_.28Open_to_LAN_in_Singleplayer.29">wiki.vg</a>
*/
public class OpenToLAN {
@ -37,7 +39,8 @@ public class OpenToLAN {
private static volatile DatagramPacket packet = null;
private static volatile Task task = null;
private OpenToLAN() { }
private OpenToLAN() {
}
/**
* Opens the server to LAN with the default config.
@ -121,7 +124,7 @@ public class OpenToLAN {
if (MinecraftServer.getNettyServer().getPort() != 0) {
if (packet == null || eventCooldown.isReady(System.currentTimeMillis())) {
final ServerListPingEvent event = new ServerListPingEvent(OPEN_TO_LAN);
MinecraftServer.getGlobalEventHandler().callEvent(ServerListPingEvent.class, event);
EventDispatcher.call(event);
final byte[] data = OPEN_TO_LAN.getPingResponse(event.getResponseData()).getBytes(StandardCharsets.UTF_8);
packet = new DatagramPacket(data, data.length, PING_ADDRESS);

View File

@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.extras.query.event.BasicQueryEvent;
import net.minestom.server.extras.query.event.FullQueryEvent;
import net.minestom.server.timer.Task;
@ -28,6 +29,7 @@ import java.util.Random;
/**
* Utility class to manage responses to the GameSpy4 Query Protocol.
*
* @see <a href="https://wiki.vg/Query">wiki.vg</a>
*/
public class Query {
@ -41,7 +43,8 @@ public class Query {
private static volatile Thread thread;
private static volatile Task task;
private Query() { }
private Query() {
}
/**
* Starts the query system, responding to queries on a random port, logging if it could not be started.
@ -190,12 +193,12 @@ public class Query {
if (remaining == 0) { // basic
BasicQueryEvent event = new BasicQueryEvent(sender, sessionID);
MinecraftServer.getGlobalEventHandler().callCancellableEvent(BasicQueryEvent.class, event,
() -> sendResponse(event.getQueryResponse(), sessionID, sender));
EventDispatcher.callCancellable(event, () ->
sendResponse(event.getQueryResponse(), sessionID, sender));
} else if (remaining == 5) { // full
FullQueryEvent event = new FullQueryEvent(sender, sessionID);
MinecraftServer.getGlobalEventHandler().callCancellableEvent(FullQueryEvent.class, event,
() -> sendResponse(event.getQueryResponse(), sessionID, sender));
EventDispatcher.callCancellable(event, () ->
sendResponse(event.getQueryResponse(), sessionID, sender));
}
}
}

View File

@ -7,6 +7,7 @@ import net.minestom.server.data.Data;
import net.minestom.server.data.DataContainer;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFColumnarSpace;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerChunkLoadEvent;
import net.minestom.server.event.player.PlayerChunkUnloadEvent;
import net.minestom.server.instance.block.Block;
@ -417,10 +418,10 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
UpdateLightPacket updateLightPacket = new UpdateLightPacket(getIdentifier(), getLastChangeTime());
updateLightPacket.chunkX = getChunkX();
updateLightPacket.chunkZ = getChunkZ();
updateLightPacket.skyLightMask = 0b111111111111111111;
updateLightPacket.emptySkyLightMask = 0b000000000000000000;
updateLightPacket.blockLightMask = 0b000000000000000000;
updateLightPacket.emptyBlockLightMask = 0b111111111111111111;
updateLightPacket.skyLightMask = 0b111111111111111111;
updateLightPacket.emptySkyLightMask = 0b000000000000000000;
updateLightPacket.blockLightMask = 0b000000000000000000;
updateLightPacket.emptyBlockLightMask = 0b111111111111111111;
byte[] bytes = new byte[2048];
Arrays.fill(bytes, (byte) 0xFF);
final List<byte[]> temp = new ArrayList<>(18);
@ -466,7 +467,7 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
if (result) {
PlayerChunkLoadEvent playerChunkLoadEvent = new PlayerChunkLoadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkLoadEvent.class, playerChunkLoadEvent);
EventDispatcher.call(playerChunkLoadEvent);
}
return result;
@ -488,7 +489,7 @@ public abstract class Chunk implements Viewable, Tickable, DataContainer {
if (result) {
PlayerChunkUnloadEvent playerChunkUnloadEvent = new PlayerChunkUnloadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkUnloadEvent.class, playerChunkUnloadEvent);
EventDispatcher.call(playerChunkUnloadEvent);
}
return result;

View File

@ -14,6 +14,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFInstanceSpace;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.handler.EventHandler;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.InstanceTickEvent;
@ -862,7 +863,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
lastInstance.UNSAFE_removeEntity(entity); // If entity is in another instance, remove it from there and add it to this
}
AddEntityToInstanceEvent event = new AddEntityToInstanceEvent(this, entity);
callCancellableEvent(AddEntityToInstanceEvent.class, event, () -> {
EventDispatcher.callCancellable(event, () -> {
final Position entityPosition = entity.getPosition();
final boolean isPlayer = entity instanceof Player;
@ -907,7 +908,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
return;
RemoveEntityFromInstanceEvent event = new RemoveEntityFromInstanceEvent(this, entity);
callCancellableEvent(RemoveEntityFromInstanceEvent.class, event, () -> {
EventDispatcher.callCancellable(event, () -> {
// Remove this entity from players viewable list and send delete entities packet
entity.getViewers().forEach(entity::removeViewer);
@ -1039,7 +1040,7 @@ public abstract class Instance implements BlockModifier, Tickable, EventHandler,
{
// Process tick events
InstanceTickEvent chunkTickEvent = new InstanceTickEvent(this, time, lastTickAge);
callEvent(InstanceTickEvent.class, chunkTickEvent);
EventDispatcher.call(chunkTickEvent);
// Set last tick age
lastTickAge = time;

View File

@ -4,6 +4,7 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
import net.minestom.server.data.SerializableData;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.instance.InstanceChunkLoadEvent;
import net.minestom.server.event.instance.InstanceChunkUnloadEvent;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
@ -384,7 +385,7 @@ public class InstanceContainer extends Instance {
final CustomBlock customBlock = getCustomBlock(x, y, z);
PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(player, blockPosition, blockStateId, customBlock, (short) 0, (short) 0);
player.callEvent(PlayerBlockBreakEvent.class, blockBreakEvent);
EventDispatcher.call(blockBreakEvent);
final boolean allowed = !blockBreakEvent.isCancelled();
if (allowed) {
// Break or change the broken block based on event result
@ -835,11 +836,11 @@ public class InstanceContainer extends Instance {
private void callChunkLoadEvent(int chunkX, int chunkZ) {
InstanceChunkLoadEvent chunkLoadEvent = new InstanceChunkLoadEvent(this, chunkX, chunkZ);
callEvent(InstanceChunkLoadEvent.class, chunkLoadEvent);
EventDispatcher.call(chunkLoadEvent);
}
private void callChunkUnloadEvent(int chunkX, int chunkZ) {
InstanceChunkUnloadEvent chunkUnloadEvent = new InstanceChunkUnloadEvent(this, chunkX, chunkZ);
callEvent(InstanceChunkUnloadEvent.class, chunkUnloadEvent);
EventDispatcher.call(chunkUnloadEvent);
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.inventory;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.inventory.InventoryClickEvent;
import net.minestom.server.inventory.click.ClickType;
import net.minestom.server.item.ItemStack;
@ -78,7 +79,7 @@ public interface InventoryClickHandler {
default void callClickEvent(@NotNull Player player, Inventory inventory, int slot,
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
InventoryClickEvent inventoryClickEvent = new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor);
player.callEvent(InventoryClickEvent.class, inventoryClickEvent);
EventDispatcher.call(inventoryClickEvent);
}
}

View File

@ -2,6 +2,7 @@ package net.minestom.server.inventory;
import net.minestom.server.entity.EquipmentSlot;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.item.EntityEquipEvent;
import net.minestom.server.inventory.click.ClickType;
import net.minestom.server.inventory.click.InventoryClickResult;
@ -189,7 +190,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
if (equipmentSlot != null) {
EntityEquipEvent entityEquipEvent = new EntityEquipEvent(player, itemStack, equipmentSlot);
player.callEvent(EntityEquipEvent.class, entityEquipEvent);
EventDispatcher.call(entityEquipEvent);
itemStack = entityEquipEvent.getEquippedItem();
}

View File

@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.inventory.InventoryClickEvent;
import net.minestom.server.event.inventory.InventoryPreClickEvent;
import net.minestom.server.inventory.AbstractInventory;
@ -187,7 +188,7 @@ public class InventoryClickProcessor {
var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor);
if(result.isCancel()){
if (result.isCancel()) {
clickResult.setRefresh(true);
return false;
}
@ -214,7 +215,7 @@ public class InventoryClickProcessor {
if (index == slot) // Prevent item lose/duplication
return false;
InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor);
if(result.isCancel()){
if (result.isCancel()) {
clickResult.setRefresh(true);
return false;
}
@ -509,7 +510,7 @@ public class InventoryClickProcessor {
{
InventoryPreClickEvent inventoryPreClickEvent = new InventoryPreClickEvent(inventory, player, slot, clickType,
clickResult.getClicked(), clickResult.getCursor());
player.callEvent(InventoryPreClickEvent.class, inventoryPreClickEvent);
EventDispatcher.call(inventoryPreClickEvent);
clickResult.setCursor(inventoryPreClickEvent.getCursorItem());
clickResult.setClicked(inventoryPreClickEvent.getClickedItem());
@ -565,7 +566,7 @@ public class InventoryClickProcessor {
private void callClickEvent(@NotNull Player player, @Nullable Inventory inventory, int slot,
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
InventoryClickEvent inventoryClickEvent = new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor);
player.callEvent(InventoryClickEvent.class, inventoryClickEvent);
EventDispatcher.call(inventoryClickEvent);
}
public void clearCache(@NotNull Player player) {

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerStartFlyingEvent;
import net.minestom.server.event.player.PlayerStopFlyingEvent;
import net.minestom.server.network.packet.client.play.ClientPlayerAbilitiesPacket;
@ -17,10 +18,10 @@ public class AbilitiesListener {
if (isFlying) {
PlayerStartFlyingEvent startFlyingEvent = new PlayerStartFlyingEvent(player);
player.callEvent(PlayerStartFlyingEvent.class, startFlyingEvent);
EventDispatcher.call(startFlyingEvent);
} else {
PlayerStopFlyingEvent stopFlyingEvent = new PlayerStopFlyingEvent(player);
player.callEvent(PlayerStopFlyingEvent.class, stopFlyingEvent);
EventDispatcher.call(stopFlyingEvent);
}
}
}

View File

@ -2,6 +2,7 @@ package net.minestom.server.listener;
import net.minestom.server.advancements.AdvancementAction;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.AdvancementTabEvent;
import net.minestom.server.network.packet.client.play.ClientAdvancementTabPacket;
@ -12,6 +13,6 @@ public class AdvancementTabListener {
final String tabId = packet.tabIdentifier;
AdvancementTabEvent advancementTabEvent = new AdvancementTabEvent(player, action, tabId);
player.callEvent(AdvancementTabEvent.class, advancementTabEvent);
EventDispatcher.call(advancementTabEvent);
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerHandAnimationEvent;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.client.play.ClientAnimationPacket;
@ -12,7 +13,7 @@ public class AnimationListener {
final ItemStack itemStack = player.getItemInHand(hand);
//itemStack.onLeftClick(player, hand);
PlayerHandAnimationEvent handAnimationEvent = new PlayerHandAnimationEvent(player, hand);
player.callCancellableEvent(PlayerHandAnimationEvent.class, handAnimationEvent, () -> {
EventDispatcher.callCancellable(handAnimationEvent, () -> {
switch (hand) {
case MAIN:
player.swingMainHand();

View File

@ -6,6 +6,7 @@ import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerBlockInteractEvent;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
@ -57,7 +58,7 @@ public class BlockPlacementListener {
PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(player, blockPosition, hand, blockFace);
playerBlockInteractEvent.setCancelled(cancel);
playerBlockInteractEvent.setBlockingItemUse(cancel);
player.callCancellableEvent(PlayerBlockInteractEvent.class, playerBlockInteractEvent, () -> {
EventDispatcher.callCancellable(playerBlockInteractEvent, () -> {
final CustomBlock customBlock = instance.getCustomBlock(blockPosition);
if (customBlock != null) {
final Data data = instance.getBlockData(blockPosition);
@ -146,7 +147,7 @@ public class BlockPlacementListener {
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, block, blockPosition, packet.hand);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
EventDispatcher.call(playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled()) {
// BlockPlacementRule check
@ -189,7 +190,7 @@ public class BlockPlacementListener {
// Player didn't try to place a block but interacted with one
final BlockPosition usePosition = blockPosition.clone().subtract(offsetX, offsetY, offsetZ);
PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, usePosition, direction);
player.callEvent(PlayerUseItemOnBlockEvent.class, event);
EventDispatcher.call(event);
refreshChunk = true;
}

View File

@ -5,6 +5,7 @@ import net.kyori.adventure.text.event.ClickEvent;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerChatEvent;
import net.minestom.server.message.ChatPosition;
import net.minestom.server.message.Messenger;
@ -49,7 +50,7 @@ public class ChatMessageListener {
PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, () -> buildDefaultChatMessage(player, message), message);
// Call the event
player.callCancellableEvent(PlayerChatEvent.class, playerChatEvent, () -> {
EventDispatcher.callCancellable(playerChatEvent, () -> {
final Function<PlayerChatEvent, Component> formatFunction = playerChatEvent.getChatFormatFunction();
Component textObject;

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.*;
import net.minestom.server.network.packet.client.play.ClientEntityActionPacket;
@ -35,9 +36,9 @@ public class EntityActionListener {
if (oldState != sneaking) {
if (sneaking) {
player.callEvent(PlayerStartSneakingEvent.class, new PlayerStartSneakingEvent(player));
EventDispatcher.call(new PlayerStartSneakingEvent(player));
} else {
player.callEvent(PlayerStopSneakingEvent.class, new PlayerStopSneakingEvent(player));
EventDispatcher.call(new PlayerStopSneakingEvent(player));
}
}
}
@ -49,15 +50,15 @@ public class EntityActionListener {
if (oldState != sprinting) {
if (sprinting) {
player.callEvent(PlayerStartSprintingEvent.class, new PlayerStartSprintingEvent(player));
EventDispatcher.call(new PlayerStartSprintingEvent(player));
} else {
player.callEvent(PlayerStopSprintingEvent.class, new PlayerStopSprintingEvent(player));
EventDispatcher.call(new PlayerStopSprintingEvent(player));
}
}
}
private static void startFlyingElytra(Player player) {
player.setFlyingWithElytra(true);
player.callEvent(PlayerStartFlyingWithElytraEvent.class, new PlayerStartFlyingWithElytraEvent(player));
EventDispatcher.call(new PlayerStartFlyingWithElytraEvent(player));
}
}

View File

@ -2,6 +2,7 @@ package net.minestom.server.listener;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.item.ItemUpdateStateEvent;
import net.minestom.server.event.player.PlayerStartDiggingEvent;
import net.minestom.server.event.player.PlayerSwapItemEvent;
@ -67,7 +68,7 @@ public class PlayerDiggingListener {
final int customBlockId = customBlock == null ? 0 : customBlock.getCustomBlockId();
PlayerStartDiggingEvent playerStartDiggingEvent = new PlayerStartDiggingEvent(player, blockPosition, blockStateId, customBlockId);
player.callEvent(PlayerStartDiggingEvent.class, playerStartDiggingEvent);
EventDispatcher.call(playerStartDiggingEvent);
if (playerStartDiggingEvent.isCancelled()) {
addEffect(player);
@ -159,7 +160,7 @@ public class PlayerDiggingListener {
final ItemStack offHand = playerInventory.getItemInOffHand();
PlayerSwapItemEvent swapItemEvent = new PlayerSwapItemEvent(player, offHand, mainHand);
player.callCancellableEvent(PlayerSwapItemEvent.class, swapItemEvent, () -> {
EventDispatcher.callCancellable(swapItemEvent, () -> {
playerInventory.setItemInMainHand(swapItemEvent.getMainHandItem());
playerInventory.setItemInOffHand(swapItemEvent.getOffHandItem());
});

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerChangeHeldSlotEvent;
import net.minestom.server.network.packet.client.play.ClientHeldItemChangePacket;
import net.minestom.server.utils.MathUtils;
@ -16,7 +17,7 @@ public class PlayerHeldListener {
final byte slot = (byte) packet.slot;
PlayerChangeHeldSlotEvent changeHeldSlotEvent = new PlayerChangeHeldSlotEvent(player, slot);
player.callEvent(PlayerChangeHeldSlotEvent.class, changeHeldSlotEvent);
EventDispatcher.call(changeHeldSlotEvent);
if (!changeHeldSlotEvent.isCancelled()) {
// Event hasn't been canceled, process it

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.client.play.*;
@ -74,7 +75,7 @@ public class PlayerPositionListener {
final Position cachedPosition = newPosition.clone();
PlayerMoveEvent playerMoveEvent = new PlayerMoveEvent(player, newPosition);
player.callEvent(PlayerMoveEvent.class, playerMoveEvent);
EventDispatcher.call(playerMoveEvent);
// True if the event call changed the player position (possibly a teleport)
final boolean positionChanged = !currentPosition.equals(player.getPosition());

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerPluginMessageEvent;
import net.minestom.server.network.packet.client.play.ClientPluginMessagePacket;
@ -8,7 +9,7 @@ public class PluginMessageListener {
public static void listener(ClientPluginMessagePacket packet, Player player) {
PlayerPluginMessageEvent pluginMessageEvent = new PlayerPluginMessageEvent(player, packet.channel, packet.data);
player.callEvent(PlayerPluginMessageEvent.class, pluginMessageEvent);
EventDispatcher.call(pluginMessageEvent);
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerResourcePackStatusEvent;
import net.minestom.server.network.packet.client.play.ClientResourcePackStatusPacket;
import net.minestom.server.resourcepack.ResourcePackStatus;
@ -10,6 +11,6 @@ public class ResourcePackListener {
public static void listener(ClientResourcePackStatusPacket packet, Player player) {
final ResourcePackStatus result = packet.result;
PlayerResourcePackStatusEvent resourcePackStatusEvent = new PlayerResourcePackStatusEvent(player, result);
player.callEvent(PlayerResourcePackStatusEvent.class, resourcePackStatusEvent);
EventDispatcher.call(resourcePackStatusEvent);
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerSettingsChangeEvent;
import net.minestom.server.network.packet.client.play.ClientSettingsPacket;
@ -11,7 +12,7 @@ public class SettingsListener {
settings.refresh(packet.locale, packet.viewDistance, packet.chatMessageType, packet.chatColors, packet.displayedSkinParts, packet.mainHand);
PlayerSettingsChangeEvent playerSettingsChangeEvent = new PlayerSettingsChangeEvent(player);
player.callEvent(PlayerSettingsChangeEvent.class, playerSettingsChangeEvent);
EventDispatcher.call(playerSettingsChangeEvent);
}
}

View File

@ -3,6 +3,7 @@ package net.minestom.server.listener;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.player.PlayerEntityInteractEvent;
import net.minestom.server.network.packet.client.play.ClientInteractEntityPacket;
@ -24,10 +25,10 @@ public class UseEntityListener {
return;
EntityAttackEvent entityAttackEvent = new EntityAttackEvent(player, entity);
player.callEvent(EntityAttackEvent.class, entityAttackEvent);
EventDispatcher.call(entityAttackEvent);
} else if (type == ClientInteractEntityPacket.Type.INTERACT) {
PlayerEntityInteractEvent playerEntityInteractEvent = new PlayerEntityInteractEvent(player, entity, packet.hand);
player.callEvent(PlayerEntityInteractEvent.class, playerEntityInteractEvent);
EventDispatcher.call(playerEntityInteractEvent);
} else {
// TODO find difference with INTERACT
//PlayerEntityInteractEvent playerEntityInteractEvent = new PlayerEntityInteractEvent(player, entity, packet.hand);

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerItemAnimationEvent;
import net.minestom.server.event.player.PlayerPreEatEvent;
import net.minestom.server.event.player.PlayerUseItemEvent;
@ -17,7 +18,7 @@ public class UseItemListener {
ItemStack itemStack = hand == Player.Hand.MAIN ? inventory.getItemInMainHand() : inventory.getItemInOffHand();
//itemStack.onRightClick(player, hand);
PlayerUseItemEvent useItemEvent = new PlayerUseItemEvent(player, hand, itemStack);
player.callEvent(PlayerUseItemEvent.class, useItemEvent);
EventDispatcher.call(useItemEvent);
final PlayerInventory playerInventory = player.getInventory();
if (useItemEvent.isCancelled()) {
@ -63,12 +64,12 @@ public class UseItemListener {
// Eating code, contains the eating time customisation
PlayerPreEatEvent playerPreEatEvent = new PlayerPreEatEvent(player, itemStack, hand, player.getDefaultEatingTime());
player.callCancellableEvent(PlayerPreEatEvent.class, playerPreEatEvent, () -> player.refreshEating(hand, playerPreEatEvent.getEatingTime()));
EventDispatcher.callCancellable(playerPreEatEvent, () -> player.refreshEating(hand, playerPreEatEvent.getEatingTime()));
}
if (itemAnimationType != null) {
PlayerItemAnimationEvent playerItemAnimationEvent = new PlayerItemAnimationEvent(player, itemAnimationType);
player.callCancellableEvent(PlayerItemAnimationEvent.class, playerItemAnimationEvent, () -> {
EventDispatcher.callCancellable(playerItemAnimationEvent, () -> {
player.refreshActiveHand(true, hand == Player.Hand.OFF, riptideSpinAttack);
player.sendPacketToViewers(player.getMetadataPacket());
});

View File

@ -1,6 +1,7 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.inventory.InventoryCloseEvent;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryClickHandler;
@ -111,7 +112,7 @@ public class WindowListener {
public static void closeWindowListener(ClientCloseWindowPacket packet, Player player) {
// if windowId == 0 then it is player's inventory, meaning that they hadn't been any open inventory packet
InventoryCloseEvent inventoryCloseEvent = new InventoryCloseEvent(player.getOpenInventory(), player);
player.callEvent(InventoryCloseEvent.class, inventoryCloseEvent);
EventDispatcher.call(inventoryCloseEvent);
player.closeInventory();

View File

@ -9,6 +9,7 @@ import net.minestom.server.adventure.audience.Audiences;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.fakeplayer.FakePlayer;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.AsyncPlayerPreLoginEvent;
import net.minestom.server.event.player.PlayerLoginEvent;
import net.minestom.server.instance.Instance;
@ -419,7 +420,7 @@ public final class ConnectionManager {
// Call pre login event
AsyncPlayerPreLoginEvent asyncPlayerPreLoginEvent = new AsyncPlayerPreLoginEvent(player, username, uuid);
player.callEvent(AsyncPlayerPreLoginEvent.class, asyncPlayerPreLoginEvent);
EventDispatcher.call(asyncPlayerPreLoginEvent);
// Close the player channel if he has been disconnected (kick)
final boolean online = player.isOnline();
@ -543,7 +544,7 @@ public final class ConnectionManager {
while ((waitingPlayer = waitingPlayers.poll()) != null) {
PlayerLoginEvent loginEvent = new PlayerLoginEvent(waitingPlayer);
waitingPlayer.callEvent(PlayerLoginEvent.class, loginEvent);
EventDispatcher.call(loginEvent);
final Instance spawningInstance = loginEvent.getSpawningInstance();
Check.notNull(spawningInstance, "You need to specify a spawning instance in the PlayerLoginEvent");

View File

@ -6,6 +6,7 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.server.ServerListPingEvent;
import net.minestom.server.ping.ServerListPingType;
import org.jetbrains.annotations.NotNull;
@ -138,12 +139,12 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter {
* Calls a {@link ServerListPingEvent} and sends the response, if the event was not cancelled.
*
* @param version the version
* @param ctx the context
* @param ctx the context
* @return {@code true} if the response was cancelled, {@code false} otherwise
*/
private static boolean trySendResponse(@NotNull ServerListPingType version, @NotNull ChannelHandlerContext ctx) {
final ServerListPingEvent event = new ServerListPingEvent(version);
MinecraftServer.getGlobalEventHandler().callEvent(ServerListPingEvent.class, event);
EventDispatcher.call(event);
if (event.isCancelled()) {
return true;

View File

@ -1,6 +1,6 @@
package net.minestom.server.network.packet.client.status;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.server.ServerListPingEvent;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.handshake.ResponsePacket;
@ -16,7 +16,7 @@ public class StatusRequestPacket implements ClientPreplayPacket {
public void process(@NotNull PlayerConnection connection) {
final ServerListPingType pingVersion = ServerListPingType.fromModernProtocolVersion(connection.getProtocolVersion());
final ServerListPingEvent statusRequestEvent = new ServerListPingEvent(connection, pingVersion);
MinecraftServer.getGlobalEventHandler().callCancellableEvent(ServerListPingEvent.class, statusRequestEvent, () -> {
EventDispatcher.callCancellable(statusRequestEvent, () -> {
final ResponsePacket responsePacket = new ResponsePacket();
responsePacket.jsonResponse = pingVersion.getPingResponse(statusRequestEvent.getResponseData());

View File

@ -159,6 +159,10 @@ public class PlayerInit {
node.addChild(EventNode.value(EventFilter.PLAYER, player -> player.getUsername().equals("TheMode911"))
.addListener(PlayerMoveEvent.class, event -> System.out.println("move!"))
.addListener(PlayerTickEvent.class, event -> System.out.println("tick!")));
//var child = node.findChild("name");
//child.addListener(PlayerTickEvent.class, (event) -> {
//});
//node.addChild(tagNode); -> Error: cannot add an item listener to a player node
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();