diff --git a/.checkstyle/checkstyle-suppressions.xml b/.checkstyle/checkstyle-suppressions.xml
index 5c677e151a1..2bf5687b5dd 100644
--- a/.checkstyle/checkstyle-suppressions.xml
+++ b/.checkstyle/checkstyle-suppressions.xml
@@ -17,4 +17,5 @@
     <suppress checks="MethodTypeParameterName"/>
     <suppress checks="CommentsIndentation"/>
     <suppress checks="InterfaceTypeParameterName"/>
+    <suppress files="[\\/]generated[\\/]" checks="[a-zA-Z0-9]*"/>
 </suppressions>
diff --git a/.gitignore b/.gitignore
index 1e698d63c71..95d321c54ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,10 @@ MANIFEST.MF
 dependency-reduced-pom.xml
 .checkstyle
 !.checkstyle/
+# We exclude the generated events from git to avoid
+# temptation to edit said generated files.
+src/generated/
+src/main/generated/
 
 # Compiled #
 ############
diff --git a/build.gradle.kts b/build.gradle.kts
index 75be8bd5d28..9bd709faa79 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,13 +1,7 @@
 import net.ltgt.gradle.errorprone.errorprone
 import org.jetbrains.gradle.ext.delegateActions
 import org.jetbrains.gradle.ext.settings
-import org.jetbrains.gradle.ext.taskTriggers
 
-buildscript {
-    dependencies {
-        classpath(libs.spoon) // bump for EIG
-    }
-}
 
 plugins {
     eclipse
@@ -16,12 +10,14 @@ plugins {
     alias(libs.plugins.indra.crossdoc)
     alias(libs.plugins.indra.publishing)
     alias(libs.plugins.indra.publishing.sonatype)
-    alias(libs.plugins.eventImplGen)
     alias(libs.plugins.ideaExt)
     alias(libs.plugins.errorprone)
     alias(libs.plugins.nexusPublish)
 }
 
+// Enable event generation to be considered part of
+// the main source set
+val generatedEventSourcesDir = project.file("src/main/generated")
 val javaTarget: String by project
 val ap by sourceSets.registering {
     compileClasspath += sourceSets.main.get().compileClasspath + sourceSets.main.get().output
@@ -34,12 +30,32 @@ configurations {
        }
     }
 }
+tasks {
+    register("printSourceDirs") {
+        doLast {
+            sourceSets.forEach { set ->
+                println("SourceSet: ${set.name}")
+                println("Java Source Dirs: ${set.java.srcDirs}" )
+            }
+        }
+    }
+}
+
+sourceSets {
+    main {
+        java {
+            srcDirs(generatedEventSourcesDir)
+        }
+    }
+}
 
 // Project dependencies
 dependencies {
     // Directly tied to what's available from Minecraft
     api(libs.log4j.api)
     api(libs.gson)
+    api(libs.eventImplGen.annotations)
+    annotationProcessor(libs.eventImplGen.processor)
 
     // Adventure
     api(platform(libs.adventure.bom))
@@ -130,27 +146,23 @@ dependencies {
     testImplementation(libs.mockito)
 }
 
+spotless {
+    java {
+        target("src/main/java/**/*.java")
+        targetExclude("src/main/generated/**/*.java")
+    }
+}
+
 tasks {
-    genEventImpl {
-        sourceCompatibility = "17" // TODO use javaTarget here
-        destinationDirectory = project.layout.buildDirectory.dir("generated/event-factory")
-
-        outputFactory = "org.spongepowered.api.event.SpongeEventFactory"
-        include("org/spongepowered/api/event/*/**/*")
-        exclude("org/spongepowered/api/event/action/InteractEvent.java")
-        exclude("org/spongepowered/api/event/cause/")
-        exclude("org/spongepowered/api/event/entity/AffectEntityEvent.java")
-        exclude("org/spongepowered/api/event/filter/")
-        exclude("org/spongepowered/api/event/impl/")
-        exclude("org/spongepowered/api/event/lifecycle/ProvideServiceEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterBuilderEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterRegistryEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterRegistryValueEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterCommandEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterFactoryEvent.java")
-        exclude("org/spongepowered/api/event/lifecycle/RegisterWorldEvent.java")
-        inclusiveAnnotations = setOf("org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod")
-        exclusiveAnnotations = setOf("org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod")
+
+    compileJava {
+        options.generatedSourceOutputDirectory = generatedEventSourcesDir
+        options.compilerArgs.addAll(listOf(
+            "-AeventGenInclusiveFolders=org/spongepowered/api/event",
+            "-AeventGenExclusiveFolders=org/spongepowered/api/event/cause,org/spongepowered/api/event/filter,org/spongepowered/api/event/impl,org/spongepowered/api/event/lifecycle",
+            "-AeventGenFactory=org.spongepowered.api.event.SpongeEventFactory",
+            "-AeventGenDebug=true",
+        ))
     }
 
     jar {
@@ -166,6 +178,15 @@ tasks {
             indraGit.applyVcsInformationToManifest(this)
         }
     }
+    checkstyleMain {
+        dependsOn(compileJava)
+    }
+    spotlessJava {
+        dependsOn(compileJava)
+    }
+    sourcesJar {
+        dependsOn(compileJava)
+    }
 
     withType(JavaCompile::class).configureEach {
         options.apply {
@@ -215,15 +236,12 @@ idea {
                 delegateBuildRunToGradle = false
                 testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
             }
-            taskTriggers {
-                beforeBuild(tasks.genEventImpl)
-            }
         }
     }
 }
 
 eclipse {
-    synchronizationTasks(tasks.genEventImpl)
+//    synchronizationTasks(tasks.genEventImpl)
 }
 
 val organization: String by project
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index dcc90890469..ce3398b856a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -37,13 +37,14 @@ guice = { module = "com.google.inject:guice", version.ref = "guice" }
 log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" }
 math = { module = "org.spongepowered:math", version.ref = "math" }
 pluginSpi = { module = "org.spongepowered:plugin-spi", version.ref = "pluginSpi" }
+eventImplGen-processor = {module = "org.spongepowered:event-impl-gen", version = "8.0.0"}
+eventImplGen-annotations = { module = "org.spongepowered:event-impl-gen-annotations", version = "8.0.0"}
 
 # build-time/annotations
 
 checkerQual = { module = "org.checkerframework:checker-qual", version.ref = "checker" }
 errorprone = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone" }
 errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorprone" }
-spoon = { module = "fr.inria.gforge.spoon:spoon-core", version = "10.4.2" } # bump for EIG
 
 # testing
 
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 6c36c128d12..b8f1d596845 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -252,6 +252,30 @@
             <sha256 value="893d56afcea1b22f83220fd7e49a6668c5b8901e39bd59dc57b42f55673721ce" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="com.google.dagger" name="dagger" version="2.42">
+         <artifact name="dagger-2.42.jar">
+            <sha256 value="7ad8147fdb5dfb481b7cde8c70da73afbaa21430ce757fcd96709fcfb6a4d56b" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="dagger-2.42.pom">
+            <sha256 value="ca6529bd6d79090f0ab6f5da452eb4fbb29377b48e6a806e7612396dcb2998e0" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
+      <component group="com.google.dagger" name="dagger" version="2.52">
+         <artifact name="dagger-2.52.jar">
+            <sha256 value="dfb8e83020786daefbd64335ce0e0ebf01646a1b407fb77a27e052baf42df458" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="dagger-2.52.pom">
+            <sha256 value="5cb60843f46bbccf97bd832d5490d26ab192af2e663fad7e5971969bf20fb94e" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
+      <component group="com.google.dagger" name="dagger" version="2.54">
+         <artifact name="dagger-2.54.jar">
+            <sha256 value="7ab0d8278a532888de19025dc6ee70a80ecd4567778a6a7e7ec256a2073e40a3" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="dagger-2.54.pom">
+            <sha256 value="af43413fd91fc49532884ca32191ab31bec609c344d4939aece9d3efef699f81" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="com.google.errorprone" name="error_prone_annotation" version="2.24.1">
          <artifact name="error_prone_annotation-2.24.1.jar">
             <sha256 value="dc202da451680aa8cdda7c68d959f27c112dca8f8fdeaf7c597de73cb2b1a0a6" origin="Generated by Gradle"/>
@@ -549,6 +573,14 @@
             <sha256 value="9acf56a8579c05bedd819d99232363e2bf327e8f73c67598dbd9885a845a3c69" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="com.palantir.javapoet" name="javapoet" version="0.6.0">
+         <artifact name="javapoet-0.6.0.jar">
+            <sha256 value="1c8dd1cc4404b9eeb5c54fef8a1cf2be7a138a42783b9460fbae9caf85ed5b2f" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="javapoet-0.6.0.pom">
+            <sha256 value="f6e34a26ac09a3a68a91cc9235cb1f8c7736b07fe89db59a324acd8d57d9e797" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="com.puppycrawl.tools" name="checkstyle" version="10.12.7">
          <artifact name="checkstyle-10.12.7.jar">
             <sha256 value="767cc2393169f0abe4292e59c3b62317149f900a472cd6b01f74346f6bdae581" origin="Generated by Gradle"/>
@@ -557,6 +589,14 @@
             <sha256 value="f6ac2b6de9ed3823c8d68977df6352f3936af5db7baeb12303cdc9d3c4f46590" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="com.squareup" name="javapoet" version="1.13.0">
+         <artifact name="javapoet-1.13.0.jar">
+            <sha256 value="4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="javapoet-1.13.0.pom">
+            <sha256 value="54a34fa8502a46bc90efdb49262600591fa80bf9a34f5a4c798311aec16ca977" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="com.squareup.okhttp3" name="okhttp" version="4.10.0">
          <artifact name="okhttp-4.10.0.jar">
             <sha256 value="7580f14fa1691206e37081ad3f92063b1603b328da0bb316f2fef02e0562e7ec" origin="Generated by Gradle"/>
@@ -728,6 +768,22 @@
             <sha256 value="5a65e06a159d20d3b4800624a570c646dbee710b2b539b3449a268558c289e9c" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="io.soabase.java-composer" name="java-composer" version="1.0">
+         <artifact name="java-composer-1.0.jar">
+            <sha256 value="d914e52079c41509cde32d8fa03b5a865d8a227867ed6fd5d8121639518d28a1" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="java-composer-1.0.pom">
+            <sha256 value="741a35966a3055c80c10631736c6cfec82d7b5e4212b3f72ded29f98935bbb5e" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
+      <component group="jakarta.inject" name="jakarta.inject-api" version="2.0.1">
+         <artifact name="jakarta.inject-api-2.0.1.jar">
+            <sha256 value="f7dc98062fccf14126abb751b64fab12c312566e8cbdc8483598bffcea93af7c" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="jakarta.inject-api-2.0.1.pom">
+            <sha256 value="e7fd7232e96307a575b2494c9367d68cf43ec98244aace3ccc23e1773ffa6fda" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="jakarta.platform" name="jakarta.jakartaee-bom" version="9.1.0">
          <artifact name="jakarta.jakartaee-bom-9.1.0.pom">
             <sha256 value="df98e0266219fdbb82562826d79a3a20776a8ba02aa787f0f0765a538654c8a4" origin="Generated by Gradle"/>
@@ -1492,6 +1548,9 @@
          <artifact name="apiguardian-api-1.1.2.module">
             <sha256 value="e08028131375b357d1d28734e9a4fb4216da84b240641cb3ef7e7c7d628223fc" origin="Generated by Gradle"/>
          </artifact>
+         <artifact name="apiguardian-api-1.1.2.pom">
+            <sha256 value="32355081d109095c3d5d374d5a43b4f4c1b75d549e983ef50723e2772e5302a0" origin="Generated by Gradle"/>
+         </artifact>
       </component>
       <component group="org.checkerframework" name="checker-qual" version="2.10.0">
          <artifact name="checker-qual-2.10.0.jar">
@@ -1505,6 +1564,9 @@
          <artifact name="checker-qual-3.19.0.module">
             <sha256 value="53e1899dde3c513ca1efd376abffac0e6907e8e84abd5f966242634c95e4d157" origin="Generated by Gradle"/>
          </artifact>
+         <artifact name="checker-qual-3.19.0.pom">
+            <sha256 value="29ba9c5ce1a94b700bd823c4ed612f5827b590f19a49775fd7eb8f997f8aa371" origin="Generated by Gradle"/>
+         </artifact>
       </component>
       <component group="org.checkerframework" name="checker-qual" version="3.33.0">
          <artifact name="checker-qual-3.33.0.jar">
@@ -1601,6 +1663,11 @@
             <sha256 value="5e583878df905b5f33a230ef690a52b8f19dab9cc892bedee069f3d8af4e960a" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.eclipse.ee4j" name="project" version="1.0.6">
+         <artifact name="project-1.0.6.pom">
+            <sha256 value="4e7d8329d8da7dcf30779d824241be145f27108932f5a5a24eb907677bc8d72d" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.eclipse.ee4j" name="project" version="1.0.7">
          <artifact name="project-1.0.7.pom">
             <sha256 value="205c039a42cbae3556efbeb04a483eb3a3cf9550bd75bf84260dc8f28218f105" origin="Generated by Gradle"/>
@@ -1758,6 +1825,14 @@
             <sha256 value="33b8c22f2424c2903241a7fea258fc41ab0c4d6889776576c519047562ee43a5" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.jspecify" name="jspecify" version="1.0.0">
+         <artifact name="jspecify-1.0.0.jar">
+            <sha256 value="1fad6e6be7557781e4d33729d49ae1cdc8fdda6fe477bb0cc68ce351eafdfbab" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="jspecify-1.0.0.module">
+            <sha256 value="d307ca77a54e18ac1ef1aaed4e5bbe014bd2f49f29e1d2f813e47c278283195b" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.junit" name="junit-bom" version="5.10.0">
          <artifact name="junit-bom-5.10.0.module">
             <sha256 value="eb3ee6127608010694a898056e7407d117296003aba5f5db801df430b9887fcf" origin="Generated by Gradle"/>
@@ -2082,6 +2157,25 @@
             <sha256 value="b68149d290f328b6b54d0f7f7d304adab5148cedd6ae18dc3baae8bf9f1757c6" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.spongepowered" name="event-impl-gen" version="8.0.0">
+         <artifact name="event-impl-gen-8.0.0.jar">
+            <sha256 value="6e26ff9a8d9f5a9fe39fe3e64781061bf068405c04095d78c044719ac2918992" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="event-impl-gen-8.0.0.module">
+            <sha256 value="5b919469a6bead6b6107212e4bf441c7576fc52f0b590db4bc13f742ebbfd983" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
+      <component group="org.spongepowered" name="event-impl-gen-annotations" version="8.0.0">
+         <artifact name="event-impl-gen-annotations-8.0.0-javadoc.jar">
+            <sha256 value="6f4b8d62436da73bedb9baf543180f5068e99b77d38f15fbd463d4df7251d4d9" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="event-impl-gen-annotations-8.0.0.jar">
+            <sha256 value="278e01efedb92a95be74714ea2bec08d29326b4893f6e957aa3bd39a15840776" origin="Generated by Gradle"/>
+         </artifact>
+         <artifact name="event-impl-gen-annotations-8.0.0.module">
+            <sha256 value="b0fddddd441038c0889450e8c0ebac970f0d606b246db99fd59c23c73e7ba534" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.spongepowered" name="math" version="2.0.1">
          <artifact name="math-2.0.1-javadoc.jar">
             <sha256 value="eef4d1e6421cd975ebdb7ae6be8632c0e89c0e8b671ee0fb542d8e6ddad2df12" origin="Generated by Gradle"/>
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 9007387b615..f27804704dc 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -13,6 +13,9 @@ plugins {
 }
 
 dependencyResolutionManagement {
+    repositories {
+        mavenLocal()
+    }
     repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
     pluginManagement.repositories.forEach(repositories::add)
 }
diff --git a/src/main/java/org/spongepowered/api/data/DataManipulator.java b/src/main/java/org/spongepowered/api/data/DataManipulator.java
index 05254bc457e..e70aba2b527 100644
--- a/src/main/java/org/spongepowered/api/data/DataManipulator.java
+++ b/src/main/java/org/spongepowered/api/data/DataManipulator.java
@@ -30,8 +30,8 @@
 import org.spongepowered.api.data.value.Value;
 import org.spongepowered.api.data.value.ValueContainer;
 import org.spongepowered.api.entity.Entity;
-import org.spongepowered.api.util.annotation.eventgen.TransformWith;
 import org.spongepowered.api.world.World;
+import org.spongepowered.eventgen.annotations.TransformWith;
 
 import java.util.Arrays;
 import java.util.Objects;
diff --git a/src/main/java/org/spongepowered/api/event/Cancellable.java b/src/main/java/org/spongepowered/api/event/Cancellable.java
index 7a5b5bd7bd7..2ad6bc82887 100644
--- a/src/main/java/org/spongepowered/api/event/Cancellable.java
+++ b/src/main/java/org/spongepowered/api/event/Cancellable.java
@@ -24,7 +24,7 @@
  */
 package org.spongepowered.api.event;
 
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 /**
  * Represents an event that can be cancelled.
diff --git a/src/main/java/org/spongepowered/api/event/Cause.java b/src/main/java/org/spongepowered/api/event/Cause.java
index ede6a617623..a1b42f7f59c 100644
--- a/src/main/java/org/spongepowered/api/event/Cause.java
+++ b/src/main/java/org/spongepowered/api/event/Cause.java
@@ -27,6 +27,7 @@
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.spongepowered.api.util.CopyableBuilder;
 import org.spongepowered.api.util.annotation.DoNotStore;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -54,6 +55,7 @@
  */
 @DoNotStore
 @SuppressWarnings("unchecked")
+@NoFactoryMethod
 public final class Cause implements Iterable<Object> {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/CompositeEvent.java b/src/main/java/org/spongepowered/api/event/CompositeEvent.java
new file mode 100644
index 00000000000..5fa4a10819a
--- /dev/null
+++ b/src/main/java/org/spongepowered/api/event/CompositeEvent.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of SpongeAPI, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) SpongePowered <https://www.spongepowered.org>
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.spongepowered.api.event;
+
+import org.spongepowered.api.event.impl.AbstractCompositeEvent;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.PropertySettings;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * A {@link CompositeEvent} is an {@link Event} that contains multiple
+ * side effectual {@link Event Events}, which may have their own side effects
+ * and may be {@link Cancellable}. In some cases, the interactions of this event
+ * may be cancellable as a whole, but are not guaranteed to revert all side
+ * effects on the {@link org.spongepowered.api.Game}. The {@link #children()} of
+ * this event are ordered in a "best-effort" basis, and may not be guaranteed
+ * to be in any particular order.
+ * <p>Using {@link #setCancelled(boolean)} will perform a best effort cancellation
+ * on each of the children events.
+ */
+@GenerateFactoryMethod
+@ImplementedBy(AbstractCompositeEvent.class)
+public interface CompositeEvent<E extends Event> extends Event, Cancellable {
+
+    @PropertySettings(useInToString = false)
+    E baseEvent();
+
+    List<Event> children();
+
+    default <A extends Event> List<? extends A> event(Class<A> type) {
+        return this.children().stream()
+            .filter(type::isInstance)
+            .map(type::cast)
+            .toList();
+    }
+
+    default <A extends Event> void applyTo(Class<A> type, Consumer<? super A> consumer) {
+        this.children().stream()
+            .filter(type::isInstance)
+            .map(type::cast)
+            .forEach(consumer);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Cancels this event and all related events captured {@link #children()}.
+     * Selectively, if individual events are wished to be cancelled,
+     * the individual events should be cancelled instead.
+     *
+     * @param cancel The new cancelled state
+     */
+    @PropertySettings(generateMethods = false)
+    @Override
+    void setCancelled(boolean cancel);
+}
diff --git a/src/main/java/org/spongepowered/api/event/Event.java b/src/main/java/org/spongepowered/api/event/Event.java
index 9496098700f..bcf481f4987 100644
--- a/src/main/java/org/spongepowered/api/event/Event.java
+++ b/src/main/java/org/spongepowered/api/event/Event.java
@@ -26,8 +26,8 @@
 
 import org.spongepowered.api.event.impl.AbstractEvent;
 import org.spongepowered.api.util.annotation.DoNotStore;
-import org.spongepowered.api.util.annotation.eventgen.AbsoluteSortPosition;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
+import org.spongepowered.eventgen.annotations.AbsoluteSortPosition;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
 
 /**
  * An event called within Sponge.
diff --git a/src/main/java/org/spongepowered/api/event/EventContext.java b/src/main/java/org/spongepowered/api/event/EventContext.java
index 645f1f66912..96aa907de4d 100644
--- a/src/main/java/org/spongepowered/api/event/EventContext.java
+++ b/src/main/java/org/spongepowered/api/event/EventContext.java
@@ -27,6 +27,7 @@
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.spongepowered.api.util.CopyableBuilder;
 import org.spongepowered.api.util.annotation.DoNotStore;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -42,6 +43,7 @@
  * in the event's {@link Cause}.
  */
 @DoNotStore
+@NoFactoryMethod
 public final class EventContext {
 
     private static final EventContext EMPTY_CONTEXT = new EventContext(Map.of());
diff --git a/src/main/java/org/spongepowered/api/event/EventContextKeys.java b/src/main/java/org/spongepowered/api/event/EventContextKeys.java
index a8019aafd34..17df7c6cb0f 100644
--- a/src/main/java/org/spongepowered/api/event/EventContextKeys.java
+++ b/src/main/java/org/spongepowered/api/event/EventContextKeys.java
@@ -53,6 +53,7 @@
 import org.spongepowered.api.world.portal.PortalLogic;
 import org.spongepowered.api.world.server.ServerLocation;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 import org.spongepowered.math.vector.Vector3d;
 import org.spongepowered.plugin.PluginContainer;
 
@@ -62,6 +63,7 @@
  * Standard keys for use within {@link EventContext}s.
  */
 @SuppressWarnings("unused")
+@NoFactoryMethod
 public final class EventContextKeys {
 
     // @formatter:off
diff --git a/src/main/java/org/spongepowered/api/event/Listener.java b/src/main/java/org/spongepowered/api/event/Listener.java
index 776dcb0d1c3..2873fd2e5aa 100644
--- a/src/main/java/org/spongepowered/api/event/Listener.java
+++ b/src/main/java/org/spongepowered/api/event/Listener.java
@@ -24,6 +24,8 @@
  */
 package org.spongepowered.api.event;
 
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -34,6 +36,7 @@
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
+@NoFactoryMethod
 public @interface Listener {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/action/CollideEvent.java b/src/main/java/org/spongepowered/api/event/action/CollideEvent.java
index 30404ad787f..31dae13241d 100644
--- a/src/main/java/org/spongepowered/api/event/action/CollideEvent.java
+++ b/src/main/java/org/spongepowered/api/event/action/CollideEvent.java
@@ -28,8 +28,8 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 import org.spongepowered.api.world.server.ServerLocation;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Fired when an {@link Entity} or {@link BlockSnapshot} collide with each other.
diff --git a/src/main/java/org/spongepowered/api/event/action/InteractEvent.java b/src/main/java/org/spongepowered/api/event/action/InteractEvent.java
index e3f3f889130..4f4ea4a3528 100644
--- a/src/main/java/org/spongepowered/api/event/action/InteractEvent.java
+++ b/src/main/java/org/spongepowered/api/event/action/InteractEvent.java
@@ -25,10 +25,12 @@
 package org.spongepowered.api.event.action;
 
 import org.spongepowered.api.event.Event;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Base event for all interactions.
  */
+@NoFactoryMethod
 public interface InteractEvent extends Event {
 
 }
diff --git a/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java b/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java
index 161452c8bdf..0f4e6e44f66 100644
--- a/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java
+++ b/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java
@@ -29,11 +29,15 @@
 import org.spongepowered.api.block.BlockTypes;
 import org.spongepowered.api.entity.living.player.Player;
 import org.spongepowered.api.event.Cancellable;
+import org.spongepowered.api.event.CompositeEvent;
 import org.spongepowered.api.event.action.InteractEvent;
+import org.spongepowered.api.event.impl.AbstractCompositeEvent;
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.util.Direction;
 import org.spongepowered.api.util.Tristate;
 import org.spongepowered.api.world.server.ServerLocation;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
 import org.spongepowered.math.vector.Vector3d;
 
 /**
@@ -101,7 +105,8 @@ interface Finish extends Primary, Cancellable {
      *
      * <p>This is usually right-click.</p>
      */
-    interface Secondary extends InteractBlockEvent, Cancellable {
+    @GenerateFactoryMethod
+    interface Secondary extends InteractBlockEvent {
 
         Tristate originalUseItemResult();
 
@@ -143,43 +148,86 @@ interface Secondary extends InteractBlockEvent, Cancellable {
          */
         Tristate useBlockResult();
 
-        /**
-         * Sets whether the {@link Player#itemInHand} should be used.
-         *
-         * <ul>
-         * <li>FALSE: The {@link ItemStack} will never be used.</li>
-         * <li>UNDEFINED: The {@link ItemStack} will be used if the block fails.
-         * </li>
-         * <li>TRUE: The {@link ItemStack} will always be used.</li>
-         * </ul>
-         *
-         * <p>Note: These results may differ depending on implementation.</p>
-         *
-         * @param result Whether the {@link Player#itemInHand} should be used
-         */
-        void setUseItemResult(Tristate result);
-
-        /**
-         * Sets whether the interacted {@link BlockSnapshot} should be used.
-         *
-         * <ul>
-         * <li>FALSE: {@link BlockSnapshot} will never be used.</li>
-         * <li>UNDEFINED: {@link BlockSnapshot} will be used as normal.</li>
-         * <li>TRUE: {@link BlockSnapshot} will always be used.</li>
-         * </ul>
-         *
-         * <p>Note: These results may differ depending on implementation.</p>
-         *
-         * @param result Whether the interacted {@link BlockSnapshot} should be
-         *     used
-         */
-        void setUseBlockResult(Tristate result);
-
         /**
          * Gets the point of interaction where the interaction occurred as a {@link Vector3d}.
          *
          * @return The interaction point
          */
         Vector3d interactionPoint();
+
+        interface Pre extends Secondary, Cancellable {
+
+            /**
+             * Sets whether the {@link Player#itemInHand} should be used.
+             *
+             * <ul>
+             * <li>FALSE: The {@link ItemStack} will never be used.</li>
+             * <li>UNDEFINED: The {@link ItemStack} will be used if the block fails.
+             * </li>
+             * <li>TRUE: The {@link ItemStack} will always be used.</li>
+             * </ul>
+             *
+             * <p>Note: These results may differ depending on implementation.</p>
+             *
+             * @param result Whether the {@link Player#itemInHand} should be used
+             */
+            void setUseItemResult(Tristate result);
+
+            /**
+             * Sets whether the interacted {@link BlockSnapshot} should be used.
+             *
+             * <ul>
+             * <li>FALSE: {@link BlockSnapshot} will never be used.</li>
+             * <li>UNDEFINED: {@link BlockSnapshot} will be used as normal.</li>
+             * <li>TRUE: {@link BlockSnapshot} will always be used.</li>
+             * </ul>
+             *
+             * <p>Note: These results may differ depending on implementation.</p>
+             *
+             * @param result Whether the interacted {@link BlockSnapshot} should be
+             *     used
+             */
+            void setUseBlockResult(Tristate result);
+        }
+
+        @ImplementedBy(AbstractCompositeEvent.class)
+        interface Post extends Secondary, CompositeEvent<Secondary> {
+
+            @Override
+            default Tristate originalUseItemResult() {
+                return this.baseEvent().originalUseItemResult();
+            }
+
+            @Override
+            default Tristate originalUseBlockResult() {
+                return this.baseEvent().originalUseBlockResult();
+            }
+
+            @Override
+            default Tristate useItemResult() {
+                return this.baseEvent().useItemResult();
+            }
+
+            @Override
+            default Tristate useBlockResult() {
+                return this.baseEvent().useBlockResult();
+            }
+
+            @Override
+            default Vector3d interactionPoint() {
+                return this.baseEvent().interactionPoint();
+            }
+
+            @Override
+            default BlockSnapshot block() {
+                return this.baseEvent().block();
+            }
+
+            @Override
+            default Direction targetSide() {
+                return this.baseEvent().targetSide();
+            }
+        }
+
     }
 }
diff --git a/src/main/java/org/spongepowered/api/event/block/ScheduleBlockUpdateEvent.java b/src/main/java/org/spongepowered/api/event/block/ScheduleBlockUpdateEvent.java
index ac3fb5f7823..0b4a5f748bd 100644
--- a/src/main/java/org/spongepowered/api/event/block/ScheduleBlockUpdateEvent.java
+++ b/src/main/java/org/spongepowered/api/event/block/ScheduleBlockUpdateEvent.java
@@ -37,7 +37,7 @@
  * Fired when a {@link ScheduledUpdate scheduled block update}
  * is being proposed to the engine.
  */
-public interface ScheduleBlockUpdateEvent<T extends Object> extends GenericEvent<T>, Cancellable {
+public interface ScheduleBlockUpdateEvent<T> extends GenericEvent<T>, Cancellable {
 
     /**
      * Gets a list of the {@link ScheduleUpdateTicket}s for this event.
diff --git a/src/main/java/org/spongepowered/api/event/cause/entity/damage/package-info.java b/src/main/java/org/spongepowered/api/event/cause/entity/damage/package-info.java
index 854a642a92d..b8d89392421 100644
--- a/src/main/java/org/spongepowered/api/event/cause/entity/damage/package-info.java
+++ b/src/main/java/org/spongepowered/api/event/cause/entity/damage/package-info.java
@@ -22,5 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
+@DefaultQualifier(NonNull.class)
 package org.spongepowered.api.event.cause.entity.damage;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/org/spongepowered/api/event/cause/entity/damage/source/package-info.java b/src/main/java/org/spongepowered/api/event/cause/entity/damage/source/package-info.java
index 2259174ac8f..2385f8466a9 100644
--- a/src/main/java/org/spongepowered/api/event/cause/entity/damage/source/package-info.java
+++ b/src/main/java/org/spongepowered/api/event/cause/entity/damage/source/package-info.java
@@ -22,5 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
+@DefaultQualifier(NonNull.class)
 package org.spongepowered.api.event.cause.entity.damage.source;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/org/spongepowered/api/event/cause/entity/package-info.java b/src/main/java/org/spongepowered/api/event/cause/entity/package-info.java
index 88639e98bbc..cb3fa67ca4c 100644
--- a/src/main/java/org/spongepowered/api/event/cause/entity/package-info.java
+++ b/src/main/java/org/spongepowered/api/event/cause/entity/package-info.java
@@ -22,5 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
+@DefaultQualifier(NonNull.class)
 package org.spongepowered.api.event.cause.entity;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/org/spongepowered/api/event/cause/package-info.java b/src/main/java/org/spongepowered/api/event/cause/package-info.java
index d4759eac38c..15dada1c460 100644
--- a/src/main/java/org/spongepowered/api/event/cause/package-info.java
+++ b/src/main/java/org/spongepowered/api/event/cause/package-info.java
@@ -22,5 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
+@DefaultQualifier(NonNull.class)
 package org.spongepowered.api.event.cause;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/org/spongepowered/api/event/data/ChangeDataHolderEvent.java b/src/main/java/org/spongepowered/api/event/data/ChangeDataHolderEvent.java
index fe6c156a31f..31de1e88d1e 100644
--- a/src/main/java/org/spongepowered/api/event/data/ChangeDataHolderEvent.java
+++ b/src/main/java/org/spongepowered/api/event/data/ChangeDataHolderEvent.java
@@ -30,8 +30,8 @@
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.event.impl.data.AbstractValueChangeEvent;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 /**
  * An event that is associated with a {@link org.spongepowered.api.data.DataHolder.Mutable} that may have some
diff --git a/src/main/java/org/spongepowered/api/event/entity/AffectEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/AffectEntityEvent.java
index a099ee8114e..b18526af11a 100644
--- a/src/main/java/org/spongepowered/api/event/entity/AffectEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/AffectEntityEvent.java
@@ -30,10 +30,11 @@
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.event.Order;
 import org.spongepowered.api.event.impl.entity.AbstractAffectEntityEvent;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
 import org.spongepowered.api.world.explosion.Explosion;
 import org.spongepowered.api.world.server.ServerLocation;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 import java.util.List;
 import java.util.function.Predicate;
@@ -48,6 +49,7 @@
  * Other cases will be included as necessary.
  */
 @ImplementedBy(AbstractAffectEntityEvent.class)
+@NoFactoryMethod
 public interface AffectEntityEvent extends Event, Cancellable {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/entity/AttackEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/AttackEntityEvent.java
index 208f68a4108..730037117d8 100644
--- a/src/main/java/org/spongepowered/api/event/entity/AttackEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/AttackEntityEvent.java
@@ -45,11 +45,11 @@
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
 import org.spongepowered.api.util.Tuple;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
 import org.spongepowered.api.world.World;
 import org.spongepowered.api.world.difficulty.Difficulties;
 import org.spongepowered.api.world.difficulty.Difficulty;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 import java.util.List;
 import java.util.Map;
diff --git a/src/main/java/org/spongepowered/api/event/entity/ChangeEntityEquipmentEvent.java b/src/main/java/org/spongepowered/api/event/entity/ChangeEntityEquipmentEvent.java
index 6ee0f580e9f..0a5885e7f09 100644
--- a/src/main/java/org/spongepowered/api/event/entity/ChangeEntityEquipmentEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/ChangeEntityEquipmentEvent.java
@@ -32,7 +32,7 @@
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
 import org.spongepowered.api.item.inventory.Slot;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Called when an entity changes an equipped item. This can occur whenever
diff --git a/src/main/java/org/spongepowered/api/event/entity/ChangeEntityWorldEvent.java b/src/main/java/org/spongepowered/api/event/entity/ChangeEntityWorldEvent.java
index 2cb09c213fe..55ced7a4acf 100644
--- a/src/main/java/org/spongepowered/api/event/entity/ChangeEntityWorldEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/ChangeEntityWorldEvent.java
@@ -27,8 +27,8 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.AbsoluteSortPosition;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.AbsoluteSortPosition;
 
 /**
  * Called when an {@link Entity} is changing {@link ServerWorld worlds}.
diff --git a/src/main/java/org/spongepowered/api/event/entity/CollideEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/CollideEntityEvent.java
index 5668e895be3..6b36c2c40af 100644
--- a/src/main/java/org/spongepowered/api/event/entity/CollideEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/CollideEntityEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.action.CollideEvent;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Fired when an {@link Entity} collides with one or more {@link Entity}'s.
diff --git a/src/main/java/org/spongepowered/api/event/entity/DamageEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/DamageEntityEvent.java
index 990a05a1deb..5854bdcc909 100644
--- a/src/main/java/org/spongepowered/api/event/entity/DamageEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/DamageEntityEvent.java
@@ -42,11 +42,11 @@
 import org.spongepowered.api.item.ItemTypes;
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.util.Tuple;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
 import org.spongepowered.api.world.World;
 import org.spongepowered.api.world.difficulty.Difficulties;
 import org.spongepowered.api.world.difficulty.Difficulty;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 import java.util.List;
 import java.util.Map;
diff --git a/src/main/java/org/spongepowered/api/event/entity/DestructEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/DestructEntityEvent.java
index 192cbdb8c44..853ba04ef86 100644
--- a/src/main/java/org/spongepowered/api/event/entity/DestructEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/DestructEntityEvent.java
@@ -29,8 +29,8 @@
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.message.AudienceMessageEvent;
 import org.spongepowered.api.event.message.MessageCancellable;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
 import org.spongepowered.api.world.gamerule.GameRules;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * An event where the {@link Entity} is being either removed usually due to
diff --git a/src/main/java/org/spongepowered/api/event/entity/ExpireEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/ExpireEntityEvent.java
index 9cb96bc2a7d..a9f265eb765 100644
--- a/src/main/java/org/spongepowered/api/event/entity/ExpireEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/ExpireEntityEvent.java
@@ -28,7 +28,7 @@
 import org.spongepowered.api.entity.living.monster.Endermite;
 import org.spongepowered.api.entity.weather.LightningBolt;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Called when an {@link Entity} is expiring from the world. Examples may
diff --git a/src/main/java/org/spongepowered/api/event/entity/HarvestEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/HarvestEntityEvent.java
index e2feb2fe8d8..3bbb689d414 100644
--- a/src/main/java/org/spongepowered/api/event/entity/HarvestEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/HarvestEntityEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Called when an {@link Entity} has been killed and is being "harvested" (drops/etc). Happens
diff --git a/src/main/java/org/spongepowered/api/event/entity/InvokePortalEvent.java b/src/main/java/org/spongepowered/api/event/entity/InvokePortalEvent.java
index e71bea00bec..e2e27b0a743 100644
--- a/src/main/java/org/spongepowered/api/event/entity/InvokePortalEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/InvokePortalEvent.java
@@ -27,9 +27,10 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.AbsoluteSortPosition;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 import org.spongepowered.api.world.portal.PortalLogic;
+import org.spongepowered.eventgen.annotations.AbsoluteSortPosition;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 import org.spongepowered.math.vector.Vector3d;
 
 import java.util.Optional;
@@ -59,6 +60,7 @@ public interface InvokePortalEvent extends Event {
      * Called when entering a portal.
      * Cancel to prevent portal effects.
      */
+    @GenerateFactoryMethod
     interface Enter extends InvokePortalEvent, Cancellable {
 
         /**
@@ -88,6 +90,7 @@ interface Enter extends InvokePortalEvent, Cancellable {
      * Canceling resets the portal transition time
      * Setting custom portal logic can change the teleport behaviour.
      */
+    @GenerateFactoryMethod
     interface Prepare extends InvokePortalEvent, Cancellable {
 
         /**
@@ -102,6 +105,7 @@ interface Prepare extends InvokePortalEvent, Cancellable {
      * Called after a {@link PortalLogic} calculated and found or generated the portal exit.
      * Note that {@link ChangeEntityWorldEvent} still fire after this.
      */
+    @GenerateFactoryMethod
     interface Execute extends InvokePortalEvent, ChangeEntityWorldEvent.Reposition, RotateEntityEvent {
 
         /**
diff --git a/src/main/java/org/spongepowered/api/event/entity/MoveEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/MoveEntityEvent.java
index bed41167130..5a550c5cabd 100644
--- a/src/main/java/org/spongepowered/api/event/entity/MoveEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/MoveEntityEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.AbsoluteSortPosition;
+import org.spongepowered.eventgen.annotations.AbsoluteSortPosition;
 import org.spongepowered.math.vector.Vector3d;
 
 /**
diff --git a/src/main/java/org/spongepowered/api/event/entity/RotateEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/RotateEntityEvent.java
index 007007ef281..f245eef5c8c 100644
--- a/src/main/java/org/spongepowered/api/event/entity/RotateEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/RotateEntityEvent.java
@@ -27,8 +27,8 @@
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.AbsoluteSortPosition;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.AbsoluteSortPosition;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 import org.spongepowered.math.vector.Vector3d;
 
 /**
diff --git a/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java
index f459b856f79..8ead9621984 100644
--- a/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java
@@ -26,9 +26,10 @@
 
 import org.spongepowered.api.entity.Entity;
 import org.spongepowered.api.event.Cause;
+import org.spongepowered.api.event.impl.entity.AbstractAffectEntityEvent;
 import org.spongepowered.api.event.impl.entity.AbstractSpawnEntityEvent;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
 
 /**
  * Raised when an {@link Entity} is spawned. This usually follows the chain of
@@ -51,7 +52,8 @@ public interface SpawnEntityEvent extends AffectEntityEvent {
      * will result in no awareness to the client that the entity was being
      * spawned and later cancelled.
      */
-    interface Pre extends SpawnEntityEvent {}
+    @ImplementedBy(value = AbstractAffectEntityEvent.class, priority = 2)
+    interface Pre extends AffectEntityEvent {}
 
     interface Custom extends SpawnEntityEvent {}
 }
diff --git a/src/main/java/org/spongepowered/api/event/entity/ai/goal/GoalEvent.java b/src/main/java/org/spongepowered/api/event/entity/ai/goal/GoalEvent.java
index 0d14efda4ac..0e9758a6f34 100644
--- a/src/main/java/org/spongepowered/api/event/entity/ai/goal/GoalEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/ai/goal/GoalEvent.java
@@ -30,7 +30,7 @@
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.event.impl.entity.ai.goal.AbstractGoalEvent;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
 
 @ImplementedBy(AbstractGoalEvent.class)
 public interface GoalEvent extends Event, Cancellable {
diff --git a/src/main/java/org/spongepowered/api/event/entity/living/player/ResourcePackStatusEvent.java b/src/main/java/org/spongepowered/api/event/entity/living/player/ResourcePackStatusEvent.java
index 5502c27384d..7dc4e4f27ba 100644
--- a/src/main/java/org/spongepowered/api/event/entity/living/player/ResourcePackStatusEvent.java
+++ b/src/main/java/org/spongepowered/api/event/entity/living/player/ResourcePackStatusEvent.java
@@ -31,7 +31,7 @@
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.network.ServerSideConnection;
 import org.spongepowered.api.profile.GameProfile;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 import java.util.Optional;
 
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/ImplementedBy.java b/src/main/java/org/spongepowered/api/event/impl/AbstractCompositeEvent.java
similarity index 56%
rename from src/main/java/org/spongepowered/api/util/annotation/eventgen/ImplementedBy.java
rename to src/main/java/org/spongepowered/api/event/impl/AbstractCompositeEvent.java
index a9d133ba950..cc4389429f8 100644
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/ImplementedBy.java
+++ b/src/main/java/org/spongepowered/api/event/impl/AbstractCompositeEvent.java
@@ -22,38 +22,38 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-package org.spongepowered.api.util.annotation.eventgen;
+package org.spongepowered.api.event.impl;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import org.spongepowered.api.event.Cancellable;
+import org.spongepowered.api.event.CompositeEvent;
+import org.spongepowered.api.event.Event;
+import org.spongepowered.eventgen.annotations.UseField;
 
-/**
- * Used to indicate the base class that a generated event class extends from.
- */
-@Inherited
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ImplementedBy {
-
-    /**
-     * Gets the class which serves as the base class which the generated class
-     * for this event interface will extend.
-     *
-     * @return The base class to use
-     */
-    Class<?> value();
-
-    /**
-     * Gets the priority for this annotation, relative to other annotations in
-     * the same hierarchy of the event interface.
-     *
-     * <p>The annotation with the highest priority will be used.</p>
-     *
-     * @return The priority to use
-     */
-    int priority() default 1;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class AbstractCompositeEvent<E extends Event> extends AbstractEvent implements CompositeEvent<E> {
+
+    @UseField
+    protected E baseEvent;
+
+    @UseField(overrideToString = true)
+    protected List<Event> children;
+
+    @UseField
+    protected boolean cancelled;
+
+    public final void postInit() {
+        this.children = Collections.unmodifiableList(this.children);
+    }
 
+    @Override
+    public void setCancelled(boolean cancel) {
+        this.cancelled = cancel;
+        this.children().forEach(event -> {
+            if (event instanceof Cancellable cancellable) {
+                cancellable.setCancelled(cancel);
+            }
+        });
+    }
 }
diff --git a/src/main/java/org/spongepowered/api/event/impl/data/AbstractValueChangeEvent.java b/src/main/java/org/spongepowered/api/event/impl/data/AbstractValueChangeEvent.java
index 34292304fcf..a19d1081fb2 100644
--- a/src/main/java/org/spongepowered/api/event/impl/data/AbstractValueChangeEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/data/AbstractValueChangeEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.data.DataTransactionResult;
 import org.spongepowered.api.event.data.ChangeDataHolderEvent;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
+import org.spongepowered.eventgen.annotations.UseField;
 
 public abstract class AbstractValueChangeEvent implements ChangeDataHolderEvent.ValueChange {
 
diff --git a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAffectEntityEvent.java b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAffectEntityEvent.java
index 7504abafd55..a6b4d36638c 100644
--- a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAffectEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAffectEntityEvent.java
@@ -29,7 +29,7 @@
 import org.spongepowered.api.event.Order;
 import org.spongepowered.api.event.entity.AffectEntityEvent;
 import org.spongepowered.api.event.impl.AbstractEvent;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
+import org.spongepowered.eventgen.annotations.UseField;
 
 import java.util.Collections;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAttackEntityEvent.java b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAttackEntityEvent.java
index 6d8531e060a..d8f63462257 100644
--- a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAttackEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractAttackEntityEvent.java
@@ -30,7 +30,7 @@
 import org.spongepowered.api.event.cause.entity.damage.ModifierFunction;
 import org.spongepowered.api.event.entity.AttackEntityEvent;
 import org.spongepowered.api.util.Tuple;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
+import org.spongepowered.eventgen.annotations.UseField;
 
 import java.util.Iterator;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractChangeEntityEquipmentEvent.java b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractChangeEntityEquipmentEvent.java
index 20e52426b5d..b1bfdea3ddc 100644
--- a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractChangeEntityEquipmentEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractChangeEntityEquipmentEvent.java
@@ -28,7 +28,7 @@
 import org.spongepowered.api.event.entity.ChangeEntityEquipmentEvent;
 import org.spongepowered.api.event.impl.AbstractEvent;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
+import org.spongepowered.eventgen.annotations.UseField;
 
 public abstract class AbstractChangeEntityEquipmentEvent extends AbstractEvent implements ChangeEntityEquipmentEvent {
 
diff --git a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractDamageEntityEvent.java b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractDamageEntityEvent.java
index 598d34e222e..55377efb27b 100644
--- a/src/main/java/org/spongepowered/api/event/impl/entity/AbstractDamageEntityEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/entity/AbstractDamageEntityEvent.java
@@ -31,7 +31,7 @@
 import org.spongepowered.api.event.cause.entity.damage.ModifierFunction;
 import org.spongepowered.api.event.entity.DamageEntityEvent;
 import org.spongepowered.api.util.Tuple;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
+import org.spongepowered.eventgen.annotations.UseField;
 
 import java.util.Iterator;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/impl/world/AbstractDetonateEvent.java b/src/main/java/org/spongepowered/api/event/impl/world/AbstractDetonateEvent.java
index 2227b7b165e..e88affc0d6f 100644
--- a/src/main/java/org/spongepowered/api/event/impl/world/AbstractDetonateEvent.java
+++ b/src/main/java/org/spongepowered/api/event/impl/world/AbstractDetonateEvent.java
@@ -26,8 +26,8 @@
 
 import org.spongepowered.api.event.impl.entity.AbstractAffectEntityEvent;
 import org.spongepowered.api.event.world.ExplosionEvent;
-import org.spongepowered.api.util.annotation.eventgen.UseField;
 import org.spongepowered.api.world.server.ServerLocation;
+import org.spongepowered.eventgen.annotations.UseField;
 
 import java.util.Collections;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/item/inventory/AffectItemStackEvent.java b/src/main/java/org/spongepowered/api/event/item/inventory/AffectItemStackEvent.java
index 6e46aafe463..a24e83a0b30 100644
--- a/src/main/java/org/spongepowered/api/event/item/inventory/AffectItemStackEvent.java
+++ b/src/main/java/org/spongepowered/api/event/item/inventory/AffectItemStackEvent.java
@@ -30,7 +30,7 @@
 import org.spongepowered.api.item.inventory.Inventory;
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/item/inventory/AffectSlotEvent.java b/src/main/java/org/spongepowered/api/event/item/inventory/AffectSlotEvent.java
index ab7d667fd58..197893a448b 100644
--- a/src/main/java/org/spongepowered/api/event/item/inventory/AffectSlotEvent.java
+++ b/src/main/java/org/spongepowered/api/event/item/inventory/AffectSlotEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.item.inventory.transaction.SlotTransaction;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/org/spongepowered/api/event/item/inventory/ChangeInventoryEvent.java b/src/main/java/org/spongepowered/api/event/item/inventory/ChangeInventoryEvent.java
index 0ba10845c86..2936292ea15 100644
--- a/src/main/java/org/spongepowered/api/event/item/inventory/ChangeInventoryEvent.java
+++ b/src/main/java/org/spongepowered/api/event/item/inventory/ChangeInventoryEvent.java
@@ -32,8 +32,8 @@
 import org.spongepowered.api.item.inventory.Inventory;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
 import org.spongepowered.api.item.inventory.Slot;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 import java.util.List;
 import java.util.Optional;
diff --git a/src/main/java/org/spongepowered/api/event/item/inventory/InteractItemEvent.java b/src/main/java/org/spongepowered/api/event/item/inventory/InteractItemEvent.java
index 74ede46988f..7a7c8c266ee 100644
--- a/src/main/java/org/spongepowered/api/event/item/inventory/InteractItemEvent.java
+++ b/src/main/java/org/spongepowered/api/event/item/inventory/InteractItemEvent.java
@@ -25,12 +25,14 @@
 package org.spongepowered.api.event.item.inventory;
 
 import org.spongepowered.api.event.Cancellable;
+import org.spongepowered.api.event.CompositeEvent;
 import org.spongepowered.api.event.action.InteractEvent;
 import org.spongepowered.api.event.block.InteractBlockEvent;
 import org.spongepowered.api.event.entity.InteractEntityEvent;
 import org.spongepowered.api.event.entity.living.AnimateHandEvent;
 import org.spongepowered.api.item.inventory.ItemStack;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Base event for all interactions with an {@link ItemStack} in hand.
@@ -64,5 +66,21 @@ interface Primary extends InteractItemEvent {
      *
      * <p>Vanilla minecraft does not call an event when interacting with an empty hand in air.</p>
      */
-    interface Secondary extends InteractItemEvent, Cancellable {}
+    @GenerateFactoryMethod
+    interface Secondary extends InteractItemEvent, Cancellable {
+
+        interface Pre extends Secondary {
+
+        }
+
+        interface Post extends CompositeEvent<Secondary>, Secondary {
+
+            @Override
+            default ItemStackSnapshot itemStack() {
+                return this.baseEvent().itemStack();
+            }
+
+        }
+
+    }
 }
diff --git a/src/main/java/org/spongepowered/api/event/item/inventory/UpdateAnvilEvent.java b/src/main/java/org/spongepowered/api/event/item/inventory/UpdateAnvilEvent.java
index 3f4f0986feb..98f865043b9 100644
--- a/src/main/java/org/spongepowered/api/event/item/inventory/UpdateAnvilEvent.java
+++ b/src/main/java/org/spongepowered/api/event/item/inventory/UpdateAnvilEvent.java
@@ -30,7 +30,7 @@
 import org.spongepowered.api.item.inventory.AnvilCost;
 import org.spongepowered.api.item.inventory.Inventory;
 import org.spongepowered.api.item.inventory.ItemStackSnapshot;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Fires whenever the left and right slots of an anvil are filled and a new result is computed.
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/ConstructPluginEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/ConstructPluginEvent.java
index dcdf4d33485..5befd25781b 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/ConstructPluginEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/ConstructPluginEvent.java
@@ -24,8 +24,10 @@
  */
 package org.spongepowered.api.event.lifecycle;
 
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 import org.spongepowered.plugin.PluginContainer;
 
+@GenerateFactoryMethod
 public interface ConstructPluginEvent extends LifecycleEvent {
 
     PluginContainer plugin();
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/EngineLifecycleEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/EngineLifecycleEvent.java
index 58cf05f64dd..a420393f18e 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/EngineLifecycleEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/EngineLifecycleEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.Engine;
 import org.spongepowered.api.event.GenericEvent;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 @NoFactoryMethod
 public interface EngineLifecycleEvent<E extends Engine> extends GenericEvent<E>, LifecycleEvent {
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/LifecycleEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/LifecycleEvent.java
index e76643aac7f..21df07bf922 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/LifecycleEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/LifecycleEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.Game;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * An event called during the lifetime (start to stop) of a
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/LoadedGameEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/LoadedGameEvent.java
index f68a02615ca..f7b31ccd64d 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/LoadedGameEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/LoadedGameEvent.java
@@ -25,11 +25,13 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Game;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Called when the implementation signals that all the aspects of the
  * {@link Game} have completed loading.
  */
+@GenerateFactoryMethod
 public interface LoadedGameEvent extends LifecycleEvent {
 
 }
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/ProvideServiceEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/ProvideServiceEvent.java
index bf449d52316..84e088cb051 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/ProvideServiceEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/ProvideServiceEvent.java
@@ -26,6 +26,7 @@
 
 import org.spongepowered.api.Engine;
 import org.spongepowered.api.event.GenericEvent;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.function.Supplier;
 
@@ -47,6 +48,7 @@
  *
  * @param <T> The service to provide.
  */
+@NoFactoryMethod
 public interface ProvideServiceEvent<T> extends GenericEvent<T>, LifecycleEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RefreshGameEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RefreshGameEvent.java
index 148585a47d8..6f06938d92b 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RefreshGameEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RefreshGameEvent.java
@@ -25,6 +25,7 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Game;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Fired when something within a {@link Game} triggers a refresh of
@@ -37,6 +38,7 @@
  *     plugin use.
  * </p>
  */
+@GenerateFactoryMethod
 public interface RefreshGameEvent extends LifecycleEvent {
 
 }
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterBuilderEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterBuilderEvent.java
index 5c027aa7ccb..e295e7e7b16 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterBuilderEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterBuilderEvent.java
@@ -26,9 +26,11 @@
 
 import org.spongepowered.api.registry.DuplicateRegistrationException;
 import org.spongepowered.api.util.Builder;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.function.Supplier;
 
+@NoFactoryMethod
 public interface RegisterBuilderEvent extends LifecycleEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterChannelEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterChannelEvent.java
index bb9e3d248be..8c8818ebd7d 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterChannelEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterChannelEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.ResourceKey;
 import org.spongepowered.api.network.channel.Channel;
 import org.spongepowered.api.registry.DuplicateRegistrationException;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Lifecycle event to indicate when network channels should be created and registered.
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterCommandEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterCommandEvent.java
index 1fbecd17c14..6640ffb14cf 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterCommandEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterCommandEvent.java
@@ -29,6 +29,7 @@
 import org.spongepowered.api.command.manager.CommandMapping;
 import org.spongepowered.api.command.registrar.CommandRegistrar;
 import org.spongepowered.api.event.GenericEvent;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 import org.spongepowered.plugin.PluginContainer;
 
 /**
@@ -60,6 +61,7 @@
  *
  * @param <C> The type of command that is being registered.
  */
+@NoFactoryMethod
 public interface RegisterCommandEvent<C> extends GenericEvent<C>, LifecycleEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataEvent.java
index 294f0620ffe..a34d4d9147b 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataEvent.java
@@ -26,7 +26,7 @@
 
 import org.spongepowered.api.data.DataManager;
 import org.spongepowered.api.data.DataRegistration;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Lifecycle event for registering custom {@link DataRegistration data} within the {@link DataManager}.
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataPackValueEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataPackValueEvent.java
index eb92a194c1a..3aaaff4c914 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataPackValueEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterDataPackValueEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.datapack.DataPackEntry;
 import org.spongepowered.api.datapack.DataPackType;
 import org.spongepowered.api.event.GenericEvent;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 @SuppressWarnings("rawtypes")
 @NoFactoryMethod
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterFactoryEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterFactoryEvent.java
index dab7e6222a9..c54152ea77d 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterFactoryEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterFactoryEvent.java
@@ -25,7 +25,9 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.registry.DuplicateRegistrationException;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
+@NoFactoryMethod
 public interface RegisterFactoryEvent extends LifecycleEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryEvent.java
index 562da7f2adc..85a176c7fde 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryEvent.java
@@ -30,10 +30,12 @@
 import org.spongepowered.api.registry.DuplicateRegistrationException;
 import org.spongepowered.api.registry.Registry;
 import org.spongepowered.api.registry.RegistryType;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.Map;
 import java.util.function.Supplier;
 
+@NoFactoryMethod
 public interface RegisterRegistryEvent extends LifecycleEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryValueEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryValueEvent.java
index d8129480980..c54883a67f1 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryValueEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/RegisterRegistryValueEvent.java
@@ -29,7 +29,9 @@
 import org.spongepowered.api.event.GenericEvent;
 import org.spongepowered.api.registry.DefaultedRegistryValue;
 import org.spongepowered.api.registry.RegistryType;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
+@NoFactoryMethod
 public interface RegisterRegistryValueEvent extends LifecycleEvent {
 
     <T> RegistryStep<T> registry(RegistryType<T> registryType);
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/StartedEngineEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/StartedEngineEvent.java
index d413aa6442b..35992a63577 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/StartedEngineEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/StartedEngineEvent.java
@@ -25,6 +25,8 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Engine;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
+@GenerateFactoryMethod
 public interface StartedEngineEvent<E extends Engine> extends EngineLifecycleEvent<E> {
 }
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/StartingEngineEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/StartingEngineEvent.java
index 4da26e16426..02556c6cd54 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/StartingEngineEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/StartingEngineEvent.java
@@ -25,6 +25,8 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Engine;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
+@GenerateFactoryMethod
 public interface StartingEngineEvent<E extends Engine> extends EngineLifecycleEvent<E> {
 }
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/StoppedGameEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/StoppedGameEvent.java
index 024fe1945b3..e1bf3f544a3 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/StoppedGameEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/StoppedGameEvent.java
@@ -25,6 +25,7 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Game;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * This event is called at the end of a {@link Game} instance, after the game's
@@ -38,6 +39,7 @@
  * <p>Most users will want to listen to {@link StoppingEngineEvent} instead, to
  * do operations tied to the lifecycle of one single engine.</p>
  */
+@GenerateFactoryMethod
 public interface StoppedGameEvent extends LifecycleEvent {
 
 }
diff --git a/src/main/java/org/spongepowered/api/event/lifecycle/StoppingEngineEvent.java b/src/main/java/org/spongepowered/api/event/lifecycle/StoppingEngineEvent.java
index 414579881a0..a57dbbe9ae4 100644
--- a/src/main/java/org/spongepowered/api/event/lifecycle/StoppingEngineEvent.java
+++ b/src/main/java/org/spongepowered/api/event/lifecycle/StoppingEngineEvent.java
@@ -25,6 +25,8 @@
 package org.spongepowered.api.event.lifecycle;
 
 import org.spongepowered.api.Engine;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
+@GenerateFactoryMethod
 public interface StoppingEngineEvent<E extends Engine> extends EngineLifecycleEvent<E> {
 }
diff --git a/src/main/java/org/spongepowered/api/event/message/AudienceMessageEvent.java b/src/main/java/org/spongepowered/api/event/message/AudienceMessageEvent.java
index 654f183e9e4..80ee098351c 100644
--- a/src/main/java/org/spongepowered/api/event/message/AudienceMessageEvent.java
+++ b/src/main/java/org/spongepowered/api/event/message/AudienceMessageEvent.java
@@ -28,7 +28,7 @@
 import net.kyori.adventure.text.Component;
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.spongepowered.api.adventure.Audiences;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.Optional;
 import java.util.function.Predicate;
diff --git a/src/main/java/org/spongepowered/api/event/message/MessageCancellable.java b/src/main/java/org/spongepowered/api/event/message/MessageCancellable.java
index 2ff2850ee4e..3f16ffeced2 100644
--- a/src/main/java/org/spongepowered/api/event/message/MessageCancellable.java
+++ b/src/main/java/org/spongepowered/api/event/message/MessageCancellable.java
@@ -25,7 +25,7 @@
 package org.spongepowered.api.event.message;
 
 import net.kyori.adventure.text.Component;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Represents an event whose message can be cancelled.
diff --git a/src/main/java/org/spongepowered/api/event/message/MessageEvent.java b/src/main/java/org/spongepowered/api/event/message/MessageEvent.java
index 814f3ecc458..389e160f54a 100644
--- a/src/main/java/org/spongepowered/api/event/message/MessageEvent.java
+++ b/src/main/java/org/spongepowered/api/event/message/MessageEvent.java
@@ -26,7 +26,7 @@
 
 import net.kyori.adventure.text.Component;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 /**
  * Describes events when a involving a {@link Component} message.
diff --git a/src/main/java/org/spongepowered/api/event/message/PlayerChatEvent.java b/src/main/java/org/spongepowered/api/event/message/PlayerChatEvent.java
index ff4ab709be0..2aa914a35e7 100644
--- a/src/main/java/org/spongepowered/api/event/message/PlayerChatEvent.java
+++ b/src/main/java/org/spongepowered/api/event/message/PlayerChatEvent.java
@@ -30,7 +30,6 @@
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Cause;
 import org.spongepowered.api.registry.RegistryReference;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 
 import java.util.Optional;
 import java.util.function.Predicate;
@@ -39,7 +38,6 @@
  * Fired when sending a chat message.
  * To modify the message use {@link Decorate}.
  */
-@NoFactoryMethod
 public interface PlayerChatEvent extends MessageEvent {
 
     /**
diff --git a/src/main/java/org/spongepowered/api/event/network/ServerSideConnectionEvent.java b/src/main/java/org/spongepowered/api/event/network/ServerSideConnectionEvent.java
index bbcc2e9bbee..e9fc2bb233c 100644
--- a/src/main/java/org/spongepowered/api/event/network/ServerSideConnectionEvent.java
+++ b/src/main/java/org/spongepowered/api/event/network/ServerSideConnectionEvent.java
@@ -39,9 +39,9 @@
 import org.spongepowered.api.profile.GameProfile;
 import org.spongepowered.api.service.ban.BanService;
 import org.spongepowered.api.service.whitelist.WhitelistService;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 import org.spongepowered.api.world.server.ServerLocation;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 import org.spongepowered.math.vector.Vector3d;
 
 import java.net.InetAddress;
diff --git a/src/main/java/org/spongepowered/api/event/package-info.java b/src/main/java/org/spongepowered/api/event/package-info.java
index 9d12180f851..e5d13b53794 100644
--- a/src/main/java/org/spongepowered/api/event/package-info.java
+++ b/src/main/java/org/spongepowered/api/event/package-info.java
@@ -22,5 +22,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
+@NoFactoryMethod(ignoreNested = true)
+@DefaultQualifier(NonNull.class)
 package org.spongepowered.api.event;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
diff --git a/src/main/java/org/spongepowered/api/event/server/ClientPingServerEvent.java b/src/main/java/org/spongepowered/api/event/server/ClientPingServerEvent.java
index 1181ae82d32..61cbbd29d73 100644
--- a/src/main/java/org/spongepowered/api/event/server/ClientPingServerEvent.java
+++ b/src/main/java/org/spongepowered/api/event/server/ClientPingServerEvent.java
@@ -33,8 +33,8 @@
 import org.spongepowered.api.network.status.StatusClient;
 import org.spongepowered.api.network.status.StatusResponse;
 import org.spongepowered.api.profile.GameProfile;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.List;
 import java.util.Optional;
diff --git a/src/main/java/org/spongepowered/api/event/user/BanUserEvent.java b/src/main/java/org/spongepowered/api/event/user/BanUserEvent.java
index 6fadd6153b7..39ec4bb4bf6 100644
--- a/src/main/java/org/spongepowered/api/event/user/BanUserEvent.java
+++ b/src/main/java/org/spongepowered/api/event/user/BanUserEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.entity.living.player.User;
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.service.ban.Ban;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Occurs when a user is banned.
diff --git a/src/main/java/org/spongepowered/api/event/user/PardonUserEvent.java b/src/main/java/org/spongepowered/api/event/user/PardonUserEvent.java
index 39473f80212..72278efaa50 100644
--- a/src/main/java/org/spongepowered/api/event/user/PardonUserEvent.java
+++ b/src/main/java/org/spongepowered/api/event/user/PardonUserEvent.java
@@ -27,7 +27,7 @@
 import org.spongepowered.api.entity.living.player.User;
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.service.ban.Ban;
-import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
 
 /**
  * Occurs when a user is pardoned.
diff --git a/src/main/java/org/spongepowered/api/event/world/ChangeWorldBorderEvent.java b/src/main/java/org/spongepowered/api/event/world/ChangeWorldBorderEvent.java
index 66c3affcc74..92077ea3d1b 100644
--- a/src/main/java/org/spongepowered/api/event/world/ChangeWorldBorderEvent.java
+++ b/src/main/java/org/spongepowered/api/event/world/ChangeWorldBorderEvent.java
@@ -27,9 +27,10 @@
 import org.spongepowered.api.entity.living.player.server.ServerPlayer;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 import org.spongepowered.api.world.border.WorldBorder;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.GenerateFactoryMethod;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 
 import java.util.Optional;
 
@@ -78,6 +79,7 @@ public interface ChangeWorldBorderEvent extends Event, Cancellable {
     /**
      * Fired when a value on a world's {@link WorldBorder} is changed.
      */
+    @GenerateFactoryMethod
     interface World extends ChangeWorldBorderEvent {
 
         /**
@@ -93,6 +95,7 @@ interface World extends ChangeWorldBorderEvent {
      * An event that is fired when a player's world border is changed. This may
      * also be fired when a player's border is set or unset.
      */
+    @GenerateFactoryMethod
     interface Player extends ChangeWorldBorderEvent {
 
         /**
diff --git a/src/main/java/org/spongepowered/api/event/world/ExplosionEvent.java b/src/main/java/org/spongepowered/api/event/world/ExplosionEvent.java
index 86322fdf353..af247cb0172 100644
--- a/src/main/java/org/spongepowered/api/event/world/ExplosionEvent.java
+++ b/src/main/java/org/spongepowered/api/event/world/ExplosionEvent.java
@@ -28,12 +28,12 @@
 import org.spongepowered.api.event.Event;
 import org.spongepowered.api.event.entity.AffectEntityEvent;
 import org.spongepowered.api.event.impl.world.AbstractDetonateEvent;
-import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
-import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
 import org.spongepowered.api.world.World;
 import org.spongepowered.api.world.explosion.Explosion;
 import org.spongepowered.api.world.server.ServerLocation;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.ImplementedBy;
+import org.spongepowered.eventgen.annotations.PropertySettings;
 
 import java.util.List;
 import java.util.function.Predicate;
diff --git a/src/main/java/org/spongepowered/api/event/world/chunk/ChunkEvent.java b/src/main/java/org/spongepowered/api/event/world/chunk/ChunkEvent.java
index 09358b7d35a..2251db3a119 100644
--- a/src/main/java/org/spongepowered/api/event/world/chunk/ChunkEvent.java
+++ b/src/main/java/org/spongepowered/api/event/world/chunk/ChunkEvent.java
@@ -27,13 +27,13 @@
 import org.spongepowered.api.ResourceKey;
 import org.spongepowered.api.event.Cancellable;
 import org.spongepowered.api.event.Event;
-import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod;
 import org.spongepowered.api.world.World;
 import org.spongepowered.api.world.chunk.BlockChunk;
 import org.spongepowered.api.world.chunk.Chunk;
 import org.spongepowered.api.world.chunk.EntityChunk;
 import org.spongepowered.api.world.chunk.WorldChunk;
 import org.spongepowered.api.world.server.ServerWorld;
+import org.spongepowered.eventgen.annotations.NoFactoryMethod;
 import org.spongepowered.math.vector.Vector3i;
 
 public interface ChunkEvent extends Event {
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/AbsoluteSortPosition.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/AbsoluteSortPosition.java
deleted file mode 100644
index 1a3cd472954..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/AbsoluteSortPosition.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to indicate the absolute position of a property when sorted.
- *
- * <p>A value of 0 indicates that a property would always be sorted first,
- * a value of 1 indicates that a property would always be sorted second,
- * and so on.</p>
- *
- * <p>If a gap is left in the absolute ordering of properties, the
- * next-highest-numbered property will be placed next. For example,
- * properties with the absolute ordering 0, 1, and 3 will still be adjacent to
- * each other.</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface AbsoluteSortPosition {
-
-    /**
-     * Gets the absolute position for the annotated property.
-     *
-     * @return the absolute position
-     */
-    int value();
-
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/FactoryMethod.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/FactoryMethod.java
deleted file mode 100644
index 53def2d9327..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/FactoryMethod.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks the annotated method as a factory method.
- * A matching method will be generated in the factory class, which forwards
- * to this method.
- *
- * <p>This annotation can be used to make backwards-compatible
- * changes to an event class. By creating a method matching the old
- * factory method signature, code expecting the old event signature
- * will continue to function.</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface FactoryMethod {
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/GenerateFactoryMethod.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/GenerateFactoryMethod.java
deleted file mode 100644
index 84d05b2eefc..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/GenerateFactoryMethod.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-/**
- * Explicitly enables generation of an event factory method for an event class.
- *
- * <p>By default, an event which contains subinterfaces will not have
- * an event factory method generated.</p>
- */
-public @interface GenerateFactoryMethod {
-
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/NoFactoryMethod.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/NoFactoryMethod.java
deleted file mode 100644
index 31872277cab..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/NoFactoryMethod.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-/**
- * Explicitly disables generation of an event factory method for an event class.
- *
- * <p>By default, an event which contains subinterfaces will not have
- * an event factory method generated.</p>
- */
-public @interface NoFactoryMethod {
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/PropertySettings.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/PropertySettings.java
deleted file mode 100644
index 4f0eb1c25b0..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/PropertySettings.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to specify the settings used when generating code for a property.
- *
- * <p>This annotation should always be placed on the getter method of a
- * property.</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface PropertySettings {
-
-    /**
-     * Indicates whether the annotated property is required to be passed in
-     * to the generated constructor.
-     *
-     * @return Whether the annotated property is required to be passed in to
-     *     the generated constructor.
-     */
-    boolean requiredParameter() default true;
-
-    /**
-     * Indicates whether the annotated property should have methods generated
-     * for it.
-     *
-     * <p>If this value is set to <code>true</code>,
-     * {@link #requiredParameter()} can only be set to <code>false</code> if
-     * the annotated property is a primitive.</p>
-     *
-     * @return Whether the annotated property should have methods generated
-     *     for it.
-     */
-    boolean generateMethods() default true;
-
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformResult.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformResult.java
deleted file mode 100644
index 86b8cbfcb21..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformResult.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to indicate that the return type of a method should be transformed by
- * calling a method on it, indicated by the {@link TransformWith} annotation.
- *
- * <p>This annotation should be placed on the method with the least specific
- * return type, if covariant return types are used.</p>
- *
- * <p>The return type of the annotation, or a superclass/superinterface of it,
- * must have a method annotated with {@link TransformWith}, with a matching
- * {@link #value()}.</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface TransformResult {
-
-    /**
-     * Gets the name used to match this annotation to a {@link TransformWith}
-     * annotation.
-     *
-     * <p>Changing this is only necessary when multiple {@link TransformWith}
-     * annotations are present in the annotated method's return type's class.
-     * </p>
-     *
-     * @return The name to use
-     */
-    String value() default "";
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformWith.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformWith.java
deleted file mode 100644
index 71574ca4f1c..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/TransformWith.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to indicate a method that will be called from the method with the
- * corresponding {@link TransformResult} annotation.
- *
- * <p>This annotation should be placed on the method with the least specific
- * return type, if covariant return types are used.</p>
- *
- * <p>The method annotated with this annotation <strong>must</strong> either return
- * an instance of the method's class, or Object (for compatibility with
- * generics).</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface TransformWith {
-
-    /**
-     * Gets the name used to match this annotation to a {@link TransformResult}
-     * annotation.
-     *
-     * <p>Changing this is only necessary when this annotation is present on
-     * multiple methods in a class, or its superinterfaces/superclass.</p>
-     *
-     * @return The name to use
-     */
-    String value() default "";
-
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/UseField.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/UseField.java
deleted file mode 100644
index 71df58e886a..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/UseField.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package org.spongepowered.api.util.annotation.eventgen;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to mark fields which should be used by the class generator.
- *
- * <p>The class generator will reference the annotated field when
- * generating methods, and set it from the constructor arguments</p>
- *
- * <p>Any field in an abstract class without this field will not be
- * set automatically, even if it matches a property from the implemented
- * event.</p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface UseField {
-
-    /**
-     * Indicates whether to use the annotated field directly in the
-     * generated '{@link #toString()}' method, rather than calling the
-     * normal accessor method.
-     *
-     * @return Whether to override the toString
-     */
-    boolean overrideToString() default false;
-
-}
diff --git a/src/main/java/org/spongepowered/api/util/annotation/eventgen/package-info.java b/src/main/java/org/spongepowered/api/util/annotation/eventgen/package-info.java
deleted file mode 100644
index 6e343110159..00000000000
--- a/src/main/java/org/spongepowered/api/util/annotation/eventgen/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of SpongeAPI, licensed under the MIT License (MIT).
- *
- * Copyright (c) SpongePowered <https://www.spongepowered.org>
- * Copyright (c) contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class)
-package org.spongepowered.api.util.annotation.eventgen;
