--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java
+++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java
@@ -2,16 +2,24 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Holder;
 import net.minecraft.core.SectionPos;
 import net.minecraft.network.protocol.game.DebugPackets;
 import net.minecraft.server.level.ServerLevel;
-import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.LevelChunk;
 import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.CraftGameEvent;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.world.GenericGameEvent;
+// CraftBukkit end
 
 public class GameEventDispatcher {
+
     private final ServerLevel level;
 
     public GameEventDispatcher(ServerLevel world) {
@@ -19,30 +27,40 @@
     }
 
     public void post(Holder<GameEvent> event, Vec3 emitterPos, GameEvent.Context emitter) {
-        int i = event.value().notificationRadius();
-        BlockPos blockPos = BlockPos.containing(emitterPos);
-        int j = SectionPos.blockToSectionCoord(blockPos.getX() - i);
-        int k = SectionPos.blockToSectionCoord(blockPos.getY() - i);
-        int l = SectionPos.blockToSectionCoord(blockPos.getZ() - i);
-        int m = SectionPos.blockToSectionCoord(blockPos.getX() + i);
-        int n = SectionPos.blockToSectionCoord(blockPos.getY() + i);
-        int o = SectionPos.blockToSectionCoord(blockPos.getZ() + i);
-        List<GameEvent.ListenerInfo> list = new ArrayList<>();
-        GameEventListenerRegistry.ListenerVisitor listenerVisitor = (listener, listenerPos) -> {
-            if (listener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) {
-                list.add(new GameEvent.ListenerInfo(event, emitterPos, emitter, listener, listenerPos));
+        int i = ((GameEvent) event.value()).notificationRadius();
+        BlockPos blockposition = BlockPos.containing(emitterPos);
+        // CraftBukkit start
+        GenericGameEvent event1 = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(event.value()), CraftLocation.toBukkit(blockposition, this.level.getWorld()), (emitter.sourceEntity() == null) ? null : emitter.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread());
+        this.level.getCraftServer().getPluginManager().callEvent(event1);
+        if (event1.isCancelled()) {
+            return;
+        }
+        i = event1.getRadius();
+        // CraftBukkit end
+        int j = SectionPos.blockToSectionCoord(blockposition.getX() - i);
+        int k = SectionPos.blockToSectionCoord(blockposition.getY() - i);
+        int l = SectionPos.blockToSectionCoord(blockposition.getZ() - i);
+        int i1 = SectionPos.blockToSectionCoord(blockposition.getX() + i);
+        int j1 = SectionPos.blockToSectionCoord(blockposition.getY() + i);
+        int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i);
+        List<GameEvent.ListenerInfo> list = new ArrayList();
+        GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_a = (gameeventlistener, vec3d1) -> {
+            if (gameeventlistener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) {
+                list.add(new GameEvent.ListenerInfo(event, emitterPos, emitter, gameeventlistener, vec3d1));
             } else {
-                listener.handleGameEvent(this.level, event, emitter, emitterPos);
+                gameeventlistener.handleGameEvent(this.level, event, emitter, emitterPos);
             }
+
         };
-        boolean bl = false;
+        boolean flag = false;
 
-        for (int p = j; p <= m; p++) {
-            for (int q = l; q <= o; q++) {
-                ChunkAccess chunkAccess = this.level.getChunkSource().getChunkNow(p, q);
-                if (chunkAccess != null) {
-                    for (int r = k; r <= n; r++) {
-                        bl |= chunkAccess.getListenerRegistry(r).visitInRangeListeners(event, emitterPos, emitter, listenerVisitor);
+        for (int l1 = j; l1 <= i1; ++l1) {
+            for (int i2 = l; i2 <= k1; ++i2) {
+                LevelChunk chunk = (LevelChunk) this.level.getChunkIfLoadedImmediately(l1, i2); // Paper - Use getChunkIfLoadedImmediately
+
+                if (chunk != null) {
+                    for (int j2 = k; j2 <= j1; ++j2) {
+                        flag |= chunk.getListenerRegistry(j2).visitInRangeListeners(event, emitterPos, emitter, gameeventlistenerregistry_a);
                     }
                 }
             }
@@ -52,17 +70,22 @@
             this.handleGameEventMessagesInQueue(list);
         }
 
-        if (bl) {
+        if (flag) {
             DebugPackets.sendGameEventInfo(this.level, event, emitterPos);
         }
+
     }
 
     private void handleGameEventMessagesInQueue(List<GameEvent.ListenerInfo> messages) {
         Collections.sort(messages);
+        Iterator iterator = messages.iterator();
 
-        for (GameEvent.ListenerInfo listenerInfo : messages) {
-            GameEventListener gameEventListener = listenerInfo.recipient();
-            gameEventListener.handleGameEvent(this.level, listenerInfo.gameEvent(), listenerInfo.context(), listenerInfo.source());
+        while (iterator.hasNext()) {
+            GameEvent.ListenerInfo gameevent_b = (GameEvent.ListenerInfo) iterator.next();
+            GameEventListener gameeventlistener = gameevent_b.recipient();
+
+            gameeventlistener.handleGameEvent(this.level, gameevent_b.gameEvent(), gameevent_b.context(), gameevent_b.source());
         }
+
     }
 }
