From 66ebba4e65454f954ab02f14c804c62d89b31c7c Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sat, 4 Apr 2026 18:56:31 -0700 Subject: [PATCH 1/4] Add core-mc project to the build No code yet --- .../main/kotlin/buildlogic/GradleExtras.kt | 4 -- .../repo-reconfiguration.settings.gradle.kts | 69 +++++++++++++------ settings.gradle.kts | 7 +- worldedit-core-mc/build.gradle.kts | 39 +++++++++++ .../main/resources/worldedit.accesswidener | 18 +++++ worldedit-fabric/build.gradle.kts | 11 +-- worldedit-libs/core-mc/build.gradle.kts | 3 + 7 files changed, 110 insertions(+), 41 deletions(-) create mode 100644 worldedit-core-mc/build.gradle.kts create mode 100644 worldedit-core-mc/src/main/resources/worldedit.accesswidener create mode 100644 worldedit-libs/core-mc/build.gradle.kts diff --git a/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt index f61f5a1eb5..d559c716cb 100644 --- a/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt +++ b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt @@ -34,9 +34,5 @@ fun RepositoryHandler.addEngineHubRepository() { maven { name = "EngineHub (Non-Mirrored)" url = URI.create("https://repo.enginehub.org/libs-release/") - metadataSources { - mavenPom() - artifact() - } } } diff --git a/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts b/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts index 43a9191235..35faef4553 100644 --- a/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts +++ b/gradle/shared-scripts/repo-reconfiguration.settings.gradle.kts @@ -1,16 +1,13 @@ // This file is responsible for reconfiguring repositories to use EngineHub's mirrors // In addition, it configures content filtering to speed up dependency resolution -import org.gradle.api.artifacts.dsl.RepositoryHandler -import org.gradle.api.artifacts.repositories.UrlArtifactRepository -import org.gradle.api.logging.Logging import java.net.URI data class RepositoryReconfiguration( val newUri: URI, - val contentConfiguration: (MavenRepositoryContentDescriptor.() -> Unit)? = null, + val contentConfiguration: (MavenArtifactRepository.() -> Unit)? = null, ) { - constructor(newUri: String, contentConfiguration: (MavenRepositoryContentDescriptor.() -> Unit)? = null) : + constructor(newUri: String, contentConfiguration: (MavenArtifactRepository.() -> Unit)? = null) : this(URI.create(newUri), contentConfiguration) } @@ -30,67 +27,97 @@ object Isolated { private val REPO_RECONFIGURATIONS = listOf( "https://repo.maven.apache.org/maven2/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/maven-central-proxy/") { - releasesOnly() + mavenContent { + releasesOnly() + } }, "https://plugins.gradle.org/m2" to RepositoryReconfiguration("https://repo.enginehub.org/internal/plugin-portal-proxy/") { - releasesOnly() + mavenContent { + releasesOnly() + } }, "https://libraries.minecraft.net/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/minecraft/") { - releasesOnly() + mavenContent { + releasesOnly() + } }, "https://maven.neoforged.net/releases/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/neoforged/") { + mavenContent { releasesOnly() includeGroupAndSubgroups("net.minecraftforge") - includeGroupAndSubgroups("net.neoforged") + includeGroupAndSubgroups("net.neoforged") + } }, "https://maven.minecraftforge.net/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/forge/") { + mavenContent { releasesOnly() - includeGroupAndSubgroups("net.minecraftforge") + includeGroupAndSubgroups("net.minecraftforge") + } }, "https://maven.parchmentmc.org/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/parchment/") { + mavenContent { releasesOnly() - includeGroup("org.parchmentmc.data") + includeGroup("org.parchmentmc.data") + } }, "https://repo.papermc.io/repository/maven-public/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/papermc-proxy/") { + mavenContent { includeGroupAndSubgroups("io.papermc") includeGroupAndSubgroups("com.velocitypowered") includeGroupAndSubgroups("ca.spottedleaf") includeGroupAndSubgroups("me.lucko") - includeModule("net.md-5", "bungeecord-chat") + includeModule("net.md-5", "bungeecord-chat") + } }, "https://maven.fabricmc.net/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/fabricmc/") { + mavenContent { releasesOnly() includeGroupAndSubgroups("fabric-loom") includeGroupAndSubgroups("net.fabricmc") - excludeModule("net.fabricmc", "yarn") + excludeModule("net.fabricmc", "yarn") + } }, "https://maven.fabricmc.net/#yarn-only" to RepositoryReconfiguration("https://repo.enginehub.org/internal/fabricmc-yarn/") { + mavenContent { releasesOnly() - includeModule("net.fabricmc", "yarn") + includeModule("net.fabricmc", "yarn") + } }, "https://repo.spongepowered.org/repository/maven-releases/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/spongepowered-releases/") { + mavenContent { releasesOnly() - includeGroupAndSubgroups("org.spongepowered") + includeGroupAndSubgroups("org.spongepowered") + } }, "https://repo.spongepowered.org/repository/maven-snapshots/" to RepositoryReconfiguration("https://repo.enginehub.org/internal/spongepowered-snapshots/") { + mavenContent { snapshotsOnly() - includeGroupAndSubgroups("org.spongepowered") + includeGroupAndSubgroups("org.spongepowered") + } }, "https://repo.enginehub.org/libs-release/" to RepositoryReconfiguration("https://repo.enginehub.org/libs-release/") { - releasesOnly() - includeGroupAndSubgroups("com.sk89q") - includeGroupAndSubgroups("org.enginehub") + mavenContent { + releasesOnly() + includeGroupAndSubgroups("com.sk89q") + includeGroupAndSubgroups("org.enginehub") + } + + metadataSources { + gradleMetadata() + mavenPom() + artifact() + } }, ).associate { (k, v) -> URI.create(k) to v } private val LOGGER = Logging.getLogger("enginehub-reconfiguring-repositories") @@ -119,9 +146,7 @@ object Isolated { if (!(repo is MavenArtifactRepository)) { error("Cannot configure content on non-Maven repository: ${repo.name} ${repo.url}") } - repo.mavenContent { - reconfiguration.contentConfiguration.invoke(this) - } + repo.run(reconfiguration.contentConfiguration) } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 0a986cbb7f..082aed569c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,11 +35,6 @@ dependencyResolutionManagement { maven { name = "EngineHub (Non-Mirrored)" url = URI.create("https://repo.enginehub.org/libs-release/") - metadataSources { - gradleMetadata() - mavenPom() - artifact() - } } ivy { url = uri("https://repo.enginehub.org/language-files/") @@ -87,7 +82,7 @@ listOf("1.21.4", "1.21.5", "1.21.6", "1.21.9", "1.21.11", "26.1").forEach { include("worldedit-bukkit:adapters:adapter-$it") } -listOf("bukkit", "core", "fabric", "neoforge", "sponge", "cli").forEach { +listOf("bukkit", "core", "core-mc", "fabric", "neoforge", "sponge", "cli").forEach { include("worldedit-libs:$it") include("worldedit-$it") } diff --git a/worldedit-core-mc/build.gradle.kts b/worldedit-core-mc/build.gradle.kts new file mode 100644 index 0000000000..1ea4dd9b27 --- /dev/null +++ b/worldedit-core-mc/build.gradle.kts @@ -0,0 +1,39 @@ +import buildlogic.addEngineHubRepository + +plugins { + alias(libs.plugins.fabric.loom) + `java-library` + id("buildlogic.core-and-platform") +} + +description = "The Minecraft-specific implementation of WorldEdit's core module." + + " This code is shared by all platforms that rely on access without an API." + +repositories { + addEngineHubRepository() +} + +loom { + accessWidenerPath.set(project.file("src/main/resources/worldedit.accesswidener")) +} + +dependencies { + "api"(project(":worldedit-core")) + + "minecraft"(libs.fabric.minecraft) + "implementation"(libs.fabric.loader) + + // Silence some warnings, since apparently this isn't on the compile classpath like it should be. + "compileOnly"(libs.errorprone.annotations) +} + +base { + archivesName.set("${project.name}-mc${libs.fabric.minecraft.get().version}") +} + +publishing { + publications.named("maven") { + artifactId = base.archivesName.get() + from(components["java"]) + } +} diff --git a/worldedit-core-mc/src/main/resources/worldedit.accesswidener b/worldedit-core-mc/src/main/resources/worldedit.accesswidener new file mode 100644 index 0000000000..96d7240b28 --- /dev/null +++ b/worldedit-core-mc/src/main/resources/worldedit.accesswidener @@ -0,0 +1,18 @@ +accessWidener v2 official + +accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor +accessible field net/minecraft/server/level/ServerChunkCache mainThreadProcessor Lnet/minecraft/server/level/ServerChunkCache$MainThreadExecutor; + +accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource; + +accessible field net/minecraft/server/level/ServerPlayerGameMode isDestroyingBlock Z + +accessible field net/minecraft/world/level/storage/DerivedLevelData wrapped Lnet/minecraft/world/level/storage/ServerLevelData; + +#accessible field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; +#mutable field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; + +accessible method net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket (Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V + +accessible field net/minecraft/server/MinecraftServer nextTickTimeNanos J +accessible field net/minecraft/server/MinecraftServer storageSource Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess; diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index dc831d093c..f2e1459c23 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -1,3 +1,4 @@ +import buildlogic.addEngineHubRepository import buildlogic.internalVersion import buildlogic.withCuiProtocolDependsOnCommonRule import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar @@ -27,15 +28,7 @@ tasks.withType().configureEach { } repositories { - maven { - name = "EngineHub (Non-Mirrored)" - url = URI.create("https://repo.enginehub.org/libs-release/") - metadataSources { - gradleMetadata() - mavenPom() - artifact() - } - } + addEngineHubRepository() } withCuiProtocolDependsOnCommonRule(libs.cuiProtocol.fabric.get().module) diff --git a/worldedit-libs/core-mc/build.gradle.kts b/worldedit-libs/core-mc/build.gradle.kts new file mode 100644 index 0000000000..3f6c7e06cb --- /dev/null +++ b/worldedit-libs/core-mc/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("buildlogic.libs") +} From 11e276e381341fbc7895cf6e42de09516384a05a Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 12 Apr 2026 16:33:35 -0700 Subject: [PATCH 2/4] Merge most of Fabric and NeoForge into core-mc --- .../buildlogic.expose-resources.gradle.kts | 10 + .../kotlin/buildlogic.platform.gradle.kts | 1 + gradle/libs.versions.toml | 2 +- worldedit-core-mc/README.md | 16 + worldedit-core-mc/build.gradle.kts | 22 +- .../sk89q/worldedit/coremc/CoreMcAdapter.java | 161 +- .../coremc/CoreMcPermissionsProvider.java | 57 +- .../coremc}/internal/ComponentConverter.java | 4 +- .../coremc/internal/CoreMcBiomeRegistry.java | 12 +- .../internal/CoreMcBlockCategoryRegistry.java | 10 +- .../internal/CoreMcBlockCommandSender.java | 21 +- .../coremc/internal/CoreMcBlockMaterial.java | 11 +- .../coremc/internal/CoreMcBlockRegistry.java | 23 +- .../coremc/internal/CoreMcCommandSender.java | 16 +- .../coremc/internal/CoreMcCommandWrapper.java | 56 +- .../coremc/internal/CoreMcConfiguration.java | 13 +- .../coremc/internal/CoreMcDataFixer.java | 34 +- .../coremc/internal/CoreMcEntity.java | 23 +- .../internal/CoreMcEntityProperties.java | 9 +- .../coremc/internal/CoreMcFakePlayer.java | 6 +- .../internal/CoreMcItemCategoryRegistry.java | 9 +- .../coremc/internal/CoreMcItemRegistry.java | 14 +- .../CoreMcLoggingProblemReporter.java | 8 +- .../worldedit/coremc/internal/CoreMcMod.java | 354 +++ .../coremc/internal/CoreMcPlatform.java | 296 ++ .../coremc/internal/CoreMcPlayer.java | 85 +- .../internal/CoreMcPropertyAdapter.java | 6 +- .../coremc/internal/CoreMcRegistries.java | 27 +- .../CoreMcServerLevelDelegateProxy.java | 45 +- .../coremc/internal/CoreMcTransmogrifier.java | 29 +- .../coremc/internal/CoreMcWatchdog.java | 9 +- .../coremc/internal/CoreMcWorld.java | 189 +- .../internal/CoreMcWorldNativeAccess.java | 17 +- .../coremc}/internal/NBTConverter.java | 2 +- .../coremc/internal}/ThreadSafeCache.java | 6 +- .../coremc/mixin/AccessorChunkMap.java | 25 +- ...essorClientboundBlockEntityDataPacket.java | 41 + .../mixin/AccessorCommandSourceStack.java | 31 + .../coremc/mixin/AccessorMinecraftServer.java | 34 + .../mixin/AccessorServerPlayerGameMode.java | 3 +- .../MixinServerGamePacketListenerImpl.java | 26 +- .../main/resources/assets/worldedit/icon.png | Bin .../resources/defaults/worldedit.properties | 0 .../src/main/resources/pack.mcmeta | 0 .../resources/worldedit-coremc.mixins.json | 18 + .../main/resources/worldedit.accesswidener | 18 - worldedit-core-mc/textconv-core-mc.py | 51 + worldedit-core/build.gradle.kts | 12 +- .../extension/platform/PlatformManager.java | 69 +- worldedit-fabric/build.gradle.kts | 23 +- .../worldedit/fabric/CommandWrapper.java | 122 - .../sk89q/worldedit/fabric/FabricAdapter.java | 299 -- .../worldedit/fabric/FabricBiomeRegistry.java | 66 - .../fabric/FabricBlockCommandSender.java | 185 -- .../worldedit/fabric/FabricBlockRegistry.java | 74 - .../fabric/FabricEntityProperties.java | 156 - .../worldedit/fabric/FabricPlatform.java | 203 +- .../worldedit/fabric/FabricWorldEdit.java | 464 +-- .../LuckoFabricPermissionsProvider.java | 29 +- .../FabricServerLevelDelegateProxy.java | 185 -- .../fabric/internal/FabricTransmogrifier.java | 135 - .../internal/FabricWorldNativeAccess.java | 172 -- .../fabric/internal/MixinConfigPlugin.java | 83 - .../fabric/internal/NBTConverter.java | 236 -- .../MixinServerGamePacketListenerImpl.java | 66 - .../src/main/resources/fabric.mod.json | 5 +- .../resources/worldedit-fabric.mixins.json | 14 - .../main/resources/worldedit.accesswidener | 18 - worldedit-mod/build.gradle.kts | 4 +- worldedit-neoforge/build.gradle.kts | 17 +- .../NeoForgeBlockCategoryRegistry.java | 48 - .../neoforge/NeoForgeBlockMaterial.java | 146 - .../neoforge/NeoForgeCommandSender.java | 159 - .../worldedit/neoforge/NeoForgeDataFixer.java | 2724 ----------------- .../neoforge/NeoForgeFakePlayer.java | 58 - .../NeoForgeItemCategoryRegistry.java | 48 - .../neoforge/NeoForgeItemRegistry.java | 51 - .../neoforge/NeoForgePermissionsProvider.java | 52 - .../worldedit/neoforge/NeoForgePlatform.java | 224 +- .../worldedit/neoforge/NeoForgePlayer.java | 300 -- .../neoforge/NeoForgeRegistries.java | 75 - .../worldedit/neoforge/NeoForgeWorld.java | 774 ----- .../worldedit/neoforge/NeoForgeWorldEdit.java | 465 +-- .../worldedit/neoforge/ThreadSafeCache.java | 80 - .../neoforge/internal/ComponentConverter.java | 77 - .../neoforge/internal/NeoForgeEntity.java | 135 - .../NeoForgeLoggingProblemReporter.java | 61 - .../internal/NeoForgePropertyAdapter.java | 70 - .../resources/META-INF/accesstransformer.cfg | 7 - .../resources/META-INF/neoforge.mods.toml | 7 +- .../resources/defaults/worldedit.properties | 33 - .../src/main/resources/pack.mcmeta | 6 - .../src/main/resources/worldedit-icon.png | Bin 5636 -> 0 bytes .../resources/worldedit-neoforge.mixins.json | 15 - 94 files changed, 1557 insertions(+), 8545 deletions(-) create mode 100644 build-logic/src/main/kotlin/buildlogic.expose-resources.gradle.kts create mode 100644 worldedit-core-mc/README.md rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java (54%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java (51%) rename {worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc}/internal/ComponentConverter.java (97%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBiomeRegistry.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBiomeRegistry.java (85%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java (82%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCommandSender.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java (91%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java (91%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockRegistry.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java (77%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricCommandSender.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandSender.java (92%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/CommandWrapper.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java (73%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricConfiguration.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcConfiguration.java (78%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java (99%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricEntity.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java (85%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeEntityProperties.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntityProperties.java (94%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricFakePlayer.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcFakePlayer.java (92%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java (83%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java (80%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricLoggingProblemReporter.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcLoggingProblemReporter.java (88%) create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java (76%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPropertyAdapter.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPropertyAdapter.java (89%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricRegistries.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java (74%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java (80%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeTransmogrifier.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java (86%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWatchdogImpl.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWatchdog.java (78%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java (80%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldNativeAccess.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java (92%) rename {worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc}/internal/NBTConverter.java (99%) rename {worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal}/ThreadSafeCache.java (92%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWatchdog.java => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorChunkMap.java (64%) create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorClientboundBlockEntityDataPacket.java create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorCommandSourceStack.java create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorMinecraftServer.java rename {worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc}/mixin/AccessorServerPlayerGameMode.java (96%) rename {worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge => worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc}/mixin/MixinServerGamePacketListenerImpl.java (71%) rename {worldedit-fabric => worldedit-core-mc}/src/main/resources/assets/worldedit/icon.png (100%) rename {worldedit-fabric => worldedit-core-mc}/src/main/resources/defaults/worldedit.properties (100%) rename {worldedit-fabric => worldedit-core-mc}/src/main/resources/pack.mcmeta (100%) create mode 100644 worldedit-core-mc/src/main/resources/worldedit-coremc.mixins.json delete mode 100644 worldedit-core-mc/src/main/resources/worldedit.accesswidener create mode 100755 worldedit-core-mc/textconv-core-mc.py delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCommandSender.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeConfiguration.java => worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java (55%) delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java delete mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerGamePacketListenerImpl.java delete mode 100644 worldedit-fabric/src/main/resources/worldedit-fabric.mixins.json delete mode 100644 worldedit-fabric/src/main/resources/worldedit.accesswidener delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCategoryRegistry.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockMaterial.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeCommandSender.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeDataFixer.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeFakePlayer.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemCategoryRegistry.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemRegistry.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePermissionsProvider.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlayer.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeRegistries.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorld.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/ThreadSafeCache.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/ComponentConverter.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeEntity.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeLoggingProblemReporter.java delete mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePropertyAdapter.java delete mode 100644 worldedit-neoforge/src/main/resources/META-INF/accesstransformer.cfg delete mode 100644 worldedit-neoforge/src/main/resources/defaults/worldedit.properties delete mode 100644 worldedit-neoforge/src/main/resources/pack.mcmeta delete mode 100644 worldedit-neoforge/src/main/resources/worldedit-icon.png delete mode 100644 worldedit-neoforge/src/main/resources/worldedit-neoforge.mixins.json diff --git a/build-logic/src/main/kotlin/buildlogic.expose-resources.gradle.kts b/build-logic/src/main/kotlin/buildlogic.expose-resources.gradle.kts new file mode 100644 index 0000000000..0901eebd0c --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.expose-resources.gradle.kts @@ -0,0 +1,10 @@ +// "Publish" (only to local projects) a resources variant for other projects to consume +configurations.consumable("resourcesVariant") { + // Similar to mainSourceElements + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category::class, Category.VERIFICATION)) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling::class, Bundling.EXTERNAL)) + attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, objects.named(VerificationType::class, "resources")) + } + outgoing.artifact(tasks.named("processResources")) +} diff --git a/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts index c4776daa92..b24794c27e 100644 --- a/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts @@ -28,6 +28,7 @@ tasks.named("shadowJ include(project(":worldedit-libs:core")) include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) include(project(":worldedit-core")) + include(project(":worldedit-core-mc")) include(dependency(jchronic)) linBusDeps.forEach { include(dependency(it)) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d8f0b30a48..a9f05f6106 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,7 @@ errorprone-core = { module = "com.google.errorprone:error_prone_core", version.r errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorprone" } # https://maven.fabricmc.net/net/fabricmc/sponge-mixin/ -fabric-mixin = "net.fabricmc:sponge-mixin:0.17.0+mixin.0.8.7" +fabric-mixin = "net.fabricmc:sponge-mixin:0.17.1+mixin.0.8.7" paperweight = "io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:2.0.0-beta.21" diff --git a/worldedit-core-mc/README.md b/worldedit-core-mc/README.md new file mode 100644 index 0000000000..6afcbe6bc5 --- /dev/null +++ b/worldedit-core-mc/README.md @@ -0,0 +1,16 @@ +# Diff Setup + +Diffing against old `worldedit-fabric` or `worldedit-neoforge` code is best done with the following setup: +1. Add the following to `.git/info/attributes`: + ``` + worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/**/*.java diff=core-mc + worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/**/*.java diff=core-mc + worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/**/*.java diff=core-mc + ``` +2. Run `git config diff.core-mc.textconv ./worldedit-core-mc/textconv-core-mc.py`. +3. Run `git config diff.renames copy` + +This will give you diffs that replace platform-specific names with `platform$`, +providing a clearer picture of the core logic changes without noise from the renames. + +Make sure to remove the `.gitattributes` changes after you're done to avoid affecting future diffs. diff --git a/worldedit-core-mc/build.gradle.kts b/worldedit-core-mc/build.gradle.kts index 1ea4dd9b27..26a25440ea 100644 --- a/worldedit-core-mc/build.gradle.kts +++ b/worldedit-core-mc/build.gradle.kts @@ -1,9 +1,11 @@ +import buildlogic.CuiProtocolCommonIsNotFabricSpecificRule import buildlogic.addEngineHubRepository plugins { alias(libs.plugins.fabric.loom) `java-library` id("buildlogic.core-and-platform") + id("buildlogic.expose-resources") } description = "The Minecraft-specific implementation of WorldEdit's core module." + @@ -13,18 +15,22 @@ repositories { addEngineHubRepository() } -loom { - accessWidenerPath.set(project.file("src/main/resources/worldedit.accesswidener")) -} - dependencies { - "api"(project(":worldedit-core")) + api(project(":worldedit-core")) + api(project(":worldedit-libs:core-mc")) + + minecraft(libs.fabric.minecraft) - "minecraft"(libs.fabric.minecraft) - "implementation"(libs.fabric.loader) + // Provided by platforms. + compileOnly(libs.fabric.mixin) + + implementation(libs.cuiProtocol.common) + components { + withModule(libs.cuiProtocol.common.get().module) + } // Silence some warnings, since apparently this isn't on the compile classpath like it should be. - "compileOnly"(libs.errorprone.annotations) + compileOnly(libs.errorprone.annotations) } base { diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java similarity index 54% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java index cf95a130b7..eeb71104f2 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java @@ -17,17 +17,23 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc; import com.mojang.serialization.Codec; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.coremc.internal.CoreMcBlockCommandSender; +import com.sk89q.worldedit.coremc.internal.CoreMcCommandSender; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.coremc.internal.CoreMcPlayer; +import com.sk89q.worldedit.coremc.internal.CoreMcTransmogrifier; +import com.sk89q.worldedit.coremc.internal.CoreMcWorld; +import com.sk89q.worldedit.coremc.internal.NBTConverter; +import com.sk89q.worldedit.coremc.mixin.AccessorCommandSourceStack; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.neoforge.internal.NBTConverter; -import com.sk89q.worldedit.neoforge.internal.NeoForgeTransmogrifier; -import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.World; @@ -41,69 +47,57 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponentPatch; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.StringRepresentable; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BaseCommandBlock; +import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.enginehub.linbus.tree.LinCompoundTag; -import java.util.Comparator; -import java.util.Map; import java.util.Objects; -import java.util.TreeMap; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; -public final class NeoForgeAdapter { +/** + * Common adapter methods for platforms sharing native Minecraft code. + */ +public final class CoreMcAdapter { - private NeoForgeAdapter() { + private CoreMcAdapter() { } - public static World adapt(ServerLevel world) { - return new NeoForgeWorld(world); + public static World fromNativeWorld(Level level) { + return new CoreMcWorld((ServerLevel) level); } - /** - * Create a Forge world from a WorldEdit world. - * - * @param world the WorldEdit world - * @return a Forge world - */ - public static ServerLevel adapt(World world) { + public static ServerLevel toNativeWorld(World world) { checkNotNull(world); - if (world instanceof NeoForgeWorld neoForgeWorld) { - return neoForgeWorld.getWorld(); - } else { - // TODO introduce a better cross-platform world API to match more easily - throw new UnsupportedOperationException("Cannot adapt from a " + world.getClass()); + if (world instanceof CoreMcWorld coreMcWorld) { + return coreMcWorld.getWorld(); } + // TODO introduce a better cross-platform world API to match more easily + throw new UnsupportedOperationException("Cannot adapt from a " + world.getClass()); } - public static Biome adapt(BiomeType biomeType) { - return ServerLifecycleHooks.getCurrentServer() - .registryAccess() - .lookupOrThrow(Registries.BIOME) + // Available as API, but not used by WorldEdit itself. + @SuppressWarnings("unused") + public static Biome toNativeBiome(BiomeType biomeType) { + return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BIOME) .getOptional(Identifier.parse(biomeType.id())) .orElseThrow(() -> new IllegalStateException("No biome for " + biomeType.id())); } - public static BiomeType adapt(Biome biome) { - Identifier id = ServerLifecycleHooks.getCurrentServer() - .registryAccess() - .lookupOrThrow(Registries.BIOME) - .getKey(biome); + public static BiomeType fromNativeBiome(Biome biome) { + Identifier id = CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BIOME).getKey(biome); Objects.requireNonNull(id, "biome is not registered"); return BiomeTypes.get(id.toString()); } @@ -149,71 +143,43 @@ public static BlockPos toBlockPos(BlockVector3 vector) { return new BlockPos(vector.x(), vector.y(), vector.z()); } - /** - * Adapts property. - * - * @deprecated without replacement, use the block adapter methods - */ - // Suppress InlineMeSuggester: There is no replacement, so this shouldn't be inlined - @SuppressWarnings("InlineMeSuggester") - @Deprecated - public static Property adaptProperty(net.minecraft.world.level.block.state.properties.Property property) { - return NeoForgeTransmogrifier.transmogToWorldEditProperty(property); - } - - /** - * Adapts properties. - * - * @deprecated without replacement, use the block adapter methods - */ - @Deprecated - public static Map, Object> adaptProperties(BlockType block, Map, Comparable> mcProps) { - Map, Object> props = new TreeMap<>(Comparator.comparing(Property::getName)); - for (Map.Entry, Comparable> prop : mcProps.entrySet()) { - Object value = prop.getValue(); - if (prop.getKey() instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - if (prop.getKey().getValueClass() == net.minecraft.core.Direction.class) { - value = adaptEnumFacing((net.minecraft.core.Direction) value); - } else { - value = ((StringRepresentable) value).getSerializedName(); - } - } - props.put(block.getProperty(prop.getKey().getName()), value); - } - return props; - } - - public static net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) { + public static net.minecraft.world.level.block.state.BlockState toNativeBlockState(BlockState blockState) { int blockStateId = BlockStateIdAccess.getBlockStateId(blockState); if (!BlockStateIdAccess.isValidInternalId(blockStateId)) { - return NeoForgeTransmogrifier.transmogToMinecraft(blockState); + return CoreMcTransmogrifier.transmogToMinecraft(blockState); } return Block.stateById(blockStateId); } - public static BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { + public static BlockState fromNativeBlockState(net.minecraft.world.level.block.state.BlockState blockState) { int blockStateId = Block.getId(blockState); BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId); if (worldEdit == null) { - return NeoForgeTransmogrifier.transmogToWorldEdit(blockState); + return CoreMcTransmogrifier.transmogToWorldEdit(blockState); } return worldEdit; } - public static Block adapt(BlockType blockType) { - return BuiltInRegistries.BLOCK.getValue(Identifier.parse(blockType.id())); + public static Block toNativeBlock(BlockType blockType) { + return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK) + .getValue(Identifier.parse(blockType.id())); } - public static BlockType adapt(Block block) { - return BlockTypes.get(BuiltInRegistries.BLOCK.getKey(block).toString()); + public static BlockType fromNativeBlock(Block block) { + return BlockTypes.get( + CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK).getKey(block).toString() + ); } - public static Item adapt(ItemType itemType) { - return BuiltInRegistries.ITEM.getValue(Identifier.parse(itemType.id())); + public static Item toNativeItem(ItemType itemType) { + return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM) + .getValue(Identifier.parse(itemType.id())); } - public static ItemType adapt(Item item) { - return ItemTypes.get(BuiltInRegistries.ITEM.getKey(item).toString()); + public static ItemType fromNativeItem(Item item) { + return ItemTypes.get( + CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM).getKey(item).toString() + ); } /** @@ -223,12 +189,15 @@ public static ItemType adapt(Item item) { "components", DataComponentPatch.EMPTY ).codec(); - public static ItemStack adapt(BaseItemStack baseItemStack) { - final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount()); + public static ItemStack toNativeItemStack(BaseItemStack baseItemStack) { + final ItemStack itemStack = new ItemStack( + toNativeItem(baseItemStack.getType()), + baseItemStack.getAmount() + ); LinCompoundTag nbt = baseItemStack.getNbt(); if (nbt != null) { DataComponentPatch componentPatch = COMPONENTS_CODEC.parse( - ServerLifecycleHooks.getCurrentServer().registryAccess().createSerializationContext(NbtOps.INSTANCE), + CoreMcPlatform.getRegistryAccess().createSerializationContext(NbtOps.INSTANCE), NBTConverter.toNative(nbt) ).getOrThrow(); itemStack.applyComponents(componentPatch); @@ -236,13 +205,15 @@ public static ItemStack adapt(BaseItemStack baseItemStack) { return itemStack; } - public static BaseItemStack adapt(ItemStack itemStack) { + public static BaseItemStack fromNativeItemStack(ItemStack itemStack) { CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( - ServerLifecycleHooks.getCurrentServer().registryAccess().createSerializationContext(NbtOps.INSTANCE), + CoreMcPlatform.getRegistryAccess().createSerializationContext(NbtOps.INSTANCE), itemStack.getComponentsPatch() ).getOrThrow(); return new BaseItemStack( - adapt(itemStack.getItem()), LazyReference.from(() -> NBTConverter.fromNative(tag)), itemStack.getCount() + fromNativeItem(itemStack.getItem()), + LazyReference.from(() -> NBTConverter.fromNative(tag)), + itemStack.getCount() ); } @@ -252,9 +223,9 @@ public static BaseItemStack adapt(ItemStack itemStack) { * @param player the player * @return the WorldEdit player */ - public static NeoForgePlayer adaptPlayer(ServerPlayer player) { + public static CoreMcPlayer fromNativePlayer(ServerPlayer player) { checkNotNull(player); - return new NeoForgePlayer(player); + return new CoreMcPlayer(player); } /** @@ -266,12 +237,14 @@ public static NeoForgePlayer adaptPlayer(ServerPlayer player) { public static Actor adaptCommandSource(CommandSourceStack commandSourceStack) { checkNotNull(commandSourceStack); if (commandSourceStack.isPlayer()) { - return adaptPlayer(commandSourceStack.getPlayer()); + return fromNativePlayer(commandSourceStack.getPlayer()); } - if (NeoForgeWorldEdit.inst.getConfig().commandBlockSupport && commandSourceStack.source instanceof BaseCommandBlock commandBlock) { - return new NeoForgeBlockCommandSender(commandBlock, commandSourceStack.getLevel(), commandSourceStack.getPosition()); + if (WorldEdit.getInstance().getPlatformManager().getConfiguration().commandBlockSupport + && ((AccessorCommandSourceStack) commandSourceStack).getSource() instanceof BaseCommandBlock commandBlock) { + return new CoreMcBlockCommandSender( + commandBlock, commandSourceStack.getLevel(), commandSourceStack.getPosition() + ); } - - return new NeoForgeCommandSender(commandSourceStack); + return new CoreMcCommandSender(commandSourceStack); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java similarity index 51% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java index 2e0df21f4f..88258efccf 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPermissionsProvider.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java @@ -17,29 +17,55 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc; -import me.lucko.fabric.api.permissions.v0.Permissions; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.coremc.internal.CoreMcConfiguration; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.GameType; +import org.jspecify.annotations.NonNull; -public interface FabricPermissionsProvider { +public interface CoreMcPermissionsProvider { + + private static @NonNull CoreMcPlatform getCoreMcPlatform() { + Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.PERMISSIONS); + if (!(platform instanceof CoreMcPlatform coreMcPlatform)) { + throw new IllegalStateException( + "Non-CoreMcPlatform is being used for capability " + Capability.PERMISSIONS + ": " + + platform.getClass() + ); + } + return coreMcPlatform; + } + + static CoreMcPermissionsProvider current() { + return getCoreMcPlatform().getPermissionsProvider(); + } + + // API for other mods to set a custom permissions provider. + @SuppressWarnings("unused") + static void setCurrent(CoreMcPermissionsProvider provider) { + getCoreMcPlatform().setPermissionsProvider(provider); + } boolean hasPermission(ServerPlayer player, String permission); void registerPermission(String permission); - class VanillaPermissionsProvider implements FabricPermissionsProvider { + class VanillaPermissionsProvider implements CoreMcPermissionsProvider { - private final FabricPlatform platform; + private final CoreMcPlatform platform; - public VanillaPermissionsProvider(FabricPlatform platform) { + public VanillaPermissionsProvider(CoreMcPlatform platform) { this.platform = platform; } @Override public boolean hasPermission(ServerPlayer player, String permission) { - FabricConfiguration configuration = platform.getConfiguration(); + CoreMcConfiguration configuration = platform.getConfiguration(); return configuration.cheatMode || player.level().getServer().getPlayerList().isOp(player.nameAndId()) || (configuration.creativeEnable && player.gameMode.getGameModeForPlayer() == GameType.CREATIVE); @@ -49,21 +75,4 @@ public boolean hasPermission(ServerPlayer player, String permission) { public void registerPermission(String permission) { } } - - class LuckoFabricPermissionsProvider extends VanillaPermissionsProvider { - - public LuckoFabricPermissionsProvider(FabricPlatform platform) { - super(platform); - } - - @Override - public boolean hasPermission(ServerPlayer player, String permission) { - return Permissions.getPermissionValue(player, permission) - .orElseGet(() -> super.hasPermission(player, permission)); - } - - @Override - public void registerPermission(String permission) { - } - } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ComponentConverter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ComponentConverter.java similarity index 97% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ComponentConverter.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ComponentConverter.java index 51ca617d3e..978ccbe347 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/ComponentConverter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ComponentConverter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric.internal; +package com.sk89q.worldedit.coremc.internal; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -35,7 +35,7 @@ import java.io.StringReader; import javax.annotation.Nullable; -public class ComponentConverter { +public final class ComponentConverter { public static class Serializer { private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBiomeRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBiomeRegistry.java similarity index 85% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBiomeRegistry.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBiomeRegistry.java index ebae9012d0..818e83502b 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBiomeRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBiomeRegistry.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -28,9 +28,9 @@ import net.minecraft.util.Util; /** - * Provides access to biome data in Forge. + * Provides access to biome data. */ -class NeoForgeBiomeRegistry implements BiomeRegistry { +public final class CoreMcBiomeRegistry implements BiomeRegistry { @Override public Component getRichName(BiomeType biomeType) { @@ -40,11 +40,11 @@ public Component getRichName(BiomeType biomeType) { @Deprecated @Override public BiomeData getData(BiomeType biome) { - return new ForgeBiomeData(biome); + return new CoreMcBiomeData(biome); } @Deprecated - private static class ForgeBiomeData implements BiomeData { + private static final class CoreMcBiomeData implements BiomeData { private final BiomeType biome; /** @@ -52,7 +52,7 @@ private static class ForgeBiomeData implements BiomeData { * * @param biome the base biome */ - private ForgeBiomeData(BiomeType biome) { + private CoreMcBiomeData(BiomeType biome) { this.biome = biome; } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java similarity index 82% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java index ed3966aa9f..3fdc5b6625 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCategoryRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; import net.minecraft.core.Holder; @@ -30,15 +31,16 @@ import java.util.Set; import java.util.stream.Collectors; -public class FabricBlockCategoryRegistry implements BlockCategoryRegistry { +public final class CoreMcBlockCategoryRegistry implements BlockCategoryRegistry { + @Override public Set getCategorisedByName(String category) { - return FabricWorldEdit.getRegistry(Registries.BLOCK) + return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK) .get(TagKey.create(Registries.BLOCK, Identifier.parse(category))) .stream() .flatMap(HolderSet.Named::stream) .map(Holder::value) - .map(FabricAdapter::adapt) + .map(CoreMcAdapter::fromNativeBlock) .collect(Collectors.toSet()); } } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCommandSender.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java similarity index 91% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCommandSender.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java index 02f0f9b164..b4fe01f97f 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCommandSender.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java @@ -17,11 +17,11 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.extension.platform.AbstractCommandBlockActor; -import com.sk89q.worldedit.neoforge.internal.ComponentConverter; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.auth.AuthorizationException; @@ -43,18 +43,18 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class NeoForgeBlockCommandSender extends AbstractCommandBlockActor { +public final class CoreMcBlockCommandSender extends AbstractCommandBlockActor { private final BaseCommandBlock sender; private final UUID uuid; private final ServerLevel level; private final Vec3 pos; - public NeoForgeBlockCommandSender(BaseCommandBlock sender, ServerLevel level, Vec3 pos) { - super(new Location(NeoForgeAdapter.adapt(checkNotNull(level)), NeoForgeAdapter.adapt(pos))); - this.level = level; - this.pos = pos; + public CoreMcBlockCommandSender(BaseCommandBlock sender, ServerLevel level, Vec3 pos) { + super(new Location(CoreMcAdapter.fromNativeWorld(checkNotNull(level)), CoreMcAdapter.adapt(pos))); this.sender = sender; + this.level = level; + this.pos = pos; this.uuid = UUID.nameUUIDFromBytes((UUID_PREFIX + sender.getName()).getBytes(StandardCharsets.UTF_8)); } @@ -136,10 +136,6 @@ public boolean hasPermission(String permission) { return true; } - public BaseCommandBlock getSender() { - return this.sender; - } - @Override public SessionKey getSessionKey() { return new SessionKey() { @@ -167,7 +163,8 @@ public String getName() { @Override public boolean isActive() { - level.getServer().submitAsync(this::updateActive) + // TODO this should probably be optimized so we only do this every so often. + level.getServer().submit(this::updateActive) .exceptionally(t -> { WorldEdit.logger.warn("Could not update command block session key active state", t); return null; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java similarity index 91% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java index 8c70c417d3..16c5f731b5 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockMaterial.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockMaterial.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; @@ -29,15 +29,14 @@ import net.minecraft.world.level.material.PushReaction; /** - * Fabric block material that pulls as much info as possible from the Minecraft - * Material, and passes the rest to another implementation, typically the - * bundled block info. + * Minecraft block material implementation for platforms sharing native code. + * Pulls as much info as possible from the Minecraft BlockState. */ -public class FabricBlockMaterial implements BlockMaterial { +public final class CoreMcBlockMaterial implements BlockMaterial { private final BlockState block; - public FabricBlockMaterial(BlockState block) { + public CoreMcBlockMaterial(BlockState block) { this.block = block; } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java similarity index 77% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockRegistry.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java index cdd812db63..5853630dc5 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java @@ -17,9 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.neoforge.internal.NeoForgeTransmogrifier; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -35,40 +35,43 @@ import java.util.OptionalInt; import java.util.TreeMap; -public class NeoForgeBlockRegistry implements BlockRegistry { +/** + * Block registry implementation for platforms sharing native code. + */ +public final class CoreMcBlockRegistry implements BlockRegistry { - private final Map materialMap = new HashMap<>(); + private final Map materialMap = new HashMap<>(); @Override public Component getRichName(BlockType blockType) { - return TranslatableComponent.of(NeoForgeAdapter.adapt(blockType).getDescriptionId()); + return TranslatableComponent.of(CoreMcAdapter.toNativeBlock(blockType).getDescriptionId()); } @Override public BlockMaterial getMaterial(BlockType blockType) { - Block block = NeoForgeAdapter.adapt(blockType); + Block block = CoreMcAdapter.toNativeBlock(blockType); return materialMap.computeIfAbsent( block.defaultBlockState(), - NeoForgeBlockMaterial::new + CoreMcBlockMaterial::new ); } @Override public Map> getProperties(BlockType blockType) { - Block block = NeoForgeAdapter.adapt(blockType); + Block block = CoreMcAdapter.toNativeBlock(blockType); Map> map = new TreeMap<>(); Collection> propertyKeys = block .defaultBlockState() .getProperties(); for (net.minecraft.world.level.block.state.properties.Property key : propertyKeys) { - map.put(key.getName(), NeoForgeTransmogrifier.transmogToWorldEditProperty(key)); + map.put(key.getName(), CoreMcTransmogrifier.transmogToWorldEditProperty(key)); } return map; } @Override public OptionalInt getInternalBlockStateId(BlockState state) { - net.minecraft.world.level.block.state.BlockState equivalent = NeoForgeAdapter.adapt(state); + net.minecraft.world.level.block.state.BlockState equivalent = CoreMcAdapter.toNativeBlockState(state); return OptionalInt.of(Block.getId(equivalent)); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricCommandSender.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandSender.java similarity index 92% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricCommandSender.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandSender.java index f92ee34f37..77a8e56d6e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricCommandSender.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandSender.java @@ -17,11 +17,10 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.AbstractNonPlayerActor; -import com.sk89q.worldedit.fabric.internal.ComponentConverter; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.formatting.WorldEditText; import com.sk89q.worldedit.util.formatting.text.Component; @@ -31,12 +30,14 @@ import java.util.Locale; import java.util.UUID; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -public class FabricCommandSender extends AbstractNonPlayerActor { +/** + * Command sender implementation for platforms sharing native code. + */ +public final class CoreMcCommandSender extends AbstractNonPlayerActor { /** * One time generated ID. @@ -45,7 +46,7 @@ public class FabricCommandSender extends AbstractNonPlayerActor { private final CommandSourceStack sender; - public FabricCommandSender(CommandSourceStack sender) { + public CoreMcCommandSender(CommandSourceStack sender) { checkNotNull(sender); checkArgument(!sender.isPlayer(), "Cannot wrap a player"); @@ -127,14 +128,9 @@ public Locale getLocale() { return WorldEdit.getInstance().getConfiguration().defaultLocale; } - public CommandSourceStack getSender() { - return this.sender; - } - @Override public SessionKey getSessionKey() { return new SessionKey() { - @Nullable @Override public String getName() { return sender.getTextName(); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/CommandWrapper.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java similarity index 73% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/CommandWrapper.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java index 4cea1b25b4..75b64bed72 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/CommandWrapper.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.internal; import com.google.common.collect.ImmutableList; import com.mojang.brigadier.Command; @@ -26,11 +26,12 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.StringRange; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestion; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.util.Substring; @@ -47,18 +48,42 @@ import static net.minecraft.commands.Commands.argument; import static net.minecraft.commands.Commands.literal; -public final class CommandWrapper { - private CommandWrapper() { +/** + * Shared command wrapper logic for registering WorldEdit commands with Brigadier. + * Platform modules only need to provide the {@code adaptCommandSource} function. + */ +public final class CoreMcCommandWrapper { + + private CoreMcCommandWrapper() { } - public static void register(CommandDispatcher dispatcher, org.enginehub.piston.Command command) { + /** + * Register a command with the given dispatcher. + * + * @param dispatcher the Brigadier dispatcher + * @param command the WorldEdit command to register + */ + public static void register(CommandDispatcher dispatcher, + org.enginehub.piston.Command command) { + Command commandRunner = ctx -> { + if (ctx.getSource().getLevel().isClientSide()) { + return 0; + } + WorldEdit.getInstance().getEventBus().post(new CommandEvent( + CoreMcAdapter.adaptCommandSource(ctx.getSource()), + "/" + ctx.getInput() + )); + return 0; + }; + ImmutableList.Builder aliases = ImmutableList.builder(); aliases.add(command.getName()).addAll(command.getAliases()); + for (String alias : aliases.build()) { - LiteralArgumentBuilder base = literal(alias).executes(FAKE_COMMAND) + LiteralArgumentBuilder base = literal(alias).executes(commandRunner) .then(argument("args", StringArgumentType.greedyString()) - .suggests(CommandWrapper::suggest) - .executes(FAKE_COMMAND)); + .suggests(CoreMcCommandWrapper::suggest) + .executes(commandRunner)); if (command.getCondition() != org.enginehub.piston.Command.Condition.TRUE) { base.requires(requirementsFor(command)); } @@ -66,26 +91,19 @@ public static void register(CommandDispatcher dispatcher, or } } - public static final Command FAKE_COMMAND = ctx -> { - if (ctx.getSource().getLevel().isClientSide()) { - return 0; - } - return 1; - }; - private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { return ctx -> { - final Actor actor = NeoForgeAdapter.adaptCommandSource(ctx); InjectedValueStore store = MapBackedValueStore.create(); - store.injectValue(Key.of(Actor.class), context -> Optional.of(actor)); + final Actor actor = CoreMcAdapter.adaptCommandSource(ctx); + store.injectValue(Key.of(Actor.class), _ -> Optional.of(actor)); return mapping.getCondition().satisfied(store); }; } private static CompletableFuture suggest(CommandContext context, - SuggestionsBuilder builder) throws CommandSyntaxException { + SuggestionsBuilder builder) { CommandSuggestionEvent event = new CommandSuggestionEvent( - NeoForgeAdapter.adaptCommandSource(context.getSource()), + CoreMcAdapter.adaptCommandSource(context.getSource()), builder.getInput() ); WorldEdit.getInstance().getEventBus().post(event); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricConfiguration.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcConfiguration.java similarity index 78% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricConfiguration.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcConfiguration.java index 76f2a9b4cf..e02c00c8d1 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricConfiguration.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcConfiguration.java @@ -17,19 +17,22 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.util.PropertiesConfiguration; import java.nio.file.Path; -public class FabricConfiguration extends PropertiesConfiguration { +public final class CoreMcConfiguration extends PropertiesConfiguration { public boolean creativeEnable = false; public boolean cheatMode = false; - public FabricConfiguration(FabricWorldEdit mod) { - super(mod.getWorkingDir().resolve("worldedit.properties")); + private final Path workingDir; + + public CoreMcConfiguration(Path workingDir) { + super(workingDir.resolve("worldedit.properties")); + this.workingDir = workingDir; } @Override @@ -40,6 +43,6 @@ protected void loadExtra() { @Override public Path getWorkingDirectoryPath() { - return FabricWorldEdit.inst.getWorkingDir(); + return workingDir; } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java similarity index 99% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java index 553b2e35fd..2f982365b5 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.google.common.base.Strings; import com.google.common.collect.Maps; @@ -33,8 +33,6 @@ import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.schemas.Schema; import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.fabric.internal.ComponentConverter; -import com.sk89q.worldedit.fabric.internal.NBTConverter; import net.minecraft.core.Direction; import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; @@ -100,7 +98,7 @@ "unchecked", "rawtypes" }) -class FabricDataFixer implements com.sk89q.worldedit.world.DataFixer { +public final class CoreMcDataFixer implements com.sk89q.worldedit.world.DataFixer { @Override public T fixUp(FixType type, T original, int srcVer) { @@ -191,7 +189,7 @@ private static String fixName(String key, int srcVer, TypeReference type) { private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final int LEGACY_VERSION = 1343; private static int DATA_VERSION; - private static FabricDataFixer INSTANCE; + private static CoreMcDataFixer INSTANCE; private final Map> converters = new EnumMap<>(LegacyType.class); private final Map> inspectors = new EnumMap<>(LegacyType.class); @@ -222,7 +220,7 @@ public TypeReference getDFUType() { } } - FabricDataFixer(int dataVersion) { + public CoreMcDataFixer(int dataVersion) { DATA_VERSION = dataVersion; INSTANCE = this; registerConverters(); @@ -252,7 +250,7 @@ public Dynamic update(TypeReference type, Dynamic dynamic, int sourceV } private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int desiredVersion) { - List converters = FabricDataFixer.this.converters.get(type); + List converters = CoreMcDataFixer.this.converters.get(type); if (converters != null && !converters.isEmpty()) { for (DataConverter converter : converters) { int dataVersion = converter.getDataVersion(); @@ -262,7 +260,7 @@ private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt } } - List inspectors = FabricDataFixer.this.inspectors.get(type); + List inspectors = CoreMcDataFixer.this.inspectors.get(type); if (inspectors != null && !inspectors.isEmpty()) { for (DataInspector inspector : inspectors) { cmp = inspector.inspect(cmp, sourceVer, desiredVersion); @@ -812,7 +810,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, private static class DataInspectorEntity implements DataInspector { - private static final Logger a = LogManager.getLogger(FabricDataFixer.class); + private static final Logger a = LogManager.getLogger(CoreMcDataFixer.class); DataInspectorEntity() { } @@ -884,7 +882,7 @@ private static class DataInspectorItemList extends DataInspectorTagged { net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String s : this.keys) { - FabricDataFixer.convertItems(nbttagcompound, s, sourceVer, targetVer); + CoreMcDataFixer.convertItems(nbttagcompound, s, sourceVer, targetVer); } return nbttagcompound; @@ -902,7 +900,7 @@ private static class DataInspectorItem extends DataInspectorTagged { net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String key : this.keys) { - FabricDataFixer.convertItem(nbttagcompound, key, sourceVer, targetVer); + CoreMcDataFixer.convertItem(nbttagcompound, key, sourceVer, targetVer); } return nbttagcompound; @@ -1857,7 +1855,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (object == null) { try { - object = ComponentConverter.Serializer.fromJson(s, FabricWorldEdit.registryAccess()); + object = ComponentConverter.Serializer.fromJson(s, CoreMcPlatform.getRegistryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -1865,7 +1863,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (object == null) { try { - object = ComponentConverter.Serializer.fromJsonLenient(s, FabricWorldEdit.registryAccess()); + object = ComponentConverter.Serializer.fromJsonLenient(s, CoreMcPlatform.getRegistryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -1879,7 +1877,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) object = Component.literal(""); } - nbttaglist.set(i, StringTag.valueOf(ComponentConverter.Serializer.toJson((Component) object, FabricWorldEdit.registryAccess()))); + nbttaglist.set(i, StringTag.valueOf(ComponentConverter.Serializer.toJson((Component) object, CoreMcPlatform.getRegistryAccess()))); } nbttagcompound1.put("pages", nbttaglist); @@ -2385,7 +2383,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) private static class DataConverterBedBlock implements DataConverter { - private static final Logger a = LogManager.getLogger(FabricDataFixer.class); + private static final Logger a = LogManager.getLogger(CoreMcDataFixer.class); DataConverterBedBlock() { } @@ -2520,7 +2518,7 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { if (object == null) { try { - object = ComponentConverter.Serializer.fromJson(s1, FabricWorldEdit.registryAccess()); + object = ComponentConverter.Serializer.fromJson(s1, CoreMcPlatform.getRegistryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -2528,7 +2526,7 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { if (object == null) { try { - object = ComponentConverter.Serializer.fromJsonLenient(s1, FabricWorldEdit.registryAccess()); + object = ComponentConverter.Serializer.fromJsonLenient(s1, CoreMcPlatform.getRegistryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -2542,7 +2540,7 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { object = Component.literal(""); } - nbttagcompound.putString(s, ComponentConverter.Serializer.toJson((Component) object, FabricWorldEdit.registryAccess())); + nbttagcompound.putString(s, ComponentConverter.Serializer.toJson((Component) object, CoreMcPlatform.getRegistryAccess())); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricEntity.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java similarity index 85% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricEntity.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java index e02facd896..cc4de5c80e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricEntity.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java @@ -17,15 +17,13 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric.internal; +package com.sk89q.worldedit.coremc.internal; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.fabric.FabricAdapter; -import com.sk89q.worldedit.fabric.FabricEntityProperties; -import com.sk89q.worldedit.fabric.FabricWorldEdit; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.concurrency.LazyReference; @@ -40,11 +38,11 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class FabricEntity implements Entity { +public final class CoreMcEntity implements Entity { private final WeakReference entityRef; - public FabricEntity(net.minecraft.world.entity.Entity entity) { + public CoreMcEntity(net.minecraft.world.entity.Entity entity) { checkNotNull(entity); this.entityRef = new WeakReference<>(entity); } @@ -56,7 +54,7 @@ public BaseEntity getState() { return null; } - net.minecraft.nbt.CompoundTag tag = FabricLoggingProblemReporter.with( + net.minecraft.nbt.CompoundTag tag = CoreMcLoggingProblemReporter.with( () -> "serializing entity " + entity.getStringUUID(), reporter -> { TagValueOutput tagValueOutput = TagValueOutput.createWithContext(reporter, entity.registryAccess()); @@ -71,7 +69,10 @@ public BaseEntity getState() { return null; } - Identifier id = FabricWorldEdit.getRegistry(Registries.ENTITY_TYPE).getKey(entity.getType()); + Identifier id = entity.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).getKey(entity.getType()); + if (id == null) { + return null; + } return new BaseEntity( EntityTypes.get(id.toString()), LazyReference.from(() -> NBTConverter.fromNative(tag)) @@ -86,7 +87,7 @@ public Location getLocation() { float yaw = entity.getYRot(); float pitch = entity.getXRot(); - return new Location(FabricAdapter.adapt(entity.level()), position, yaw, pitch); + return new Location(CoreMcAdapter.fromNativeWorld(entity.level()), position, yaw, pitch); } else { return new Location(NullWorld.getInstance()); } @@ -102,7 +103,7 @@ public boolean setLocation(Location location) { public Extent getExtent() { net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { - return FabricAdapter.adapt(entity.level()); + return CoreMcAdapter.fromNativeWorld(entity.level()); } else { return NullWorld.getInstance(); } @@ -124,7 +125,7 @@ public T getFacet(Class cls) { net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { if (EntityProperties.class.isAssignableFrom(cls)) { - return (T) new FabricEntityProperties(entity); + return (T) new CoreMcEntityProperties(entity); } else { return null; } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeEntityProperties.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntityProperties.java similarity index 94% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeEntityProperties.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntityProperties.java index 31fd70a3e2..08d9ed2bff 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeEntityProperties.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntityProperties.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.entity.metadata.EntityProperties; import net.minecraft.server.level.ServerPlayer; @@ -45,11 +45,14 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class NeoForgeEntityProperties implements EntityProperties { +/** + * Entity properties implementation for platforms sharing native code. + */ +public final class CoreMcEntityProperties implements EntityProperties { private final Entity entity; - public NeoForgeEntityProperties(Entity entity) { + public CoreMcEntityProperties(Entity entity) { checkNotNull(entity); this.entity = entity; } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricFakePlayer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcFakePlayer.java similarity index 92% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricFakePlayer.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcFakePlayer.java index 4b2daa1e76..a6c7553c28 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricFakePlayer.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcFakePlayer.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.mojang.authlib.GameProfile; import net.minecraft.server.level.ClientInformation; @@ -31,7 +31,7 @@ import java.nio.charset.StandardCharsets; import java.util.UUID; -public class FabricFakePlayer extends ServerPlayer { +public final class CoreMcFakePlayer extends ServerPlayer { private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( UUID.nameUUIDFromBytes("worldedit".getBytes(StandardCharsets.UTF_8)), "[WorldEdit]" @@ -40,7 +40,7 @@ public class FabricFakePlayer extends ServerPlayer { "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false, ParticleStatus.MINIMAL ); - public FabricFakePlayer(ServerLevel world) { + public CoreMcFakePlayer(ServerLevel world) { super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java similarity index 83% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java index 78f10d1b34..97884aed65 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemCategoryRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; import net.minecraft.core.Holder; @@ -30,15 +31,15 @@ import java.util.Set; import java.util.stream.Collectors; -public class FabricItemCategoryRegistry implements ItemCategoryRegistry { +public final class CoreMcItemCategoryRegistry implements ItemCategoryRegistry { @Override public Set getCategorisedByName(String category) { - return FabricWorldEdit.getRegistry(Registries.ITEM) + return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM) .get(TagKey.create(Registries.ITEM, Identifier.parse(category))) .stream() .flatMap(HolderSet.Named::stream) .map(Holder::value) - .map(FabricAdapter::adapt) + .map(CoreMcAdapter::fromNativeItem) .collect(Collectors.toSet()); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java similarity index 80% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java index 384ac042f9..b920fdba41 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricItemRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java @@ -17,10 +17,10 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.fabric.internal.ComponentConverter; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; @@ -28,12 +28,11 @@ import com.sk89q.worldedit.world.registry.BundledItemRegistry; @SuppressWarnings("removal") -public class FabricItemRegistry extends BundledItemRegistry { - +public final class CoreMcItemRegistry extends BundledItemRegistry { @Override public Component getRichName(ItemType itemType) { return TranslatableComponent.of( - FabricAdapter.adapt(itemType).getDescriptionId() + CoreMcAdapter.toNativeItem(itemType).getDescriptionId() ); } @@ -41,10 +40,9 @@ public Component getRichName(ItemType itemType) { public Component getRichName(BaseItemStack itemStack) { return GsonComponentSerializer.INSTANCE.deserialize( ComponentConverter.Serializer.toJson( - FabricAdapter.adapt(itemStack).getItemName(), - FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().registryAccess() + CoreMcAdapter.toNativeItemStack(itemStack).getItemName(), + CoreMcPlatform.getRegistryAccess() ) ); } - } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricLoggingProblemReporter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcLoggingProblemReporter.java similarity index 88% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricLoggingProblemReporter.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcLoggingProblemReporter.java index 7f5afe5a7e..ea90f36b67 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricLoggingProblemReporter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcLoggingProblemReporter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric.internal; +package com.sk89q.worldedit.coremc.internal; import net.minecraft.util.ProblemReporter; import org.apache.logging.log4j.LogManager; @@ -26,16 +26,16 @@ import java.util.function.Function; import java.util.function.Supplier; -public final class FabricLoggingProblemReporter implements ProblemReporter, AutoCloseable { +public final class CoreMcLoggingProblemReporter implements ProblemReporter, AutoCloseable { private static final Logger LOGGER = LogManager.getLogger(); public static T with(Supplier contextSupplier, Function consumer) { - try (var problemReporter = new FabricLoggingProblemReporter(contextSupplier)) { + try (var problemReporter = new CoreMcLoggingProblemReporter(contextSupplier)) { return consumer.apply(problemReporter); } } - FabricLoggingProblemReporter(Supplier contextSupplier) { + CoreMcLoggingProblemReporter(Supplier contextSupplier) { this.contextSupplier = contextSupplier; } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java new file mode 100644 index 0000000000..f65cbf54b6 --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java @@ -0,0 +1,354 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.internal; + +import com.mojang.brigadier.CommandDispatcher; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.PermissionCondition; +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; +import com.sk89q.worldedit.event.platform.PlatformReadyEvent; +import com.sk89q.worldedit.event.platform.PlatformUnreadyEvent; +import com.sk89q.worldedit.event.platform.PlatformsRegisteredEvent; +import com.sk89q.worldedit.event.platform.SessionIdleEvent; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extension.platform.PlatformManager; +import com.sk89q.worldedit.internal.anvil.ChunkDeleter; +import com.sk89q.worldedit.internal.event.InteractionDebouncer; +import com.sk89q.worldedit.registry.CommonRegistries; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.biome.BiomeCategory; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockCategory; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.entity.EntityType; +import com.sk89q.worldedit.world.generation.ConfiguredFeatureType; +import com.sk89q.worldedit.world.generation.StructureType; +import com.sk89q.worldedit.world.generation.TreeType; +import com.sk89q.worldedit.world.item.ItemCategory; +import com.sk89q.worldedit.world.item.ItemType; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.feature.CoralTreeFeature; +import net.minecraft.world.level.levelgen.feature.FallenTreeFeature; +import net.minecraft.world.level.levelgen.feature.TreeFeature; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import org.enginehub.piston.Command; +import org.enginehub.worldeditcui.protocol.CUIPacket; +import org.enginehub.worldeditcui.protocol.CUIPacketHandler; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME; + +public abstract class CoreMcMod { + + private InteractionDebouncer debouncer; + private CoreMcPlatform platform; + private CoreMcConfiguration config; + private Path workingDir; + + protected abstract String getInternalVersion(); + + protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform platform) { + return new CoreMcPermissionsProvider.VanillaPermissionsProvider(platform); + } + + protected final void init(CoreMcPlatform platform, Path gameConfigDir) { + this.workingDir = gameConfigDir.resolve("worldedit"); + if (!Files.exists(workingDir)) { + try { + Files.createDirectory(workingDir); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + this.platform = platform; + this.debouncer = new InteractionDebouncer(platform); + + WorldEdit.getInstance().getPlatformManager().register(platform); + + this.config = new CoreMcConfiguration(workingDir); + + platform.setPermissionsProvider(createPermissionsProvider(platform)); + } + + protected CoreMcConfiguration getConfig() { + return this.config; + } + + protected void setupRegistries(MinecraftServer server) { + // Blocks + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.BLOCK).keySet()) { + String key = name.toString(); + if (BlockType.REGISTRY.get(key) == null) { + BlockType.REGISTRY.register(key, new BlockType(key, + input -> CoreMcAdapter.fromNativeBlockState(CoreMcAdapter.toNativeBlock(input.getBlockType()).defaultBlockState()))); + } + } + // Items + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.ITEM).keySet()) { + String key = name.toString(); + if (ItemType.REGISTRY.get(key) == null) { + ItemType.REGISTRY.register(key, new ItemType(key)); + } + } + // Entities + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).keySet()) { + String key = name.toString(); + if (EntityType.REGISTRY.get(key) == null) { + EntityType.REGISTRY.register(key, new EntityType(key)); + } + } + // Biomes + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.BIOME).keySet()) { + String key = name.toString(); + if (BiomeType.REGISTRY.get(key) == null) { + BiomeType.REGISTRY.register(key, new BiomeType(key)); + } + } + // Tags + server.registryAccess().lookupOrThrow(Registries.BLOCK).getTags().map(t -> t.key().location()).forEach(name -> { + String key = name.toString(); + if (BlockCategory.REGISTRY.get(key) == null) { + BlockCategory.REGISTRY.register(key, new BlockCategory(key)); + } + }); + server.registryAccess().lookupOrThrow(Registries.ITEM).getTags().map(t -> t.key().location()).forEach(name -> { + String key = name.toString(); + if (ItemCategory.REGISTRY.get(key) == null) { + ItemCategory.REGISTRY.register(key, new ItemCategory(key)); + } + }); + Registry biomeRegistry = server.registryAccess().lookupOrThrow(Registries.BIOME); + biomeRegistry.getTags().forEach(tag -> { + String key = tag.key().location().toString(); + if (BiomeCategory.REGISTRY.get(key) == null) { + BiomeCategory.REGISTRY.register(key, new BiomeCategory( + key, + () -> biomeRegistry.get(tag.key()) + .stream() + .flatMap(HolderSet.Named::stream) + .map(Holder::value) + .map(CoreMcAdapter::fromNativeBiome) + .collect(Collectors.toSet())) + ); + } + }); + // Features + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).keySet()) { + String key = name.toString(); + if (ConfiguredFeatureType.REGISTRY.get(key) == null) { + ConfiguredFeatureType.REGISTRY.register(key, new ConfiguredFeatureType(key)); + } + } + // Structures + for (Identifier name : server.registryAccess().lookupOrThrow(Registries.STRUCTURE).keySet()) { + String key = name.toString(); + if (StructureType.REGISTRY.get(key) == null) { + StructureType.REGISTRY.register(key, new StructureType(key)); + } + } + // Trees + Registry placedFeatureRegistry = server.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE); + for (Identifier name : placedFeatureRegistry.keySet()) { + // Do some hackery to make sure this is a tree + var underlyingFeature = placedFeatureRegistry.get(name).get().value().feature().value().feature(); + if (underlyingFeature instanceof TreeFeature || underlyingFeature instanceof FallenTreeFeature || underlyingFeature instanceof CoralTreeFeature) { + String key = name.toString(); + if (TreeType.REGISTRY.get(key) == null) { + TreeType.REGISTRY.register(key, new TreeType(key)); + } + } + } + + // Common registries + CommonRegistries.init(); + } + + protected void registerCommands(CommandDispatcher dispatcher) { + WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent()); + + PlatformManager manager = WorldEdit.getInstance().getPlatformManager(); + Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS); + if (commandsPlatform != platform || !platform.isHookingEvents()) { + // We're not in control of commands/events -- do not register. + return; + } + + List commands = manager.getPlatformCommandManager().getCommandManager() + .getAllCommands().toList(); + for (Command command : commands) { + CoreMcCommandWrapper.register(dispatcher, command); + Set perms = command.getCondition().as(PermissionCondition.class) + .map(PermissionCondition::getPermissions) + .orElseGet(Collections::emptySet); + if (!perms.isEmpty()) { + perms.forEach(platform.getPermissionsProvider()::registerPermission); + } + } + } + + protected void serverAboutToStart() { + final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME); + if (Files.exists(delChunks)) { + ChunkDeleter.runFromFile(delChunks, true); + } + } + + protected void serverStarted(MinecraftServer server) { + setupRegistries(server); + + config.load(); + WorldEdit.getInstance().getEventBus().post(new ConfigurationLoadEvent(config)); + WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent(platform)); + } + + protected void serverStopping() { + WorldEdit worldEdit = WorldEdit.getInstance(); + worldEdit.getSessionManager().unload(); + WorldEdit.getInstance().getEventBus().post(new PlatformUnreadyEvent(platform)); + } + + private boolean skipEvents() { + return platform == null || !platform.isHookingEvents(); + } + + private boolean skipInteractionEvent(Player player, InteractionHand hand) { + return skipEvents() || hand != InteractionHand.MAIN_HAND || player.level().isClientSide() || !(player instanceof ServerPlayer); + } + + public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { + if (skipInteractionEvent(playerEntity, hand)) { + return; + } + + WorldEdit we = WorldEdit.getInstance(); + CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(playerEntity); + + Optional previousResult = debouncer.getDuplicateInteractionResult(player); + if (previousResult.isPresent()) { + return; + } + + boolean result = we.handleArmSwing(player); + debouncer.setLastInteraction(player, result); + } + + protected boolean onLeftClickBlock(Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { + if (skipInteractionEvent(playerEntity, hand)) { + return false; + } + + ServerPlayer serverPlayer = (ServerPlayer) playerEntity; + WorldEdit we = WorldEdit.getInstance(); + CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); + CoreMcWorld world = (CoreMcWorld) CoreMcAdapter.fromNativeWorld(serverPlayer.level()); + Direction direction = CoreMcAdapter.adaptEnumFacing(face); + + Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); + + boolean result = we.handleBlockLeftClick(player, pos, direction) || we.handleArmSwing(player); + debouncer.setLastInteraction(player, result); + + return result; + } + + protected boolean onRightClickBlock(Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { + if (skipInteractionEvent(playerEntity, hand)) { + return false; + } + + ServerPlayer serverPlayer = (ServerPlayer) playerEntity; + WorldEdit we = WorldEdit.getInstance(); + CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); + CoreMcWorld world = (CoreMcWorld) CoreMcAdapter.fromNativeWorld(serverPlayer.level()); + Direction direction = CoreMcAdapter.adaptEnumFacing(face); + + Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); + + boolean result = we.handleBlockRightClick(player, pos, direction) || we.handleRightClick(player); + debouncer.setLastInteraction(player, result); + + return result; + } + + protected Optional onRightClickItem(Player playerEntity, InteractionHand hand) { + if (skipInteractionEvent(playerEntity, hand)) { + return Optional.empty(); + } + + ServerPlayer serverPlayer = (ServerPlayer) playerEntity; + WorldEdit we = WorldEdit.getInstance(); + CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); + + Optional previousResult = debouncer.getDuplicateInteractionResult(player); + if (previousResult.isPresent()) { + return previousResult; + } + + boolean result = we.handleRightClick(player); + debouncer.setLastInteraction(player, result); + + return Optional.of(result); + } + + protected void onPlayerDisconnect(Player playerEntity) { + if (!(playerEntity instanceof ServerPlayer player)) { + return; + } + debouncer.clearInteraction(CoreMcAdapter.fromNativePlayer(player)); + + WorldEdit.getInstance().getEventBus() + .post(new SessionIdleEvent(new CoreMcPlayer.SessionKeyImpl(player))); + } + + protected void onCuiPacket(CUIPacket payload, CUIPacketHandler.PacketContext context) { + if (!(context.player() instanceof ServerPlayer player)) { + return; + } + CoreMcPlayer actor = CoreMcAdapter.fromNativePlayer(player); + LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); + session.handleCUIInitializationMessage(payload.eventType(), payload.args(), actor); + } +} diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java new file mode 100644 index 0000000000..dc07bbb2d1 --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java @@ -0,0 +1,296 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.internal; + +import com.google.common.collect.Sets; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.AbstractPlatform; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.MultiUserPlatform; +import com.sk89q.worldedit.extension.platform.Preference; +import com.sk89q.worldedit.extension.platform.Watchdog; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.lifecycle.ConstantLifecycled; +import com.sk89q.worldedit.util.lifecycle.Lifecycled; +import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; +import com.sk89q.worldedit.world.DataFixer; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.registry.Registries; +import net.minecraft.SharedConstants; +import net.minecraft.core.BlockPos; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.Identifier; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ServerLevelData; +import org.enginehub.piston.CommandManager; +import org.enginehub.worldeditcui.protocol.CUIPacket; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import javax.annotation.Nullable; + +public abstract class CoreMcPlatform extends AbstractPlatform implements MultiUserPlatform { + + private static final Lifecycled WORLD_EDITING_PLATFORM = WorldEdit.getInstance().getPlatformManager() + .getPreferred(Capability.WORLD_EDITING) + .flatMap(platform -> { + if (platform instanceof CoreMcPlatform coreMcPlatform) { + return new ConstantLifecycled<>(coreMcPlatform); + } else { + return SimpleLifecycled.invalid(); + } + }); + + public static CoreMcPlatform forWorldEditing() { + return WORLD_EDITING_PLATFORM.valueOrThrow(); + } + + public static Optional optionallyForWorldEditing() { + return WORLD_EDITING_PLATFORM.value(); + } + + private static final Lifecycled REGISTRY_ACCESS = WORLD_EDITING_PLATFORM + .flatMap(platform -> platform.server.map(MinecraftServer::registryAccess)); + + public static RegistryAccess getRegistryAccess() { + return REGISTRY_ACCESS.valueOrThrow(); + } + + private static final Lifecycled CUI_PLATFORM = WorldEdit.getInstance().getPlatformManager() + .getPreferred(Capability.WORLDEDIT_CUI) + .flatMap(platform -> { + if (platform instanceof CoreMcPlatform coreMcPlatform) { + return new ConstantLifecycled<>(coreMcPlatform); + } else { + return SimpleLifecycled.invalid(); + } + }); + + public static CoreMcPlatform forCui() { + return CUI_PLATFORM.valueOrThrow(); + } + + protected static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS, + SideEffect.UPDATE + ); + + private final CoreMcMod mod; + private final CoreMcDataFixer dataFixer; + private final CoreMcRegistries registries; + private final Lifecycled server; + private final Lifecycled watchdog; + private boolean hookingEvents = false; + private CoreMcPermissionsProvider permissionsProvider; + + protected CoreMcPlatform(CoreMcMod mod, Lifecycled server) { + this.mod = mod; + this.dataFixer = new CoreMcDataFixer(getDataVersion()); + this.registries = new CoreMcRegistries(); + this.server = server; + this.watchdog = server.flatMap(s -> { + if (s instanceof DedicatedServer dedicatedServer) { + return new ConstantLifecycled<>(new CoreMcWatchdog(dedicatedServer)); + } else { + return SimpleLifecycled.invalid(); + } + }); + } + + // region Methods to be implemented by subclasses that are not public API + + protected abstract void sendCUIPacket(ServerPlayer player, CUIPacket packet); + + protected void extraOnBlockStateChange(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState) { + } + + // endregion + + public CoreMcMod getMod() { + return mod; + } + + /** + * {@return the permissions provider for this platform} + * + *

Queried via {@link Capability#PERMISSIONS}. + */ + public CoreMcPermissionsProvider getPermissionsProvider() { + return permissionsProvider; + } + + /** + * Set the permissions provider for this platform. + * + * @param provider the permissions provider + */ + public void setPermissionsProvider(CoreMcPermissionsProvider provider) { + this.permissionsProvider = Objects.requireNonNull(provider); + } + + public boolean isHookingEvents() { + return hookingEvents; + } + + @Override + public Registries getRegistries() { + return registries; + } + + @Override + public int getDataVersion() { + return SharedConstants.getCurrentVersion().dataVersion().version(); + } + + @Override + public DataFixer getDataFixer() { + return dataFixer; + } + + @Override + public boolean isValidMobType(String type) { + return BuiltInRegistries.ENTITY_TYPE.containsKey(Identifier.parse(type)); + } + + @Override + public void reload() { + getConfiguration().load(); + super.reload(); + } + + @Override + @Nullable + public Watchdog getWatchdog() { + return watchdog.value().orElse(null); + } + + @Override + public List getWorlds() { + Iterable worlds = server.valueOrThrow().getAllLevels(); + List ret = new ArrayList<>(); + for (ServerLevel world : worlds) { + ret.add(new CoreMcWorld(world)); + } + return ret; + } + + @Nullable + @Override + public Player matchPlayer(Player player) { + if (player instanceof CoreMcPlayer) { + return player; + } else { + ServerPlayer entity = server.valueOrThrow().getPlayerList().getPlayerByName(player.getName()); + return entity != null ? CoreMcAdapter.fromNativePlayer(entity) : null; + } + } + + @Nullable + @Override + public World matchWorld(World world) { + if (world instanceof CoreMcWorld) { + return world; + } else { + for (ServerLevel ws : server.valueOrThrow().getAllLevels()) { + if (((ServerLevelData) ws.getLevelData()).getLevelName().equals(world.getName())) { + return new CoreMcWorld(ws); + } + } + + return null; + } + } + + @Override + public void registerCommands(CommandManager manager) { + // No-op, we register using the platform's event system. + } + + @Override + public void setGameHooksEnabled(boolean enabled) { + this.hookingEvents = enabled; + } + + @Override + public CoreMcConfiguration getConfiguration() { + return mod.getConfig(); + } + + @Override + public String getVersion() { + return mod.getInternalVersion(); + } + + @Override + public String getPlatformVersion() { + return getVersion(); + } + + @Override + public Map getCapabilities() { + Map capabilities = new EnumMap<>(Capability.class); + capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS); + capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL); + capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL); + capabilities.put(Capability.PERMISSIONS, Preference.NORMAL); + capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL); + capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED); + return capabilities; + } + + @Override + public Set getSupportedSideEffects() { + return SUPPORTED_SIDE_EFFECTS; + } + + @Override + public long getTickCount() { + return server.valueOrThrow().getTickCount(); + } + + @Override + public Collection getConnectedUsers() { + List users = new ArrayList<>(); + PlayerList scm = server.valueOrThrow().getPlayerList(); + for (ServerPlayer entity : scm.getPlayers()) { + users.add(CoreMcAdapter.fromNativePlayer(entity)); + } + return users; + } +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java similarity index 76% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java index 5e0a9de72e..469b4c4fb0 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java @@ -17,14 +17,15 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.coremc.mixin.AccessorClientboundBlockEntityDataPacket; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; import com.sk89q.worldedit.extent.inventory.BlockBag; -import com.sk89q.worldedit.fabric.internal.ComponentConverter; -import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; @@ -39,11 +40,8 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -58,12 +56,20 @@ import java.util.UUID; import javax.annotation.Nullable; -public class FabricPlayer extends AbstractPlayerActor { +/** + * Common player implementation for platforms sharing native Minecraft code. + */ +public class CoreMcPlayer extends AbstractPlayerActor { private final ServerPlayer player; - protected FabricPlayer(ServerPlayer player) { + public CoreMcPlayer(ServerPlayer player) { this.player = player; + + if (getUniqueId() == null) { + throw new AssertionError("Player UUID cannot be null"); + } + ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); } @@ -74,8 +80,12 @@ public UUID getUniqueId() { @Override public BaseItemStack getItemInHand(HandSide handSide) { - ItemStack is = this.player.getItemInHand(handSide == HandSide.MAIN_HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); - return FabricAdapter.adapt(is); + ItemStack is = this.player.getItemInHand( + handSide == HandSide.MAIN_HAND + ? InteractionHand.MAIN_HAND + : InteractionHand.OFF_HAND + ); + return CoreMcAdapter.fromNativeItemStack(is); } @Override @@ -92,15 +102,16 @@ public BaseEntity getState() { public Location getLocation() { Vector3 position = Vector3.at(this.player.getX(), this.player.getY(), this.player.getZ()); return new Location( - FabricWorldEdit.inst.getWorld(this.player.level()), + CoreMcAdapter.fromNativeWorld(this.player.level()), position, this.player.getYRot(), - this.player.getXRot()); + this.player.getXRot() + ); } @Override public boolean setLocation(Location location) { - ServerLevel level = (ServerLevel) FabricAdapter.adapt((World) location.getExtent()); + ServerLevel level = CoreMcAdapter.toNativeWorld((World) location.getExtent()); this.player.teleportTo( level, location.getX(), location.getY(), location.getZ(), @@ -108,28 +119,27 @@ public boolean setLocation(Location location) { location.getYaw(), location.getPitch(), true ); - // This check doesn't really ever get to be false in Fabric - // Since Fabric API doesn't allow cancelling the teleport. - // However, other mods could theoretically mix this in, so allow the detection. + // This may be false if the teleport was cancelled by a mod return this.player.level() == level; } @Override public World getWorld() { - return FabricWorldEdit.inst.getWorld(this.player.level()); + return CoreMcAdapter.fromNativeWorld(this.player.level()); } @Override public void giveItem(BaseItemStack itemStack) { - this.player.getInventory().add(FabricAdapter.adapt(itemStack)); + this.player.getInventory().add(CoreMcAdapter.toNativeItemStack(itemStack)); } @Override public void dispatchCUIEvent(CUIEvent event) { - ServerPlayNetworking.send( - this.player, - new CUIPacket(event.getTypeId(), event.getParameters()) - ); + CoreMcPlatform.forCui().sendCUIPacket(this.player, new CUIPacket(event.getTypeId(), event.getParameters())); + } + + public ServerPlayer getPlayer() { + return this.player; } @Override @@ -169,15 +179,16 @@ public void printError(String msg) { public void print(Component component) { this.player.sendSystemMessage(ComponentConverter.Serializer.fromJson( GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())), - player.level().registryAccess() + player.registryAccess() )); } private void sendColorized(String msg, ChatFormatting formatting) { for (String part : msg.split("\n", 0)) { - MutableComponent component = net.minecraft.network.chat.Component.literal(part) - .withStyle(style -> style.withColor(formatting)); - this.player.sendSystemMessage(component); + this.player.sendSystemMessage( + net.minecraft.network.chat.Component.literal(part) + .withStyle(style -> style.withColor(formatting)) + ); } } @@ -189,7 +200,7 @@ public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { @Override public String[] getGroups() { - return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username); + return new String[]{}; } @Override @@ -199,7 +210,7 @@ public BlockBag getInventoryBlockBag() { @Override public boolean hasPermission(String perm) { - return FabricWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm); + return CoreMcPermissionsProvider.current().hasPermission(player, perm); } @Nullable @@ -224,23 +235,25 @@ public void setFlying(boolean flying) { @Override public > void sendFakeBlock(BlockVector3 pos, B block) { World world = getWorld(); - if (!(world instanceof FabricWorld fabricWorld)) { + if (!(world instanceof CoreMcWorld coreMcWorld)) { return; } - BlockPos loc = FabricAdapter.toBlockPos(pos); + BlockPos loc = CoreMcAdapter.toBlockPos(pos); if (block == null) { - final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket(fabricWorld.getWorld(), loc); + final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( + coreMcWorld.getWorld(), loc + ); player.connection.send(packetOut); } else { final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( loc, - FabricAdapter.adapt(block.toImmutableState()) + CoreMcAdapter.toNativeBlockState(block.toImmutableState()) ); player.connection.send(packetOut); if (block instanceof BaseBlock baseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { final LinCompoundTag nbtData = baseBlock.getNbt(); if (nbtData != null) { - player.connection.send(new ClientboundBlockEntityDataPacket( + player.connection.send(AccessorClientboundBlockEntityDataPacket.create( new BlockPos(pos.x(), pos.y(), pos.z()), BlockEntityType.STRUCTURE_BLOCK, NBTConverter.toNative(nbtData) @@ -255,13 +268,13 @@ public SessionKey getSessionKey() { return new SessionKeyImpl(player); } - static class SessionKeyImpl implements SessionKey { - // If not static, this will leak a reference + // If not static, this will leak a reference + public static final class SessionKeyImpl implements SessionKey { private final UUID uuid; private final String name; - SessionKeyImpl(ServerPlayer player) { + public SessionKeyImpl(ServerPlayer player) { this.uuid = player.getUUID(); this.name = player.getName().getString(); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPropertyAdapter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPropertyAdapter.java similarity index 89% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPropertyAdapter.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPropertyAdapter.java index bbfbc28720..14d1c09cce 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPropertyAdapter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPropertyAdapter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric.internal; +package com.sk89q.worldedit.coremc.internal; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.registry.state.Property; @@ -27,12 +27,12 @@ import static com.google.common.base.Preconditions.checkArgument; -class FabricPropertyAdapter> implements Property { +public final class CoreMcPropertyAdapter> implements Property { private final net.minecraft.world.level.block.state.properties.Property property; private final List values; - FabricPropertyAdapter(net.minecraft.world.level.block.state.properties.Property property) { + public CoreMcPropertyAdapter(net.minecraft.world.level.block.state.properties.Property property) { this.property = property; this.values = ImmutableList.copyOf(property.getPossibleValues()); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricRegistries.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java similarity index 74% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricRegistries.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java index 143bd0bd33..d4801c2bee 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricRegistries.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.world.registry.BiomeRegistry; import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; @@ -27,16 +27,15 @@ import com.sk89q.worldedit.world.registry.ItemRegistry; /** - * World data for the Fabric platform. + * Registry aggregation for Minecraft platforms sharing native code. */ -class FabricRegistries extends BundledRegistries { +public final class CoreMcRegistries extends BundledRegistries { - private static final FabricRegistries INSTANCE = new FabricRegistries(); - private final BlockRegistry blockRegistry = new FabricBlockRegistry(); - private final BiomeRegistry biomeRegistry = new FabricBiomeRegistry(); - private final ItemRegistry itemRegistry = new FabricItemRegistry(); - private final BlockCategoryRegistry blockCategoryRegistry = new FabricBlockCategoryRegistry(); - private final ItemCategoryRegistry itemCategoryRegistry = new FabricItemCategoryRegistry(); + private final BlockRegistry blockRegistry = new CoreMcBlockRegistry(); + private final BiomeRegistry biomeRegistry = new CoreMcBiomeRegistry(); + private final ItemRegistry itemRegistry = new CoreMcItemRegistry(); + private final BlockCategoryRegistry blockCategoryRegistry = new CoreMcBlockCategoryRegistry(); + private final ItemCategoryRegistry itemCategoryRegistry = new CoreMcItemCategoryRegistry(); @Override public BlockRegistry getBlockRegistry() { @@ -62,14 +61,4 @@ public BlockCategoryRegistry getBlockCategoryRegistry() { public ItemCategoryRegistry getItemCategoryRegistry() { return itemCategoryRegistry; } - - /** - * Get a static instance. - * - * @return an instance - */ - public static FabricRegistries getInstance() { - return INSTANCE; - } - } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java similarity index 80% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java index 746ba6d121..b0bd60bfea 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java @@ -17,14 +17,14 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.internal; +package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.neoforge.NeoForgeAdapter; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.concurrency.LazyReference; import net.minecraft.core.BlockPos; @@ -45,18 +45,18 @@ import java.util.Map; import java.util.function.Predicate; -public class NeoForgeServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { +public final class CoreMcServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { private final EditSession editSession; private final ServerLevel serverLevel; private final Map createdBlockEntities = new HashMap<>(); - private NeoForgeServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel) { + private CoreMcServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel) { this.editSession = editSession; this.serverLevel = serverLevel; } - public record LevelAndProxy(WorldGenLevel level, NeoForgeServerLevelDelegateProxy proxy) implements AutoCloseable { + public record LevelAndProxy(WorldGenLevel level, CoreMcServerLevelDelegateProxy proxy) implements AutoCloseable { @Override public void close() throws MaxChangedBlocksException { proxy.close(); @@ -64,7 +64,7 @@ public void close() throws MaxChangedBlocksException { } public static LevelAndProxy newInstance(EditSession editSession, ServerLevel serverLevel) { - NeoForgeServerLevelDelegateProxy proxy = new NeoForgeServerLevelDelegateProxy(editSession, serverLevel); + CoreMcServerLevelDelegateProxy proxy = new CoreMcServerLevelDelegateProxy(editSession, serverLevel); return new LevelAndProxy( (WorldGenLevel) Proxy.newProxyInstance( serverLevel.getClass().getClassLoader(), @@ -79,18 +79,18 @@ public static LevelAndProxy newInstance(EditSession editSession, ServerLevel ser private BlockEntity getBlockEntity(BlockPos blockPos) { // This doesn't synthesize or load from world. I think editing existing block entities without setting the block // (in the context of features) should not be supported in the first place. - BlockVector3 pos = NeoForgeAdapter.adapt(blockPos); + BlockVector3 pos = CoreMcAdapter.adapt(blockPos); return createdBlockEntities.get(pos); } private BlockState getBlockState(BlockPos blockPos) { - return NeoForgeAdapter.adapt(this.editSession.getBlockWithBuffer(NeoForgeAdapter.adapt(blockPos))); + return CoreMcAdapter.toNativeBlockState(this.editSession.getBlockWithBuffer(CoreMcAdapter.adapt(blockPos))); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { try { handleBlockEntity(blockPos, blockState); - return editSession.setBlock(NeoForgeAdapter.adapt(blockPos), NeoForgeAdapter.adapt(blockState)); + return editSession.setBlock(CoreMcAdapter.adapt(blockPos), CoreMcAdapter.fromNativeBlockState(blockState)); } catch (MaxChangedBlocksException e) { throw new RuntimeException(e); } @@ -99,7 +99,7 @@ private boolean setBlock(BlockPos blockPos, BlockState blockState) { // For BlockEntity#setBlockState, not sure why it's deprecated @SuppressWarnings("deprecation") private void handleBlockEntity(BlockPos blockPos, BlockState blockState) { - BlockVector3 pos = NeoForgeAdapter.adapt(blockPos); + BlockVector3 pos = CoreMcAdapter.adapt(blockPos); if (blockState.hasBlockEntity()) { if (!(blockState.getBlock() instanceof EntityBlock entityBlock)) { // This will probably never happen, as Mojang's own code assumes that @@ -124,9 +124,9 @@ private boolean removeBlock(BlockPos blockPos) { } private boolean addEntity(Entity entity) { - Vector3 pos = NeoForgeAdapter.adapt(entity.getPosition(0.0f)); - Location location = new Location(NeoForgeAdapter.adapt(serverLevel), pos.x(), pos.y(), pos.z()); - BaseEntity baseEntity = new NeoForgeEntity(entity).getState(); + Vector3 pos = CoreMcAdapter.adapt(entity.getPosition(0.0f)); + Location location = new Location(CoreMcAdapter.fromNativeWorld(serverLevel), pos.x(), pos.y(), pos.z()); + BaseEntity baseEntity = new CoreMcEntity(entity).getState(); return editSession.createEntity(location, baseEntity) != null; } @@ -136,7 +136,7 @@ public void close() throws MaxChangedBlocksException { BlockVector3 blockPos = entry.getKey(); BlockEntity blockEntity = entry.getValue(); - net.minecraft.nbt.CompoundTag tag = NeoForgeLoggingProblemReporter.with( + net.minecraft.nbt.CompoundTag tag = CoreMcLoggingProblemReporter.with( () -> "saving block entity at " + blockPos, reporter -> { var tagValueOutput = TagValueOutput.createWithContext(reporter, serverLevel.registryAccess()); @@ -146,7 +146,7 @@ public void close() throws MaxChangedBlocksException { ); editSession.setBlock( blockPos, - NeoForgeAdapter.adapt(blockEntity.getBlockState()) + CoreMcAdapter.fromNativeBlockState(blockEntity.getBlockState()) .toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))) ); } @@ -155,39 +155,40 @@ public void close() throws MaxChangedBlocksException { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { switch (method.getName()) { - case "getBlockState", "m_8055_" -> { + case "getBlockState" -> { if (args.length == 1 && args[0] instanceof BlockPos blockPos) { return getBlockState(blockPos); } } - case "isStateAtPosition", "m_7433_" -> { + case "isStateAtPosition" -> { if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) { @SuppressWarnings("unchecked") Predicate predicate = (Predicate) args[1]; return predicate.test(getBlockState(blockPos)); } } - case "getBlockEntity", "m_7702_" -> { + case "getBlockEntity" -> { if (args.length == 1 && args[0] instanceof BlockPos blockPos) { return getBlockEntity(blockPos); } } - case "setBlock", "m_7731_" -> { + case "setBlock" -> { if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof BlockState blockState) { return setBlock(blockPos, blockState); } } - case "removeBlock", "destroyBlock", "m_7471_", "m_7740_" -> { + case "removeBlock", "destroyBlock" -> { if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Boolean) { return removeBlock(blockPos); } } - case "addEntity", "m_8872_", "addFreshEntityWithPassengers", "m_47205_" -> { + case "addFreshEntityWithPassengers" -> { if (args.length >= 1 && args[0] instanceof Entity entity) { return addEntity(entity); } } - default -> { } + default -> { + } } return method.invoke(this.serverLevel, args); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeTransmogrifier.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java similarity index 86% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeTransmogrifier.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java index 0f95732868..c07252f016 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeTransmogrifier.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java @@ -17,13 +17,13 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.internal; +package com.sk89q.worldedit.coremc.internal; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.neoforge.NeoForgeAdapter; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.registry.state.BooleanProperty; import com.sk89q.worldedit.registry.state.DirectionalProperty; import com.sk89q.worldedit.registry.state.EnumProperty; @@ -43,11 +43,10 @@ /** * Raw, un-cached transformations. */ -public class NeoForgeTransmogrifier { - +public final class CoreMcTransmogrifier { private static final LoadingCache, Property> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override - public Property load(net.minecraft.world.level.block.state.properties.Property property) throws Exception { + public Property load(net.minecraft.world.level.block.state.properties.Property property) { return switch (property) { case net.minecraft.world.level.block.state.properties.BooleanProperty booleanProperty -> new BooleanProperty(property.getName(), ImmutableList.copyOf(booleanProperty.getPossibleValues())); @@ -56,17 +55,14 @@ public Property load(net.minecraft.world.level.block.state.properties.Propert case net.minecraft.world.level.block.state.properties.EnumProperty enumProperty -> { if (property.getValueClass() == net.minecraft.core.Direction.class) { yield new DirectionalProperty(property.getName(), property.getPossibleValues().stream() - .map(v -> NeoForgeAdapter.adaptEnumFacing((net.minecraft.core.Direction) v)) + .map(v -> CoreMcAdapter.adaptEnumFacing((net.minecraft.core.Direction) v)) .collect(ImmutableList.toImmutableList())); } - // Note: do not make x.asString a method reference. - // It will cause runtime bootstrap exceptions. - //noinspection Convert2MethodRef yield new EnumProperty(property.getName(), enumProperty.getPossibleValues().stream() - .map(x -> x.getSerializedName()) + .map(StringRepresentable::getSerializedName) .collect(ImmutableList.toImmutableList())); } - default -> new NeoForgePropertyAdapter<>(property); + default -> new CoreMcPropertyAdapter<>(property); }; } }); @@ -81,7 +77,7 @@ public static Map, Object> transmogToWorldEditProperties(BlockType b Object value = blockState.getValue(property); if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { if (property.getValueClass() == net.minecraft.core.Direction.class) { - value = NeoForgeAdapter.adaptEnumFacing((net.minecraft.core.Direction) value); + value = CoreMcAdapter.adaptEnumFacing((net.minecraft.core.Direction) value); } else { value = ((StringRepresentable) value).getSerializedName(); } @@ -104,7 +100,7 @@ private static net.minecraft.world.level.block.state.BlockState transmogToMinecr if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { if (property.getValueClass() == net.minecraft.core.Direction.class) { Direction dir = (Direction) value; - value = NeoForgeAdapter.adapt(dir); + value = CoreMcAdapter.adapt(dir); } else { String enumName = (String) value; value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getValue((String) value).orElseThrow(() -> @@ -119,17 +115,18 @@ private static net.minecraft.world.level.block.state.BlockState transmogToMinecr } public static net.minecraft.world.level.block.state.BlockState transmogToMinecraft(BlockState blockState) { - Block mcBlock = NeoForgeAdapter.adapt(blockState.getBlockType()); + Block mcBlock = CoreMcAdapter.toNativeBlock(blockState.getBlockType()); net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); Map, Object> states = blockState.getStates(); return transmogToMinecraftProperties(mcBlock.getStateDefinition(), newState, states); } public static BlockState transmogToWorldEdit(net.minecraft.world.level.block.state.BlockState blockState) { - BlockType blockType = NeoForgeAdapter.adapt(blockState.getBlock()); + BlockType blockType = CoreMcAdapter.fromNativeBlock(blockState.getBlock()); return blockType.getState(transmogToWorldEditProperties(blockType, blockState)); } - private NeoForgeTransmogrifier() { + private CoreMcTransmogrifier() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWatchdogImpl.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWatchdog.java similarity index 78% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWatchdogImpl.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWatchdog.java index cf4107b4ac..6dfa0eb9da 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWatchdogImpl.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWatchdog.java @@ -17,21 +17,22 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric.internal; +package com.sk89q.worldedit.coremc.internal; +import com.sk89q.worldedit.coremc.mixin.AccessorMinecraftServer; import com.sk89q.worldedit.extension.platform.Watchdog; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Util; -public final class FabricWatchdogImpl implements Watchdog { +public final class CoreMcWatchdog implements Watchdog { private final MinecraftServer server; - public FabricWatchdogImpl(MinecraftServer server) { + public CoreMcWatchdog(MinecraftServer server) { this.server = server; } @Override public void tick() { - server.nextTickTimeNanos = Util.getNanos(); + ((AccessorMinecraftServer) server).setNextTickTimeNanos(Util.getNanos()); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java similarity index 80% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java index bb81378a7c..b3a27ddda3 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -33,14 +33,12 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.mixin.AccessorChunkMap; +import com.sk89q.worldedit.coremc.mixin.AccessorMinecraftServer; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.fabric.internal.FabricEntity; -import com.sk89q.worldedit.fabric.internal.FabricLoggingProblemReporter; -import com.sk89q.worldedit.fabric.internal.FabricServerLevelDelegateProxy; -import com.sk89q.worldedit.fabric.internal.FabricWorldNativeAccess; -import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.Constants; @@ -52,6 +50,7 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.io.file.SafeFiles; import com.sk89q.worldedit.world.AbstractWorld; @@ -78,7 +77,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; @@ -97,7 +95,6 @@ import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.status.ChunkStatus; @@ -108,7 +105,6 @@ import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.level.saveddata.WeatherData; -import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.TagValueOutput; @@ -121,7 +117,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -137,31 +132,31 @@ import static com.google.common.base.Preconditions.checkState; /** - * An adapter to Minecraft worlds for WorldEdit. + * Shared implementation of a Minecraft world for platforms sharing native code. */ -public class FabricWorld extends AbstractWorld { +public final class CoreMcWorld extends AbstractWorld { private static final RandomSource random = RandomSource.create(); - private static Identifier getDimensionRegistryKey(Level world) { + private static Identifier getDimensionRegistryKey(ServerLevel world) { return Objects.requireNonNull(world.getServer(), "server cannot be null") .registryAccess() .lookupOrThrow(Registries.DIMENSION_TYPE) .getKey(world.dimensionType()); } - private final WeakReference worldRef; - private final FabricWorldNativeAccess worldNativeAccess; + private final WeakReference worldRef; + private final CoreMcWorldNativeAccess worldNativeAccess; /** * Construct a new world. * * @param world the world */ - FabricWorld(Level world) { + public CoreMcWorld(ServerLevel world) { checkNotNull(world); this.worldRef = new WeakReference<>(world); - this.worldNativeAccess = new FabricWorldNativeAccess(worldRef); + this.worldNativeAccess = new CoreMcWorldNativeAccess(worldRef); } /** @@ -170,8 +165,8 @@ private static Identifier getDimensionRegistryKey(Level world) { * @return the world * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) */ - public Level getWorld() { - Level world = worldRef.get(); + public ServerLevel getWorld() { + ServerLevel world = worldRef.get(); if (world != null) { return world; } else { @@ -181,8 +176,7 @@ public Level getWorld() { @Override public String getName() { - LevelData levelProperties = getWorld().getLevelData(); - return ((ServerLevelData) levelProperties).getLevelName(); + return ((ServerLevelData) getWorld().getLevelData()).getLevelName(); } @Override @@ -192,10 +186,8 @@ public String id() { @Override public Path getStoragePath() { - final Level world = getWorld(); - MinecraftServer server = world.getServer(); - checkState(server != null, "Need a server world"); - return server.storageSource.getDimensionPath(world.dimension()); + ServerLevel world = getWorld(); + return ((AccessorMinecraftServer) world.getServer()).getStorageSource().getDimensionPath(world.dimension()); } @Override @@ -207,20 +199,19 @@ public > boolean setBlock(BlockVector3 position, B @Override public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) { worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); - return Sets.intersection(FabricWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); + return Sets.intersection(CoreMcPlatform.SUPPORTED_SIDE_EFFECTS, sideEffectSet.getSideEffectsToApply()); } @Override public int getBlockLightLevel(BlockVector3 position) { checkNotNull(position); - return getWorld().getMaxLocalRawBrightness(FabricAdapter.toBlockPos(position)); + return getWorld().getMaxLocalRawBrightness(CoreMcAdapter.toBlockPos(position)); } @Override public boolean clearContainerBlockContents(BlockVector3 position) { checkNotNull(position); - - BlockEntity tile = getWorld().getBlockEntity(FabricAdapter.toBlockPos(position)); + BlockEntity tile = getWorld().getBlockEntity(CoreMcAdapter.toBlockPos(position)); if (tile instanceof Clearable clearable) { clearable.clearContent(); return true; @@ -236,7 +227,7 @@ public BiomeType getBiome(BlockVector3 position) { } private BiomeType getBiomeInChunk(BlockVector3 position, ChunkAccess chunk) { - return FabricAdapter.adapt( + return CoreMcAdapter.fromNativeBiome( chunk.getNoiseBiome(position.x() >> 2, position.y() >> 2, position.z() >> 2).value() ); } @@ -251,22 +242,21 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { var biomeArray = (PalettedContainer>) chunk.getSection(chunk.getSectionIndex(position.y())).getBiomes(); biomeArray.getAndSetUnchecked( (position.x() >> 2) & 3, (position.y() >> 2) & 3, (position.z() >> 2) & 3, - getWorld().registryAccess().lookup(Registries.BIOME) - .orElseThrow() + getWorld().registryAccess().lookupOrThrow(Registries.BIOME) .getOrThrow(ResourceKey.create(Registries.BIOME, Identifier.parse(biome.id()))) ); chunk.markUnsaved(); return true; } - private static final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(FabricFakePlayer::new)); + private static final LoadingCache fakePlayers + = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(CoreMcFakePlayer::new)); @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); - ServerLevel world = (ServerLevel) getWorld(); - final FabricFakePlayer fakePlayer; + ItemStack stack = CoreMcAdapter.toNativeItemStack(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); + ServerLevel world = getWorld(); + final CoreMcFakePlayer fakePlayer; try { fakePlayer = fakePlayers.get(world); } catch (ExecutionException ignored) { @@ -274,20 +264,19 @@ public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { } fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); fakePlayer.absSnapTo(position.x(), position.y(), position.z(), - (float) face.toVector().toYaw(), (float) face.toVector().toPitch()); - final BlockPos blockPos = FabricAdapter.toBlockPos(position); - final BlockHitResult rayTraceResult = new BlockHitResult(FabricAdapter.toVec3(position), - FabricAdapter.adapt(face), blockPos, false); + (float) face.toVector().toYaw(), (float) face.toVector().toPitch()); + final BlockPos blockPos = CoreMcAdapter.toBlockPos(position); + final BlockHitResult rayTraceResult = new BlockHitResult(CoreMcAdapter.toVec3(position), + CoreMcAdapter.adapt(face), blockPos, false); UseOnContext itemUseContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); InteractionResult used = stack.useOn(itemUseContext); - if (used != InteractionResult.SUCCESS) { - // try activating the block - used = getWorld().getBlockState(blockPos).useItemOn(stack, world, fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); - } - if (used != InteractionResult.SUCCESS) { - used = stack.use(world, fakePlayer, InteractionHand.MAIN_HAND); + if (!used.consumesAction()) { + used = world.getBlockState(blockPos).useItemOn(stack, world, fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); + if (!used.consumesAction()) { + used = stack.getItem().use(world, fakePlayer, InteractionHand.MAIN_HAND); + } } - return used == InteractionResult.SUCCESS; + return used.consumesAction(); } @Override @@ -299,30 +288,24 @@ public void dropItem(Vector3 position, BaseItemStack item) { return; } - ItemEntity entity = new ItemEntity(getWorld(), position.x(), position.y(), position.z(), FabricAdapter.adapt(item)); + ItemEntity entity = new ItemEntity(getWorld(), position.x(), position.y(), position.z(), CoreMcAdapter.toNativeItemStack(item)); entity.setPickUpDelay(10); getWorld().addFreshEntity(entity); } @Override public void simulateBlockMine(BlockVector3 position) { - BlockPos pos = FabricAdapter.toBlockPos(position); + BlockPos pos = CoreMcAdapter.toBlockPos(position); getWorld().destroyBlock(pos, true); } @Override public boolean canPlaceAt(BlockVector3 position, BlockState blockState) { - return FabricAdapter.adapt(blockState).canSurvive(getWorld(), FabricAdapter.toBlockPos(position)); + return CoreMcAdapter.toNativeBlockState(blockState).canSurvive(getWorld(), CoreMcAdapter.toBlockPos(position)); } @Override public boolean regenerate(Region region, Extent extent, RegenOptions options) { - // Don't even try to regen if it's going to fail. - ChunkSource provider = getWorld().getChunkSource(); - if (!(provider instanceof ServerChunkCache)) { - return false; - } - if (options.getSeed().isPresent()) { throw new UnsupportedOperationException("26.1+ worldgen does not support overriding the seed for regen"); } @@ -340,7 +323,7 @@ private void doRegen(Region region, Extent extent, RegenOptions options) throws Path tempDir = Files.createTempDirectory("WorldEditWorldGen"); LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("WorldEditTempGen")) { - ServerLevel originalWorld = (ServerLevel) getWorld(); + ServerLevel originalWorld = getWorld(); ResourceKey worldRegKey = originalWorld.dimension(); try (ServerLevel serverWorld = new ServerLevel( @@ -373,7 +356,7 @@ private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); // drive executor until loading finishes - serverWorld.getChunkSource().mainThreadProcessor + ((AccessorChunkMap) serverWorld.getChunkSource().chunkMap).getMainThreadExecutor() .managedBlock(() -> { // bail out early if a future fails if (chunkLoadings.stream().anyMatch(ftr -> @@ -393,12 +376,12 @@ private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld } for (BlockVector3 vec : region) { - BlockPos pos = FabricAdapter.toBlockPos(vec); + BlockPos pos = CoreMcAdapter.toBlockPos(vec); ChunkAccess chunk = chunks.get(ChunkPos.containing(pos)); - BlockStateHolder state = FabricAdapter.adapt(chunk.getBlockState(pos)); + BlockStateHolder state = CoreMcAdapter.fromNativeBlockState(chunk.getBlockState(pos)); BlockEntity blockEntity = chunk.getBlockEntity(pos); if (blockEntity != null) { - CompoundTag tag = FabricLoggingProblemReporter.with( + CompoundTag tag = CoreMcLoggingProblemReporter.with( () -> "serializing block entity at " + pos, reporter -> { var tagValueOutput = TagValueOutput.createWithContext(reporter, getWorld().registryAccess()); @@ -431,7 +414,7 @@ private List> submitChunkLoadTasks(Region region, @SuppressWarnings("deprecation") @Nullable - private static ResourceKey createTreeFeatureGenerator(com.sk89q.worldedit.util.TreeGenerator.TreeType type) { + private static ResourceKey createTreeFeatureGenerator(TreeGenerator.TreeType type) { return switch (type) { // Based off of the SaplingGenerator class, as well as uses of DefaultBiomeFeatures fields case TREE -> TreePlacements.OAK_CHECKED; @@ -459,7 +442,7 @@ private static ResourceKey createTreeFeatureGenerator(com.sk89q.w case RANDOM -> { // We're intentionally using index here to get a random tree type @SuppressWarnings("EnumOrdinal") - com.sk89q.worldedit.util.TreeGenerator.TreeType randomTreeType = com.sk89q.worldedit.util.TreeGenerator.TreeType.values()[ThreadLocalRandom.current().nextInt(com.sk89q.worldedit.util.TreeGenerator.TreeType.values().length)]; + TreeGenerator.TreeType randomTreeType = TreeGenerator.TreeType.values()[ThreadLocalRandom.current().nextInt(TreeGenerator.TreeType.values().length)]; yield createTreeFeatureGenerator(randomTreeType); } default -> null; @@ -468,19 +451,19 @@ private static ResourceKey createTreeFeatureGenerator(com.sk89q.w @SuppressWarnings("deprecation") @Override - public boolean generateTree(com.sk89q.worldedit.util.TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { - ServerLevel world = (ServerLevel) getWorld(); + public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { + ServerLevel world = getWorld(); PlacedFeature generator = Optional.ofNullable(createTreeFeatureGenerator(type)) .map(k -> world.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE).getValue(k)) .orElse(null); ServerChunkCache chunkManager = world.getChunkSource(); - if (type == com.sk89q.worldedit.util.TreeGenerator.TreeType.CHORUS_PLANT) { + if (type == TreeGenerator.TreeType.CHORUS_PLANT) { position = position.add(0, 1, 0); } - try (FabricServerLevelDelegateProxy.LevelAndProxy proxyLevel = FabricServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { return generator != null && generator.place( proxyLevel.level(), chunkManager.getGenerator(), random, - FabricAdapter.toBlockPos(position) + CoreMcAdapter.toBlockPos(position) ); } } @@ -491,26 +474,26 @@ public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 if (customResult != null) { return customResult; } - ServerLevel world = (ServerLevel) getWorld(); + ServerLevel world = getWorld(); PlacedFeature generator = world.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE).getValue(Identifier.tryParse(type.id())); ServerChunkCache chunkManager = world.getChunkSource(); - try (FabricServerLevelDelegateProxy.LevelAndProxy proxyLevel = FabricServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { return generator != null && generator.place( - proxyLevel.level(), chunkManager.getGenerator(), random, - FabricAdapter.toBlockPos(position) + proxyLevel.level(), chunkManager.getGenerator(), random, + CoreMcAdapter.toBlockPos(position) ); } } @Override public boolean generateFeature(ConfiguredFeatureType type, EditSession editSession, BlockVector3 position) { - ServerLevel world = (ServerLevel) getWorld(); + ServerLevel world = getWorld(); ConfiguredFeature feature = world.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(Identifier.tryParse(type.id())); ServerChunkCache chunkManager = world.getChunkSource(); - try (FabricServerLevelDelegateProxy.LevelAndProxy proxyLevel = FabricServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { return feature != null && feature.place( proxyLevel.level(), chunkManager.getGenerator(), random, - FabricAdapter.toBlockPos(position) + CoreMcAdapter.toBlockPos(position) ); } catch (MaxChangedBlocksException e) { throw new RuntimeException(e); @@ -519,7 +502,7 @@ public boolean generateFeature(ConfiguredFeatureType type, EditSession editSessi @Override public boolean generateStructure(StructureType type, EditSession editSession, BlockVector3 position) { - ServerLevel world = (ServerLevel) getWorld(); + ServerLevel world = getWorld(); Registry structureRegistry = world.registryAccess().lookupOrThrow(Registries.STRUCTURE); Structure structure = structureRegistry.getValue(Identifier.tryParse(type.id())); if (structure == null) { @@ -527,7 +510,7 @@ public boolean generateStructure(StructureType type, EditSession editSession, Bl } ServerChunkCache chunkManager = world.getChunkSource(); - try (FabricServerLevelDelegateProxy.LevelAndProxy proxyLevel = FabricServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { ChunkPos chunkPos = ChunkPos.containing(new BlockPos(position.x(), position.y(), position.z())); StructureStart structureStart = structure.generate( structureRegistry.wrapAsHolder(structure), world.dimension(), world.registryAccess(), @@ -559,7 +542,7 @@ public boolean generateStructure(StructureType type, EditSession editSession, Bl @Override public void checkLoadedChunk(BlockVector3 pt) { - getWorld().getChunk(FabricAdapter.toBlockPos(pt)); + getWorld().getChunk(CoreMcAdapter.toBlockPos(pt)); } @Override @@ -573,16 +556,16 @@ public void sendBiomeUpdates(Iterable chunks) { for (BlockVector2 chunk : chunks) { nativeChunks.add(getWorld().getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); } - ((ServerLevel) getWorld()).getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); + getWorld().getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); } @Override public void fixLighting(Iterable chunks) { - Level world = getWorld(); + ServerLevel world = getWorld(); for (BlockVector2 chunk : chunks) { // Fetch the chunk after light initialization at least // We'll be doing a full relight anyways, so we don't need to be LIGHT yet - ((ServerLevel) world).getChunkSource().getLightEngine().lightChunk(world.getChunk( + world.getChunkSource().getLightEngine().lightChunk(world.getChunk( chunk.x(), chunk.z(), ChunkStatus.INITIALIZE_LIGHT ), false).exceptionally(t -> { WorldEdit.logger.warn("Failed to relight chunk at " + chunk, t); @@ -650,16 +633,15 @@ public int getMaxY() { @Override public BlockVector3 getSpawnPosition() { - return FabricAdapter.adapt(getWorld().getLevelData().getRespawnData().pos()); + return CoreMcAdapter.adapt(getWorld().getLevelData().getRespawnData().pos()); } @Override public BlockState getBlock(BlockVector3 position) { net.minecraft.world.level.block.state.BlockState mcState = getWorld() - .getChunk(position.x() >> 4, position.z() >> 4) - .getBlockState(FabricAdapter.toBlockPos(position)); - - return FabricAdapter.adapt(mcState); + .getChunk(position.x() >> 4, position.z() >> 4) + .getBlockState(CoreMcAdapter.toBlockPos(position)); + return CoreMcAdapter.fromNativeBlockState(mcState); } @Override @@ -669,7 +651,7 @@ public BaseBlock getFullBlock(BlockVector3 position) { BlockEntity tile = ((LevelChunk) getWorld().getChunk(pos)).getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); if (tile != null) { - CompoundTag tag = FabricLoggingProblemReporter.with( + CompoundTag tag = CoreMcLoggingProblemReporter.with( () -> "serializing block entity at " + pos, reporter -> { var tagValueOutput = TagValueOutput.createWithContext(reporter, getWorld().registryAccess()); @@ -691,9 +673,9 @@ public int hashCode() { @Override public boolean equals(Object o) { return switch (o) { - case FabricWorld other -> { - Level otherWorld = other.worldRef.get(); - Level thisWorld = worldRef.get(); + case CoreMcWorld other -> { + ServerLevel otherWorld = other.worldRef.get(); + ServerLevel thisWorld = worldRef.get(); yield otherWorld != null && otherWorld.equals(thisWorld); } case World world -> world.getName().equals(getName()); @@ -703,36 +685,33 @@ public boolean equals(Object o) { @Override public List getEntities(Region region) { - final Level world = getWorld(); + final ServerLevel world = getWorld(); AABB box = new AABB( - FabricAdapter.toVec3(region.getMinimumPoint()), - FabricAdapter.toVec3(region.getMaximumPoint().add(BlockVector3.ONE)) + CoreMcAdapter.toVec3(region.getMinimumPoint()), + CoreMcAdapter.toVec3(region.getMaximumPoint().add(BlockVector3.ONE)) ); List nmsEntities = world.getEntities( (net.minecraft.world.entity.Entity) null, box, - e -> region.contains(FabricAdapter.adapt(e.blockPosition())) + e -> region.contains(CoreMcAdapter.adapt(e.blockPosition())) ); return nmsEntities.stream() - .map(FabricEntity::new) + .map(CoreMcEntity::new) .collect(ImmutableList.toImmutableList()); } @Override public List getEntities() { - final Level world = getWorld(); - if (!(world instanceof ServerLevel serverLevel)) { - return Collections.emptyList(); - } - return Streams.stream(serverLevel.getAllEntities()) - .map(FabricEntity::new) + final ServerLevel world = getWorld(); + return Streams.stream(world.getAllEntities()) + .map(entity -> new CoreMcEntity(entity)) .collect(ImmutableList.toImmutableList()); } @Nullable @Override public Entity createEntity(Location location, BaseEntity entity) { - ServerLevel world = (ServerLevel) getWorld(); + ServerLevel world = getWorld(); String entityId = entity.getType().id(); final Optional> entityType = EntityType.byString(entityId); if (entityType.isEmpty()) { @@ -754,7 +733,7 @@ public Entity createEntity(Location location, BaseEntity entity) { }); if (createdEntity != null) { world.addFreshEntityWithPassengers(createdEntity); - return new FabricEntity(createdEntity); + return new CoreMcEntity(createdEntity); } return null; } @@ -777,7 +756,7 @@ public Mask createLiquidMask() { return new AbstractExtentMask(this) { @Override public boolean test(BlockVector3 vector) { - return FabricAdapter.adapt(getExtent().getBlock(vector)).getBlock() instanceof LiquidBlock; + return CoreMcAdapter.toNativeBlockState(getExtent().getBlock(vector)).getBlock() instanceof LiquidBlock; } }; } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldNativeAccess.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java similarity index 92% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldNativeAccess.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java index de54fef426..f1e34f8a3d 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldNativeAccess.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java @@ -17,17 +17,16 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.internal; +package com.sk89q.worldedit.coremc.internal; +import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.neoforge.NeoForgeAdapter; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import net.minecraft.core.BlockPos; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -40,11 +39,11 @@ import java.util.Objects; import javax.annotation.Nullable; -public class NeoForgeWorldNativeAccess implements WorldNativeAccess { +public final class CoreMcWorldNativeAccess implements WorldNativeAccess { private final WeakReference world; private SideEffectSet sideEffectSet; - public NeoForgeWorldNativeAccess(WeakReference world) { + public CoreMcWorldNativeAccess(WeakReference world) { this.world = world; } @@ -67,7 +66,7 @@ public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { int stateId = BlockStateIdAccess.getBlockStateId(state); return BlockStateIdAccess.isValidInternalId(stateId) ? Block.stateById(stateId) - : NeoForgeAdapter.adapt(state); + : CoreMcAdapter.toNativeBlockState(state); } @Override @@ -106,12 +105,12 @@ public void updateLightingForBlock(BlockPos position) { @Override public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) { net.minecraft.nbt.CompoundTag nativeTag = NBTConverter.toNative(tag); - Level level = getWorld(); + ServerLevel level = getWorld(); BlockEntity tileEntity = level.getChunkAt(position).getBlockEntity(position); if (tileEntity == null) { return false; } - return NeoForgeLoggingProblemReporter.with( + return CoreMcLoggingProblemReporter.with( () -> "loading tile entity at " + position, reporter -> { var tagValueInput = TagValueInput.create(reporter, level.registryAccess(), nativeTag); @@ -175,6 +174,6 @@ public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newSta @Override public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { getWorld().updatePOIOnBlockStateChange(pos, oldState, newState); - newState.onBlockStateChange(getWorld(), pos, oldState); + CoreMcPlatform.forWorldEditing().extraOnBlockStateChange(getWorld(), pos, oldState, newState); } } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NBTConverter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/NBTConverter.java similarity index 99% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NBTConverter.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/NBTConverter.java index b2813e7fbc..d0230a9b30 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NBTConverter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/NBTConverter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.internal; +package com.sk89q.worldedit.coremc.internal; import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.ByteTag; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ThreadSafeCache.java similarity index 92% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ThreadSafeCache.java index d769334316..92131860de 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/ThreadSafeCache.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/ThreadSafeCache.java @@ -17,9 +17,8 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.coremc.internal; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -31,7 +30,7 @@ /** * Caches data that cannot be accessed from another thread safely. */ -public class ThreadSafeCache implements ServerTickEvents.EndTick { +public class ThreadSafeCache { private static final long REFRESH_DELAY = 1000 * 30; private static final ThreadSafeCache INSTANCE = new ThreadSafeCache(); @@ -47,7 +46,6 @@ public Set getOnlineIds() { return onlineIds; } - @Override public void onEndTick(MinecraftServer server) { long now = System.currentTimeMillis(); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWatchdog.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorChunkMap.java similarity index 64% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWatchdog.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorChunkMap.java index c6a9b475ae..0b24ac85a0 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWatchdog.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorChunkMap.java @@ -17,22 +17,15 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.coremc.mixin; -import com.sk89q.worldedit.extension.platform.Watchdog; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.util.Util; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.util.thread.BlockableEventLoop; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; -class NeoForgeWatchdog implements Watchdog { - - private final DedicatedServer server; - - NeoForgeWatchdog(DedicatedServer server) { - this.server = server; - } - - @Override - public void tick() { - server.nextTickTimeNanos = Util.getNanos(); - } +@Mixin(ChunkMap.class) +public interface AccessorChunkMap { + @Accessor + BlockableEventLoop getMainThreadExecutor(); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorClientboundBlockEntityDataPacket.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorClientboundBlockEntityDataPacket.java new file mode 100644 index 0000000000..75bac830d3 --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorClientboundBlockEntityDataPacket.java @@ -0,0 +1,41 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ClientboundBlockEntityDataPacket.class) +public interface AccessorClientboundBlockEntityDataPacket { + // We want to call this as it will be replaced at runtime + @SuppressWarnings("DoNotCallSuggester") + @Invoker("") + static ClientboundBlockEntityDataPacket create( + final BlockPos pos, + final BlockEntityType type, + final CompoundTag tag + ) { + throw new AssertionError("Should be replaced by Mixin"); + } +} diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorCommandSourceStack.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorCommandSourceStack.java new file mode 100644 index 0000000000..c8973c75ac --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorCommandSourceStack.java @@ -0,0 +1,31 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.mixin; + +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(CommandSourceStack.class) +public interface AccessorCommandSourceStack { + @Accessor + CommandSource getSource(); +} diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorMinecraftServer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorMinecraftServer.java new file mode 100644 index 0000000000..2f6388aaee --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorMinecraftServer.java @@ -0,0 +1,34 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.mixin; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.storage.LevelStorageSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MinecraftServer.class) +public interface AccessorMinecraftServer { + @Accessor + void setNextTickTimeNanos(long nextTickTimeNanos); + + @Accessor + LevelStorageSource.LevelStorageAccess getStorageSource(); +} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/AccessorServerPlayerGameMode.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorServerPlayerGameMode.java similarity index 96% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/AccessorServerPlayerGameMode.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorServerPlayerGameMode.java index 234799dc28..af29455420 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/AccessorServerPlayerGameMode.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/AccessorServerPlayerGameMode.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.mixin; +package com.sk89q.worldedit.coremc.mixin; import net.minecraft.server.level.ServerPlayerGameMode; import org.spongepowered.asm.mixin.Mixin; @@ -25,7 +25,6 @@ @Mixin(ServerPlayerGameMode.class) public interface AccessorServerPlayerGameMode { - @Accessor("isDestroyingBlock") boolean isDestroyingBlock(); } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/MixinServerGamePacketListenerImpl.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java similarity index 71% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/MixinServerGamePacketListenerImpl.java rename to worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java index 5c94f5b140..1287dd73a4 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/mixin/MixinServerGamePacketListenerImpl.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java @@ -17,10 +17,10 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge.mixin; +package com.sk89q.worldedit.coremc.mixin; import com.google.errorprone.annotations.Keep; -import com.sk89q.worldedit.neoforge.NeoForgeWorldEdit; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.network.protocol.game.ServerboundSwingPacket; import net.minecraft.server.level.ServerPlayer; @@ -41,22 +41,28 @@ public class MixinServerGamePacketListenerImpl { private int ignoreSwingPackets; @Keep - @SuppressWarnings("UnusedVariable") - @Inject(method = "handleAnimate", at = @At("HEAD")) - private void onAnimate(ServerboundSwingPacket packet, CallbackInfo ci) { + @Inject( + method = "handleAnimate", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;swing(Lnet/minecraft/world/InteractionHand;)V") + ) + private void onAnimate(ServerboundSwingPacket packet, @SuppressWarnings("UnusedVariable") CallbackInfo ci) { if (!((AccessorServerPlayerGameMode) this.player.gameMode).isDestroyingBlock()) { if (this.ignoreSwingPackets > 0) { this.ignoreSwingPackets--; - } else if (NeoForgeWorldEdit.inst != null) { - NeoForgeWorldEdit.inst.onLeftClickAir(this.player, packet.getHand()); + } else { + CoreMcPlatform.optionallyForWorldEditing().ifPresent(platform -> + platform.getMod().onLeftClickAir(this.player, packet.getHand()) + ); } } } @Keep - @SuppressWarnings("UnusedVariable") - @Inject(method = "handlePlayerAction", at = @At("HEAD")) - private void onAction(ServerboundPlayerActionPacket packet, CallbackInfo ci) { + @Inject( + method = "handlePlayerAction", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;resetLastActionTime()V") + ) + private void onAction(ServerboundPlayerActionPacket packet, @SuppressWarnings("UnusedVariable") CallbackInfo ci) { switch (packet.getAction()) { case DROP_ITEM, DROP_ALL_ITEMS, START_DESTROY_BLOCK -> this.ignoreSwingPackets++; default -> { diff --git a/worldedit-fabric/src/main/resources/assets/worldedit/icon.png b/worldedit-core-mc/src/main/resources/assets/worldedit/icon.png similarity index 100% rename from worldedit-fabric/src/main/resources/assets/worldedit/icon.png rename to worldedit-core-mc/src/main/resources/assets/worldedit/icon.png diff --git a/worldedit-fabric/src/main/resources/defaults/worldedit.properties b/worldedit-core-mc/src/main/resources/defaults/worldedit.properties similarity index 100% rename from worldedit-fabric/src/main/resources/defaults/worldedit.properties rename to worldedit-core-mc/src/main/resources/defaults/worldedit.properties diff --git a/worldedit-fabric/src/main/resources/pack.mcmeta b/worldedit-core-mc/src/main/resources/pack.mcmeta similarity index 100% rename from worldedit-fabric/src/main/resources/pack.mcmeta rename to worldedit-core-mc/src/main/resources/pack.mcmeta diff --git a/worldedit-core-mc/src/main/resources/worldedit-coremc.mixins.json b/worldedit-core-mc/src/main/resources/worldedit-coremc.mixins.json new file mode 100644 index 0000000000..3e2a614b29 --- /dev/null +++ b/worldedit-core-mc/src/main/resources/worldedit-coremc.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "package": "com.sk89q.worldedit.coremc.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "AccessorChunkMap", + "AccessorClientboundBlockEntityDataPacket", + "AccessorCommandSourceStack", + "AccessorMinecraftServer", + "AccessorServerPlayerGameMode", + "MixinServerGamePacketListenerImpl" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/worldedit-core-mc/src/main/resources/worldedit.accesswidener b/worldedit-core-mc/src/main/resources/worldedit.accesswidener deleted file mode 100644 index 96d7240b28..0000000000 --- a/worldedit-core-mc/src/main/resources/worldedit.accesswidener +++ /dev/null @@ -1,18 +0,0 @@ -accessWidener v2 official - -accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor -accessible field net/minecraft/server/level/ServerChunkCache mainThreadProcessor Lnet/minecraft/server/level/ServerChunkCache$MainThreadExecutor; - -accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource; - -accessible field net/minecraft/server/level/ServerPlayerGameMode isDestroyingBlock Z - -accessible field net/minecraft/world/level/storage/DerivedLevelData wrapped Lnet/minecraft/world/level/storage/ServerLevelData; - -#accessible field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; -#mutable field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; - -accessible method net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket (Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V - -accessible field net/minecraft/server/MinecraftServer nextTickTimeNanos J -accessible field net/minecraft/server/MinecraftServer storageSource Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess; diff --git a/worldedit-core-mc/textconv-core-mc.py b/worldedit-core-mc/textconv-core-mc.py new file mode 100755 index 0000000000..d62b4e7c61 --- /dev/null +++ b/worldedit-core-mc/textconv-core-mc.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +Git textconv filter that normalizes platform-specific terms to platform$. + +Replaces Fabric/NeoForge/CoreMc identifiers with neutral placeholders so that +git diff only shows code changes. + +Setup: + git config diff.core-mc.textconv ./worldedit-core-mc/textconv-core-mc.py +""" +import re +import sys + + +def normalize(content: str) -> str: + """Replace all platform-specific terms with placeholders.""" + # Package names -- longest (with .internal) first to avoid partial matches + content = content.replace("com.sk89q.worldedit.fabric.internal", "com.sk89q.worldedit._platform_.internal") + content = content.replace("com.sk89q.worldedit.neoforge.internal", "com.sk89q.worldedit._platform_.internal") + content = content.replace("com.sk89q.worldedit.coremc.internal", "com.sk89q.worldedit._platform_.internal") + content = content.replace("com.sk89q.worldedit.fabric", "com.sk89q.worldedit._platform_") + content = content.replace("com.sk89q.worldedit.neoforge", "com.sk89q.worldedit._platform_") + content = content.replace("com.sk89q.worldedit.coremc", "com.sk89q.worldedit._platform_") + + # PascalCase class/type prefixes: FabricPlayer -> platform$Player + content = re.sub(r"\bFabric(?=[A-Z])", "platform$", content) + content = re.sub(r"\bNeoForge(?=[A-Z])", "platform$", content) + content = re.sub(r"\bCoreMc(?=[A-Z])", "platform$", content) + + # camelCase variable prefixes: fabricWorld -> platform$World + content = re.sub(r"\bfabric(?=[A-Z])", "platform$", content) + content = re.sub(r"\bneoForge(?=[A-Z])", "platform$", content) + content = re.sub(r"\bcoreMc(?=[A-Z])", "platform$", content) + + return content + + +def main() -> int: + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + return 2 + + with open(sys.argv[1]) as f: + content = f.read() + + sys.stdout.write(normalize(content)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 51a6506fdb..1d69bf7a09 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -4,6 +4,7 @@ plugins { `java-library` antlr id("buildlogic.core-and-platform") + id("buildlogic.expose-resources") } configurations { @@ -122,17 +123,6 @@ tasks.named("processResources") { } } -// "Publish" a resources variant for other projects to consume -configurations.consumable("resourcesVariant") { - // Similar to mainSourceElements - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category::class, Category.VERIFICATION)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling::class, Bundling.EXTERNAL)) - attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, objects.named(VerificationType::class, "resources")) - } - outgoing.artifact(tasks.named("processResources")) -} - configure { publications.named("maven") { artifactId = the().archivesName.get() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 2a01d6925d..a61eb098d3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.extension.platform; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; @@ -46,18 +47,19 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors; import com.sk89q.worldedit.util.eventbus.Subscribe; +import com.sk89q.worldedit.util.lifecycle.Lifecycled; import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; import com.sk89q.worldedit.world.World; import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.Collection; -import java.util.EnumMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -78,7 +80,11 @@ public class PlatformManager { private final PlatformCommandManager platformCommandManager; private final SimpleLifecycled executorService; private final Map platforms = Maps.newHashMap(); - private final Map preferences = new EnumMap<>(Capability.class); + private final ImmutableMap> preferences = Stream.of(Capability.values()) + .collect(Maps.toImmutableEnumMap( + c -> c, + _ -> SimpleLifecycled.invalid() + )); private @Nullable String firstSeenVersion; private final AtomicBoolean initialized = new AtomicBoolean(); private final AtomicBoolean configured = new AtomicBoolean(); @@ -144,12 +150,14 @@ public synchronized boolean unregister(Platform platform) { // Check whether this platform was chosen to be the preferred one // for any capability and be sure to remove it - Iterator> it = preferences.entrySet().iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - if (entry.getValue().equals(platform)) { - entry.getKey().uninitialize(this, entry.getValue()); - it.remove(); + for (Entry> entry : preferences.entrySet()) { + Capability cap = entry.getKey(); + SimpleLifecycled lifecycled = entry.getValue(); + + Platform value = lifecycled.value().orElse(null); + if (platform.equals(value)) { + cap.uninitialize(this, platform); + lifecycled.invalidate(); choosePreferred = true; // Have to choose new favorites } } @@ -162,6 +170,28 @@ public synchronized boolean unregister(Platform platform) { return removed; } + private SimpleLifecycled getPreferredUnsynchronized(Capability capability) { + SimpleLifecycled prefLifecycled = preferences.get(capability); + assert prefLifecycled != null : "All capabilities should have a lifecycled in the map"; + return prefLifecycled; + } + + /** + * Get the preferred platform for handling a certain capability. + * + *

+ * The lifecycled will be valid if a platform is currently preferred for the capability, and invalid otherwise. + * If preferences are updated, then the lifecycled will be invalidated and a new value will be set if a new + * preferred platform is found. + *

+ * + * @param capability the capability + * @return the lifecycled preferred platform + */ + public synchronized Lifecycled getPreferred(Capability capability) { + return getPreferredUnsynchronized(capability); + } + /** * Get the preferred platform for handling a certain capability. Throws if none are available. * @@ -170,9 +200,9 @@ public synchronized boolean unregister(Platform platform) { * @throws NoCapablePlatformException thrown if no platform is capable */ public synchronized Platform queryCapability(Capability capability) throws NoCapablePlatformException { - Platform platform = preferences.get(checkNotNull(capability)); - if (platform != null) { - return platform; + Optional platform = getPreferredUnsynchronized(checkNotNull(capability)).value(); + if (platform.isPresent()) { + return platform.get(); } else { if (preferences.isEmpty()) { // Not all platforms registered, this is being called too early! @@ -192,7 +222,10 @@ private synchronized void choosePreferred() { for (Capability capability : Capability.values()) { Platform preferred = findMostPreferred(capability); if (preferred != null) { - Platform oldPreferred = preferences.put(capability, preferred); + SimpleLifecycled prefLifecycled = getPreferredUnsynchronized(capability); + + Platform oldPreferred = prefLifecycled.value().orElse(null); + prefLifecycled.newValue(preferred); // only (re)initialize if it changed if (preferred != oldPreferred) { // uninitialize if needed @@ -205,7 +238,7 @@ private synchronized void choosePreferred() { } // Fire configuration event - if (preferences.containsKey(Capability.CONFIGURATION) && configured.compareAndSet(false, true)) { + if (getPreferredUnsynchronized(Capability.CONFIGURATION).isValid() && configured.compareAndSet(false, true)) { worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration())); } } @@ -365,7 +398,9 @@ public void handlePlatformsRegistered(PlatformsRegisteredEvent event) { */ @Subscribe public void handleNewPlatformReady(PlatformReadyEvent event) { - preferences.forEach((cap, platform) -> cap.ready(this, platform)); + preferences.forEach((cap, platform) -> + platform.value().ifPresent(p -> cap.ready(this, p)) + ); platforms.put(event.getPlatform(), true); if (!executorService.isValid()) { executorService.newValue(createExecutor()); @@ -377,7 +412,9 @@ public void handleNewPlatformReady(PlatformReadyEvent event) { */ @Subscribe public void handleNewPlatformUnready(PlatformUnreadyEvent event) { - preferences.forEach((cap, platform) -> cap.unready(this, platform)); + preferences.forEach((cap, platform) -> + platform.value().ifPresent(p -> cap.unready(this, p)) + ); platforms.put(event.getPlatform(), false); if (!platforms.containsValue(true)) { executorService.value().ifPresent(ListeningExecutorService::shutdownNow); diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index f2e1459c23..49df120495 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -19,10 +19,6 @@ platform { val fabricApiConfiguration: Configuration = configurations.create("fabricApi") -loom { - accessWidenerPath.set(project.file("src/main/resources/worldedit.accesswidener")) -} - tasks.withType().configureEach { javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) } @@ -34,12 +30,13 @@ repositories { withCuiProtocolDependsOnCommonRule(libs.cuiProtocol.fabric.get().module) dependencies { - "api"(project(":worldedit-core")) + api(project(":worldedit-core")) + api(project(":worldedit-core-mc")) - "minecraft"(libs.fabric.minecraft) - "implementation"(libs.fabric.loader) - "implementation"(libs.cuiProtocol.fabric) - "include"(libs.cuiProtocol.fabric) { + minecraft(libs.fabric.minecraft) + implementation(libs.fabric.loader) + implementation(libs.cuiProtocol.fabric) + include(libs.cuiProtocol.fabric) { attributes { attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling::class, Bundling.SHADOWED)) } @@ -56,15 +53,15 @@ dependencies { // [2] Request the matching dependency from fabric-loom for (wantedDependency in wantedDependencies) { val dep = fabricApi.module(wantedDependency, libs.versions.fabric.api.get()) - "include"(dep) - "implementation"(dep) + include(dep) + implementation(dep) } // No need for this at runtime - "compileOnly"(libs.fabric.permissions.api) + compileOnly(libs.fabric.permissions.api) // Silence some warnings, since apparently this isn't on the compile classpath like it should be. - "compileOnly"(libs.errorprone.annotations) + compileOnly(libs.errorprone.annotations) } configure { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java deleted file mode 100644 index e782a870de..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/CommandWrapper.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.google.common.collect.ImmutableList; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.context.StringRange; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestion; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.internal.util.Substring; -import net.minecraft.commands.CommandSourceStack; -import org.enginehub.piston.inject.InjectedValueStore; -import org.enginehub.piston.inject.Key; -import org.enginehub.piston.inject.MapBackedValueStore; - -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.function.Predicate; - -import static com.sk89q.worldedit.fabric.FabricAdapter.adaptCommandSource; -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - - -public final class CommandWrapper { - - private CommandWrapper() { - } - - public static void register(CommandDispatcher dispatcher, org.enginehub.piston.Command command) { - ImmutableList.Builder aliases = ImmutableList.builder(); - aliases.add(command.getName()).addAll(command.getAliases()); - - Command commandRunner = ctx -> { - WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent( - adaptCommandSource(ctx.getSource()), - "/" + ctx.getInput() - )); - return 0; - }; - - for (String alias : aliases.build()) { - LiteralArgumentBuilder base = literal(alias).executes(commandRunner) - .then(argument("args", StringArgumentType.greedyString()) - .suggests(CommandWrapper::suggest) - .executes(commandRunner)); - if (command.getCondition() != org.enginehub.piston.Command.Condition.TRUE) { - base.requires(requirementsFor(command)); - } - dispatcher.register(base); - } - } - - private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { - return ctx -> { - InjectedValueStore store = MapBackedValueStore.create(); - final Actor actor = FabricAdapter.adaptCommandSource(ctx); - store.injectValue(Key.of(Actor.class), context -> Optional.of(actor)); - return mapping.getCondition().satisfied(store); - }; - } - - private static CompletableFuture suggest(CommandContext context, - SuggestionsBuilder builder) throws CommandSyntaxException { - CommandSuggestionEvent event = new CommandSuggestionEvent( - FabricAdapter.adaptCommandSource(context.getSource()), - builder.getInput() - ); - WorldEdit.getInstance().getEventBus().post(event); - List suggestions = event.getSuggestions(); - - ImmutableList.Builder result = ImmutableList.builder(); - - for (Substring suggestion : suggestions) { - String suggestionText = suggestion.getSubstring(); - // If at end, we are actually suggesting the next argument - // Ensure there is a space! - if (suggestion.getStart() == suggestion.getEnd() - && suggestion.getEnd() == builder.getInput().length() - && !builder.getInput().endsWith(" ") - && !builder.getInput().endsWith("\"")) { - suggestionText = " " + suggestionText; - } - result.add(new Suggestion( - StringRange.between(suggestion.getStart(), suggestion.getEnd()), - suggestionText - )); - } - - return CompletableFuture.completedFuture( - Suggestions.create(builder.getInput(), result.build()) - ); - } - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java deleted file mode 100644 index 34c3337634..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.mojang.serialization.Codec; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.fabric.internal.FabricTransmogrifier; -import com.sk89q.worldedit.fabric.internal.NBTConverter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.core.BlockPos; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.component.DataComponentPatch; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.resources.Identifier; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BaseCommandBlock; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.storage.TagValueOutput; -import net.minecraft.world.phys.Vec3; -import org.enginehub.linbus.tree.LinCompoundTag; - -import java.util.Comparator; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkNotNull; - -public final class FabricAdapter { - - private FabricAdapter() { - } - - public static World adapt(net.minecraft.world.level.Level world) { - return new FabricWorld(world); - } - - /** - * Create a Fabric world from a WorldEdit world. - * - * @param world the WorldEdit world - * @return a Fabric world - */ - public static net.minecraft.world.level.Level adapt(World world) { - checkNotNull(world); - if (world instanceof FabricWorld fabricWorld) { - return fabricWorld.getWorld(); - } else { - // TODO introduce a better cross-platform world API to match more easily - throw new UnsupportedOperationException("Cannot adapt from a " + world.getClass()); - } - } - - public static Biome adapt(BiomeType biomeType) { - return FabricWorldEdit.getRegistry(Registries.BIOME) - .getValue(Identifier.parse(biomeType.id())); - } - - public static BiomeType adapt(Biome biome) { - Identifier id = FabricWorldEdit.getRegistry(Registries.BIOME).getKey(biome); - Objects.requireNonNull(id, "biome is not registered"); - return BiomeTypes.get(id.toString()); - } - - public static Vector3 adapt(Vec3 vector) { - return Vector3.at(vector.x, vector.y, vector.z); - } - - public static BlockVector3 adapt(BlockPos pos) { - return BlockVector3.at(pos.getX(), pos.getY(), pos.getZ()); - } - - public static Vec3 toVec3(BlockVector3 vector) { - return new Vec3(vector.x(), vector.y(), vector.z()); - } - - public static net.minecraft.core.Direction adapt(Direction face) { - return switch (face) { - case NORTH -> net.minecraft.core.Direction.NORTH; - case SOUTH -> net.minecraft.core.Direction.SOUTH; - case WEST -> net.minecraft.core.Direction.WEST; - case EAST -> net.minecraft.core.Direction.EAST; - case DOWN -> net.minecraft.core.Direction.DOWN; - default -> net.minecraft.core.Direction.UP; - }; - } - - public static Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction face) { - if (face == null) { - return null; - } - return switch (face) { - case NORTH -> Direction.NORTH; - case SOUTH -> Direction.SOUTH; - case WEST -> Direction.WEST; - case EAST -> Direction.EAST; - case DOWN -> Direction.DOWN; - default -> Direction.UP; - }; - } - - public static BlockPos toBlockPos(BlockVector3 vector) { - return new BlockPos(vector.x(), vector.y(), vector.z()); - } - - /** - * Adapts property. - * - * @deprecated without replacement, use the block adapter methods - */ - // Suppress InlineMeSuggester: There is no replacement, so this shouldn't be inlined - @SuppressWarnings("InlineMeSuggester") - @Deprecated - public static Property adaptProperty(net.minecraft.world.level.block.state.properties.Property property) { - return FabricTransmogrifier.transmogToWorldEditProperty(property); - } - - /** - * Adapts properties. - * - * @deprecated without replacement, use the block adapter methods - */ - @Deprecated - public static Map, Object> adaptProperties(BlockType block, Map, Comparable> mcProps) { - Map, Object> props = new TreeMap<>(Comparator.comparing(Property::getName)); - for (Map.Entry, Comparable> prop : mcProps.entrySet()) { - Object value = prop.getValue(); - if (prop.getKey() instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - if (prop.getKey().getValueClass() == net.minecraft.core.Direction.class) { - value = adaptEnumFacing((net.minecraft.core.Direction) value); - } else { - value = ((StringRepresentable) value).getSerializedName(); - } - } - props.put(block.getProperty(prop.getKey().getName()), value); - } - return props; - } - - public static net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) { - int blockStateId = BlockStateIdAccess.getBlockStateId(blockState); - if (!BlockStateIdAccess.isValidInternalId(blockStateId)) { - return FabricTransmogrifier.transmogToMinecraft(blockState); - } - return Block.stateById(blockStateId); - } - - public static BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) { - int blockStateId = Block.getId(blockState); - BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId); - if (worldEdit == null) { - return FabricTransmogrifier.transmogToWorldEdit(blockState); - } - return worldEdit; - } - - public static BaseBlock adapt(BlockEntity blockEntity) { - if (!blockEntity.hasLevel()) { - throw new IllegalArgumentException("BlockEntity must have a level"); - } - RegistryAccess registries = blockEntity.getLevel().registryAccess(); - return adapt(blockEntity, registries); - } - - public static BaseBlock adapt(BlockEntity blockEntity, RegistryAccess registries) { - int blockStateId = Block.getId(blockEntity.getBlockState()); - BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId); - if (worldEdit == null) { - worldEdit = FabricTransmogrifier.transmogToWorldEdit(blockEntity.getBlockState()); - } - // Save this outside the reference to ensure it doesn't mutate - net.minecraft.nbt.CompoundTag savedNative = com.sk89q.worldedit.fabric.internal.FabricLoggingProblemReporter.with( - () -> "serializing block entity " + blockEntity.getClass().getSimpleName(), - reporter -> { - var tagValueOutput = TagValueOutput.createWithContext(reporter, registries); - blockEntity.saveWithId(tagValueOutput); - return tagValueOutput.buildResult(); - } - ); - - return worldEdit.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(savedNative))); - } - - public static Block adapt(BlockType blockType) { - return FabricWorldEdit.getRegistry(Registries.BLOCK).getValue(Identifier.parse(blockType.id())); - } - - public static BlockType adapt(Block block) { - return BlockTypes.get(FabricWorldEdit.getRegistry(Registries.BLOCK).getKey(block).toString()); - } - - public static Item adapt(ItemType itemType) { - return FabricWorldEdit.getRegistry(Registries.ITEM).getValue(Identifier.parse(itemType.id())); - } - - public static ItemType adapt(Item item) { - return ItemTypes.get(FabricWorldEdit.getRegistry(Registries.ITEM).getKey(item).toString()); - } - - /** - * For serializing and deserializing components. - */ - private static final Codec COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf( - "components", DataComponentPatch.EMPTY - ).codec(); - - public static ItemStack adapt(BaseItemStack baseItemStack) { - final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount()); - LinCompoundTag nbt = baseItemStack.getNbt(); - if (nbt != null) { - DataComponentPatch componentPatch = COMPONENTS_CODEC.parse( - FabricWorldEdit.registryAccess().createSerializationContext(NbtOps.INSTANCE), - NBTConverter.toNative(nbt) - ).getOrThrow(); - itemStack.applyComponents(componentPatch); - } - return itemStack; - } - - public static BaseItemStack adapt(ItemStack itemStack) { - CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( - FabricWorldEdit.registryAccess().createSerializationContext(NbtOps.INSTANCE), - itemStack.getComponentsPatch() - ).getOrThrow(); - return new BaseItemStack( - adapt(itemStack.getItem()), LazyReference.from(() -> NBTConverter.fromNative(tag)), itemStack.getCount() - ); - } - - /** - * Get the WorldEdit proxy for the given player. - * - * @param player the player - * @return the WorldEdit player - */ - public static FabricPlayer adaptPlayer(ServerPlayer player) { - checkNotNull(player); - return new FabricPlayer(player); - } - - /** - * Get the WorldEdit proxy for the given command source. - * - * @param commandSourceStack the command source - * @return the WorldEdit actor - */ - public static Actor adaptCommandSource(CommandSourceStack commandSourceStack) { - checkNotNull(commandSourceStack); - if (commandSourceStack.isPlayer()) { - return adaptPlayer(commandSourceStack.getPlayer()); - } - if (FabricWorldEdit.inst.getConfig().commandBlockSupport && commandSourceStack.source instanceof BaseCommandBlock commandBlock) { - return new FabricBlockCommandSender(commandBlock, commandSourceStack.getLevel(), commandSourceStack.getPosition()); - } - - return new FabricCommandSender(commandSourceStack); - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java deleted file mode 100644 index ffe1a2b380..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBiomeRegistry.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.world.biome.BiomeData; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.registry.BiomeRegistry; -import net.minecraft.resources.Identifier; -import net.minecraft.util.Util; - -/** - * Provides access to biome data in Fabric. - */ -class FabricBiomeRegistry implements BiomeRegistry { - - @Override - public Component getRichName(BiomeType biomeType) { - return TranslatableComponent.of(Util.makeDescriptionId("biome", Identifier.parse(biomeType.id()))); - } - - @Deprecated - @Override - public BiomeData getData(BiomeType biome) { - return new FabricBiomeData(biome); - } - - @Deprecated - private static class FabricBiomeData implements BiomeData { - private final BiomeType biome; - - /** - * Create a new instance. - * - * @param biome the base biome - */ - private FabricBiomeData(BiomeType biome) { - this.biome = biome; - } - - @SuppressWarnings("deprecation") - @Override - public String getName() { - return biome.id(); - } - } - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCommandSender.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCommandSender.java deleted file mode 100644 index a0a9c91509..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockCommandSender.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.platform.AbstractCommandBlockActor; -import com.sk89q.worldedit.fabric.internal.ComponentConverter; -import com.sk89q.worldedit.session.SessionKey; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.auth.AuthorizationException; -import com.sk89q.worldedit.util.formatting.WorldEditText; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.SectionPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BaseCommandBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.phys.Vec3; - -import java.nio.charset.StandardCharsets; -import java.util.Locale; -import java.util.UUID; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class FabricBlockCommandSender extends AbstractCommandBlockActor { - private final BaseCommandBlock sender; - private final UUID uuid; - private final ServerLevel level; - private final Vec3 pos; - - public FabricBlockCommandSender(BaseCommandBlock sender, ServerLevel level, Vec3 pos) { - super(new Location(FabricAdapter.adapt(checkNotNull(level)), FabricAdapter.adapt(checkNotNull(pos)))); - - this.sender = sender; - this.level = level; - this.pos = pos; - this.uuid = UUID.nameUUIDFromBytes((UUID_PREFIX + sender.getName()).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public String getName() { - return sender.getName().getString(); - } - - @Override - @Deprecated - public void printRaw(String msg) { - for (String part : msg.split("\n", 0)) { - sendMessage(net.minecraft.network.chat.Component.literal(part)); - } - } - - @Override - @Deprecated - public void printDebug(String msg) { - sendColorized(msg, ChatFormatting.GRAY); - } - - @Override - @Deprecated - public void print(String msg) { - sendColorized(msg, ChatFormatting.LIGHT_PURPLE); - } - - @Override - @Deprecated - public void printError(String msg) { - sendColorized(msg, ChatFormatting.RED); - } - - @Override - public void print(Component component) { - sendMessage(ComponentConverter.Serializer.fromJson( - GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())), - this.level.registryAccess() - )); - } - - private void sendColorized(String msg, ChatFormatting formatting) { - for (String part : msg.split("\n", 0)) { - var component = net.minecraft.network.chat.Component.literal(part); - component.withStyle(formatting); - sendMessage(component); - } - } - - private void sendMessage(net.minecraft.network.chat.Component textComponent) { - this.sender.setLastOutput(textComponent); - } - - @Override - public Locale getLocale() { - return WorldEdit.getInstance().getConfiguration().defaultLocale; - } - - @Override - public UUID getUniqueId() { - return uuid; - } - - @Override - public String[] getGroups() { - return new String[0]; - } - - @Override - public void checkPermission(String permission) throws AuthorizationException { - if (!hasPermission(permission)) { - throw new AuthorizationException(); - } - } - - @Override - public boolean hasPermission(String permission) { - return true; - } - - public BaseCommandBlock getSender() { - return this.sender; - } - - @Override - public SessionKey getSessionKey() { - return new SessionKey() { - - private volatile boolean active = true; - - private void updateActive() { - BlockPos blockPos = new BlockPos((int) pos.x, (int) pos.y, (int) pos.z); - int chunkX = SectionPos.blockToSectionCoord(blockPos.getX()); - int chunkZ = SectionPos.blockToSectionCoord(blockPos.getZ()); - if (!level.getChunkSource().hasChunk(chunkX, chunkZ)) { - active = false; - return; - } - Block type = level.getBlockState(blockPos).getBlock(); - active = type == Blocks.COMMAND_BLOCK - || type == Blocks.CHAIN_COMMAND_BLOCK - || type == Blocks.REPEATING_COMMAND_BLOCK; - } - - @Override - public String getName() { - return sender.getName().getString(); - } - - @Override - public boolean isActive() { - level.getServer().execute(this::updateActive); - return active; - } - - @Override - public boolean isPersistent() { - return true; - } - - @Override - public UUID getUniqueId() { - return uuid; - } - }; - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java deleted file mode 100644 index 48ef164a80..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricBlockRegistry.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.sk89q.worldedit.fabric.internal.FabricTransmogrifier; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.registry.BlockMaterial; -import com.sk89q.worldedit.world.registry.BlockRegistry; -import net.minecraft.world.level.block.Block; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.OptionalInt; -import java.util.TreeMap; - -public class FabricBlockRegistry implements BlockRegistry { - - private final Map materialMap = new HashMap<>(); - - @Override - public Component getRichName(BlockType blockType) { - return TranslatableComponent.of(FabricAdapter.adapt(blockType).getDescriptionId()); - } - - @Override - public BlockMaterial getMaterial(BlockType blockType) { - Block block = FabricAdapter.adapt(blockType); - return materialMap.computeIfAbsent( - block.defaultBlockState(), - FabricBlockMaterial::new - ); - } - - @Override - public Map> getProperties(BlockType blockType) { - Block block = FabricAdapter.adapt(blockType); - Map> map = new TreeMap<>(); - Collection> propertyKeys = block - .defaultBlockState() - .getProperties(); - for (net.minecraft.world.level.block.state.properties.Property key : propertyKeys) { - map.put(key.getName(), FabricTransmogrifier.transmogToWorldEditProperty(key)); - } - return map; - } - - @Override - public OptionalInt getInternalBlockStateId(BlockState state) { - net.minecraft.world.level.block.state.BlockState equivalent = FabricAdapter.adapt(state); - return OptionalInt.of(Block.getId(equivalent)); - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java deleted file mode 100644 index 97badd1292..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntityProperties.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric; - -import com.sk89q.worldedit.entity.metadata.EntityProperties; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.ExperienceOrb; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.TamableAnimal; -import net.minecraft.world.entity.ambient.AmbientCreature; -import net.minecraft.world.entity.animal.Animal; -import net.minecraft.world.entity.animal.fish.WaterAnimal; -import net.minecraft.world.entity.animal.golem.AbstractGolem; -import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.decoration.ItemFrame; -import net.minecraft.world.entity.decoration.painting.Painting; -import net.minecraft.world.entity.item.FallingBlockEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.entity.npc.Npc; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.entity.vehicle.boat.Boat; -import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; -import net.minecraft.world.item.trading.Merchant; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class FabricEntityProperties implements EntityProperties { - - private final Entity entity; - - public FabricEntityProperties(Entity entity) { - checkNotNull(entity); - this.entity = entity; - } - - @Override - public boolean isPlayerDerived() { - return entity instanceof Player; - } - - @Override - public boolean isProjectile() { - return entity instanceof Projectile; - } - - @Override - public boolean isItem() { - return entity instanceof ItemEntity; - } - - @Override - public boolean isFallingBlock() { - return entity instanceof FallingBlockEntity; - } - - @Override - public boolean isPainting() { - return entity instanceof Painting; - } - - @Override - public boolean isItemFrame() { - return entity instanceof ItemFrame; - } - - @Override - public boolean isBoat() { - return entity instanceof Boat; - } - - @Override - public boolean isMinecart() { - return entity instanceof AbstractMinecart; - } - - @Override - public boolean isTNT() { - return entity instanceof PrimedTnt; - } - - @Override - public boolean isExperienceOrb() { - return entity instanceof ExperienceOrb; - } - - @Override - public boolean isLiving() { - return entity instanceof Mob; - } - - @Override - public boolean isAnimal() { - return entity instanceof Animal; - } - - @Override - public boolean isAmbient() { - return entity instanceof AmbientCreature; - } - - @Override - public boolean isNPC() { - return entity instanceof Npc || entity instanceof Merchant; - } - - @Override - public boolean isGolem() { - return entity instanceof AbstractGolem; - } - - @Override - public boolean isTamed() { - return entity instanceof TamableAnimal tamableAnimal && tamableAnimal.isTame(); - } - - @Override - public boolean isTagged() { - return entity.hasCustomName(); - } - - @Override - public boolean isArmorStand() { - return entity instanceof ArmorStand; - } - - @Override - public boolean isPasteable() { - return !(entity instanceof ServerPlayer || entity instanceof EnderDragon); - } - - @Override - public boolean isWaterCreature() { - return entity instanceof WaterAnimal; - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index 7f2c4dd3fa..a340aaddb6 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -19,155 +19,31 @@ package com.sk89q.worldedit.fabric; -import com.google.common.collect.Sets; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.AbstractPlatform; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.MultiUserPlatform; -import com.sk89q.worldedit.extension.platform.Preference; -import com.sk89q.worldedit.extension.platform.Watchdog; -import com.sk89q.worldedit.fabric.internal.FabricWatchdogImpl; -import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.util.lifecycle.Lifecycled; -import com.sk89q.worldedit.world.DataFixer; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.registry.Registries; -import net.minecraft.SharedConstants; -import net.minecraft.resources.Identifier; -import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ServerLevel; +import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.level.storage.ServerLevelData; -import org.enginehub.piston.CommandManager; +import org.enginehub.worldeditcui.protocol.CUIPacket; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import javax.annotation.Nullable; +class FabricPlatform extends CoreMcPlatform { -class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { - - private final FabricWorldEdit mod; - private final FabricDataFixer dataFixer; - private final Lifecycled> watchdog; - private boolean hookingEvents = false; - - FabricPlatform(FabricWorldEdit mod) { - this.mod = mod; - this.dataFixer = new FabricDataFixer(getDataVersion()); - - this.watchdog = FabricWorldEdit.LIFECYCLED_SERVER.map( - server -> server instanceof DedicatedServer - ? Optional.of(new FabricWatchdogImpl(server)) - : Optional.empty() - ); - } - - boolean isHookingEvents() { - return hookingEvents; - } - - @Override - public Registries getRegistries() { - return FabricRegistries.getInstance(); - } - - @Override - public int getDataVersion() { - return SharedConstants.getCurrentVersion().dataVersion().version(); + private static Lifecycled createMinecraftServerLifecycled() { + SimpleLifecycled lifecycledServer = SimpleLifecycled.invalid(); + ServerLifecycleEvents.SERVER_STARTING.register(lifecycledServer::newValue); + ServerLifecycleEvents.SERVER_STOPPING.register(_ -> lifecycledServer.invalidate()); + return lifecycledServer; } - @Override - public DataFixer getDataFixer() { - return dataFixer; - } - - @Override - public boolean isValidMobType(String type) { - return FabricWorldEdit.getRegistry(net.minecraft.core.registries.Registries.ENTITY_TYPE) - .containsKey(Identifier.parse(type)); - } - - @Override - public void reload() { - getConfiguration().load(); - super.reload(); - } - - @Override - public int schedule(long delay, long period, Runnable task) { - return -1; - } - - @Override - @Nullable - public Watchdog getWatchdog() { - return watchdog.value().flatMap(Function.identity()).orElse(null); - } - - @Override - public List getWorlds() { - Iterable worlds = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getAllLevels(); - List ret = new ArrayList<>(); - for (ServerLevel world : worlds) { - ret.add(new FabricWorld(world)); - } - return ret; - } - - @Nullable - @Override - public Player matchPlayer(Player player) { - if (player instanceof FabricPlayer) { - return player; - } else { - ServerPlayer entity = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow() - .getPlayerList().getPlayerByName(player.getName()); - return entity != null ? new FabricPlayer(entity) : null; - } - } - - @Nullable - @Override - public World matchWorld(World world) { - if (world instanceof FabricWorld) { - return world; - } else { - for (ServerLevel ws : FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getAllLevels()) { - if (((ServerLevelData) ws.getLevelData()).getLevelName().equals(world.getName())) { - return new FabricWorld(ws); - } - } - - return null; - } - } - - @Override - public void registerCommands(CommandManager manager) { - // No-op, we register using Fabric's event - } - - @Override - public void setGameHooksEnabled(boolean enabled) { - this.hookingEvents = enabled; - } - - @Override - public FabricConfiguration getConfiguration() { - return mod.getConfig(); + FabricPlatform(FabricWorldEdit mod) { + super(mod, createMinecraftServerLifecycled()); } @Override - public String getVersion() { - return mod.getInternalVersion(); + public void sendCUIPacket(ServerPlayer player, CUIPacket packet) { + ServerPlayNetworking.send(player, packet); } @Override @@ -175,55 +51,8 @@ public String getPlatformName() { return "Fabric-Official"; } - @Override - public String getPlatformVersion() { - return mod.getInternalVersion(); - } - @Override public String id() { return "enginehub:fabric"; } - - @Override - public Map getCapabilities() { - Map capabilities = new EnumMap<>(Capability.class); - capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS); - capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL); - capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL); - capabilities.put(Capability.PERMISSIONS, Preference.NORMAL); - capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL); - capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED); - return capabilities; - } - - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.LIGHTING, - SideEffect.NEIGHBORS, - SideEffect.UPDATE - ); - - @Override - public Set getSupportedSideEffects() { - return SUPPORTED_SIDE_EFFECTS; - } - - @Override - public long getTickCount() { - return FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getTickCount(); - } - - @Override - public Collection getConnectedUsers() { - List users = new ArrayList<>(); - PlayerList scm = FabricWorldEdit.LIFECYCLED_SERVER.valueOrThrow().getPlayerList(); - for (ServerPlayer entity : scm.getPlayers()) { - if (entity != null) { - users.add(new FabricPlayer(entity)); - } - } - return users; - } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java index 663e3020c9..f647bcc339 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java @@ -19,35 +19,11 @@ package com.sk89q.worldedit.fabric; -import com.mojang.brigadier.CommandDispatcher; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.util.PermissionCondition; -import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; -import com.sk89q.worldedit.event.platform.PlatformReadyEvent; -import com.sk89q.worldedit.event.platform.PlatformUnreadyEvent; -import com.sk89q.worldedit.event.platform.PlatformsRegisteredEvent; -import com.sk89q.worldedit.event.platform.SessionIdleEvent; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.Platform; -import com.sk89q.worldedit.extension.platform.PlatformManager; -import com.sk89q.worldedit.internal.anvil.ChunkDeleter; -import com.sk89q.worldedit.internal.event.InteractionDebouncer; +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.coremc.internal.CoreMcMod; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.coremc.internal.ThreadSafeCache; import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.registry.CommonRegistries; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.lifecycle.Lifecycled; -import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; -import com.sk89q.worldedit.world.biome.BiomeCategory; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockCategory; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.generation.ConfiguredFeatureType; -import com.sk89q.worldedit.world.generation.StructureType; -import com.sk89q.worldedit.world.generation.TreeType; -import com.sk89q.worldedit.world.item.ItemCategory; -import com.sk89q.worldedit.world.item.ItemType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -61,92 +37,21 @@ import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.metadata.ModMetadata; import net.fabricmc.loader.api.metadata.version.VersionPredicate; -import net.minecraft.commands.CommandBuildContext; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.feature.CoralTreeFeature; -import net.minecraft.world.level.levelgen.feature.FallenTreeFeature; -import net.minecraft.world.level.levelgen.feature.TreeFeature; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import net.minecraft.world.phys.BlockHitResult; import org.apache.logging.log4j.Logger; -import org.enginehub.piston.Command; -import org.enginehub.worldeditcui.protocol.CUIPacket; import org.enginehub.worldeditcui.protocol.CUIPacketHandler; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer; -import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME; /** * The Fabric implementation of WorldEdit. */ -public class FabricWorldEdit implements ModInitializer { +public class FabricWorldEdit extends CoreMcMod implements ModInitializer { private static final Logger LOGGER = LogManagerCompat.getLogger(); - public static final String MOD_ID = "worldedit"; - - public static final Lifecycled LIFECYCLED_SERVER; - - static { - SimpleLifecycled lifecycledServer = SimpleLifecycled.invalid(); - ServerLifecycleEvents.SERVER_STARTED.register(lifecycledServer::newValue); - ServerLifecycleEvents.SERVER_STOPPING.register(__ -> lifecycledServer.invalidate()); - LIFECYCLED_SERVER = lifecycledServer; - } - - /** - * {@return current server's registry access} Not for long-term storage. - */ - public static RegistryAccess registryAccess() { - return LIFECYCLED_SERVER.valueOrThrow().registryAccess(); - } - - /** - * {@return current server's registry} Not for long-term storage. - * - * @param key the registry key - */ - public static Registry getRegistry(ResourceKey> key) { - return LIFECYCLED_SERVER.valueOrThrow().registryAccess().lookupOrThrow(key); - } - - private FabricPermissionsProvider provider; public static FabricWorldEdit inst; - private InteractionDebouncer debouncer; - private FabricPlatform platform; - private FabricConfiguration config; - private Path workingDir; - private ModContainer container; public FabricWorldEdit() { @@ -159,60 +64,43 @@ public void onInitialize() { () -> new IllegalStateException("WorldEdit mod missing in Fabric") ); - // Setup working directory - workingDir = FabricLoader.getInstance().getConfigDir().resolve("worldedit"); - if (!Files.exists(workingDir)) { - try { - Files.createDirectory(workingDir); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - this.platform = new FabricPlatform(this); - debouncer = new InteractionDebouncer(platform); - - WorldEdit.getInstance().getPlatformManager().register(platform); - - config = new FabricConfiguration(this); - this.provider = getInitialPermissionsProvider(); + init(new FabricPlatform(this), FabricLoader.getInstance().getConfigDir()); CUIPacketHandler.instance().registerServerboundHandler(this::onCuiPacket); - ServerTickEvents.END_SERVER_TICK.register(ThreadSafeCache.getInstance()); - CommandRegistrationCallback.EVENT.register(this::registerCommands); - ServerLifecycleEvents.SERVER_STARTING.register(this::onStartingServer); - ServerLifecycleEvents.SERVER_STARTED.register(this::onStartServer); - ServerLifecycleEvents.SERVER_STOPPING.register(this::onStopServer); - ServerPlayConnectionEvents.DISCONNECT.register(this::onPlayerDisconnect); - AttackBlockCallback.EVENT.register(this::onLeftClickBlock); - UseBlockCallback.EVENT.register(this::onRightClickBlock); - UseItemCallback.EVENT.register(this::onRightClickItem); + ServerTickEvents.END_SERVER_TICK.register(server -> ThreadSafeCache.getInstance().onEndTick(server)); + CommandRegistrationCallback.EVENT.register((dispatcher, _, _) -> registerCommands(dispatcher)); + ServerLifecycleEvents.SERVER_STARTING.register(_ -> serverAboutToStart()); + ServerLifecycleEvents.SERVER_STARTED.register(this::serverStarted); + ServerLifecycleEvents.SERVER_STOPPING.register(_ -> serverStopping()); + ServerPlayConnectionEvents.DISCONNECT.register((handler, _) -> onPlayerDisconnect(handler.player)); + AttackBlockCallback.EVENT.register( + (playerEntity, _, hand, blockPos, direction) -> + onLeftClickBlock(playerEntity, hand, blockPos, direction) + ? InteractionResult.SUCCESS : InteractionResult.PASS + ); + UseBlockCallback.EVENT.register( + (playerEntity, _, hand, blockHitResult) -> + onRightClickBlock(playerEntity, hand, blockHitResult.getBlockPos(), blockHitResult.getDirection()) + ? InteractionResult.SUCCESS : InteractionResult.PASS + ); + UseItemCallback.EVENT.register((playerEntity, _, hand) -> { + Optional result = onRightClickItem(playerEntity, hand); + if (result.isPresent()) { + return result.get() ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + return InteractionResult.PASS; + }); LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded"); } - private void registerCommands(CommandDispatcher dispatcher, CommandBuildContext registryAccess, Commands.CommandSelection environment) { - WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent()); - PlatformManager manager = WorldEdit.getInstance().getPlatformManager(); - Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS); - if (commandsPlatform != platform || !platform.isHookingEvents()) { - // We're not in control of commands/events -- do not register. - return; - } - - List commands = manager.getPlatformCommandManager().getCommandManager() - .getAllCommands().toList(); - for (Command command : commands) { - CommandWrapper.register(dispatcher, command); - Set perms = command.getCondition().as(PermissionCondition.class) - .map(PermissionCondition::getPermissions) - .orElseGet(Collections::emptySet); - if (!perms.isEmpty()) { - perms.forEach(getPermissionsProvider()::registerPermission); - } - } + @Override + protected String getInternalVersion() { + return container.getMetadata().getVersion().getFriendlyString(); } - private FabricPermissionsProvider getInitialPermissionsProvider() { + @Override + protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform platform) { try { Class.forName("me.lucko.fabric.api.permissions.v0.Permissions", false, getClass().getClassLoader()); Optional version = FabricLoader.getInstance().getModContainer("fabric-permissions-api-v0") @@ -223,7 +111,7 @@ private FabricPermissionsProvider getInitialPermissionsProvider() { throw new RuntimeException("Fabric permissions version " + version.get() + " is not supported. Please update Fabric Permissions API"); } - return new FabricPermissionsProvider.LuckoFabricPermissionsProvider(platform); + return new LuckoFabricPermissionsProvider(platform); } catch (ClassNotFoundException ignored) { // fallback to vanilla } catch (Exception e) { @@ -231,286 +119,6 @@ private FabricPermissionsProvider getInitialPermissionsProvider() { LOGGER.warn("Failed to load Fabric permissions provider. Falling back to Minecraft", e); } - return new FabricPermissionsProvider.VanillaPermissionsProvider(platform); - } - - private void setupRegistries(MinecraftServer server) { - // Blocks - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.BLOCK).keySet()) { - String key = name.toString(); - if (BlockType.REGISTRY.get(key) == null) { - BlockType.REGISTRY.register(key, new BlockType(key, - input -> FabricAdapter.adapt(FabricAdapter.adapt(input.getBlockType()).defaultBlockState()))); - } - } - // Items - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.ITEM).keySet()) { - String key = name.toString(); - if (ItemType.REGISTRY.get(key) == null) { - ItemType.REGISTRY.register(key, new ItemType(key)); - } - } - // Entities - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.ENTITY_TYPE).keySet()) { - String key = name.toString(); - if (EntityType.REGISTRY.get(key) == null) { - EntityType.REGISTRY.register(key, new EntityType(key)); - } - } - // Biomes - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.BIOME).keySet()) { - String key = name.toString(); - if (BiomeType.REGISTRY.get(key) == null) { - BiomeType.REGISTRY.register(key, new BiomeType(key)); - } - } - // Tags - server.registryAccess().lookupOrThrow(Registries.BLOCK).getTags().map(t -> t.key().location()).forEach(name -> { - String key = name.toString(); - if (BlockCategory.REGISTRY.get(key) == null) { - BlockCategory.REGISTRY.register(key, new BlockCategory(key)); - } - }); - server.registryAccess().lookupOrThrow(Registries.ITEM).getTags().map(t -> t.key().location()).forEach(name -> { - String key = name.toString(); - if (ItemCategory.REGISTRY.get(key) == null) { - ItemCategory.REGISTRY.register(key, new ItemCategory(key)); - } - }); - Registry biomeRegistry = server.registryAccess().lookupOrThrow(Registries.BIOME); - biomeRegistry.getTags().forEach(tag -> { - String key = tag.key().location().toString(); - if (BiomeCategory.REGISTRY.get(key) == null) { - BiomeCategory.REGISTRY.register(key, new BiomeCategory( - key, - () -> biomeRegistry.get(tag.key()) - .stream() - .flatMap(HolderSet.Named::stream) - .map(Holder::value) - .map(FabricAdapter::adapt) - .collect(Collectors.toSet())) - ); - } - }); - // Features - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).keySet()) { - String key = name.toString(); - if (ConfiguredFeatureType.REGISTRY.get(key) == null) { - ConfiguredFeatureType.REGISTRY.register(key, new ConfiguredFeatureType(key)); - } - } - // Structures - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.STRUCTURE).keySet()) { - String key = name.toString(); - if (StructureType.REGISTRY.get(key) == null) { - StructureType.REGISTRY.register(key, new StructureType(key)); - } - } - // Trees - Registry placedFeatureRegistry = server.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE); - for (Identifier name : placedFeatureRegistry.keySet()) { - // Do some hackery to make sure this is a tree - var underlyingFeature = placedFeatureRegistry.get(name).get().value().feature().value().feature(); - if (underlyingFeature instanceof TreeFeature || underlyingFeature instanceof FallenTreeFeature || underlyingFeature instanceof CoralTreeFeature) { - String key = name.toString(); - if (TreeType.REGISTRY.get(key) == null) { - TreeType.REGISTRY.register(key, new TreeType(key)); - } - } - } - - // Common registries - CommonRegistries.init(); - } - - private void onStartingServer(MinecraftServer minecraftServer) { - final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME); - if (Files.exists(delChunks)) { - ChunkDeleter.runFromFile(delChunks, true); - } - } - - private void onStartServer(MinecraftServer minecraftServer) { - setupRegistries(minecraftServer); - - config.load(); - WorldEdit.getInstance().getEventBus().post(new ConfigurationLoadEvent(config)); - WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent(platform)); - } - - private void onStopServer(MinecraftServer minecraftServer) { - WorldEdit worldEdit = WorldEdit.getInstance(); - worldEdit.getSessionManager().unload(); - WorldEdit.getInstance().getEventBus().post(new PlatformUnreadyEvent(platform)); - } - - private boolean skipEvents() { - return platform == null || !platform.isHookingEvents(); - } - - private boolean skipInteractionEvent(Player player, InteractionHand hand) { - return skipEvents() || hand != InteractionHand.MAIN_HAND || player.level().isClientSide() || !(player instanceof ServerPlayer); - } - - private InteractionResult onLeftClickBlock(Player playerEntity, Level world, InteractionHand hand, BlockPos blockPos, Direction direction) { - if (skipInteractionEvent(playerEntity, hand)) { - return InteractionResult.PASS; - } - - WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); - FabricWorld localWorld = getWorld(world); - Location pos = new Location(localWorld, - blockPos.getX(), - blockPos.getY(), - blockPos.getZ() - ); - com.sk89q.worldedit.util.Direction weDirection = FabricAdapter.adaptEnumFacing(direction); - - boolean result = we.handleBlockLeftClick(player, pos, weDirection) || we.handleArmSwing(player); - debouncer.setLastInteraction(player, result); - - return result ? InteractionResult.SUCCESS : InteractionResult.PASS; - } - - private InteractionResult onRightClickBlock(Player playerEntity, Level world, InteractionHand hand, BlockHitResult blockHitResult) { - if (skipInteractionEvent(playerEntity, hand)) { - return InteractionResult.PASS; - } - - WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); - FabricWorld localWorld = getWorld(world); - Location pos = new Location(localWorld, - blockHitResult.getBlockPos().getX(), - blockHitResult.getBlockPos().getY(), - blockHitResult.getBlockPos().getZ() - ); - com.sk89q.worldedit.util.Direction direction = FabricAdapter.adaptEnumFacing(blockHitResult.getDirection()); - - boolean result = we.handleBlockRightClick(player, pos, direction) || we.handleRightClick(player); - debouncer.setLastInteraction(player, result); - - return result ? InteractionResult.SUCCESS : InteractionResult.PASS; - } - - public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { - if (skipInteractionEvent(playerEntity, hand)) { - return; - } - - WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer(playerEntity); - - Optional previousResult = debouncer.getDuplicateInteractionResult(player); - if (previousResult.isPresent()) { - return; - } - - boolean result = we.handleArmSwing(player); - debouncer.setLastInteraction(player, result); - } - - private InteractionResult onRightClickItem(Player playerEntity, Level world, InteractionHand hand) { - if (skipInteractionEvent(playerEntity, hand)) { - return InteractionResult.PASS; - } - - WorldEdit we = WorldEdit.getInstance(); - FabricPlayer player = adaptPlayer((ServerPlayer) playerEntity); - - Optional previousResult = debouncer.getDuplicateInteractionResult(player); - if (previousResult.isPresent()) { - return previousResult.get() ? InteractionResult.SUCCESS : InteractionResult.PASS; - } - - boolean result = we.handleRightClick(player); - debouncer.setLastInteraction(player, result); - - return result ? InteractionResult.SUCCESS : InteractionResult.PASS; - } - - private void onPlayerDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server) { - debouncer.clearInteraction(adaptPlayer(handler.player)); - - WorldEdit.getInstance().getEventBus() - .post(new SessionIdleEvent(new FabricPlayer.SessionKeyImpl(handler.player))); - } - - private void onCuiPacket(CUIPacket payload, CUIPacketHandler.PacketContext context) { - if (!(context.player() instanceof ServerPlayer player)) { - // Ignore - this is not a server-bound packet - return; - } - - FabricPlayer actor = FabricAdapter.adaptPlayer(player); - LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); - session.handleCUIInitializationMessage(payload.eventType(), payload.args(), actor); - } - - /** - * Get the configuration. - * - * @return the Fabric configuration - */ - FabricConfiguration getConfig() { - return this.config; - } - - /** - * Get the session for a player. - * - * @param player the player - * @return the session - */ - public LocalSession getSession(ServerPlayer player) { - checkNotNull(player); - return WorldEdit.getInstance().getSessionManager().get(adaptPlayer(player)); - } - - /** - * Get the WorldEdit proxy for the given world. - * - * @param world the world - * @return the WorldEdit world - */ - public FabricWorld getWorld(Level world) { - checkNotNull(world); - return new FabricWorld(world); - } - - /** - * Get the WorldEdit proxy for the platform. - * - * @return the WorldEdit platform - */ - public Platform getPlatform() { - return this.platform; - } - - /** - * Get the working directory where WorldEdit's files are stored. - * - * @return the working directory - */ - public Path getWorkingDir() { - return this.workingDir; - } - - /** - * Get the version of the WorldEdit-Fabric implementation. - * - * @return a version string - */ - String getInternalVersion() { - return container.getMetadata().getVersion().getFriendlyString(); - } - - public void setPermissionsProvider(FabricPermissionsProvider provider) { - this.provider = provider; - } - - public FabricPermissionsProvider getPermissionsProvider() { - return provider; + return super.createPermissionsProvider(platform); } } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeConfiguration.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java similarity index 55% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeConfiguration.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java index 7af1234912..f1234c1dcc 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeConfiguration.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java @@ -17,29 +17,22 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.fabric; -import com.sk89q.worldedit.util.PropertiesConfiguration; +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import me.lucko.fabric.api.permissions.v0.Permissions; +import net.minecraft.server.level.ServerPlayer; -import java.nio.file.Path; +final class LuckoFabricPermissionsProvider extends CoreMcPermissionsProvider.VanillaPermissionsProvider { -public class NeoForgeConfiguration extends PropertiesConfiguration { - - public boolean creativeEnable = false; - public boolean cheatMode = false; - - public NeoForgeConfiguration(NeoForgeWorldEdit mod) { - super(mod.getWorkingDir().resolve("worldedit.properties")); - } - - @Override - protected void loadExtra() { - creativeEnable = getBool("use-in-creative", false); - cheatMode = getBool("cheat-mode", false); + LuckoFabricPermissionsProvider(CoreMcPlatform platform) { + super(platform); } @Override - public Path getWorkingDirectoryPath() { - return NeoForgeWorldEdit.inst.getWorkingDir(); + public boolean hasPermission(ServerPlayer player, String permission) { + return Permissions.getPermissionValue(player, permission) + .orElseGet(() -> super.hasPermission(player, permission)); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java deleted file mode 100644 index 34b0cac1f1..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.internal; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.fabric.FabricAdapter; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.util.Location; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Predicate; - -public class FabricServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { - - private final EditSession editSession; - private final ServerLevel serverLevel; - private final Map createdBlockEntities = new HashMap<>(); - - private FabricServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel) { - this.editSession = editSession; - this.serverLevel = serverLevel; - } - - public record LevelAndProxy(WorldGenLevel level, FabricServerLevelDelegateProxy proxy) implements AutoCloseable { - @Override - public void close() throws MaxChangedBlocksException { - proxy.close(); - } - } - - public static LevelAndProxy newInstance(EditSession editSession, ServerLevel serverLevel) { - FabricServerLevelDelegateProxy proxy = new FabricServerLevelDelegateProxy(editSession, serverLevel); - return new LevelAndProxy( - (WorldGenLevel) Proxy.newProxyInstance( - serverLevel.getClass().getClassLoader(), - serverLevel.getClass().getInterfaces(), - proxy - ), - proxy - ); - } - - @Nullable - private BlockEntity getBlockEntity(BlockPos blockPos) { - // This doesn't synthesize or load from world. I think editing existing block entities without setting the block - // (in the context of features) should not be supported in the first place. - BlockVector3 pos = FabricAdapter.adapt(blockPos); - return createdBlockEntities.get(pos); - } - - private BlockState getBlockState(BlockPos blockPos) { - return FabricAdapter.adapt(this.editSession.getBlockWithBuffer(FabricAdapter.adapt(blockPos))); - } - - private boolean setBlock(BlockPos blockPos, BlockState blockState) { - try { - handleBlockEntity(blockPos, blockState); - return editSession.setBlock(FabricAdapter.adapt(blockPos), FabricAdapter.adapt(blockState)); - } catch (MaxChangedBlocksException e) { - throw new RuntimeException(e); - } - } - - // For BlockEntity#setBlockState, not sure why it's deprecated - @SuppressWarnings("deprecation") - private void handleBlockEntity(BlockPos blockPos, BlockState blockState) { - BlockVector3 pos = FabricAdapter.adapt(blockPos); - if (blockState.hasBlockEntity()) { - if (!(blockState.getBlock() instanceof EntityBlock entityBlock)) { - // This will probably never happen, as Mojang's own code assumes that - // hasBlockEntity implies instanceof EntityBlock, but just to be safe... - throw new AssertionError("BlockState has block entity but block is not an EntityBlock: " + blockState); - } - BlockEntity newEntity = entityBlock.newBlockEntity(blockPos, blockState); - if (newEntity != null) { - newEntity.setBlockState(blockState); - createdBlockEntities.put(pos, newEntity); - // Should we load existing NBT here? This is for feature / structure gen so it seems unnecessary. - // But it would align with the behavior of the real setBlock method. - return; - } - } - // Discard any block entity that was previously created if new block is set without block entity - createdBlockEntities.remove(pos); - } - - private boolean removeBlock(BlockPos blockPos) { - return setBlock(blockPos, Blocks.AIR.defaultBlockState()); - } - - private boolean addEntity(Entity entity) { - Vector3 pos = FabricAdapter.adapt(entity.getPosition(0.0f)); - Location location = new Location(FabricAdapter.adapt(serverLevel), pos.x(), pos.y(), pos.z()); - BaseEntity baseEntity = new FabricEntity(entity).getState(); - return editSession.createEntity(location, baseEntity) != null; - } - - @Override - public void close() throws MaxChangedBlocksException { - for (Map.Entry entry : createdBlockEntities.entrySet()) { - BlockVector3 blockPos = entry.getKey(); - BlockEntity blockEntity = entry.getValue(); - editSession.setBlock( - blockPos, - FabricAdapter.adapt(blockEntity, serverLevel.registryAccess()) - ); - } - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - switch (method.getName()) { - case "getBlockState", "method_8320" -> { - if (args.length == 1 && args[0] instanceof BlockPos blockPos) { - return getBlockState(blockPos); - } - } - case "isStateAtPosition", "method_16358" -> { - if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) { - @SuppressWarnings("unchecked") - Predicate predicate = (Predicate) args[1]; - return predicate.test(getBlockState(blockPos)); - } - } - case "getBlockEntity", "method_8321" -> { - if (args.length == 1 && args[0] instanceof BlockPos blockPos) { - return getBlockEntity(blockPos); - } - } - case "setBlock", "method_8652" -> { - if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof BlockState blockState) { - return setBlock(blockPos, blockState); - } - } - case "removeBlock", "destroyBlock", "method_8650", "method_8651" -> { - if (args.length >= 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Boolean) { - return removeBlock(blockPos); - } - } - case "addEntity", "method_14175", "addFreshEntityWithPassengers", "method_30771" -> { - if (args.length >= 1 && args[0] instanceof Entity entity) { - return addEntity(entity); - } - } - default -> { - } - } - - return method.invoke(this.serverLevel, args); - } - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java deleted file mode 100644 index 4b26f77ab9..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricTransmogrifier.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.internal; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.fabric.FabricAdapter; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockType; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.StateDefinition; - -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; - -/** - * Raw, un-cached transformations. - */ -public class FabricTransmogrifier { - - private static final LoadingCache, Property> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { - @Override - public Property load(net.minecraft.world.level.block.state.properties.Property property) throws Exception { - return switch (property) { - case net.minecraft.world.level.block.state.properties.BooleanProperty booleanProperty -> - new BooleanProperty(property.getName(), ImmutableList.copyOf(booleanProperty.getPossibleValues())); - case net.minecraft.world.level.block.state.properties.IntegerProperty integerProperty -> - new IntegerProperty(property.getName(), ImmutableList.copyOf(integerProperty.getPossibleValues())); - case net.minecraft.world.level.block.state.properties.EnumProperty enumProperty -> { - if (property.getValueClass() == net.minecraft.core.Direction.class) { - yield new DirectionalProperty(property.getName(), property.getPossibleValues().stream() - .map(v -> FabricAdapter.adaptEnumFacing((net.minecraft.core.Direction) v)) - .collect(ImmutableList.toImmutableList())); - } - // Note: do not make x.asString a method reference. - // It will cause runtime bootstrap exceptions. - //noinspection Convert2MethodRef - yield new EnumProperty(property.getName(), enumProperty.getPossibleValues().stream() - .map(x -> x.getSerializedName()) - .collect(ImmutableList.toImmutableList())); - } - default -> new FabricPropertyAdapter<>(property); - }; - } - }); - - public static Property transmogToWorldEditProperty(net.minecraft.world.level.block.state.properties.Property property) { - return PROPERTY_CACHE.getUnchecked(property); - } - - private static Map, Object> transmogToWorldEditProperties(BlockType block, net.minecraft.world.level.block.state.BlockState blockState) { - Map, Object> props = new TreeMap<>(Comparator.comparing(Property::name)); - for (net.minecraft.world.level.block.state.properties.Property property : blockState.getProperties()) { - Object value = blockState.getValue(property); - if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - if (property.getValueClass() == net.minecraft.core.Direction.class) { - value = FabricAdapter.adaptEnumFacing((net.minecraft.core.Direction) value); - } else { - value = ((StringRepresentable) value).getSerializedName(); - } - } - props.put(block.getProperty(property.getName()), value); - } - return props; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static net.minecraft.world.level.block.state.BlockState transmogToMinecraftProperties( - StateDefinition stateContainer, - net.minecraft.world.level.block.state.BlockState newState, - Map, Object> states - ) { - for (Map.Entry, Object> state : states.entrySet()) { - net.minecraft.world.level.block.state.properties.Property property = stateContainer.getProperty(state.getKey().name()); - Comparable value = (Comparable) state.getValue(); - // we may need to adapt this value, depending on the source prop - if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { - if (property.getValueClass() == net.minecraft.core.Direction.class) { - Direction dir = (Direction) value; - value = FabricAdapter.adapt(dir); - } else { - String enumName = (String) value; - value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getValue((String) value).orElseThrow(() -> - new IllegalStateException("Enum property " + property.getName() + " does not contain " + enumName) - ); - } - } - - newState = newState.setValue(property, value); - } - return newState; - } - - public static net.minecraft.world.level.block.state.BlockState transmogToMinecraft(BlockState blockState) { - Block mcBlock = FabricAdapter.adapt(blockState.getBlockType()); - net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); - Map, Object> states = blockState.getStates(); - return transmogToMinecraftProperties(mcBlock.getStateDefinition(), newState, states); - } - - public static com.sk89q.worldedit.world.block.BlockState transmogToWorldEdit(net.minecraft.world.level.block.state.BlockState blockState) { - BlockType blockType = FabricAdapter.adapt(blockState.getBlock()); - return blockType.getState(transmogToWorldEditProperties(blockType, blockState)); - } - - private FabricTransmogrifier() { - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java deleted file mode 100644 index 38ac1c61b6..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.internal; - -import com.sk89q.worldedit.fabric.FabricAdapter; -import com.sk89q.worldedit.internal.block.BlockStateIdAccess; -import com.sk89q.worldedit.internal.wna.WorldNativeAccess; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.FullChunkStatus; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.storage.TagValueInput; -import org.enginehub.linbus.tree.LinCompoundTag; - -import java.lang.ref.WeakReference; -import java.util.Objects; -import javax.annotation.Nullable; - -public class FabricWorldNativeAccess implements WorldNativeAccess { - private final WeakReference world; - private SideEffectSet sideEffectSet; - - public FabricWorldNativeAccess(WeakReference world) { - this.world = world; - } - - private Level getWorld() { - return Objects.requireNonNull(world.get(), "The reference to the world was lost"); - } - - @Override - public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { - this.sideEffectSet = sideEffectSet; - } - - @Override - public LevelChunk getChunk(int x, int z) { - return getWorld().getChunk(x, z); - } - - @Override - public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { - int stateId = BlockStateIdAccess.getBlockStateId(state); - return BlockStateIdAccess.isValidInternalId(stateId) - ? Block.stateById(stateId) - : FabricAdapter.adapt(state); - } - - @Override - public BlockState getBlockState(LevelChunk chunk, BlockPos position) { - return chunk.getBlockState(position); - } - - @Nullable - @Override - public BlockState setBlockState(LevelChunk chunk, BlockPos position, BlockState state) { - int flags = 0; - if (sideEffectSet != null) { - if (!sideEffectSet.shouldApply(SideEffect.UPDATE)) { - // We don't skip block entity side-effects as that's likely to cause problems. - flags |= Block.UPDATE_SKIP_ON_PLACE | Block.UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE; - } - } - return chunk.setBlockState(position, state, flags); - } - - @Override - public BlockState getValidBlockForPosition(BlockState block, BlockPos position) { - return Block.updateFromNeighbourShapes(block, getWorld(), position); - } - - @Override - public BlockPos getPosition(int x, int y, int z) { - return new BlockPos(x, y, z); - } - - @Override - public void updateLightingForBlock(BlockPos position) { - getWorld().getChunkSource().getLightEngine().checkBlock(position); - } - - @Override - public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) { - CompoundTag nativeTag = NBTConverter.toNative(tag); - Level level = getWorld(); - BlockEntity tileEntity = level.getChunkAt(position).getBlockEntity(position); - if (tileEntity == null) { - return false; - } - return FabricLoggingProblemReporter.with( - () -> "loading tile entity at " + position, - reporter -> { - var tagValueInput = TagValueInput.create(reporter, level.registryAccess(), nativeTag); - tileEntity.loadWithComponents(tagValueInput); - tileEntity.setChanged(); - return true; - } - ); - } - - @Override - public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, BlockState oldState, BlockState newState) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - getWorld().sendBlockUpdated(position, oldState, newState, Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS); - } - } - - @Override - public boolean isChunkTicking(LevelChunk chunk) { - return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING); - } - - @Override - public void markBlockChanged(LevelChunk chunk, BlockPos position) { - if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { - ((ServerChunkCache) getWorld().getChunkSource()).blockChanged(position); - } - } - - @Override - public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { - getWorld().updateNeighborsAt(pos, oldState.getBlock()); - if (newState.hasAnalogOutputSignal()) { - getWorld().updateNeighbourForOutputSignal(pos, newState.getBlock()); - } - } - - @Override - public void updateBlock(BlockPos pos, BlockState oldState, BlockState newState) { - Level world = getWorld(); - newState.onPlace(world, pos, oldState, false); - } - - @Override - public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState, int recursionLimit) { - Level world = getWorld(); - oldState.affectNeighborsAfterRemoval((ServerLevel) world, pos, false); - oldState.updateIndirectNeighbourShapes(world, pos, Block.UPDATE_CLIENTS, recursionLimit); - newState.updateNeighbourShapes(world, pos, Block.UPDATE_CLIENTS, recursionLimit); - newState.updateIndirectNeighbourShapes(world, pos, Block.UPDATE_CLIENTS, recursionLimit); - } - - @Override - public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { - getWorld().updatePOIOnBlockStateChange(pos, oldState, newState); - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java deleted file mode 100644 index d3aebc8ad9..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/MixinConfigPlugin.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.internal; - -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import org.apache.logging.log4j.Logger; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; - -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class MixinConfigPlugin implements IMixinConfigPlugin { - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - @Override - public void onLoad(String mixinPackage) { - } - - @Override - public String getRefMapperConfig() { - return null; - } - - @Override - public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - if (mixinClassName.equals("com.sk89q.worldedit.fabric.mixin.MixinLevelChunkSetBlockHook")) { - List conflictingContainers = Stream.of("carpet", "quickcarpet") - .map(FabricLoader.getInstance()::getModContainer) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toList()); - if (!conflictingContainers.isEmpty()) { - List conflictingIds = conflictingContainers.stream() - .map(mc -> mc.getMetadata().getId()) - .collect(Collectors.toList()); - LOGGER.warn("{} detected, disabling UPDATE mixin {}", conflictingIds, mixinClassName); - } - return conflictingContainers.isEmpty(); - } - return true; - } - - @Override - public void acceptTargets(Set myTargets, Set otherTargets) { - } - - @Override - public List getMixins() { - return null; - } - - @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - } - - @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - } -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java deleted file mode 100644 index c43d28b630..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.internal; - -import net.minecraft.nbt.EndTag; -import net.minecraft.nbt.Tag; -import org.enginehub.linbus.common.LinTagId; -import org.enginehub.linbus.tree.LinByteArrayTag; -import org.enginehub.linbus.tree.LinByteTag; -import org.enginehub.linbus.tree.LinCompoundTag; -import org.enginehub.linbus.tree.LinDoubleTag; -import org.enginehub.linbus.tree.LinEndTag; -import org.enginehub.linbus.tree.LinFloatTag; -import org.enginehub.linbus.tree.LinIntArrayTag; -import org.enginehub.linbus.tree.LinIntTag; -import org.enginehub.linbus.tree.LinListTag; -import org.enginehub.linbus.tree.LinLongArrayTag; -import org.enginehub.linbus.tree.LinLongTag; -import org.enginehub.linbus.tree.LinShortTag; -import org.enginehub.linbus.tree.LinStringTag; -import org.enginehub.linbus.tree.LinTag; -import org.enginehub.linbus.tree.LinTagType; - -import java.util.Arrays; -import java.util.Set; - -/** - * Converts between LinBus and Minecraft NBT classes. - */ -public final class NBTConverter { - - private NBTConverter() { - } - - public static net.minecraft.nbt.Tag toNative(LinTag tag) { - return switch (tag) { - case LinIntArrayTag t -> toNative(t); - case LinListTag t -> toNative(t); - case LinLongTag t -> toNative(t); - case LinLongArrayTag t -> toNative(t); - case LinStringTag t -> toNative(t); - case LinIntTag t -> toNative(t); - case LinByteTag t -> toNative(t); - case LinByteArrayTag t -> toNative(t); - case LinCompoundTag t -> toNative(t); - case LinFloatTag t -> toNative(t); - case LinShortTag t -> toNative(t); - case LinDoubleTag t -> toNative(t); - case LinEndTag ignored -> EndTag.INSTANCE; - }; - } - - public static net.minecraft.nbt.IntArrayTag toNative(LinIntArrayTag tag) { - int[] value = tag.value(); - return new net.minecraft.nbt.IntArrayTag(Arrays.copyOf(value, value.length)); - } - - public static net.minecraft.nbt.ListTag toNative(LinListTag tag) { - net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag(); - for (LinTag child : tag.value()) { - list.addAndUnwrap(toNative(child)); - } - return list; - } - - public static net.minecraft.nbt.LongTag toNative(LinLongTag tag) { - return net.minecraft.nbt.LongTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.LongArrayTag toNative(LinLongArrayTag tag) { - return new net.minecraft.nbt.LongArrayTag(tag.value().clone()); - } - - public static net.minecraft.nbt.StringTag toNative(LinStringTag tag) { - return net.minecraft.nbt.StringTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.IntTag toNative(LinIntTag tag) { - return net.minecraft.nbt.IntTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.ByteTag toNative(LinByteTag tag) { - return net.minecraft.nbt.ByteTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.ByteArrayTag toNative(LinByteArrayTag tag) { - return new net.minecraft.nbt.ByteArrayTag(tag.value().clone()); - } - - public static net.minecraft.nbt.CompoundTag toNative(LinCompoundTag tag) { - net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag(); - tag.value().forEach((key, value) -> compound.put(key, toNative(value))); - return compound; - } - - public static net.minecraft.nbt.FloatTag toNative(LinFloatTag tag) { - return net.minecraft.nbt.FloatTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.ShortTag toNative(LinShortTag tag) { - return net.minecraft.nbt.ShortTag.valueOf(tag.value()); - } - - public static net.minecraft.nbt.DoubleTag toNative(LinDoubleTag tag) { - return net.minecraft.nbt.DoubleTag.valueOf(tag.value()); - } - - public static LinTag fromNative(net.minecraft.nbt.Tag other) { - return switch (other) { - case net.minecraft.nbt.IntArrayTag tags -> fromNative(tags); - case net.minecraft.nbt.ListTag tags -> fromNative(tags); - case net.minecraft.nbt.EndTag endTag -> fromNative(endTag); - case net.minecraft.nbt.LongTag longTag -> fromNative(longTag); - case net.minecraft.nbt.LongArrayTag tags -> fromNative(tags); - case net.minecraft.nbt.StringTag stringTag -> fromNative(stringTag); - case net.minecraft.nbt.IntTag intTag -> fromNative(intTag); - case net.minecraft.nbt.ByteTag byteTag -> fromNative(byteTag); - case net.minecraft.nbt.ByteArrayTag tags -> fromNative(tags); - case net.minecraft.nbt.CompoundTag compoundTag -> fromNative(compoundTag); - case net.minecraft.nbt.FloatTag floatTag -> fromNative(floatTag); - case net.minecraft.nbt.ShortTag shortTag -> fromNative(shortTag); - case net.minecraft.nbt.DoubleTag doubleTag -> fromNative(doubleTag); - }; - } - - public static LinIntArrayTag fromNative(net.minecraft.nbt.IntArrayTag other) { - int[] value = other.getAsIntArray(); - return LinIntArrayTag.of(Arrays.copyOf(value, value.length)); - } - - private static byte identifyRawElementType(net.minecraft.nbt.ListTag list) { - byte b = 0; - - for (Tag tag : list) { - byte c = tag.getId(); - if (b == 0) { - b = c; - } else if (b != c) { - return 10; - } - } - - return b; - } - - private static net.minecraft.nbt.CompoundTag wrapTag(net.minecraft.nbt.Tag tag) { - if (tag instanceof net.minecraft.nbt.CompoundTag compoundTag) { - return compoundTag; - } - var compoundTag = new net.minecraft.nbt.CompoundTag(); - compoundTag.put("", tag); - return compoundTag; - } - - public static LinListTag fromNative(net.minecraft.nbt.ListTag other) { - byte rawType = identifyRawElementType(other); - LinListTag.Builder> list = LinListTag.builder(LinTagType.fromId( - LinTagId.fromId(rawType) - )); - for (net.minecraft.nbt.Tag tag : other) { - if (rawType == LinTagId.COMPOUND.id() && !(tag instanceof net.minecraft.nbt.CompoundTag)) { - list.add(fromNative(wrapTag(tag))); - } else { - list.add(fromNative(tag)); - } - } - return list.build(); - } - - public static LinEndTag fromNative(net.minecraft.nbt.EndTag other) { - return LinEndTag.instance(); - } - - public static LinLongTag fromNative(net.minecraft.nbt.LongTag other) { - return LinLongTag.of(other.value()); - } - - public static LinLongArrayTag fromNative(net.minecraft.nbt.LongArrayTag other) { - return LinLongArrayTag.of(other.getAsLongArray().clone()); - } - - public static LinStringTag fromNative(net.minecraft.nbt.StringTag other) { - return LinStringTag.of(other.value()); - } - - public static LinIntTag fromNative(net.minecraft.nbt.IntTag other) { - return LinIntTag.of(other.value()); - } - - public static LinByteTag fromNative(net.minecraft.nbt.ByteTag other) { - return LinByteTag.of(other.value()); - } - - public static LinByteArrayTag fromNative(net.minecraft.nbt.ByteArrayTag other) { - return LinByteArrayTag.of(other.getAsByteArray().clone()); - } - - public static LinCompoundTag fromNative(net.minecraft.nbt.CompoundTag other) { - Set tags = other.keySet(); - LinCompoundTag.Builder builder = LinCompoundTag.builder(); - for (String tagName : tags) { - builder.put(tagName, fromNative(other.get(tagName))); - } - return builder.build(); - } - - public static LinFloatTag fromNative(net.minecraft.nbt.FloatTag other) { - return LinFloatTag.of(other.value()); - } - - public static LinShortTag fromNative(net.minecraft.nbt.ShortTag other) { - return LinShortTag.of(other.value()); - } - - public static LinDoubleTag fromNative(net.minecraft.nbt.DoubleTag other) { - return LinDoubleTag.of(other.value()); - } - -} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerGamePacketListenerImpl.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerGamePacketListenerImpl.java deleted file mode 100644 index 99d036a0cc..0000000000 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinServerGamePacketListenerImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.fabric.mixin; - -import com.google.errorprone.annotations.Keep; -import com.sk89q.worldedit.fabric.FabricWorldEdit; -import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; -import net.minecraft.network.protocol.game.ServerboundSwingPacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ServerGamePacketListenerImpl.class) -public class MixinServerGamePacketListenerImpl { - @Shadow - public ServerPlayer player; - - @Unique - private int ignoreSwingPackets; - - @Keep - @SuppressWarnings("UnusedVariable") - @Inject(method = "handleAnimate", at = @At("HEAD")) - private void onAnimate(ServerboundSwingPacket packet, CallbackInfo ci) { - if (!this.player.gameMode.isDestroyingBlock) { - if (this.ignoreSwingPackets > 0) { - this.ignoreSwingPackets--; - } else if (FabricWorldEdit.inst != null) { - FabricWorldEdit.inst.onLeftClickAir(this.player, packet.getHand()); - } - } - } - - @Keep - @SuppressWarnings("UnusedVariable") - @Inject(method = "handlePlayerAction", at = @At("HEAD")) - private void onAction(ServerboundPlayerActionPacket packet, CallbackInfo ci) { - switch (packet.getAction()) { - case DROP_ITEM, DROP_ALL_ITEMS, START_DESTROY_BLOCK -> this.ignoreSwingPackets++; - default -> { - } - } - } -} diff --git a/worldedit-fabric/src/main/resources/fabric.mod.json b/worldedit-fabric/src/main/resources/fabric.mod.json index ae1fe696ce..8a7e826f9d 100644 --- a/worldedit-fabric/src/main/resources/fabric.mod.json +++ b/worldedit-fabric/src/main/resources/fabric.mod.json @@ -43,7 +43,6 @@ "fabric-permissions-api-v0": "*" }, "mixins": [ - "worldedit-fabric.mixins.json" - ], - "accessWidener" : "worldedit.accesswidener" + "worldedit-coremc.mixins.json" + ] } diff --git a/worldedit-fabric/src/main/resources/worldedit-fabric.mixins.json b/worldedit-fabric/src/main/resources/worldedit-fabric.mixins.json deleted file mode 100644 index 1097e53aa4..0000000000 --- a/worldedit-fabric/src/main/resources/worldedit-fabric.mixins.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "required": true, - "package": "com.sk89q.worldedit.fabric.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "MixinServerGamePacketListenerImpl" - ], - "plugin": "com.sk89q.worldedit.fabric.internal.MixinConfigPlugin", - "server": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/worldedit-fabric/src/main/resources/worldedit.accesswidener b/worldedit-fabric/src/main/resources/worldedit.accesswidener deleted file mode 100644 index 96d7240b28..0000000000 --- a/worldedit-fabric/src/main/resources/worldedit.accesswidener +++ /dev/null @@ -1,18 +0,0 @@ -accessWidener v2 official - -accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor -accessible field net/minecraft/server/level/ServerChunkCache mainThreadProcessor Lnet/minecraft/server/level/ServerChunkCache$MainThreadExecutor; - -accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource; - -accessible field net/minecraft/server/level/ServerPlayerGameMode isDestroyingBlock Z - -accessible field net/minecraft/world/level/storage/DerivedLevelData wrapped Lnet/minecraft/world/level/storage/ServerLevelData; - -#accessible field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; -#mutable field net/minecraft/world/level/storage/PrimaryLevelData worldOptions Lnet/minecraft/world/level/levelgen/WorldOptions; - -accessible method net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket (Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V - -accessible field net/minecraft/server/MinecraftServer nextTickTimeNanos J -accessible field net/minecraft/server/MinecraftServer storageSource Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess; diff --git a/worldedit-mod/build.gradle.kts b/worldedit-mod/build.gradle.kts index d381755974..438dad0897 100644 --- a/worldedit-mod/build.gradle.kts +++ b/worldedit-mod/build.gradle.kts @@ -108,14 +108,16 @@ tasks.register("jar") { exclude("org/enginehub/piston/") exclude("org/enginehub/linbus/") exclude("net/kyori/examination/") - // Exclude worldedit-core + // Exclude worldedit-core and worldedit-core-mc (already included from fabric side) exclude { val pathString = it.relativePath.pathString pathString.startsWith("com/sk89q/worldedit/") && !pathString.startsWith("com/sk89q/worldedit/neoforge/") } // Questionable excludes. So far the two files from each jar are the same. + exclude("assets/worldedit/icon.png") exclude("defaults/worldedit.properties") exclude("pack.mcmeta") + exclude("worldedit-coremc.mixins.json") } manifest { from(mergeManifests.flatMap { it.outputManifest }) diff --git a/worldedit-neoforge/build.gradle.kts b/worldedit-neoforge/build.gradle.kts index ba74700b2b..70fe733073 100644 --- a/worldedit-neoforge/build.gradle.kts +++ b/worldedit-neoforge/build.gradle.kts @@ -27,6 +27,10 @@ jarJar.disableDefaultSources() repositories { addEngineHubRepository() + maven { + name = "FabricMC" + url = uri("https://maven.fabricmc.net/") + } mavenCentral() } @@ -35,6 +39,7 @@ configurations { resolvable("coreResourcesResolvable") { extendsFrom(coreResourcesScope.get()) attributes { + // Attributes are related to how `expose-resources` works, see that plugin file for details. attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category::class, Category.VERIFICATION)) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling::class, Bundling.EXTERNAL)) attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, objects.named(VerificationType::class, "resources")) @@ -46,6 +51,7 @@ withCuiProtocolDependsOnCommonRule(libs.cuiProtocol.neoforge.get().module) dependencies { api(project(":worldedit-core")) + api(project(":worldedit-core-mc")) implementation(libs.neoforge) implementation(libs.cuiProtocol.neoforge) @@ -56,20 +62,11 @@ dependencies { } "coreResourcesScope"(project(":worldedit-core")) -} - -minecraft { - accessTransformers { - file("src/main/resources/META-INF/accesstransformer.cfg") - } + "coreResourcesScope"(project(":worldedit-core-mc")) } runs { val runConfig = Action { - systemProperties(mapOf( - "forge.logging.markers" to "SCAN,REGISTRIES,REGISTRYDUMP", - "forge.logging.console.level" to "debug" - )) workingDirectory(project.file("run").canonicalPath) modSources(sourceSets["main"]) dependencies { diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCategoryRegistry.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCategoryRegistry.java deleted file mode 100644 index 38ce898b51..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockCategoryRegistry.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.google.common.collect.ImmutableSet; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.tags.TagKey; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -import java.util.Set; - -public class NeoForgeBlockCategoryRegistry implements BlockCategoryRegistry { - @Override - public Set getCategorisedByName(String category) { - return ServerLifecycleHooks.getCurrentServer().registryAccess().lookupOrThrow(Registries.BLOCK) - .get(TagKey.create( - Registries.BLOCK, - Identifier.parse(category) - )) - .stream() - .flatMap(HolderSet.Named::stream) - .map(Holder::value) - .map(NeoForgeAdapter::adapt) - .collect(ImmutableSet.toImmutableSet()); - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockMaterial.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockMaterial.java deleted file mode 100644 index 96db7265e3..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeBlockMaterial.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.sk89q.worldedit.world.registry.BlockMaterial; -import net.minecraft.core.BlockPos; -import net.minecraft.world.Clearable; -import net.minecraft.world.level.EmptyBlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; - -/** - * Forge block material that pulls as much info as possible from the Minecraft - * Material, and passes the rest to another implementation, typically the - * bundled block info. - */ -public class NeoForgeBlockMaterial implements BlockMaterial { - - private final BlockState block; - - public NeoForgeBlockMaterial(BlockState block) { - this.block = block; - } - - @Override - public boolean isAir() { - return block.isAir(); - } - - @Override - public boolean isFullCube() { - return Block.isShapeFullBlock(block.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); - } - - @Override - public boolean isOpaque() { - return block.canOcclude(); - } - - @Override - public boolean isPowerSource() { - return block.isSignalSource(); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isLiquid() { - return block.liquid(); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isSolid() { - return block.isSolid(); - } - - @Override - public float getHardness() { - return block.getDestroySpeed(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); - } - - @Override - @SuppressWarnings("deprecation") - public float getResistance() { - return block.getBlock().getExplosionResistance(); - } - - @Override - public float getSlipperiness() { - return block.getBlock().getFriction(); - } - - @Override - @SuppressWarnings("deprecation") - public int getLightValue() { - return block.getLightEmission(); - } - - @Override - public boolean isFragileWhenPushed() { - return block.getPistonPushReaction() == PushReaction.DESTROY; - } - - @Override - public boolean isUnpushable() { - return block.getPistonPushReaction() == PushReaction.BLOCK; - } - - @Override - public boolean isTicksRandomly() { - return block.isRandomlyTicking(); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isMovementBlocker() { - return block.blocksMotion(); - } - - @SuppressWarnings("deprecation") - @Override - public boolean isBurnable() { - return block.ignitedByLava(); - } - - @Override - public boolean isToolRequired() { - return block.requiresCorrectToolForDrops(); - } - - @Override - public boolean isReplacedDuringPlacement() { - return block.canBeReplaced(); - } - - @Override - public boolean isTranslucent() { - return !block.canOcclude(); - } - - @Override - public boolean hasContainer() { - return block.getBlock() instanceof EntityBlock entityBlock - && entityBlock.newBlockEntity(BlockPos.ZERO, block) instanceof Clearable; - } - -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeCommandSender.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeCommandSender.java deleted file mode 100644 index 258cc47350..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeCommandSender.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.platform.AbstractNonPlayerActor; -import com.sk89q.worldedit.neoforge.internal.ComponentConverter; -import com.sk89q.worldedit.session.SessionKey; -import com.sk89q.worldedit.util.formatting.WorldEditText; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; - -import java.util.Locale; -import java.util.UUID; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -public class NeoForgeCommandSender extends AbstractNonPlayerActor { - - /** - * One time generated ID. - */ - private static final UUID DEFAULT_ID = UUID.fromString("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be"); - - private final CommandSourceStack sender; - - public NeoForgeCommandSender(CommandSourceStack sender) { - checkNotNull(sender); - checkArgument(!sender.isPlayer(), "Cannot wrap a player"); - - this.sender = sender; - } - - @Override - public UUID getUniqueId() { - return DEFAULT_ID; - } - - @Override - public String getName() { - return sender.getTextName(); - } - - @Override - @Deprecated - public void printRaw(String msg) { - for (String part : msg.split("\n", 0)) { - sendMessage(net.minecraft.network.chat.Component.literal(part)); - } - } - - @Override - @Deprecated - public void printDebug(String msg) { - sendColorized(msg, ChatFormatting.GRAY); - } - - @Override - @Deprecated - public void print(String msg) { - sendColorized(msg, ChatFormatting.LIGHT_PURPLE); - } - - @Override - @Deprecated - public void printError(String msg) { - sendColorized(msg, ChatFormatting.RED); - } - - @Override - public void print(Component component) { - sendMessage(ComponentConverter.Serializer.fromJson( - GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())), - sender.registryAccess() - )); - } - - private void sendColorized(String msg, ChatFormatting formatting) { - for (String part : msg.split("\n", 0)) { - var component = net.minecraft.network.chat.Component.literal(part); - component.withStyle(formatting); - sendMessage(component); - } - } - - private void sendMessage(net.minecraft.network.chat.Component textComponent) { - this.sender.sendSystemMessage(textComponent); - } - - @Override - public String[] getGroups() { - return new String[0]; - } - - @Override - public boolean hasPermission(String perm) { - return true; - } - - @Override - public void checkPermission(String permission) { - } - - @Override - public Locale getLocale() { - return WorldEdit.getInstance().getConfiguration().defaultLocale; - } - - public CommandSourceStack getSender() { - return this.sender; - } - - @Override - public SessionKey getSessionKey() { - return new SessionKey() { - @Nullable - @Override - public String getName() { - return sender.getTextName(); - } - - @Override - public boolean isActive() { - return true; - } - - @Override - public boolean isPersistent() { - return true; - } - - @Override - public UUID getUniqueId() { - return DEFAULT_ID; - } - }; - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeDataFixer.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeDataFixer.java deleted file mode 100644 index 80c693e075..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeDataFixer.java +++ /dev/null @@ -1,2724 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.google.common.base.Strings; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.mojang.datafixers.DSL.TypeReference; -import com.mojang.datafixers.DataFixer; -import com.mojang.datafixers.schemas.Schema; -import com.mojang.serialization.Dynamic; -import com.sk89q.worldedit.neoforge.internal.ComponentConverter; -import com.sk89q.worldedit.neoforge.internal.NBTConverter; -import net.minecraft.core.Direction; -import net.minecraft.core.UUIDUtil; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.FloatTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.Identifier; -import net.minecraft.util.GsonHelper; -import net.minecraft.util.datafix.DataFixers; -import net.minecraft.util.datafix.fixes.References; -import net.minecraft.world.item.DyeColor; -import net.neoforged.neoforge.server.ServerLifecycleHooks; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.enginehub.linbus.tree.LinCompoundTag; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import javax.annotation.Nullable; - -/** - * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) - * - *

- * We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy - * which is safer, faster and cleaner code. - *

- * - *

- * The pre DFU code did not fail when the Source version was unknown. - *

- * - *

- * This class also provides util methods for converting compounds to wrap the update call to - * receive the source version in the compound. - *

- */ -@SuppressWarnings({ - "UnnecessarilyQualifiedStaticUsage", - "StringSplitter", - "ImmutableEnumChecker", - "MissingOverride", - "StaticAssignmentInConstructor", - "EffectivelyPrivate", - "FallThrough", - "MutablePublicArray", - "unused", - "unchecked", - "rawtypes" -}) -class NeoForgeDataFixer implements com.sk89q.worldedit.world.DataFixer { - - @SuppressWarnings("unchecked") - @Override - public T fixUp(FixType type, T original, int srcVer) { - if (type == FixTypes.CHUNK) { - return (T) fixChunk((LinCompoundTag) original, srcVer); - } else if (type == FixTypes.BLOCK_ENTITY) { - return (T) fixBlockEntity((LinCompoundTag) original, srcVer); - } else if (type == FixTypes.ENTITY) { - return (T) fixEntity((LinCompoundTag) original, srcVer); - } else if (type == FixTypes.BLOCK_STATE) { - return (T) fixBlockState((String) original, srcVer); - } else if (type == FixTypes.ITEM_TYPE) { - return (T) fixItemType((String) original, srcVer); - } else if (type == FixTypes.BIOME) { - return (T) fixBiome((String) original, srcVer); - } - return original; - } - - private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) { - net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(originalChunk); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer); - return NBTConverter.fromNative(fixed); - } - - private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origTileEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer); - return NBTConverter.fromNative(fixed); - } - - private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { - net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(origEnt); - net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer); - return NBTConverter.fromNative(fixed); - } - - private String fixBlockState(String blockState, int srcVer) { - net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); - Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); - return nbtToState(fixed); - } - - private String nbtToState(net.minecraft.nbt.CompoundTag tagCompound) { - StringBuilder sb = new StringBuilder(); - sb.append(tagCompound.getString("Name").get()); - tagCompound.getCompound("Properties").ifPresent(props -> { - sb.append('['); - sb.append(props.keySet().stream().map(k -> k + "=" + props.getString(k).get().replace("\"", "")).collect(Collectors.joining(","))); - sb.append(']'); - }); - return sb.toString(); - } - - private static net.minecraft.nbt.CompoundTag stateToNBT(String blockState) { - int propIdx = blockState.indexOf('['); - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); - if (propIdx < 0) { - tag.putString("Name", blockState); - } else { - tag.putString("Name", blockState.substring(0, propIdx)); - net.minecraft.nbt.CompoundTag propTag = new net.minecraft.nbt.CompoundTag(); - String props = blockState.substring(propIdx + 1, blockState.length() - 1); - String[] propArr = props.split(","); - for (String pair : propArr) { - final String[] split = pair.split("="); - propTag.putString(split[0], split[1]); - } - tag.put("Properties", propTag); - } - return tag; - } - - private String fixBiome(String key, int srcVer) { - return fixName(key, srcVer, References.BIOME); - } - - private String fixItemType(String key, int srcVer) { - return fixName(key, srcVer, References.ITEM_NAME); - } - - private static String fixName(String key, int srcVer, TypeReference type) { - return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, DATA_VERSION) - .asString().result().orElse(key); - } - - private static final NbtOps OPS_NBT = NbtOps.INSTANCE; - private static final int LEGACY_VERSION = 1343; - private static int DATA_VERSION; - private static NeoForgeDataFixer INSTANCE; - - private final Map> converters = new EnumMap<>(LegacyType.class); - private final Map> inspectors = new EnumMap<>(LegacyType.class); - - // Set on build - private final DataFixer fixer; - private static final Map DFU_TO_LEGACY = new HashMap<>(); - - public enum LegacyType { - LEVEL(References.LEVEL), - PLAYER(References.PLAYER), - CHUNK(References.CHUNK), - BLOCK_ENTITY(References.BLOCK_ENTITY), - ENTITY(References.ENTITY), - ITEM_INSTANCE(References.ITEM_STACK), - OPTIONS(References.OPTIONS), - STRUCTURE(References.STRUCTURE); - - private final TypeReference type; - - LegacyType(TypeReference type) { - this.type = type; - DFU_TO_LEGACY.put(type.typeName(), this); - } - - public TypeReference getDFUType() { - return type; - } - } - - NeoForgeDataFixer(int dataVersion) { - DATA_VERSION = dataVersion; - INSTANCE = this; - registerConverters(); - registerInspectors(); - this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); - } - - private class WrappedDataFixer implements DataFixer { - private final DataFixer realFixer; - - WrappedDataFixer(DataFixer realFixer) { - this.realFixer = realFixer; - } - - @Override - public Dynamic update(TypeReference type, Dynamic dynamic, int sourceVer, int targetVer) { - LegacyType legacyType = DFU_TO_LEGACY.get(type.typeName()); - if (sourceVer < LEGACY_VERSION && legacyType != null) { - net.minecraft.nbt.CompoundTag cmp = (net.minecraft.nbt.CompoundTag) dynamic.getValue(); - int desiredVersion = Math.min(targetVer, LEGACY_VERSION); - - cmp = convert(legacyType, cmp, sourceVer, desiredVersion); - sourceVer = desiredVersion; - dynamic = new Dynamic(OPS_NBT, cmp); - } - return realFixer.update(type, dynamic, sourceVer, targetVer); - } - - private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int desiredVersion) { - List converters = NeoForgeDataFixer.this.converters.get(type); - if (converters != null && !converters.isEmpty()) { - for (DataConverter converter : converters) { - int dataVersion = converter.getDataVersion(); - if (dataVersion > sourceVer && dataVersion <= desiredVersion) { - cmp = converter.convert(cmp); - } - } - } - - List inspectors = NeoForgeDataFixer.this.inspectors.get(type); - if (inspectors != null && !inspectors.isEmpty()) { - for (DataInspector inspector : inspectors) { - cmp = inspector.inspect(cmp, sourceVer, desiredVersion); - } - } - - return cmp; - } - - @Override - public Schema getSchema(int i) { - return realFixer.getSchema(i); - } - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { - return convert(type.getDFUType(), cmp); - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type.getDFUType(), cmp, sourceVer); - } - - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - return convert(type.getDFUType(), cmp, sourceVer, targetVer); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { - int i = cmp.getIntOr("DataVersion", -1); - return convert(type, cmp, i); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type, cmp, sourceVer, DATA_VERSION); - } - - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (sourceVer >= targetVer) { - return cmp; - } - return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); - } - - - public interface DataInspector { - net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); - } - - public interface DataConverter { - - int getDataVersion(); - - net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); - } - - - private void registerInspector(LegacyType type, DataInspector inspector) { - this.inspectors.computeIfAbsent(type, k -> new ArrayList<>()).add(inspector); - } - - private void registerConverter(LegacyType type, DataConverter converter) { - int version = converter.getDataVersion(); - - List list = this.converters.computeIfAbsent(type, k -> new ArrayList<>()); - if (!list.isEmpty() && list.getLast().getDataVersion() > version) { - for (int j = 0; j < list.size(); ++j) { - if (list.get(j).getDataVersion() > version) { - list.add(j, converter); - break; - } - } - } else { - list.add(converter); - } - } - - private void registerInspectors() { - registerEntityItemList("EntityHorseDonkey", "SaddleItem", "Items"); - registerEntityItemList("EntityHorseMule", "Items"); - registerEntityItemList("EntityMinecartChest", "Items"); - registerEntityItemList("EntityMinecartHopper", "Items"); - registerEntityItemList("EntityVillager", "Inventory"); - registerEntityItemListEquipment("EntityArmorStand"); - registerEntityItemListEquipment("EntityBat"); - registerEntityItemListEquipment("EntityBlaze"); - registerEntityItemListEquipment("EntityCaveSpider"); - registerEntityItemListEquipment("EntityChicken"); - registerEntityItemListEquipment("EntityCow"); - registerEntityItemListEquipment("EntityCreeper"); - registerEntityItemListEquipment("EntityEnderDragon"); - registerEntityItemListEquipment("EntityEnderman"); - registerEntityItemListEquipment("EntityEndermite"); - registerEntityItemListEquipment("EntityEvoker"); - registerEntityItemListEquipment("EntityGhast"); - registerEntityItemListEquipment("EntityGiantZombie"); - registerEntityItemListEquipment("EntityGuardian"); - registerEntityItemListEquipment("EntityGuardianElder"); - registerEntityItemListEquipment("EntityHorse"); - registerEntityItemListEquipment("EntityHorseDonkey"); - registerEntityItemListEquipment("EntityHorseMule"); - registerEntityItemListEquipment("EntityHorseSkeleton"); - registerEntityItemListEquipment("EntityHorseZombie"); - registerEntityItemListEquipment("EntityIronGolem"); - registerEntityItemListEquipment("EntityMagmaCube"); - registerEntityItemListEquipment("EntityMushroomCow"); - registerEntityItemListEquipment("EntityOcelot"); - registerEntityItemListEquipment("EntityPig"); - registerEntityItemListEquipment("EntityPigZombie"); - registerEntityItemListEquipment("EntityRabbit"); - registerEntityItemListEquipment("EntitySheep"); - registerEntityItemListEquipment("EntityShulker"); - registerEntityItemListEquipment("EntitySilverfish"); - registerEntityItemListEquipment("EntitySkeleton"); - registerEntityItemListEquipment("EntitySkeletonStray"); - registerEntityItemListEquipment("EntitySkeletonWither"); - registerEntityItemListEquipment("EntitySlime"); - registerEntityItemListEquipment("EntitySnowman"); - registerEntityItemListEquipment("EntitySpider"); - registerEntityItemListEquipment("EntitySquid"); - registerEntityItemListEquipment("EntityVex"); - registerEntityItemListEquipment("EntityVillager"); - registerEntityItemListEquipment("EntityVindicator"); - registerEntityItemListEquipment("EntityWitch"); - registerEntityItemListEquipment("EntityWither"); - registerEntityItemListEquipment("EntityWolf"); - registerEntityItemListEquipment("EntityZombie"); - registerEntityItemListEquipment("EntityZombieHusk"); - registerEntityItemListEquipment("EntityZombieVillager"); - registerEntityItemSingle("EntityFireworks", "FireworksItem"); - registerEntityItemSingle("EntityHorse", "ArmorItem"); - registerEntityItemSingle("EntityHorse", "SaddleItem"); - registerEntityItemSingle("EntityHorseMule", "SaddleItem"); - registerEntityItemSingle("EntityHorseSkeleton", "SaddleItem"); - registerEntityItemSingle("EntityHorseZombie", "SaddleItem"); - registerEntityItemSingle("EntityItem", "Item"); - registerEntityItemSingle("EntityItemFrame", "Item"); - registerEntityItemSingle("EntityPotion", "Potion"); - - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItem("TileEntityRecordPlayer", "RecordItem")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityBrewingStand", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityChest", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDispenser", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityDropper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityFurnace", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityHopper", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorItemList("TileEntityShulkerBox", "Items")); - registerInspector(LegacyType.BLOCK_ENTITY, new DataInspectorMobSpawnerMobs()); - registerInspector(LegacyType.CHUNK, new DataInspectorChunks()); - registerInspector(LegacyType.ENTITY, new DataInspectorCommandBlock()); - registerInspector(LegacyType.ENTITY, new DataInspectorEntityPassengers()); - registerInspector(LegacyType.ENTITY, new DataInspectorMobSpawnerMinecart()); - registerInspector(LegacyType.ENTITY, new DataInspectorVillagers()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorBlockEntity()); - registerInspector(LegacyType.ITEM_INSTANCE, new DataInspectorEntity()); - registerInspector(LegacyType.LEVEL, new DataInspectorLevelPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayer()); - registerInspector(LegacyType.PLAYER, new DataInspectorPlayerVehicle()); - registerInspector(LegacyType.STRUCTURE, new DataInspectorStructure()); - } - - private void registerConverters() { - registerConverter(LegacyType.ENTITY, new DataConverterEquipment()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterSignText()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterMaterialId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionId()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterSpawnEgg()); - registerConverter(LegacyType.ENTITY, new DataConverterMinecart()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterMobSpawner()); - registerConverter(LegacyType.ENTITY, new DataConverterUUID()); - registerConverter(LegacyType.ENTITY, new DataConverterHealth()); - registerConverter(LegacyType.ENTITY, new DataConverterSaddle()); - registerConverter(LegacyType.ENTITY, new DataConverterHanging()); - registerConverter(LegacyType.ENTITY, new DataConverterDropChances()); - registerConverter(LegacyType.ENTITY, new DataConverterRiding()); - registerConverter(LegacyType.ENTITY, new DataConverterArmorStand()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBook()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterCookedFish()); - registerConverter(LegacyType.ENTITY, new DataConverterZombie()); - registerConverter(LegacyType.OPTIONS, new DataConverterVBO()); - registerConverter(LegacyType.ENTITY, new DataConverterGuardian()); - registerConverter(LegacyType.ENTITY, new DataConverterSkeleton()); - registerConverter(LegacyType.ENTITY, new DataConverterZombieType()); - registerConverter(LegacyType.ENTITY, new DataConverterHorse()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterTileEntity()); - registerConverter(LegacyType.ENTITY, new DataConverterEntity()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBanner()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterPotionWater()); - registerConverter(LegacyType.ENTITY, new DataConverterShulker()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterShulkerBoxItem()); - registerConverter(LegacyType.BLOCK_ENTITY, new DataConverterShulkerBoxBlock()); - registerConverter(LegacyType.OPTIONS, new DataConverterLang()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterTotem()); - registerConverter(LegacyType.CHUNK, new DataConverterBedBlock()); - registerConverter(LegacyType.ITEM_INSTANCE, new DataConverterBedItem()); - } - - private void registerEntityItemList(String type, String... keys) { - registerInspector(LegacyType.ENTITY, new DataInspectorItemList(type, keys)); - } - - private void registerEntityItemSingle(String type, String key) { - registerInspector(LegacyType.ENTITY, new DataInspectorItem(type, key)); - } - - private void registerEntityItemListEquipment(String type) { - registerEntityItemList(type, "ArmorItems", "HandItems"); - } - - private static final Map OLD_ID_TO_KEY_MAP = new HashMap<>(); - - static { - final Map map = OLD_ID_TO_KEY_MAP; - map.put("EntityItem", Identifier.parse("item")); - map.put("EntityExperienceOrb", Identifier.parse("xp_orb")); - map.put("EntityAreaEffectCloud", Identifier.parse("area_effect_cloud")); - map.put("EntityGuardianElder", Identifier.parse("elder_guardian")); - map.put("EntitySkeletonWither", Identifier.parse("wither_skeleton")); - map.put("EntitySkeletonStray", Identifier.parse("stray")); - map.put("EntityEgg", Identifier.parse("egg")); - map.put("EntityLeash", Identifier.parse("leash_knot")); - map.put("EntityPainting", Identifier.parse("painting")); - map.put("EntityTippedArrow", Identifier.parse("arrow")); - map.put("EntitySnowball", Identifier.parse("snowball")); - map.put("EntityLargeFireball", Identifier.parse("fireball")); - map.put("EntitySmallFireball", Identifier.parse("small_fireball")); - map.put("EntityEnderPearl", Identifier.parse("ender_pearl")); - map.put("EntityEnderSignal", Identifier.parse("eye_of_ender_signal")); - map.put("EntityPotion", Identifier.parse("potion")); - map.put("EntityThrownExpBottle", Identifier.parse("xp_bottle")); - map.put("EntityItemFrame", Identifier.parse("item_frame")); - map.put("EntityWitherSkull", Identifier.parse("wither_skull")); - map.put("EntityTNTPrimed", Identifier.parse("tnt")); - map.put("EntityFallingBlock", Identifier.parse("falling_block")); - map.put("EntityFireworks", Identifier.parse("fireworks_rocket")); - map.put("EntityZombieHusk", Identifier.parse("husk")); - map.put("EntitySpectralArrow", Identifier.parse("spectral_arrow")); - map.put("EntityShulkerBullet", Identifier.parse("shulker_bullet")); - map.put("EntityDragonFireball", Identifier.parse("dragon_fireball")); - map.put("EntityZombieVillager", Identifier.parse("zombie_villager")); - map.put("EntityHorseSkeleton", Identifier.parse("skeleton_horse")); - map.put("EntityHorseZombie", Identifier.parse("zombie_horse")); - map.put("EntityArmorStand", Identifier.parse("armor_stand")); - map.put("EntityHorseDonkey", Identifier.parse("donkey")); - map.put("EntityHorseMule", Identifier.parse("mule")); - map.put("EntityEvokerFangs", Identifier.parse("evocation_fangs")); - map.put("EntityEvoker", Identifier.parse("evocation_illager")); - map.put("EntityVex", Identifier.parse("vex")); - map.put("EntityVindicator", Identifier.parse("vindication_illager")); - map.put("EntityIllagerIllusioner", Identifier.parse("illusion_illager")); - map.put("EntityMinecartCommandBlock", Identifier.parse("commandblock_minecart")); - map.put("EntityBoat", Identifier.parse("boat")); - map.put("EntityMinecartRideable", Identifier.parse("minecart")); - map.put("EntityMinecartChest", Identifier.parse("chest_minecart")); - map.put("EntityMinecartFurnace", Identifier.parse("furnace_minecart")); - map.put("EntityMinecartTNT", Identifier.parse("tnt_minecart")); - map.put("EntityMinecartHopper", Identifier.parse("hopper_minecart")); - map.put("EntityMinecartMobSpawner", Identifier.parse("spawner_minecart")); - map.put("EntityCreeper", Identifier.parse("creeper")); - map.put("EntitySkeleton", Identifier.parse("skeleton")); - map.put("EntitySpider", Identifier.parse("spider")); - map.put("EntityGiantZombie", Identifier.parse("giant")); - map.put("EntityZombie", Identifier.parse("zombie")); - map.put("EntitySlime", Identifier.parse("slime")); - map.put("EntityGhast", Identifier.parse("ghast")); - map.put("EntityPigZombie", Identifier.parse("zombie_pigman")); - map.put("EntityEnderman", Identifier.parse("enderman")); - map.put("EntityCaveSpider", Identifier.parse("cave_spider")); - map.put("EntitySilverfish", Identifier.parse("silverfish")); - map.put("EntityBlaze", Identifier.parse("blaze")); - map.put("EntityMagmaCube", Identifier.parse("magma_cube")); - map.put("EntityEnderDragon", Identifier.parse("ender_dragon")); - map.put("EntityWither", Identifier.parse("wither")); - map.put("EntityBat", Identifier.parse("bat")); - map.put("EntityWitch", Identifier.parse("witch")); - map.put("EntityEndermite", Identifier.parse("endermite")); - map.put("EntityGuardian", Identifier.parse("guardian")); - map.put("EntityShulker", Identifier.parse("shulker")); - map.put("EntityPig", Identifier.parse("pig")); - map.put("EntitySheep", Identifier.parse("sheep")); - map.put("EntityCow", Identifier.parse("cow")); - map.put("EntityChicken", Identifier.parse("chicken")); - map.put("EntitySquid", Identifier.parse("squid")); - map.put("EntityWolf", Identifier.parse("wolf")); - map.put("EntityMushroomCow", Identifier.parse("mooshroom")); - map.put("EntitySnowman", Identifier.parse("snowman")); - map.put("EntityOcelot", Identifier.parse("ocelot")); - map.put("EntityIronGolem", Identifier.parse("villager_golem")); - map.put("EntityHorse", Identifier.parse("horse")); - map.put("EntityRabbit", Identifier.parse("rabbit")); - map.put("EntityPolarBear", Identifier.parse("polar_bear")); - map.put("EntityLlama", Identifier.parse("llama")); - map.put("EntityLlamaSpit", Identifier.parse("llama_spit")); - map.put("EntityParrot", Identifier.parse("parrot")); - map.put("EntityVillager", Identifier.parse("villager")); - map.put("EntityEnderCrystal", Identifier.parse("ender_crystal")); - map.put("TileEntityFurnace", Identifier.parse("furnace")); - map.put("TileEntityChest", Identifier.parse("chest")); - map.put("TileEntityEnderChest", Identifier.parse("ender_chest")); - map.put("TileEntityRecordPlayer", Identifier.parse("jukebox")); - map.put("TileEntityDispenser", Identifier.parse("dispenser")); - map.put("TileEntityDropper", Identifier.parse("dropper")); - map.put("TileEntitySign", Identifier.parse("sign")); - map.put("TileEntityMobSpawner", Identifier.parse("mob_spawner")); - map.put("TileEntityNote", Identifier.parse("noteblock")); - map.put("TileEntityPiston", Identifier.parse("piston")); - map.put("TileEntityBrewingStand", Identifier.parse("brewing_stand")); - map.put("TileEntityEnchantTable", Identifier.parse("enchanting_table")); - map.put("TileEntityEnderPortal", Identifier.parse("end_portal")); - map.put("TileEntityBeacon", Identifier.parse("beacon")); - map.put("TileEntitySkull", Identifier.parse("skull")); - map.put("TileEntityLightDetector", Identifier.parse("daylight_detector")); - map.put("TileEntityHopper", Identifier.parse("hopper")); - map.put("TileEntityComparator", Identifier.parse("comparator")); - map.put("TileEntityFlowerPot", Identifier.parse("flower_pot")); - map.put("TileEntityBanner", Identifier.parse("banner")); - map.put("TileEntityStructure", Identifier.parse("structure_block")); - map.put("TileEntityEndGateway", Identifier.parse("end_gateway")); - map.put("TileEntityCommand", Identifier.parse("command_block")); - map.put("TileEntityShulkerBox", Identifier.parse("shulker_box")); - map.put("TileEntityBed", Identifier.parse("bed")); - } - - private static Identifier getKey(String type) { - final Identifier key = OLD_ID_TO_KEY_MAP.get(type); - if (key == null) { - throw new IllegalArgumentException("Unknown mapping for " + type); - } - return key; - } - - private static void convertCompound(LegacyType type, net.minecraft.nbt.CompoundTag cmp, String key, int sourceVer, int targetVer) { - cmp.put(key, convert(type, cmp.getCompoundOrEmpty(key), sourceVer, targetVer)); - } - - private static void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - if (nbttagcompound.getCompound(key).isPresent()) { - convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); - } - } - - private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { - nbttagcompound.getList(key).ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompoundOrEmpty(j), sourceVer, targetVer)); - } - }); - } - - private static class DataConverterEquipment implements DataConverter { - - DataConverterEquipment() { - } - - @Override - public int getDataVersion() { - return 100; - } - - @Override - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - ListTag nbttaglist = cmp.getListOrEmpty("Equipment"); - - if (!nbttaglist.isEmpty() && cmp.getCompound("HandItems").isEmpty()) { - ListTag nbttaglist1 = new ListTag(); - nbttaglist1.add(nbttaglist.get(0)); - nbttaglist1.add(new net.minecraft.nbt.CompoundTag()); - cmp.put("HandItems", nbttaglist1); - } - - if (nbttaglist.size() > 1 && cmp.getCompound("ArmorItem").isEmpty()) { - ListTag nbttaglist1 = new ListTag(); - nbttaglist1.add(nbttaglist.get(1)); - nbttaglist1.add(nbttaglist.get(2)); - nbttaglist1.add(nbttaglist.get(3)); - nbttaglist1.add(nbttaglist.get(4)); - cmp.put("ArmorItems", nbttaglist1); - } - - cmp.remove("Equipment"); - cmp.getList("DropChances").ifPresent(nbttaglist1 -> { - ListTag nbttaglist2; - - if (cmp.getCompound("HandDropChances").isEmpty()) { - nbttaglist2 = new ListTag(); - nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloatOr(0, 0F))); - nbttaglist2.add(FloatTag.valueOf(0.0F)); - cmp.put("HandDropChances", nbttaglist2); - } - - if (cmp.getCompound("ArmorDropChances").isEmpty()) { - nbttaglist2 = new ListTag(); - nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloatOr(1, 0F))); - nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloatOr(2, 0F))); - nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloatOr(3, 0F))); - nbttaglist2.add(FloatTag.valueOf(nbttaglist1.getFloatOr(4, 0F))); - cmp.put("ArmorDropChances", nbttaglist2); - } - - cmp.remove("DropChances"); - }); - - return cmp; - } - } - - private static class DataInspectorBlockEntity implements DataInspector { - - private static final Map b = Maps.newHashMap(); - private static final Map c = Maps.newHashMap(); - - DataInspectorBlockEntity() { - } - - @Nullable - private static String convertEntityId(int i, String s) { - String key = Identifier.parse(s).toString(); - if (i < 515 && DataInspectorBlockEntity.b.containsKey(key)) { - return DataInspectorBlockEntity.b.get(key); - } else { - return DataInspectorBlockEntity.c.get(key); - } - } - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - Optional nbttagcompound1Optional = cmp.getCompound("tag"); - - if (nbttagcompound1Optional.isPresent()) { - var nbttagcompound1 = nbttagcompound1Optional.get(); - - nbttagcompound1.getCompound("BlockEntityTag").ifPresent(nbttagcompound2 -> { - String s = cmp.getString("id").get(); - String s1 = convertEntityId(sourceVer, s); - boolean flag; - - if (s1 == null) { - // CraftBukkit - Remove unnecessary warning (occurs when deserializing a Shulker Box item) - // DataInspectorBlockEntity.a.warn("Unable to resolve BlockEntity for ItemInstance: {}", s); - flag = false; - } else { - flag = !nbttagcompound2.contains("id"); - nbttagcompound2.putString("id", s1); - } - - convert(LegacyType.BLOCK_ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - }); - } - - return cmp; - } - - static { - Map map = DataInspectorBlockEntity.b; - - map.put("minecraft:furnace", "Furnace"); - map.put("minecraft:lit_furnace", "Furnace"); - map.put("minecraft:chest", "Chest"); - map.put("minecraft:trapped_chest", "Chest"); - map.put("minecraft:ender_chest", "EnderChest"); - map.put("minecraft:jukebox", "RecordPlayer"); - map.put("minecraft:dispenser", "Trap"); - map.put("minecraft:dropper", "Dropper"); - map.put("minecraft:sign", "Sign"); - map.put("minecraft:mob_spawner", "MobSpawner"); - map.put("minecraft:noteblock", "Music"); - map.put("minecraft:brewing_stand", "Cauldron"); - map.put("minecraft:enhanting_table", "EnchantTable"); - map.put("minecraft:command_block", "CommandBlock"); - map.put("minecraft:beacon", "Beacon"); - map.put("minecraft:skull", "Skull"); - map.put("minecraft:daylight_detector", "DLDetector"); - map.put("minecraft:hopper", "Hopper"); - map.put("minecraft:banner", "Banner"); - map.put("minecraft:flower_pot", "FlowerPot"); - map.put("minecraft:repeating_command_block", "CommandBlock"); - map.put("minecraft:chain_command_block", "CommandBlock"); - map.put("minecraft:standing_sign", "Sign"); - map.put("minecraft:wall_sign", "Sign"); - map.put("minecraft:piston_head", "Piston"); - map.put("minecraft:daylight_detector_inverted", "DLDetector"); - map.put("minecraft:unpowered_comparator", "Comparator"); - map.put("minecraft:powered_comparator", "Comparator"); - map.put("minecraft:wall_banner", "Banner"); - map.put("minecraft:standing_banner", "Banner"); - map.put("minecraft:structure_block", "Structure"); - map.put("minecraft:end_portal", "Airportal"); - map.put("minecraft:end_gateway", "EndGateway"); - map.put("minecraft:shield", "Shield"); - map = DataInspectorBlockEntity.c; - map.put("minecraft:furnace", "minecraft:furnace"); - map.put("minecraft:lit_furnace", "minecraft:furnace"); - map.put("minecraft:chest", "minecraft:chest"); - map.put("minecraft:trapped_chest", "minecraft:chest"); - map.put("minecraft:ender_chest", "minecraft:enderchest"); - map.put("minecraft:jukebox", "minecraft:jukebox"); - map.put("minecraft:dispenser", "minecraft:dispenser"); - map.put("minecraft:dropper", "minecraft:dropper"); - map.put("minecraft:sign", "minecraft:sign"); - map.put("minecraft:mob_spawner", "minecraft:mob_spawner"); - map.put("minecraft:noteblock", "minecraft:noteblock"); - map.put("minecraft:brewing_stand", "minecraft:brewing_stand"); - map.put("minecraft:enhanting_table", "minecraft:enchanting_table"); - map.put("minecraft:command_block", "minecraft:command_block"); - map.put("minecraft:beacon", "minecraft:beacon"); - map.put("minecraft:skull", "minecraft:skull"); - map.put("minecraft:daylight_detector", "minecraft:daylight_detector"); - map.put("minecraft:hopper", "minecraft:hopper"); - map.put("minecraft:banner", "minecraft:banner"); - map.put("minecraft:flower_pot", "minecraft:flower_pot"); - map.put("minecraft:repeating_command_block", "minecraft:command_block"); - map.put("minecraft:chain_command_block", "minecraft:command_block"); - map.put("minecraft:shulker_box", "minecraft:shulker_box"); - map.put("minecraft:white_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:orange_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:magenta_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:light_blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:yellow_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:lime_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:pink_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:gray_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:silver_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:cyan_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:purple_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:blue_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:brown_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:green_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:red_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:black_shulker_box", "minecraft:shulker_box"); - map.put("minecraft:bed", "minecraft:bed"); - map.put("minecraft:standing_sign", "minecraft:sign"); - map.put("minecraft:wall_sign", "minecraft:sign"); - map.put("minecraft:piston_head", "minecraft:piston"); - map.put("minecraft:daylight_detector_inverted", "minecraft:daylight_detector"); - map.put("minecraft:unpowered_comparator", "minecraft:comparator"); - map.put("minecraft:powered_comparator", "minecraft:comparator"); - map.put("minecraft:wall_banner", "minecraft:banner"); - map.put("minecraft:standing_banner", "minecraft:banner"); - map.put("minecraft:structure_block", "minecraft:structure_block"); - map.put("minecraft:end_portal", "minecraft:end_portal"); - map.put("minecraft:end_gateway", "minecraft:end_gateway"); - map.put("minecraft:shield", "minecraft:shield"); - } - } - - private static class DataInspectorEntity implements DataInspector { - - private static final Logger a = LogManager.getLogger(NeoForgeDataFixer.class); - - DataInspectorEntity() { - } - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - cmp.getCompound("tag").flatMap(nbttagcompound1 -> nbttagcompound1.getCompound("EntityTag")).ifPresent(nbttagcompound2 -> { - String s = cmp.getString("id").orElse(null); - String s1; - - if ("minecraft:armor_stand".equals(s)) { - s1 = sourceVer < 515 ? "ArmorStand" : "minecraft:armor_stand"; - } else { - if (!"minecraft:spawn_egg".equals(s)) { - return; - } - - s1 = nbttagcompound2.getString("id").orElse(null); - } - - boolean flag; - - if (s1 == null) { - DataInspectorEntity.a.warn("Unable to resolve Entity for ItemInstance: {}", s); - flag = false; - } else { - flag = nbttagcompound2.getString("id").isEmpty(); - nbttagcompound2.putString("id", s1); - } - - convert(LegacyType.ENTITY, nbttagcompound2, sourceVer, targetVer); - if (flag) { - nbttagcompound2.remove("id"); - } - }); - - return cmp; - } - } - - - private abstract static class DataInspectorTagged implements DataInspector { - - private final Identifier key; - - DataInspectorTagged(String type) { - this.key = getKey(type); - } - - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.getString("id").isPresent() && this.key.equals(Identifier.parse(cmp.getString("id").get()))) { - cmp = this.inspectChecked(cmp, sourceVer, targetVer); - } - - return cmp; - } - - abstract net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer); - } - - private static class DataInspectorItemList extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItemList(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String s : this.keys) { - NeoForgeDataFixer.convertItems(nbttagcompound, s, sourceVer, targetVer); - } - - return nbttagcompound; - } - } - - private static class DataInspectorItem extends DataInspectorTagged { - - private final String[] keys; - - DataInspectorItem(String oclass, String... astring) { - super(oclass); - this.keys = astring; - } - - net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { - for (String key : this.keys) { - NeoForgeDataFixer.convertItem(nbttagcompound, key, sourceVer, targetVer); - } - - return nbttagcompound; - } - } - - private static class DataConverterMaterialId implements DataConverter { - - private static final String[] materials = new String[2268]; - - DataConverterMaterialId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.getShort("id").ifPresent(short0 -> { - if (short0 > 0 && short0 < materials.length && materials[short0] != null) { - cmp.putString("id", materials[short0]); - } - }); - - return cmp; - } - - static { - materials[1] = "minecraft:stone"; - materials[2] = "minecraft:grass"; - materials[3] = "minecraft:dirt"; - materials[4] = "minecraft:cobblestone"; - materials[5] = "minecraft:planks"; - materials[6] = "minecraft:sapling"; - materials[7] = "minecraft:bedrock"; - materials[8] = "minecraft:flowing_water"; - materials[9] = "minecraft:water"; - materials[10] = "minecraft:flowing_lava"; - materials[11] = "minecraft:lava"; - materials[12] = "minecraft:sand"; - materials[13] = "minecraft:gravel"; - materials[14] = "minecraft:gold_ore"; - materials[15] = "minecraft:iron_ore"; - materials[16] = "minecraft:coal_ore"; - materials[17] = "minecraft:log"; - materials[18] = "minecraft:leaves"; - materials[19] = "minecraft:sponge"; - materials[20] = "minecraft:glass"; - materials[21] = "minecraft:lapis_ore"; - materials[22] = "minecraft:lapis_block"; - materials[23] = "minecraft:dispenser"; - materials[24] = "minecraft:sandstone"; - materials[25] = "minecraft:noteblock"; - materials[27] = "minecraft:golden_rail"; - materials[28] = "minecraft:detector_rail"; - materials[29] = "minecraft:sticky_piston"; - materials[30] = "minecraft:web"; - materials[31] = "minecraft:tallgrass"; - materials[32] = "minecraft:deadbush"; - materials[33] = "minecraft:piston"; - materials[35] = "minecraft:wool"; - materials[37] = "minecraft:yellow_flower"; - materials[38] = "minecraft:red_flower"; - materials[39] = "minecraft:brown_mushroom"; - materials[40] = "minecraft:red_mushroom"; - materials[41] = "minecraft:gold_block"; - materials[42] = "minecraft:iron_block"; - materials[43] = "minecraft:double_stone_slab"; - materials[44] = "minecraft:stone_slab"; - materials[45] = "minecraft:brick_block"; - materials[46] = "minecraft:tnt"; - materials[47] = "minecraft:bookshelf"; - materials[48] = "minecraft:mossy_cobblestone"; - materials[49] = "minecraft:obsidian"; - materials[50] = "minecraft:torch"; - materials[51] = "minecraft:fire"; - materials[52] = "minecraft:mob_spawner"; - materials[53] = "minecraft:oak_stairs"; - materials[54] = "minecraft:chest"; - materials[56] = "minecraft:diamond_ore"; - materials[57] = "minecraft:diamond_block"; - materials[58] = "minecraft:crafting_table"; - materials[60] = "minecraft:farmland"; - materials[61] = "minecraft:furnace"; - materials[62] = "minecraft:lit_furnace"; - materials[65] = "minecraft:ladder"; - materials[66] = "minecraft:rail"; - materials[67] = "minecraft:stone_stairs"; - materials[69] = "minecraft:lever"; - materials[70] = "minecraft:stone_pressure_plate"; - materials[72] = "minecraft:wooden_pressure_plate"; - materials[73] = "minecraft:redstone_ore"; - materials[76] = "minecraft:redstone_torch"; - materials[77] = "minecraft:stone_button"; - materials[78] = "minecraft:snow_layer"; - materials[79] = "minecraft:ice"; - materials[80] = "minecraft:snow"; - materials[81] = "minecraft:cactus"; - materials[82] = "minecraft:clay"; - materials[84] = "minecraft:jukebox"; - materials[85] = "minecraft:fence"; - materials[86] = "minecraft:pumpkin"; - materials[87] = "minecraft:netherrack"; - materials[88] = "minecraft:soul_sand"; - materials[89] = "minecraft:glowstone"; - materials[90] = "minecraft:portal"; - materials[91] = "minecraft:lit_pumpkin"; - materials[95] = "minecraft:stained_glass"; - materials[96] = "minecraft:trapdoor"; - materials[97] = "minecraft:monster_egg"; - materials[98] = "minecraft:stonebrick"; - materials[99] = "minecraft:brown_mushroom_block"; - materials[100] = "minecraft:red_mushroom_block"; - materials[101] = "minecraft:iron_bars"; - materials[102] = "minecraft:glass_pane"; - materials[103] = "minecraft:melon_block"; - materials[106] = "minecraft:vine"; - materials[107] = "minecraft:fence_gate"; - materials[108] = "minecraft:brick_stairs"; - materials[109] = "minecraft:stone_brick_stairs"; - materials[110] = "minecraft:mycelium"; - materials[111] = "minecraft:waterlily"; - materials[112] = "minecraft:nether_brick"; - materials[113] = "minecraft:nether_brick_fence"; - materials[114] = "minecraft:nether_brick_stairs"; - materials[116] = "minecraft:enchanting_table"; - materials[119] = "minecraft:end_portal"; - materials[120] = "minecraft:end_portal_frame"; - materials[121] = "minecraft:end_stone"; - materials[122] = "minecraft:dragon_egg"; - materials[123] = "minecraft:redstone_lamp"; - materials[125] = "minecraft:double_wooden_slab"; - materials[126] = "minecraft:wooden_slab"; - materials[127] = "minecraft:cocoa"; - materials[128] = "minecraft:sandstone_stairs"; - materials[129] = "minecraft:emerald_ore"; - materials[130] = "minecraft:ender_chest"; - materials[131] = "minecraft:tripwire_hook"; - materials[133] = "minecraft:emerald_block"; - materials[134] = "minecraft:spruce_stairs"; - materials[135] = "minecraft:birch_stairs"; - materials[136] = "minecraft:jungle_stairs"; - materials[137] = "minecraft:command_block"; - materials[138] = "minecraft:beacon"; - materials[139] = "minecraft:cobblestone_wall"; - materials[141] = "minecraft:carrots"; - materials[142] = "minecraft:potatoes"; - materials[143] = "minecraft:wooden_button"; - materials[145] = "minecraft:anvil"; - materials[146] = "minecraft:trapped_chest"; - materials[147] = "minecraft:light_weighted_pressure_plate"; - materials[148] = "minecraft:heavy_weighted_pressure_plate"; - materials[151] = "minecraft:daylight_detector"; - materials[152] = "minecraft:redstone_block"; - materials[153] = "minecraft:quartz_ore"; - materials[154] = "minecraft:hopper"; - materials[155] = "minecraft:quartz_block"; - materials[156] = "minecraft:quartz_stairs"; - materials[157] = "minecraft:activator_rail"; - materials[158] = "minecraft:dropper"; - materials[159] = "minecraft:stained_hardened_clay"; - materials[160] = "minecraft:stained_glass_pane"; - materials[161] = "minecraft:leaves2"; - materials[162] = "minecraft:log2"; - materials[163] = "minecraft:acacia_stairs"; - materials[164] = "minecraft:dark_oak_stairs"; - materials[170] = "minecraft:hay_block"; - materials[171] = "minecraft:carpet"; - materials[172] = "minecraft:hardened_clay"; - materials[173] = "minecraft:coal_block"; - materials[174] = "minecraft:packed_ice"; - materials[175] = "minecraft:double_plant"; - materials[256] = "minecraft:iron_shovel"; - materials[257] = "minecraft:iron_pickaxe"; - materials[258] = "minecraft:iron_axe"; - materials[259] = "minecraft:flint_and_steel"; - materials[260] = "minecraft:apple"; - materials[261] = "minecraft:bow"; - materials[262] = "minecraft:arrow"; - materials[263] = "minecraft:coal"; - materials[264] = "minecraft:diamond"; - materials[265] = "minecraft:iron_ingot"; - materials[266] = "minecraft:gold_ingot"; - materials[267] = "minecraft:iron_sword"; - materials[268] = "minecraft:wooden_sword"; - materials[269] = "minecraft:wooden_shovel"; - materials[270] = "minecraft:wooden_pickaxe"; - materials[271] = "minecraft:wooden_axe"; - materials[272] = "minecraft:stone_sword"; - materials[273] = "minecraft:stone_shovel"; - materials[274] = "minecraft:stone_pickaxe"; - materials[275] = "minecraft:stone_axe"; - materials[276] = "minecraft:diamond_sword"; - materials[277] = "minecraft:diamond_shovel"; - materials[278] = "minecraft:diamond_pickaxe"; - materials[279] = "minecraft:diamond_axe"; - materials[280] = "minecraft:stick"; - materials[281] = "minecraft:bowl"; - materials[282] = "minecraft:mushroom_stew"; - materials[283] = "minecraft:golden_sword"; - materials[284] = "minecraft:golden_shovel"; - materials[285] = "minecraft:golden_pickaxe"; - materials[286] = "minecraft:golden_axe"; - materials[287] = "minecraft:string"; - materials[288] = "minecraft:feather"; - materials[289] = "minecraft:gunpowder"; - materials[290] = "minecraft:wooden_hoe"; - materials[291] = "minecraft:stone_hoe"; - materials[292] = "minecraft:iron_hoe"; - materials[293] = "minecraft:diamond_hoe"; - materials[294] = "minecraft:golden_hoe"; - materials[295] = "minecraft:wheat_seeds"; - materials[296] = "minecraft:wheat"; - materials[297] = "minecraft:bread"; - materials[298] = "minecraft:leather_helmet"; - materials[299] = "minecraft:leather_chestplate"; - materials[300] = "minecraft:leather_leggings"; - materials[301] = "minecraft:leather_boots"; - materials[302] = "minecraft:chainmail_helmet"; - materials[303] = "minecraft:chainmail_chestplate"; - materials[304] = "minecraft:chainmail_leggings"; - materials[305] = "minecraft:chainmail_boots"; - materials[306] = "minecraft:iron_helmet"; - materials[307] = "minecraft:iron_chestplate"; - materials[308] = "minecraft:iron_leggings"; - materials[309] = "minecraft:iron_boots"; - materials[310] = "minecraft:diamond_helmet"; - materials[311] = "minecraft:diamond_chestplate"; - materials[312] = "minecraft:diamond_leggings"; - materials[313] = "minecraft:diamond_boots"; - materials[314] = "minecraft:golden_helmet"; - materials[315] = "minecraft:golden_chestplate"; - materials[316] = "minecraft:golden_leggings"; - materials[317] = "minecraft:golden_boots"; - materials[318] = "minecraft:flint"; - materials[319] = "minecraft:porkchop"; - materials[320] = "minecraft:cooked_porkchop"; - materials[321] = "minecraft:painting"; - materials[322] = "minecraft:golden_apple"; - materials[323] = "minecraft:sign"; - materials[324] = "minecraft:wooden_door"; - materials[325] = "minecraft:bucket"; - materials[326] = "minecraft:water_bucket"; - materials[327] = "minecraft:lava_bucket"; - materials[328] = "minecraft:minecart"; - materials[329] = "minecraft:saddle"; - materials[330] = "minecraft:iron_door"; - materials[331] = "minecraft:redstone"; - materials[332] = "minecraft:snowball"; - materials[333] = "minecraft:boat"; - materials[334] = "minecraft:leather"; - materials[335] = "minecraft:milk_bucket"; - materials[336] = "minecraft:brick"; - materials[337] = "minecraft:clay_ball"; - materials[338] = "minecraft:reeds"; - materials[339] = "minecraft:paper"; - materials[340] = "minecraft:book"; - materials[341] = "minecraft:slime_ball"; - materials[342] = "minecraft:chest_minecart"; - materials[343] = "minecraft:furnace_minecart"; - materials[344] = "minecraft:egg"; - materials[345] = "minecraft:compass"; - materials[346] = "minecraft:fishing_rod"; - materials[347] = "minecraft:clock"; - materials[348] = "minecraft:glowstone_dust"; - materials[349] = "minecraft:fish"; - materials[350] = "minecraft:cooked_fish"; // Paper - cooked_fished -> cooked_fish - materials[351] = "minecraft:dye"; - materials[352] = "minecraft:bone"; - materials[353] = "minecraft:sugar"; - materials[354] = "minecraft:cake"; - materials[355] = "minecraft:bed"; - materials[356] = "minecraft:repeater"; - materials[357] = "minecraft:cookie"; - materials[358] = "minecraft:filled_map"; - materials[359] = "minecraft:shears"; - materials[360] = "minecraft:melon"; - materials[361] = "minecraft:pumpkin_seeds"; - materials[362] = "minecraft:melon_seeds"; - materials[363] = "minecraft:beef"; - materials[364] = "minecraft:cooked_beef"; - materials[365] = "minecraft:chicken"; - materials[366] = "minecraft:cooked_chicken"; - materials[367] = "minecraft:rotten_flesh"; - materials[368] = "minecraft:ender_pearl"; - materials[369] = "minecraft:blaze_rod"; - materials[370] = "minecraft:ghast_tear"; - materials[371] = "minecraft:gold_nugget"; - materials[372] = "minecraft:nether_wart"; - materials[373] = "minecraft:potion"; - materials[374] = "minecraft:glass_bottle"; - materials[375] = "minecraft:spider_eye"; - materials[376] = "minecraft:fermented_spider_eye"; - materials[377] = "minecraft:blaze_powder"; - materials[378] = "minecraft:magma_cream"; - materials[379] = "minecraft:brewing_stand"; - materials[380] = "minecraft:cauldron"; - materials[381] = "minecraft:ender_eye"; - materials[382] = "minecraft:speckled_melon"; - materials[383] = "minecraft:spawn_egg"; - materials[384] = "minecraft:experience_bottle"; - materials[385] = "minecraft:fire_charge"; - materials[386] = "minecraft:writable_book"; - materials[387] = "minecraft:written_book"; - materials[388] = "minecraft:emerald"; - materials[389] = "minecraft:item_frame"; - materials[390] = "minecraft:flower_pot"; - materials[391] = "minecraft:carrot"; - materials[392] = "minecraft:potato"; - materials[393] = "minecraft:baked_potato"; - materials[394] = "minecraft:poisonous_potato"; - materials[395] = "minecraft:map"; - materials[396] = "minecraft:golden_carrot"; - materials[397] = "minecraft:skull"; - materials[398] = "minecraft:carrot_on_a_stick"; - materials[399] = "minecraft:nether_star"; - materials[400] = "minecraft:pumpkin_pie"; - materials[401] = "minecraft:fireworks"; - materials[402] = "minecraft:firework_charge"; - materials[403] = "minecraft:enchanted_book"; - materials[404] = "minecraft:comparator"; - materials[405] = "minecraft:netherbrick"; - materials[406] = "minecraft:quartz"; - materials[407] = "minecraft:tnt_minecart"; - materials[408] = "minecraft:hopper_minecart"; - materials[417] = "minecraft:iron_horse_armor"; - materials[418] = "minecraft:golden_horse_armor"; - materials[419] = "minecraft:diamond_horse_armor"; - materials[420] = "minecraft:lead"; - materials[421] = "minecraft:name_tag"; - materials[422] = "minecraft:command_block_minecart"; - materials[2256] = "minecraft:record_13"; - materials[2257] = "minecraft:record_cat"; - materials[2258] = "minecraft:record_blocks"; - materials[2259] = "minecraft:record_chirp"; - materials[2260] = "minecraft:record_far"; - materials[2261] = "minecraft:record_mall"; - materials[2262] = "minecraft:record_mellohi"; - materials[2263] = "minecraft:record_stal"; - materials[2264] = "minecraft:record_strad"; - materials[2265] = "minecraft:record_ward"; - materials[2266] = "minecraft:record_11"; - materials[2267] = "minecraft:record_wait"; - } - } - - private static class DataConverterArmorStand implements DataConverter { - - DataConverterArmorStand() { - } - - public int getDataVersion() { - return 147; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("ArmorStand".equals(cmp.getString("id").orElse(null)) && cmp.getBoolean("Silent").orElse(false) && !cmp.getBoolean("Marker").orElse(false)) { - cmp.remove("Silent"); - } - - return cmp; - } - } - - private static class DataConverterBanner implements DataConverter { - - DataConverterBanner() { - } - - public int getDataVersion() { - return 804; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:banner".equals(cmp.getString("id").orElse(null))) { - cmp.getCompound("tag").ifPresent(nbttagcompound1 -> nbttagcompound1.getCompound("BlockEntityTag").ifPresent(nbttagcompound2 -> { - if (nbttagcompound2.getShort("Base").isPresent()) { - cmp.putShort("Damage", (short) (nbttagcompound2.getShort("Base").get() & 15)); - if (nbttagcompound1.getCompound("display").isPresent()) { - CompoundTag nbttagcompound3 = nbttagcompound1.getCompound("display").get(); - - if (nbttagcompound3.getList("Lore").isPresent()) { - ListTag nbttaglist = nbttagcompound3.getList("Lore").get(); - - if (nbttaglist.size() == 1 && "(+NBT)".equals(nbttaglist.getString(0).orElse(null))) { - return; - } - } - } - - nbttagcompound2.remove("Base"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - } - })); - } - - return cmp; - } - } - - private static class DataConverterPotionId implements DataConverter { - - private static final String[] potions = new String[128]; - - DataConverterPotionId() { - } - - public int getDataVersion() { - return 102; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:potion".equals(cmp.getString("id").orElse(null))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("tag"); - short short0 = cmp.getShortOr("Damage", (short) 0); - - if (nbttagcompound1.getString("Potion").isEmpty()) { - String s = DataConverterPotionId.potions[short0 & 127]; - - nbttagcompound1.putString("Potion", s == null ? "minecraft:water" : s); - cmp.put("tag", nbttagcompound1); - if ((short0 & 16384) == 16384) { - cmp.putString("id", "minecraft:splash_potion"); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - - static { - DataConverterPotionId.potions[0] = "minecraft:water"; - DataConverterPotionId.potions[1] = "minecraft:regeneration"; - DataConverterPotionId.potions[2] = "minecraft:swiftness"; - DataConverterPotionId.potions[3] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[4] = "minecraft:poison"; - DataConverterPotionId.potions[5] = "minecraft:healing"; - DataConverterPotionId.potions[6] = "minecraft:night_vision"; - DataConverterPotionId.potions[7] = null; - DataConverterPotionId.potions[8] = "minecraft:weakness"; - DataConverterPotionId.potions[9] = "minecraft:strength"; - DataConverterPotionId.potions[10] = "minecraft:slowness"; - DataConverterPotionId.potions[11] = "minecraft:leaping"; - DataConverterPotionId.potions[12] = "minecraft:harming"; - DataConverterPotionId.potions[13] = "minecraft:water_breathing"; - DataConverterPotionId.potions[14] = "minecraft:invisibility"; - DataConverterPotionId.potions[15] = null; - DataConverterPotionId.potions[16] = "minecraft:awkward"; - DataConverterPotionId.potions[17] = "minecraft:regeneration"; - DataConverterPotionId.potions[18] = "minecraft:swiftness"; - DataConverterPotionId.potions[19] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[20] = "minecraft:poison"; - DataConverterPotionId.potions[21] = "minecraft:healing"; - DataConverterPotionId.potions[22] = "minecraft:night_vision"; - DataConverterPotionId.potions[23] = null; - DataConverterPotionId.potions[24] = "minecraft:weakness"; - DataConverterPotionId.potions[25] = "minecraft:strength"; - DataConverterPotionId.potions[26] = "minecraft:slowness"; - DataConverterPotionId.potions[27] = "minecraft:leaping"; - DataConverterPotionId.potions[28] = "minecraft:harming"; - DataConverterPotionId.potions[29] = "minecraft:water_breathing"; - DataConverterPotionId.potions[30] = "minecraft:invisibility"; - DataConverterPotionId.potions[31] = null; - DataConverterPotionId.potions[32] = "minecraft:thick"; - DataConverterPotionId.potions[33] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[34] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[35] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[36] = "minecraft:strong_poison"; - DataConverterPotionId.potions[37] = "minecraft:strong_healing"; - DataConverterPotionId.potions[38] = "minecraft:night_vision"; - DataConverterPotionId.potions[39] = null; - DataConverterPotionId.potions[40] = "minecraft:weakness"; - DataConverterPotionId.potions[41] = "minecraft:strong_strength"; - DataConverterPotionId.potions[42] = "minecraft:slowness"; - DataConverterPotionId.potions[43] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[44] = "minecraft:strong_harming"; - DataConverterPotionId.potions[45] = "minecraft:water_breathing"; - DataConverterPotionId.potions[46] = "minecraft:invisibility"; - DataConverterPotionId.potions[47] = null; - DataConverterPotionId.potions[48] = null; - DataConverterPotionId.potions[49] = "minecraft:strong_regeneration"; - DataConverterPotionId.potions[50] = "minecraft:strong_swiftness"; - DataConverterPotionId.potions[51] = "minecraft:fire_resistance"; - DataConverterPotionId.potions[52] = "minecraft:strong_poison"; - DataConverterPotionId.potions[53] = "minecraft:strong_healing"; - DataConverterPotionId.potions[54] = "minecraft:night_vision"; - DataConverterPotionId.potions[55] = null; - DataConverterPotionId.potions[56] = "minecraft:weakness"; - DataConverterPotionId.potions[57] = "minecraft:strong_strength"; - DataConverterPotionId.potions[58] = "minecraft:slowness"; - DataConverterPotionId.potions[59] = "minecraft:strong_leaping"; - DataConverterPotionId.potions[60] = "minecraft:strong_harming"; - DataConverterPotionId.potions[61] = "minecraft:water_breathing"; - DataConverterPotionId.potions[62] = "minecraft:invisibility"; - DataConverterPotionId.potions[63] = null; - DataConverterPotionId.potions[64] = "minecraft:mundane"; - DataConverterPotionId.potions[65] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[66] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[67] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[68] = "minecraft:long_poison"; - DataConverterPotionId.potions[69] = "minecraft:healing"; - DataConverterPotionId.potions[70] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[71] = null; - DataConverterPotionId.potions[72] = "minecraft:long_weakness"; - DataConverterPotionId.potions[73] = "minecraft:long_strength"; - DataConverterPotionId.potions[74] = "minecraft:long_slowness"; - DataConverterPotionId.potions[75] = "minecraft:long_leaping"; - DataConverterPotionId.potions[76] = "minecraft:harming"; - DataConverterPotionId.potions[77] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[78] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[79] = null; - DataConverterPotionId.potions[80] = "minecraft:awkward"; - DataConverterPotionId.potions[81] = "minecraft:long_regeneration"; - DataConverterPotionId.potions[82] = "minecraft:long_swiftness"; - DataConverterPotionId.potions[83] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[84] = "minecraft:long_poison"; - DataConverterPotionId.potions[85] = "minecraft:healing"; - DataConverterPotionId.potions[86] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[87] = null; - DataConverterPotionId.potions[88] = "minecraft:long_weakness"; - DataConverterPotionId.potions[89] = "minecraft:long_strength"; - DataConverterPotionId.potions[90] = "minecraft:long_slowness"; - DataConverterPotionId.potions[91] = "minecraft:long_leaping"; - DataConverterPotionId.potions[92] = "minecraft:harming"; - DataConverterPotionId.potions[93] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[94] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[95] = null; - DataConverterPotionId.potions[96] = "minecraft:thick"; - DataConverterPotionId.potions[97] = "minecraft:regeneration"; - DataConverterPotionId.potions[98] = "minecraft:swiftness"; - DataConverterPotionId.potions[99] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[100] = "minecraft:poison"; - DataConverterPotionId.potions[101] = "minecraft:strong_healing"; - DataConverterPotionId.potions[102] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[103] = null; - DataConverterPotionId.potions[104] = "minecraft:long_weakness"; - DataConverterPotionId.potions[105] = "minecraft:strength"; - DataConverterPotionId.potions[106] = "minecraft:long_slowness"; - DataConverterPotionId.potions[107] = "minecraft:leaping"; - DataConverterPotionId.potions[108] = "minecraft:strong_harming"; - DataConverterPotionId.potions[109] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[110] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[111] = null; - DataConverterPotionId.potions[112] = null; - DataConverterPotionId.potions[113] = "minecraft:regeneration"; - DataConverterPotionId.potions[114] = "minecraft:swiftness"; - DataConverterPotionId.potions[115] = "minecraft:long_fire_resistance"; - DataConverterPotionId.potions[116] = "minecraft:poison"; - DataConverterPotionId.potions[117] = "minecraft:strong_healing"; - DataConverterPotionId.potions[118] = "minecraft:long_night_vision"; - DataConverterPotionId.potions[119] = null; - DataConverterPotionId.potions[120] = "minecraft:long_weakness"; - DataConverterPotionId.potions[121] = "minecraft:strength"; - DataConverterPotionId.potions[122] = "minecraft:long_slowness"; - DataConverterPotionId.potions[123] = "minecraft:leaping"; - DataConverterPotionId.potions[124] = "minecraft:strong_harming"; - DataConverterPotionId.potions[125] = "minecraft:long_water_breathing"; - DataConverterPotionId.potions[126] = "minecraft:long_invisibility"; - DataConverterPotionId.potions[127] = null; - } - } - - private static class DataConverterSpawnEgg implements DataConverter { - - private static final String[] eggs = new String[256]; - - DataConverterSpawnEgg() { - } - - public int getDataVersion() { - return 105; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:spawn_egg".equals(cmp.getString("id").orElse(null))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("tag"); - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttagcompound1.getCompoundOrEmpty("EntityTag"); - short short0 = cmp.getShortOr("Damage", (short) 0); - - if (nbttagcompound2.getString("id").isEmpty()) { - String s = DataConverterSpawnEgg.eggs[short0 & 255]; - - if (s != null) { - nbttagcompound2.putString("id", s); - nbttagcompound1.put("EntityTag", nbttagcompound2); - cmp.put("tag", nbttagcompound1); - } - } - - if (short0 != 0) { - cmp.putShort("Damage", (short) 0); - } - } - - return cmp; - } - - static { - - DataConverterSpawnEgg.eggs[1] = "Item"; - DataConverterSpawnEgg.eggs[2] = "XPOrb"; - DataConverterSpawnEgg.eggs[7] = "ThrownEgg"; - DataConverterSpawnEgg.eggs[8] = "LeashKnot"; - DataConverterSpawnEgg.eggs[9] = "Painting"; - DataConverterSpawnEgg.eggs[10] = "Arrow"; - DataConverterSpawnEgg.eggs[11] = "Snowball"; - DataConverterSpawnEgg.eggs[12] = "Fireball"; - DataConverterSpawnEgg.eggs[13] = "SmallFireball"; - DataConverterSpawnEgg.eggs[14] = "ThrownEnderpearl"; - DataConverterSpawnEgg.eggs[15] = "EyeOfEnderSignal"; - DataConverterSpawnEgg.eggs[16] = "ThrownPotion"; - DataConverterSpawnEgg.eggs[17] = "ThrownExpBottle"; - DataConverterSpawnEgg.eggs[18] = "ItemFrame"; - DataConverterSpawnEgg.eggs[19] = "WitherSkull"; - DataConverterSpawnEgg.eggs[20] = "PrimedTnt"; - DataConverterSpawnEgg.eggs[21] = "FallingSand"; - DataConverterSpawnEgg.eggs[22] = "FireworksRocketEntity"; - DataConverterSpawnEgg.eggs[23] = "TippedArrow"; - DataConverterSpawnEgg.eggs[24] = "SpectralArrow"; - DataConverterSpawnEgg.eggs[25] = "ShulkerBullet"; - DataConverterSpawnEgg.eggs[26] = "DragonFireball"; - DataConverterSpawnEgg.eggs[30] = "ArmorStand"; - DataConverterSpawnEgg.eggs[41] = "Boat"; - DataConverterSpawnEgg.eggs[42] = "MinecartRideable"; - DataConverterSpawnEgg.eggs[43] = "MinecartChest"; - DataConverterSpawnEgg.eggs[44] = "MinecartFurnace"; - DataConverterSpawnEgg.eggs[45] = "MinecartTNT"; - DataConverterSpawnEgg.eggs[46] = "MinecartHopper"; - DataConverterSpawnEgg.eggs[47] = "MinecartSpawner"; - DataConverterSpawnEgg.eggs[40] = "MinecartCommandBlock"; - DataConverterSpawnEgg.eggs[48] = "Mob"; - DataConverterSpawnEgg.eggs[49] = "Monster"; - DataConverterSpawnEgg.eggs[50] = "Creeper"; - DataConverterSpawnEgg.eggs[51] = "Skeleton"; - DataConverterSpawnEgg.eggs[52] = "Spider"; - DataConverterSpawnEgg.eggs[53] = "Giant"; - DataConverterSpawnEgg.eggs[54] = "Zombie"; - DataConverterSpawnEgg.eggs[55] = "Slime"; - DataConverterSpawnEgg.eggs[56] = "Ghast"; - DataConverterSpawnEgg.eggs[57] = "PigZombie"; - DataConverterSpawnEgg.eggs[58] = "Enderman"; - DataConverterSpawnEgg.eggs[59] = "CaveSpider"; - DataConverterSpawnEgg.eggs[60] = "Silverfish"; - DataConverterSpawnEgg.eggs[61] = "Blaze"; - DataConverterSpawnEgg.eggs[62] = "LavaSlime"; - DataConverterSpawnEgg.eggs[63] = "EnderDragon"; - DataConverterSpawnEgg.eggs[64] = "WitherBoss"; - DataConverterSpawnEgg.eggs[65] = "Bat"; - DataConverterSpawnEgg.eggs[66] = "Witch"; - DataConverterSpawnEgg.eggs[67] = "Endermite"; - DataConverterSpawnEgg.eggs[68] = "Guardian"; - DataConverterSpawnEgg.eggs[69] = "Shulker"; - DataConverterSpawnEgg.eggs[90] = "Pig"; - DataConverterSpawnEgg.eggs[91] = "Sheep"; - DataConverterSpawnEgg.eggs[92] = "Cow"; - DataConverterSpawnEgg.eggs[93] = "Chicken"; - DataConverterSpawnEgg.eggs[94] = "Squid"; - DataConverterSpawnEgg.eggs[95] = "Wolf"; - DataConverterSpawnEgg.eggs[96] = "MushroomCow"; - DataConverterSpawnEgg.eggs[97] = "SnowMan"; - DataConverterSpawnEgg.eggs[98] = "Ozelot"; - DataConverterSpawnEgg.eggs[99] = "VillagerGolem"; - DataConverterSpawnEgg.eggs[100] = "EntityHorse"; - DataConverterSpawnEgg.eggs[101] = "Rabbit"; - DataConverterSpawnEgg.eggs[120] = "Villager"; - DataConverterSpawnEgg.eggs[200] = "EnderCrystal"; - } - } - - private static class DataConverterMinecart implements DataConverter { - - private static final List a = List.of("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock"); - - DataConverterMinecart() { - } - - public int getDataVersion() { - return 106; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Minecart".equals(cmp.getString("id").orElse(null))) { - String s = "MinecartRideable"; - int i = cmp.getIntOr("Type", 0); - - if (i > 0 && i < DataConverterMinecart.a.size()) { - s = DataConverterMinecart.a.get(i); - } - - cmp.putString("id", s); - cmp.remove("Type"); - } - - return cmp; - } - } - - private static class DataConverterMobSpawner implements DataConverter { - - DataConverterMobSpawner() { - } - - public int getDataVersion() { - return 107; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("MobSpawner".equals(cmp.getString("id").orElse(null))) { - cmp.getString("EntityId").ifPresent(s -> { - CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("SpawnData"); - - nbttagcompound1.putString("id", s.isEmpty() ? "Pig" : s); - cmp.put("SpawnData", nbttagcompound1); - cmp.remove("EntityId"); - }); - - cmp.getList("SpawnPotentials").ifPresent(nbttaglist -> { - for (int i = 0; i < nbttaglist.size(); ++i) { - CompoundTag nbttagcompound2 = nbttaglist.getCompoundOrEmpty(i); - - if (nbttagcompound2.getString("Type").isPresent()) { - CompoundTag nbttagcompound3 = nbttagcompound2.getCompoundOrEmpty("Properties"); - - nbttagcompound3.putString("id", nbttagcompound2.getString("Type").get()); - nbttagcompound2.put("Entity", nbttagcompound3); - nbttagcompound2.remove("Type"); - nbttagcompound2.remove("Properties"); - } - } - }); - - } - - return cmp; - } - } - - private static class DataConverterUUID implements DataConverter { - - DataConverterUUID() { - } - - public int getDataVersion() { - return 108; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.getString("UUID").ifPresent(uuid -> { - cmp.putIntArray("UUID", UUIDUtil.uuidToIntArray(UUID.fromString(uuid))); - }); - - return cmp; - } - } - - private static class DataConverterHealth implements DataConverter { - - private static final Set a = Sets.newHashSet("ArmorStand", "Bat", "Blaze", "CaveSpider", "Chicken", "Cow", "Creeper", "EnderDragon", "Enderman", "Endermite", "EntityHorse", "Ghast", "Giant", "Guardian", "LavaSlime", "MushroomCow", "Ozelot", "Pig", "PigZombie", "Rabbit", "Sheep", "Shulker", "Silverfish", "Skeleton", "Slime", "SnowMan", "Spider", "Squid", "Villager", "VillagerGolem", "Witch", "WitherBoss", "Wolf", "Zombie"); - - DataConverterHealth() { - } - - public int getDataVersion() { - return 109; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (DataConverterHealth.a.contains(cmp.getString("id").orElse(null))) { - float f; - - if (cmp.getFloat("HealF").isPresent()) { - f = cmp.getFloat("HealF").get(); - cmp.remove("HealF"); - } else { - if (cmp.getFloat("Health").isEmpty()) { - return cmp; - } - - f = cmp.getFloat("Health").get(); - } - - cmp.putFloat("Health", f); - } - - return cmp; - } - } - - private static class DataConverterSaddle implements DataConverter { - - DataConverterSaddle() { - } - - public int getDataVersion() { - return 110; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id").orElse(null)) && cmp.getCompound("SaddleItem").isEmpty() && cmp.getBoolean("Saddle").orElse(false)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound1.putString("id", "minecraft:saddle"); - nbttagcompound1.putByte("Count", (byte) 1); - nbttagcompound1.putShort("Damage", (short) 0); - cmp.put("SaddleItem", nbttagcompound1); - cmp.remove("Saddle"); - } - - return cmp; - } - } - - private static class DataConverterHanging implements DataConverter { - - DataConverterHanging() { - } - - public int getDataVersion() { - return 111; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id").orElse(null); - boolean flag = "Painting".equals(s); - boolean flag1 = "ItemFrame".equals(s); - - if ((flag || flag1) && cmp.getByte("Facing").isEmpty()) { - Direction enumdirection; - - if (cmp.getByte("Direction").isPresent()) { - enumdirection = Direction.from2DDataValue(cmp.getByte("Direction").get()); - cmp.putInt("TileX", cmp.getIntOr("TileX", 0) + enumdirection.getStepX()); - cmp.putInt("TileY", cmp.getIntOr("TileY", 0) + enumdirection.getStepY()); - cmp.putInt("TileZ", cmp.getIntOr("TileZ", 0) + enumdirection.getStepZ()); - cmp.remove("Direction"); - if (flag1 && cmp.getByte("ItemRotation").isPresent()) { - cmp.putByte("ItemRotation", (byte) (cmp.getByte("ItemRotation").get() * 2)); - } - } else { - enumdirection = Direction.from2DDataValue(cmp.getByte("Dir").get()); - cmp.remove("Dir"); - } - - cmp.putByte("Facing", (byte) enumdirection.get2DDataValue()); - } - - return cmp; - } - } - - private static class DataConverterDropChances implements DataConverter { - - DataConverterDropChances() { - } - - public int getDataVersion() { - return 113; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.getList("HandDropChances").ifPresent(nbttaglist -> { - if (nbttaglist.size() == 2 && nbttaglist.getFloatOr(0, 0.0F) == 0.0F && nbttaglist.getFloatOr(1, 0.0F) == 0.0F) { - cmp.remove("HandDropChances"); - } - }); - - cmp.getList("ArmorDropChances").ifPresent(nbttaglist -> { - if (nbttaglist.size() == 4 && nbttaglist.getFloatOr(0, 0.0F) == 0.0F && nbttaglist.getFloatOr(1, 0.0F) == 0.0F && nbttaglist.getFloatOr(2, 0.0F) == 0.0F && nbttaglist.getFloatOr(3, 0.0F) == 0.0F) { - cmp.remove("ArmorDropChances"); - } - }); - - return cmp; - } - } - - private static class DataConverterRiding implements DataConverter { - - DataConverterRiding() { - } - - public int getDataVersion() { - return 135; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - while (cmp.getCompound("Riding").isPresent()) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = this.b(cmp); - - this.convert(cmp, nbttagcompound1); - cmp = nbttagcompound1; - } - - return cmp; - } - - protected void convert(net.minecraft.nbt.CompoundTag nbttagcompound, net.minecraft.nbt.CompoundTag nbttagcompound1) { - ListTag nbttaglist = new ListTag(); - - nbttaglist.add(nbttagcompound); - nbttagcompound1.put("Passengers", nbttaglist); - } - - protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagcompound) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttagcompound.getCompoundOrEmpty("Riding"); - - nbttagcompound.remove("Riding"); - return nbttagcompound1; - } - } - - private static class DataConverterBook implements DataConverter { - - DataConverterBook() { - } - - public int getDataVersion() { - return 165; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:written_book".equals(cmp.getString("id").orElse(null))) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("tag"); - - nbttagcompound1.getList("pages").ifPresent(nbttaglist -> { - for (int i = 0; i < nbttaglist.size(); ++i) { - String s = nbttaglist.getString(i).orElse(null); - Object object = null; - - if (!"null".equals(s) && !Strings.isNullOrEmpty(s)) { - if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) { - object = Component.literal(s); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class); - if (object == null) { - object = Component.literal(""); - } - } catch (JsonParseException jsonparseexception) { - ; - } - - if (object == null) { - try { - object = ComponentConverter.Serializer.fromJson(s, ServerLifecycleHooks.getCurrentServer().registryAccess()); - } catch (JsonParseException jsonparseexception1) { - ; - } - } - - if (object == null) { - try { - object = ComponentConverter.Serializer.fromJsonLenient(s, ServerLifecycleHooks.getCurrentServer().registryAccess()); - } catch (JsonParseException jsonparseexception2) { - ; - } - } - - if (object == null) { - object = Component.literal(s); - } - } - } else { - object = Component.literal(""); - } - - nbttaglist.set(i, StringTag.valueOf(ComponentConverter.Serializer.toJson((Component) object, ServerLifecycleHooks.getCurrentServer().registryAccess()))); - } - - nbttagcompound1.put("pages", nbttaglist); - }); - } - - return cmp; - } - } - - private static class DataConverterCookedFish implements DataConverter { - - private static final Identifier a = Identifier.parse("cooked_fished"); - - DataConverterCookedFish() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if (cmp.getString("id").isPresent() && DataConverterCookedFish.a.equals(Identifier.parse(cmp.getString("id").get()))) { - cmp.putString("id", "minecraft:cooked_fish"); - } - - return cmp; - } - } - - private static class DataConverterZombie implements DataConverter { - - private static final Random a = new Random(); - - DataConverterZombie() { - } - - public int getDataVersion() { - return 502; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id").orElse(null)) && cmp.getBoolean("IsVillager").orElse(false)) { - if (!cmp.contains("ZombieType")) { - int i = -1; - - i = cmp.getInt("VillagerProfession").flatMap(profession -> { - try { - return Optional.of(this.convert(profession)); - } catch (RuntimeException runtimeexception) { - return Optional.empty(); - } - }).orElse(i); - - if (i == -1) { - i = this.convert(DataConverterZombie.a.nextInt(6)); - } - - cmp.putInt("ZombieType", i); - } - - cmp.remove("IsVillager"); - } - - return cmp; - } - - private int convert(int i) { - return i >= 0 && i < 6 ? i : -1; - } - } - - private static class DataConverterVBO implements DataConverter { - - DataConverterVBO() { - } - - public int getDataVersion() { - return 505; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.putString("useVbo", "true"); - return cmp; - } - } - - private static class DataConverterGuardian implements DataConverter { - - DataConverterGuardian() { - } - - public int getDataVersion() { - return 700; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Guardian".equals(cmp.getString("id").orElse(null))) { - if (cmp.getBoolean("Elder").orElse(false)) { - cmp.putString("id", "ElderGuardian"); - } - - cmp.remove("Elder"); - } - - return cmp; - } - } - - private static class DataConverterSkeleton implements DataConverter { - - DataConverterSkeleton() { - } - - public int getDataVersion() { - return 701; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id").orElse(null); - - if ("Skeleton".equals(s)) { - int i = cmp.getIntOr("SkeletonType", 0); - - if (i == 1) { - cmp.putString("id", "WitherSkeleton"); - } else if (i == 2) { - cmp.putString("id", "Stray"); - } - - cmp.remove("SkeletonType"); - } - - return cmp; - } - } - - private static class DataConverterZombieType implements DataConverter { - - DataConverterZombieType() { - } - - public int getDataVersion() { - return 702; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Zombie".equals(cmp.getString("id").orElse(null))) { - int i = cmp.getIntOr("ZombieType", 0); - - switch (i) { - case 1: - case 2: - case 3: - case 4: - case 5: - cmp.putString("id", "ZombieVillager"); - cmp.putInt("Profession", i - 1); - break; - case 6: - cmp.putString("id", "Husk"); - case 0: - default: - break; - } - - cmp.remove("ZombieType"); - } - - return cmp; - } - } - - private static class DataConverterHorse implements DataConverter { - - DataConverterHorse() { - } - - public int getDataVersion() { - return 703; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("EntityHorse".equals(cmp.getString("id").orElse(null))) { - int i = cmp.getIntOr("Type", 0); - - switch (i) { - case 1: - cmp.putString("id", "Donkey"); - break; - - case 2: - cmp.putString("id", "Mule"); - break; - - case 3: - cmp.putString("id", "ZombieHorse"); - break; - - case 4: - cmp.putString("id", "SkeletonHorse"); - break; - - case 0: - default: - cmp.putString("id", "Horse"); - break; - } - - cmp.remove("Type"); - } - - return cmp; - } - } - - private static class DataConverterTileEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - DataConverterTileEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterTileEntity.a.get(cmp.getString("id").orElse(null)); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - - static { - DataConverterTileEntity.a.put("Airportal", "minecraft:end_portal"); - DataConverterTileEntity.a.put("Banner", "minecraft:banner"); - DataConverterTileEntity.a.put("Beacon", "minecraft:beacon"); - DataConverterTileEntity.a.put("Cauldron", "minecraft:brewing_stand"); - DataConverterTileEntity.a.put("Chest", "minecraft:chest"); - DataConverterTileEntity.a.put("Comparator", "minecraft:comparator"); - DataConverterTileEntity.a.put("Control", "minecraft:command_block"); - DataConverterTileEntity.a.put("DLDetector", "minecraft:daylight_detector"); - DataConverterTileEntity.a.put("Dropper", "minecraft:dropper"); - DataConverterTileEntity.a.put("EnchantTable", "minecraft:enchanting_table"); - DataConverterTileEntity.a.put("EndGateway", "minecraft:end_gateway"); - DataConverterTileEntity.a.put("EnderChest", "minecraft:ender_chest"); - DataConverterTileEntity.a.put("FlowerPot", "minecraft:flower_pot"); - DataConverterTileEntity.a.put("Furnace", "minecraft:furnace"); - DataConverterTileEntity.a.put("Hopper", "minecraft:hopper"); - DataConverterTileEntity.a.put("MobSpawner", "minecraft:mob_spawner"); - DataConverterTileEntity.a.put("Music", "minecraft:noteblock"); - DataConverterTileEntity.a.put("Piston", "minecraft:piston"); - DataConverterTileEntity.a.put("RecordPlayer", "minecraft:jukebox"); - DataConverterTileEntity.a.put("Sign", "minecraft:sign"); - DataConverterTileEntity.a.put("Skull", "minecraft:skull"); - DataConverterTileEntity.a.put("Structure", "minecraft:structure_block"); - DataConverterTileEntity.a.put("Trap", "minecraft:dispenser"); - } - } - - private static class DataConverterEntity implements DataConverter { - - private static final Map a = Maps.newHashMap(); - - DataConverterEntity() { - } - - public int getDataVersion() { - return 704; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = DataConverterEntity.a.get(cmp.getString("id").orElse(null)); - - if (s != null) { - cmp.putString("id", s); - } - - return cmp; - } - - static { - DataConverterEntity.a.put("AreaEffectCloud", "minecraft:area_effect_cloud"); - DataConverterEntity.a.put("ArmorStand", "minecraft:armor_stand"); - DataConverterEntity.a.put("Arrow", "minecraft:arrow"); - DataConverterEntity.a.put("Bat", "minecraft:bat"); - DataConverterEntity.a.put("Blaze", "minecraft:blaze"); - DataConverterEntity.a.put("Boat", "minecraft:boat"); - DataConverterEntity.a.put("CaveSpider", "minecraft:cave_spider"); - DataConverterEntity.a.put("Chicken", "minecraft:chicken"); - DataConverterEntity.a.put("Cow", "minecraft:cow"); - DataConverterEntity.a.put("Creeper", "minecraft:creeper"); - DataConverterEntity.a.put("Donkey", "minecraft:donkey"); - DataConverterEntity.a.put("DragonFireball", "minecraft:dragon_fireball"); - DataConverterEntity.a.put("ElderGuardian", "minecraft:elder_guardian"); - DataConverterEntity.a.put("EnderCrystal", "minecraft:ender_crystal"); - DataConverterEntity.a.put("EnderDragon", "minecraft:ender_dragon"); - DataConverterEntity.a.put("Enderman", "minecraft:enderman"); - DataConverterEntity.a.put("Endermite", "minecraft:endermite"); - DataConverterEntity.a.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal"); - DataConverterEntity.a.put("FallingSand", "minecraft:falling_block"); - DataConverterEntity.a.put("Fireball", "minecraft:fireball"); - DataConverterEntity.a.put("FireworksRocketEntity", "minecraft:fireworks_rocket"); - DataConverterEntity.a.put("Ghast", "minecraft:ghast"); - DataConverterEntity.a.put("Giant", "minecraft:giant"); - DataConverterEntity.a.put("Guardian", "minecraft:guardian"); - DataConverterEntity.a.put("Horse", "minecraft:horse"); - DataConverterEntity.a.put("Husk", "minecraft:husk"); - DataConverterEntity.a.put("Item", "minecraft:item"); - DataConverterEntity.a.put("ItemFrame", "minecraft:item_frame"); - DataConverterEntity.a.put("LavaSlime", "minecraft:magma_cube"); - DataConverterEntity.a.put("LeashKnot", "minecraft:leash_knot"); - DataConverterEntity.a.put("MinecartChest", "minecraft:chest_minecart"); - DataConverterEntity.a.put("MinecartCommandBlock", "minecraft:commandblock_minecart"); - DataConverterEntity.a.put("MinecartFurnace", "minecraft:furnace_minecart"); - DataConverterEntity.a.put("MinecartHopper", "minecraft:hopper_minecart"); - DataConverterEntity.a.put("MinecartRideable", "minecraft:minecart"); - DataConverterEntity.a.put("MinecartSpawner", "minecraft:spawner_minecart"); - DataConverterEntity.a.put("MinecartTNT", "minecraft:tnt_minecart"); - DataConverterEntity.a.put("Mule", "minecraft:mule"); - DataConverterEntity.a.put("MushroomCow", "minecraft:mooshroom"); - DataConverterEntity.a.put("Ozelot", "minecraft:ocelot"); - DataConverterEntity.a.put("Painting", "minecraft:painting"); - DataConverterEntity.a.put("Pig", "minecraft:pig"); - DataConverterEntity.a.put("PigZombie", "minecraft:zombie_pigman"); - DataConverterEntity.a.put("PolarBear", "minecraft:polar_bear"); - DataConverterEntity.a.put("PrimedTnt", "minecraft:tnt"); - DataConverterEntity.a.put("Rabbit", "minecraft:rabbit"); - DataConverterEntity.a.put("Sheep", "minecraft:sheep"); - DataConverterEntity.a.put("Shulker", "minecraft:shulker"); - DataConverterEntity.a.put("ShulkerBullet", "minecraft:shulker_bullet"); - DataConverterEntity.a.put("Silverfish", "minecraft:silverfish"); - DataConverterEntity.a.put("Skeleton", "minecraft:skeleton"); - DataConverterEntity.a.put("SkeletonHorse", "minecraft:skeleton_horse"); - DataConverterEntity.a.put("Slime", "minecraft:slime"); - DataConverterEntity.a.put("SmallFireball", "minecraft:small_fireball"); - DataConverterEntity.a.put("SnowMan", "minecraft:snowman"); - DataConverterEntity.a.put("Snowball", "minecraft:snowball"); - DataConverterEntity.a.put("SpectralArrow", "minecraft:spectral_arrow"); - DataConverterEntity.a.put("Spider", "minecraft:spider"); - DataConverterEntity.a.put("Squid", "minecraft:squid"); - DataConverterEntity.a.put("Stray", "minecraft:stray"); - DataConverterEntity.a.put("ThrownEgg", "minecraft:egg"); - DataConverterEntity.a.put("ThrownEnderpearl", "minecraft:ender_pearl"); - DataConverterEntity.a.put("ThrownExpBottle", "minecraft:xp_bottle"); - DataConverterEntity.a.put("ThrownPotion", "minecraft:potion"); - DataConverterEntity.a.put("Villager", "minecraft:villager"); - DataConverterEntity.a.put("VillagerGolem", "minecraft:villager_golem"); - DataConverterEntity.a.put("Witch", "minecraft:witch"); - DataConverterEntity.a.put("WitherBoss", "minecraft:wither"); - DataConverterEntity.a.put("WitherSkeleton", "minecraft:wither_skeleton"); - DataConverterEntity.a.put("WitherSkull", "minecraft:wither_skull"); - DataConverterEntity.a.put("Wolf", "minecraft:wolf"); - DataConverterEntity.a.put("XPOrb", "minecraft:xp_orb"); - DataConverterEntity.a.put("Zombie", "minecraft:zombie"); - DataConverterEntity.a.put("ZombieHorse", "minecraft:zombie_horse"); - DataConverterEntity.a.put("ZombieVillager", "minecraft:zombie_villager"); - } - } - - private static class DataConverterPotionWater implements DataConverter { - - DataConverterPotionWater() { - } - - public int getDataVersion() { - return 806; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - String s = cmp.getString("id").orElse(null); - - if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(s)) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("tag"); - - if (nbttagcompound1.getString("Potion").isEmpty()) { - nbttagcompound1.putString("Potion", "minecraft:water"); - } - - if (cmp.getCompound("tag").isEmpty()) { - cmp.put("tag", nbttagcompound1); - } - } - - return cmp; - } - } - - private static class DataConverterShulker implements DataConverter { - - DataConverterShulker() { - } - - public int getDataVersion() { - return 808; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id").orElse(null)) && cmp.getByte("Color").isEmpty()) { - cmp.putByte("Color", (byte) 10); - } - - return cmp; - } - } - - private static class DataConverterShulkerBoxItem implements DataConverter { - - public static final String[] a = new String[] { "minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box" }; - - DataConverterShulkerBoxItem() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker_box".equals(cmp.getString("id").orElse(null)) ) { - cmp.getCompound("tag").ifPresent(nbttagcompound1 -> { - nbttagcompound1.getCompound("BlockEntityTag").ifPresent(nbttagcompound2 -> { - if (nbttagcompound2.getList("Items").map(ListTag::isEmpty).orElse(true)) { - nbttagcompound2.remove("Items"); - } - - int i = nbttagcompound2.getIntOr("Color", 0); - - nbttagcompound2.remove("Color"); - if (nbttagcompound2.isEmpty()) { - nbttagcompound1.remove("BlockEntityTag"); - } - - if (nbttagcompound1.isEmpty()) { - cmp.remove("tag"); - } - - cmp.putString("id", DataConverterShulkerBoxItem.a[i % 16]); - }); - }); - } - - return cmp; - } - } - - private static class DataConverterShulkerBoxBlock implements DataConverter { - - DataConverterShulkerBoxBlock() { - } - - public int getDataVersion() { - return 813; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:shulker".equals(cmp.getString("id").orElse(null))) { - cmp.remove("Color"); - } - - return cmp; - } - } - - private static class DataConverterLang implements DataConverter { - - DataConverterLang() { - } - - public int getDataVersion() { - return 816; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - cmp.getString("lang").ifPresent(lang -> { - cmp.putString("lang", lang.toLowerCase(Locale.ROOT)); - }); - - return cmp; - } - } - - private static class DataConverterTotem implements DataConverter { - - DataConverterTotem() { - } - - public int getDataVersion() { - return 820; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:totem".equals(cmp.getString("id").orElse(null))) { - cmp.putString("id", "minecraft:totem_of_undying"); - } - - return cmp; - } - } - - private static class DataConverterBedBlock implements DataConverter { - - private static final Logger a = LogManager.getLogger(NeoForgeDataFixer.class); - - DataConverterBedBlock() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - boolean flag = true; - - try { - net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompoundOrEmpty("Level"); - int i = nbttagcompound1.getIntOr("xPos", 0); - int j = nbttagcompound1.getIntOr("zPos", 0); - ListTag nbttaglist = nbttagcompound1.getListOrEmpty("TileEntities"); - ListTag nbttaglist1 = nbttagcompound1.getListOrEmpty("Sections"); - - for (int k = 0; k < nbttaglist1.size(); ++k) { - net.minecraft.nbt.CompoundTag nbttagcompound2 = nbttaglist1.getCompoundOrEmpty(k); - byte b0 = nbttagcompound2.getByteOr("Y", (byte) 0); - byte[] abyte = nbttagcompound2.getByteArray("Blocks").orElse(new byte[]{}); - - for (int l = 0; l < abyte.length; ++l) { - if (416 == (abyte[l] & 255) << 4) { - int i1 = l & 15; - int j1 = l >> 8 & 15; - int k1 = l >> 4 & 15; - net.minecraft.nbt.CompoundTag nbttagcompound3 = new net.minecraft.nbt.CompoundTag(); - - nbttagcompound3.putString("id", "bed"); - nbttagcompound3.putInt("x", i1 + (i << 4)); - nbttagcompound3.putInt("y", j1 + (b0 << 4)); - nbttagcompound3.putInt("z", k1 + (j << 4)); - nbttaglist.add(nbttagcompound3); - } - } - } - } catch (Exception exception) { - DataConverterBedBlock.a.warn("Unable to datafix Bed blocks, level format may be missing tags."); - } - - return cmp; - } - } - - private static class DataConverterBedItem implements DataConverter { - - DataConverterBedItem() { - } - - public int getDataVersion() { - return 1125; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("minecraft:bed".equals(cmp.getString("id").orElse(null)) && cmp.getShortOr("Damage", (short) 0) == 0) { - cmp.putShort("Damage", (short) DyeColor.RED.getId()); - } - - return cmp; - } - } - - private static class DataConverterSignText implements DataConverter { - - public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { - MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { - if (jsonelement.isJsonPrimitive()) { - return Component.literal(jsonelement.getAsString()); - } else if (jsonelement.isJsonArray()) { - JsonArray jsonarray = jsonelement.getAsJsonArray(); - MutableComponent iTextComponent = null; - Iterator iterator = jsonarray.iterator(); - - while (iterator.hasNext()) { - JsonElement jsonelement1 = iterator.next(); - MutableComponent iTextComponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); - - if (iTextComponent == null) { - iTextComponent = iTextComponent1; - } else { - iTextComponent.append(iTextComponent1); - } - } - - return iTextComponent; - } else { - throw new JsonParseException("Don't know how to turn " + jsonelement + " into a Component"); - } - } - - public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { - return this.a(jsonelement, type, jsondeserializationcontext); - } - }).create(); - - DataConverterSignText() { - } - - public int getDataVersion() { - return 101; - } - - public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { - if ("Sign".equals(cmp.getString("id").orElse(null))) { - this.convert(cmp, "Text1"); - this.convert(cmp, "Text2"); - this.convert(cmp, "Text3"); - this.convert(cmp, "Text4"); - } - - return cmp; - } - - private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { - String s1 = nbttagcompound.getString(s).orElse(null); - Object object = null; - - if (!"null".equals(s1) && !Strings.isNullOrEmpty(s1)) { - if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) { - object = Component.literal(s1); - } else { - try { - object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class); - if (object == null) { - object = Component.literal(""); - } - } catch (JsonParseException jsonparseexception) { - ; - } - - if (object == null) { - try { - object = ComponentConverter.Serializer.fromJson(s1, ServerLifecycleHooks.getCurrentServer().registryAccess()); - } catch (JsonParseException jsonparseexception1) { - ; - } - } - - if (object == null) { - try { - object = ComponentConverter.Serializer.fromJsonLenient(s1, ServerLifecycleHooks.getCurrentServer().registryAccess()); - } catch (JsonParseException jsonparseexception2) { - ; - } - } - - if (object == null) { - object = Component.literal(s1); - } - } - } else { - object = Component.literal(""); - } - - nbttagcompound.putString(s, ComponentConverter.Serializer.toJson((Component) object, ServerLifecycleHooks.getCurrentServer().registryAccess())); - } - } - - private static class DataInspectorPlayerVehicle implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - cmp.getCompound("RootVehicle").ifPresent(nbttagcompound1 -> { - if (nbttagcompound1.getCompound("Entity").isPresent()) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - }); - - return cmp; - } - } - - private static class DataInspectorLevelPlayer implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.getCompound("Player").isPresent()) { - convertCompound(LegacyType.PLAYER, cmp, "Player", sourceVer, targetVer); - } - - return cmp; - } - } - - private static class DataInspectorStructure implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - cmp.getList("entities").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.getCompound("nbt").isPresent()) { - convertCompound(LegacyType.ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - }); - - cmp.getList("blocks").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = (net.minecraft.nbt.CompoundTag) nbttaglist.get(j); - if (nbttagcompound1.getCompound("nbt").isPresent()) { - convertCompound(LegacyType.BLOCK_ENTITY, nbttagcompound1, "nbt", sourceVer, targetVer); - } - } - }); - - return cmp; - } - } - - private static class DataInspectorChunks implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - cmp.getCompound("Level").ifPresent(nbttagcompound1 -> { - nbttagcompound1.getList("Entities").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); - } - }); - - nbttagcompound1.getList("TileEntities").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer)); - } - }); - }); - - return cmp; - } - } - - private static class DataInspectorEntityPassengers implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - cmp.getList("Passengers").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.set(j, convert(LegacyType.ENTITY, nbttaglist.getCompoundOrEmpty(j), sourceVer, targetVer)); - } - }); - - return cmp; - } - } - - private static class DataInspectorPlayer implements DataInspector { - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - convertItems(cmp, "Inventory", sourceVer, targetVer); - convertItems(cmp, "EnderItems", sourceVer, targetVer); - if (cmp.getCompound("ShoulderEntityLeft").isPresent()) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityLeft", sourceVer, targetVer); - } - - if (cmp.getCompound("ShoulderEntityRight").isPresent()) { - convertCompound(LegacyType.ENTITY, cmp, "ShoulderEntityRight", sourceVer, targetVer); - } - - return cmp; - } - } - - private static class DataInspectorVillagers implements DataInspector { - Identifier entityVillager = getKey("EntityVillager"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.getString("id").isPresent() && entityVillager.equals(Identifier.parse(cmp.getString("id").get()))) { - cmp.getCompound("Offers").flatMap(nbttagcompound1 -> nbttagcompound1.getList("Recipes")).ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - CompoundTag nbttagcompound2 = nbttaglist.getCompoundOrEmpty(j); - - convertItem(nbttagcompound2, "buy", sourceVer, targetVer); - convertItem(nbttagcompound2, "buyB", sourceVer, targetVer); - convertItem(nbttagcompound2, "sell", sourceVer, targetVer); - nbttaglist.set(j, nbttagcompound2); - } - }); - } - - return cmp; - } - } - - private static class DataInspectorMobSpawnerMinecart implements DataInspector { - Identifier entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); - Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - String s = cmp.getString("id").get(); - if (entityMinecartMobSpawner.equals(Identifier.parse(s))) { - cmp.putString("id", tileEntityMobSpawner.toString()); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", s); - } - - return cmp; - } - } - - private static class DataInspectorMobSpawnerMobs implements DataInspector { - Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.getString("id").isPresent() && tileEntityMobSpawner.equals(Identifier.parse(cmp.getString("id").get()))) { - cmp.getList("SpawnPotentials").ifPresent(nbttaglist -> { - for (int j = 0; j < nbttaglist.size(); ++j) { - net.minecraft.nbt.CompoundTag nbttagcompound1 = nbttaglist.getCompoundOrEmpty(j); - - convertCompound(LegacyType.ENTITY, nbttagcompound1, "Entity", sourceVer, targetVer); - } - }); - - convertCompound(LegacyType.ENTITY, cmp, "SpawnData", sourceVer, targetVer); - } - - return cmp; - } - } - - private static class DataInspectorCommandBlock implements DataInspector { - Identifier tileEntityCommand = getKey("TileEntityCommand"); - - @Override - public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { - if (cmp.getString("id").isPresent() && tileEntityCommand.equals(Identifier.parse(cmp.getString("id").get()))) { - cmp.putString("id", "Control"); - convert(LegacyType.BLOCK_ENTITY, cmp, sourceVer, targetVer); - cmp.putString("id", "MinecartCommandBlock"); - } - - return cmp; - } - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeFakePlayer.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeFakePlayer.java deleted file mode 100644 index 07447e3164..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeFakePlayer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.mojang.authlib.GameProfile; -import net.minecraft.server.level.ClientInformation; -import net.minecraft.server.level.ParticleStatus; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stat; -import net.minecraft.world.entity.HumanoidArm; -import net.minecraft.world.entity.player.ChatVisiblity; - -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -public class NeoForgeFakePlayer extends ServerPlayer { - private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile( - UUID.nameUUIDFromBytes("worldedit".getBytes(StandardCharsets.UTF_8)), - "[WorldEdit]" - ); - private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation( - "en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false, ParticleStatus.MINIMAL - ); - - public NeoForgeFakePlayer(ServerLevel world) { - super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO); - } - - @Override - public void tick() { - } - - @Override - public void awardStat(Stat stat, int incrementer) { - } - - @Override - public void awardStat(Stat stat) { - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemCategoryRegistry.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemCategoryRegistry.java deleted file mode 100644 index c834d1b75d..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemCategoryRegistry.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.google.common.collect.ImmutableSet; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.tags.TagKey; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -import java.util.Set; - -public class NeoForgeItemCategoryRegistry implements ItemCategoryRegistry { - @Override - public Set getCategorisedByName(String category) { - return ServerLifecycleHooks.getCurrentServer().registryAccess().lookupOrThrow(Registries.ITEM) - .get(TagKey.create( - Registries.ITEM, - Identifier.parse(category) - )) - .stream() - .flatMap(HolderSet.Named::stream) - .map(Holder::value) - .map(NeoForgeAdapter::adapt) - .collect(ImmutableSet.toImmutableSet()); - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemRegistry.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemRegistry.java deleted file mode 100644 index 8eaed37f9c..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeItemRegistry.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.neoforge.internal.ComponentConverter; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.registry.BundledItemRegistry; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -@SuppressWarnings("removal") -public class NeoForgeItemRegistry extends BundledItemRegistry { - - @Override - public Component getRichName(ItemType itemType) { - return TranslatableComponent.of( - NeoForgeAdapter.adapt(itemType).getDescriptionId() - ); - } - - @Override - public Component getRichName(BaseItemStack itemStack) { - return GsonComponentSerializer.INSTANCE.deserialize( - ComponentConverter.Serializer.toJson( - NeoForgeAdapter.adapt(itemStack).getItemName(), - ServerLifecycleHooks.getCurrentServer().registryAccess() - ) - ); - } - -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePermissionsProvider.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePermissionsProvider.java deleted file mode 100644 index f62752133e..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePermissionsProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.GameType; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -public interface NeoForgePermissionsProvider { - - boolean hasPermission(ServerPlayer player, String permission); - - void registerPermission(String permission); - - class VanillaPermissionsProvider implements NeoForgePermissionsProvider { - - private final NeoForgePlatform platform; - - public VanillaPermissionsProvider(NeoForgePlatform platform) { - this.platform = platform; - } - - @Override - public boolean hasPermission(ServerPlayer player, String permission) { - NeoForgeConfiguration configuration = platform.getConfiguration(); - return configuration.cheatMode - || ServerLifecycleHooks.getCurrentServer().getPlayerList().isOp(player.nameAndId()) - || (configuration.creativeEnable && player.gameMode.getGameModeForPlayer() == GameType.CREATIVE); - } - - @Override - public void registerPermission(String permission) { - } - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java index aceeecc01a..86fd6fbe4f 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java @@ -19,177 +19,52 @@ package com.sk89q.worldedit.neoforge; -import com.google.common.collect.Sets; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.util.PermissionCondition; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.AbstractPlatform; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.MultiUserPlatform; -import com.sk89q.worldedit.extension.platform.Preference; -import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.util.io.ResourceLoader; -import com.sk89q.worldedit.world.DataFixer; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.registry.Registries; -import net.minecraft.SharedConstants; -import net.minecraft.commands.Commands; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.Identifier; +import com.sk89q.worldedit.util.lifecycle.Lifecycled; +import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; +import net.minecraft.core.BlockPos; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.level.storage.ServerLevelData; -import net.neoforged.neoforge.server.ServerLifecycleHooks; -import org.enginehub.piston.Command; -import org.enginehub.piston.CommandManager; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.server.ServerAboutToStartEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import org.enginehub.worldeditcui.protocol.CUIPacket; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; +class NeoForgePlatform extends CoreMcPlatform { -class NeoForgePlatform extends AbstractPlatform implements MultiUserPlatform { + private static Lifecycled createMinecraftServerLifecycled() { + SimpleLifecycled lifecycled = SimpleLifecycled.invalid(); + NeoForge.EVENT_BUS.addListener( + ServerAboutToStartEvent.class, event -> lifecycled.newValue(event.getServer()) + ); + NeoForge.EVENT_BUS.addListener(ServerStoppedEvent.class, _ -> lifecycled.invalidate()); + return lifecycled; + } - private final NeoForgeWorldEdit mod; - private final NeoForgeDataFixer dataFixer; - private @Nullable NeoForgeWatchdog watchdog; - private boolean hookingEvents = false; private final ResourceLoader resourceLoader = new NeoForgeResourceLoader(WorldEdit.getInstance()); NeoForgePlatform(NeoForgeWorldEdit mod) { - this.mod = mod; - this.dataFixer = new NeoForgeDataFixer(getDataVersion()); - } - - boolean isHookingEvents() { - return hookingEvents; - } - - @Override - public ResourceLoader getResourceLoader() { - return resourceLoader; + super(mod, createMinecraftServerLifecycled()); } @Override - public Registries getRegistries() { - return NeoForgeRegistries.getInstance(); + public void sendCUIPacket(ServerPlayer player, CUIPacket packet) { + PacketDistributor.sendToPlayer(player, packet); } @Override - public int getDataVersion() { - return SharedConstants.getCurrentVersion().dataVersion().version(); + protected void extraOnBlockStateChange(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState) { + newState.onBlockStateChange(level, pos, oldState); } @Override - public DataFixer getDataFixer() { - return dataFixer; - } - - @Override - public boolean isValidMobType(String type) { - return BuiltInRegistries.ENTITY_TYPE.containsKey(Identifier.parse(type)); - } - - @Override - public void reload() { - getConfiguration().load(); - super.reload(); - } - - @Override - public int schedule(long delay, long period, Runnable task) { - return -1; - } - - @Override - @Nullable - public NeoForgeWatchdog getWatchdog() { - if (watchdog == null) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server instanceof DedicatedServer dedicatedServer) { - watchdog = new NeoForgeWatchdog(dedicatedServer); - } - } - return watchdog; - } - - @Override - public List getWorlds() { - Iterable worlds = ServerLifecycleHooks.getCurrentServer().getAllLevels(); - List ret = new ArrayList<>(); - for (ServerLevel world : worlds) { - ret.add(new NeoForgeWorld(world)); - } - return ret; - } - - @Nullable - @Override - public Player matchPlayer(Player player) { - if (player instanceof NeoForgePlayer) { - return player; - } else { - ServerPlayer entity = ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayerByName(player.getName()); - return entity != null ? new NeoForgePlayer(entity) : null; - } - } - - @Nullable - @Override - public World matchWorld(World world) { - if (world instanceof NeoForgeWorld) { - return world; - } else { - for (ServerLevel ws : ServerLifecycleHooks.getCurrentServer().getAllLevels()) { - if (((ServerLevelData) ws.getLevelData()).getLevelName().equals(world.getName())) { - return new NeoForgeWorld(ws); - } - } - - return null; - } - } - - @Override - public void registerCommands(CommandManager manager) { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server == null) { - return; - } - Commands mcMan = server.getCommands(); - - for (Command command : manager.getAllCommands().toList()) { - CommandWrapper.register(mcMan.getDispatcher(), command); - Set perms = command.getCondition().as(PermissionCondition.class) - .map(PermissionCondition::getPermissions) - .orElseGet(Collections::emptySet); - if (!perms.isEmpty()) { - perms.forEach(NeoForgeWorldEdit.inst.getPermissionsProvider()::registerPermission); - } - } - } - - @Override - public void setGameHooksEnabled(boolean enabled) { - this.hookingEvents = enabled; - } - - @Override - public NeoForgeConfiguration getConfiguration() { - return mod.getConfig(); - } - - @Override - public String getVersion() { - return mod.getInternalVersion(); + public ResourceLoader getResourceLoader() { + return resourceLoader; } @Override @@ -197,55 +72,8 @@ public String getPlatformName() { return "NeoForge-Official"; } - @Override - public String getPlatformVersion() { - return mod.getInternalVersion(); - } - @Override public String id() { return "enginehub:neoforge"; } - - @Override - public Map getCapabilities() { - Map capabilities = new EnumMap<>(Capability.class); - capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS); - capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL); - capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL); - capabilities.put(Capability.PERMISSIONS, Preference.NORMAL); - capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL); - capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED); - return capabilities; - } - - private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.LIGHTING, - SideEffect.NEIGHBORS, - SideEffect.UPDATE - ); - - @Override - public Set getSupportedSideEffects() { - return SUPPORTED_SIDE_EFFECTS; - } - - @Override - public long getTickCount() { - return ServerLifecycleHooks.getCurrentServer().getTickCount(); - } - - @Override - public Collection getConnectedUsers() { - List users = new ArrayList<>(); - PlayerList scm = ServerLifecycleHooks.getCurrentServer().getPlayerList(); - for (ServerPlayer entity : scm.getPlayers()) { - if (entity != null) { - users.add(new NeoForgePlayer(entity)); - } - } - return users; - } } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlayer.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlayer.java deleted file mode 100644 index af8090b8aa..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlayer.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; -import com.sk89q.worldedit.extent.inventory.BlockBag; -import com.sk89q.worldedit.internal.cui.CUIEvent; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.neoforge.internal.ComponentConverter; -import com.sk89q.worldedit.neoforge.internal.NBTConverter; -import com.sk89q.worldedit.session.SessionKey; -import com.sk89q.worldedit.util.HandSide; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.formatting.WorldEditText; -import com.sk89q.worldedit.util.formatting.component.TextUtils; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockTypes; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.neoforged.neoforge.network.PacketDistributor; -import org.enginehub.linbus.tree.LinCompoundTag; -import org.enginehub.worldeditcui.protocol.CUIPacket; - -import java.util.Locale; -import java.util.Set; -import java.util.UUID; -import javax.annotation.Nullable; - -public class NeoForgePlayer extends AbstractPlayerActor { - - private final ServerPlayer player; - - protected NeoForgePlayer(ServerPlayer player) { - this.player = player; - - if (getUniqueId() == null) { - throw new AssertionError("Player UUID cannot be null"); - } - - ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); - } - - @Override - public UUID getUniqueId() { - return player.getUUID(); - } - - @Override - public BaseItemStack getItemInHand(HandSide handSide) { - ItemStack is = this.player.getItemInHand( - handSide == HandSide.MAIN_HAND - ? InteractionHand.MAIN_HAND - : InteractionHand.OFF_HAND - ); - return NeoForgeAdapter.adapt(is); - } - - @Override - public String getName() { - return this.player.getName().getString(); - } - - @Override - public BaseEntity getState() { - throw new UnsupportedOperationException("Cannot create a state from this object"); - } - - @Override - public Location getLocation() { - Vector3 position = Vector3.at(this.player.getX(), this.player.getY(), this.player.getZ()); - return new Location( - NeoForgeWorldEdit.inst.getWorld(this.player.level()), - position, - this.player.getYRot(), - this.player.getXRot()); - } - - @Override - public boolean setLocation(Location location) { - ServerLevel level = NeoForgeAdapter.adapt((World) location.getExtent()); - this.player.teleportTo( - level, - location.getX(), location.getY(), location.getZ(), - Set.of(), - location.getYaw(), location.getPitch(), - true - ); - // This may be false if the teleport was cancelled by a mod - return this.player.level() == level; - } - - @Override - public World getWorld() { - return NeoForgeWorldEdit.inst.getWorld(this.player.level()); - } - - @Override - public void giveItem(BaseItemStack itemStack) { - this.player.getInventory().add(NeoForgeAdapter.adapt(itemStack)); - } - - @Override - public void dispatchCUIEvent(CUIEvent event) { - PacketDistributor.sendToPlayer(this.player, new CUIPacket(event.getTypeId(), event.getParameters())); - } - - private void sendMessage(net.minecraft.network.chat.Component textComponent) { - this.player.sendSystemMessage(textComponent); - } - - @Override - @Deprecated - public void printRaw(String msg) { - for (String part : msg.split("\n", 0)) { - sendMessage(net.minecraft.network.chat.Component.literal(part)); - } - } - - @Override - @Deprecated - public void printDebug(String msg) { - sendColorized(msg, ChatFormatting.GRAY); - } - - @Override - @Deprecated - public void print(String msg) { - sendColorized(msg, ChatFormatting.LIGHT_PURPLE); - } - - @Override - @Deprecated - public void printError(String msg) { - sendColorized(msg, ChatFormatting.RED); - } - - @Override - public void print(Component component) { - sendMessage(ComponentConverter.Serializer.fromJson( - GsonComponentSerializer.INSTANCE.serialize(WorldEditText.format(component, getLocale())), - this.player.registryAccess() - )); - } - - private void sendColorized(String msg, ChatFormatting formatting) { - for (String part : msg.split("\n", 0)) { - var component = net.minecraft.network.chat.Component.literal(part); - component.withStyle(formatting); - sendMessage(component); - } - } - - @Override - public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { - this.player.connection.teleport(pos.x(), pos.y(), pos.z(), yaw, pitch); - return true; - } - - @Override - public String[] getGroups() { - return new String[] {}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username); - } - - @Override - public BlockBag getInventoryBlockBag() { - return null; - } - - @Override - public boolean hasPermission(String perm) { - return NeoForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm); - } - - @Nullable - @Override - public T getFacet(Class cls) { - return null; - } - - @Override - public boolean isAllowedToFly() { - return player.mayFly(); - } - - @Override - public void setFlying(boolean flying) { - if (player.getAbilities().flying != flying) { - player.getAbilities().flying = flying; - player.onUpdateAbilities(); - } - } - - @Override - public Locale getLocale() { - return TextUtils.getLocaleByMinecraftTag(player.getLanguage()); - } - - @Override - public > void sendFakeBlock(BlockVector3 pos, B block) { - World world = getWorld(); - if (!(world instanceof NeoForgeWorld neoForgeWorld)) { - return; - } - BlockPos loc = NeoForgeAdapter.toBlockPos(pos); - if (block == null) { - final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( - neoForgeWorld.getWorld(), - loc - ); - player.connection.send(packetOut); - } else { - player.connection.send(new ClientboundBlockUpdatePacket( - loc, NeoForgeAdapter.adapt(block.toImmutableState()) - )); - if (block instanceof BaseBlock baseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { - final LinCompoundTag nbtData = baseBlock.getNbt(); - if (nbtData != null) { - player.connection.send(new ClientboundBlockEntityDataPacket( - new BlockPos(pos.x(), pos.y(), pos.z()), - BlockEntityType.STRUCTURE_BLOCK, - NBTConverter.toNative(nbtData) - )); - } - } - } - } - - @Override - public SessionKey getSessionKey() { - return new SessionKeyImpl(player); - } - - static class SessionKeyImpl implements SessionKey { - // If not static, this will leak a reference - - private final UUID uuid; - private final String name; - - SessionKeyImpl(ServerPlayer player) { - this.uuid = player.getUUID(); - this.name = player.getName().getString(); - } - - @Override - public UUID getUniqueId() { - return uuid; - } - - @Nullable - @Override - public String getName() { - return name; - } - - @Override - public boolean isActive() { - // We can't directly check if the player is online because - // the list of players is not thread safe - return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid); - } - - @Override - public boolean isPersistent() { - return true; - } - - } - -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeRegistries.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeRegistries.java deleted file mode 100644 index 2aa4bb7604..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeRegistries.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.sk89q.worldedit.world.registry.BiomeRegistry; -import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; -import com.sk89q.worldedit.world.registry.BlockRegistry; -import com.sk89q.worldedit.world.registry.BundledRegistries; -import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; -import com.sk89q.worldedit.world.registry.ItemRegistry; - -/** - * World data for the Forge platform. - */ -class NeoForgeRegistries extends BundledRegistries { - - private static final NeoForgeRegistries INSTANCE = new NeoForgeRegistries(); - private final BlockRegistry blockRegistry = new NeoForgeBlockRegistry(); - private final BiomeRegistry biomeRegistry = new NeoForgeBiomeRegistry(); - private final ItemRegistry itemRegistry = new NeoForgeItemRegistry(); - private final BlockCategoryRegistry blockCategoryRegistry = new NeoForgeBlockCategoryRegistry(); - private final ItemCategoryRegistry itemCategoryRegistry = new NeoForgeItemCategoryRegistry(); - - @Override - public BlockRegistry getBlockRegistry() { - return blockRegistry; - } - - @Override - public BiomeRegistry getBiomeRegistry() { - return biomeRegistry; - } - - @Override - public ItemRegistry getItemRegistry() { - return itemRegistry; - } - - @Override - public BlockCategoryRegistry getBlockCategoryRegistry() { - return blockCategoryRegistry; - } - - @Override - public ItemCategoryRegistry getItemCategoryRegistry() { - return itemCategoryRegistry; - } - - /** - * Get a static instance. - * - * @return an instance - */ - public static NeoForgeRegistries getInstance() { - return INSTANCE; - } - -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorld.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorld.java deleted file mode 100644 index b59c68be4d..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorld.java +++ /dev/null @@ -1,774 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.common.collect.Streams; -import com.google.common.util.concurrent.Futures; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.AbstractExtentMask; -import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.neoforge.internal.NBTConverter; -import com.sk89q.worldedit.neoforge.internal.NeoForgeEntity; -import com.sk89q.worldedit.neoforge.internal.NeoForgeLoggingProblemReporter; -import com.sk89q.worldedit.neoforge.internal.NeoForgeServerLevelDelegateProxy; -import com.sk89q.worldedit.neoforge.internal.NeoForgeWorldNativeAccess; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.util.io.file.SafeFiles; -import com.sk89q.worldedit.world.AbstractWorld; -import com.sk89q.worldedit.world.RegenOptions; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.generation.ConfiguredFeatureType; -import com.sk89q.worldedit.world.generation.StructureType; -import com.sk89q.worldedit.world.generation.WorldEditTreeGeneration; -import com.sk89q.worldedit.world.item.ItemTypes; -import com.sk89q.worldedit.world.weather.WeatherType; -import com.sk89q.worldedit.world.weather.WeatherTypes; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; -import net.minecraft.core.registries.Registries; -import net.minecraft.data.worldgen.placement.EndPlacements; -import net.minecraft.data.worldgen.placement.TreePlacements; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.util.Util; -import net.minecraft.util.thread.BlockableEventLoop; -import net.minecraft.world.Clearable; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EntitySpawnReason; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.PalettedContainer; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.Structure; -import net.minecraft.world.level.levelgen.structure.StructureStart; -import net.minecraft.world.level.saveddata.WeatherData; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.ServerLevelData; -import net.minecraft.world.level.storage.TagValueOutput; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import org.enginehub.linbus.tree.LinCompoundTag; - -import java.lang.ref.WeakReference; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ThreadLocalRandom; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -/** - * An adapter to Minecraft worlds for WorldEdit. - */ -public class NeoForgeWorld extends AbstractWorld { - - private static final RandomSource random = RandomSource.create(); - - private static Identifier getDimensionRegistryKey(ServerLevel world) { - return Objects.requireNonNull(world.getServer(), "server cannot be null") - .registryAccess() - .lookupOrThrow(Registries.DIMENSION_TYPE) - .getKey(world.dimensionType()); - } - - private final WeakReference worldRef; - private final NeoForgeWorldNativeAccess nativeAccess; - - /** - * Construct a new world. - * - * @param world the world - */ - NeoForgeWorld(ServerLevel world) { - checkNotNull(world); - this.worldRef = new WeakReference<>(world); - this.nativeAccess = new NeoForgeWorldNativeAccess(worldRef); - } - - /** - * Get the underlying handle to the world. - * - * @return the world - * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) - */ - public ServerLevel getWorld() { - ServerLevel world = worldRef.get(); - if (world != null) { - return world; - } else { - throw new RuntimeException("The reference to the world was lost (i.e. the world may have been unloaded)"); - } - } - - @Override - public String getName() { - return ((ServerLevelData) getWorld().getLevelData()).getLevelName(); - } - - @Override - public String id() { - return getName() + "_" + getDimensionRegistryKey(getWorld()); - } - - @Override - public Path getStoragePath() { - final ServerLevel world = getWorld(); - return world.getServer().storageSource.getDimensionPath(world.dimension()); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { - clearContainerBlockContents(position); - return nativeAccess.setBlock(position, block, sideEffects); - } - - @Override - public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) { - nativeAccess.applySideEffects(position, previousType, sideEffectSet); - return Sets.intersection(NeoForgeWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); - } - - @Override - public int getBlockLightLevel(BlockVector3 position) { - checkNotNull(position); - return getWorld().getLightEmission(NeoForgeAdapter.toBlockPos(position)); - } - - @Override - public boolean clearContainerBlockContents(BlockVector3 position) { - checkNotNull(position); - - BlockEntity tile = getWorld().getBlockEntity(NeoForgeAdapter.toBlockPos(position)); - if (tile instanceof Clearable clearable) { - clearable.clearContent(); - return true; - } - return false; - } - - @Override - public BiomeType getBiome(BlockVector3 position) { - checkNotNull(position); - - LevelChunk chunk = getWorld().getChunk(position.x() >> 4, position.z() >> 4); - return getBiomeInChunk(position, chunk); - } - - private BiomeType getBiomeInChunk(BlockVector3 position, ChunkAccess chunk) { - return NeoForgeAdapter.adapt( - chunk.getNoiseBiome(position.x() >> 2, position.y() >> 2, position.z() >> 2).value() - ); - } - - @Override - public boolean setBiome(BlockVector3 position, BiomeType biome) { - checkNotNull(position); - checkNotNull(biome); - - LevelChunk chunk = getWorld().getChunk(position.x() >> 4, position.z() >> 4); - var biomes = (PalettedContainer>) chunk.getSection(chunk.getSectionIndex(position.y())).getBiomes(); - biomes.getAndSetUnchecked( - (position.x() >> 2) & 3, (position.y() >> 2) & 3, (position.z() >> 2) & 3, - getWorld().registryAccess().lookupOrThrow(Registries.BIOME) - .getOrThrow(ResourceKey.create(Registries.BIOME, Identifier.parse(biome.id()))) - ); - chunk.markUnsaved(); - return true; - } - - private static final LoadingCache fakePlayers - = CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(NeoForgeFakePlayer::new)); - - @Override - public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - ItemStack stack = NeoForgeAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); - ServerLevel world = getWorld(); - final NeoForgeFakePlayer fakePlayer; - try { - fakePlayer = fakePlayers.get(world); - } catch (ExecutionException ignored) { - return false; - } - fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); - fakePlayer.absSnapTo(position.x(), position.y(), position.z(), - (float) face.toVector().toYaw(), (float) face.toVector().toPitch()); - final BlockPos blockPos = NeoForgeAdapter.toBlockPos(position); - final BlockHitResult rayTraceResult = new BlockHitResult(NeoForgeAdapter.toVec3(position), - NeoForgeAdapter.adapt(face), blockPos, false); - UseOnContext itemUseContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); - InteractionResult used = stack.onItemUseFirst(itemUseContext); - if (used != InteractionResult.SUCCESS) { - // try activating the block - InteractionResult resultType = getWorld().getBlockState(blockPos).useItemOn(stack, world, fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); - if (resultType.consumesAction()) { - used = resultType; - } else { - used = stack.getItem().use(world, fakePlayer, InteractionHand.MAIN_HAND); - } - } - return used == InteractionResult.SUCCESS; - } - - @Override - public void dropItem(Vector3 position, BaseItemStack item) { - checkNotNull(position); - checkNotNull(item); - - if (item.getType() == ItemTypes.AIR) { - return; - } - - ItemEntity entity = new ItemEntity(getWorld(), position.x(), position.y(), position.z(), NeoForgeAdapter.adapt(item)); - entity.setPickUpDelay(10); - getWorld().addFreshEntity(entity); - } - - @Override - public void simulateBlockMine(BlockVector3 position) { - BlockPos pos = NeoForgeAdapter.toBlockPos(position); - getWorld().destroyBlock(pos, true); - } - - @Override - public boolean canPlaceAt(BlockVector3 position, BlockState blockState) { - return NeoForgeAdapter.adapt(blockState).canSurvive(getWorld(), NeoForgeAdapter.toBlockPos(position)); - } - - // For unmapped regen names, see Fabric! - - @Override - public boolean regenerate(Region region, Extent extent, RegenOptions options) { - if (options.getSeed().isPresent()) { - throw new UnsupportedOperationException("26.1+ worldgen does not support overriding the seed for regen"); - } - - try { - doRegen(region, extent, options); - } catch (Exception e) { - throw new IllegalStateException("Regen failed", e); - } - - return true; - } - - private void doRegen(Region region, Extent extent, RegenOptions options) throws Exception { - Path tempDir = Files.createTempDirectory("WorldEditWorldGen"); - LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); - try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("WorldEditTempGen")) { - ServerLevel originalWorld = getWorld(); - - ResourceKey worldRegKey = originalWorld.dimension(); - try (ServerLevel serverWorld = new ServerLevel( - originalWorld.getServer(), Util.backgroundExecutor(), session, - ((ServerLevelData) originalWorld.getLevelData()), - worldRegKey, - new LevelStem( - originalWorld.dimensionTypeRegistration(), - originalWorld.getChunkSource().getGenerator() - ), - originalWorld.isDebug(), - originalWorld.getSeed(), - // No spawners are needed for this world. - ImmutableList.of(), - // This controls ticking, we don't need it so set it to false. - false - )) { - regenForWorld(region, extent, serverWorld, options); - - // drive the server executor until all tasks are popped off - originalWorld.getServer().managedBlock(() -> originalWorld.getServer().getPendingTasksCount() == 0); - } - } finally { - SafeFiles.tryHardToDeleteDir(tempDir); - } - } - - private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, - RegenOptions options) throws WorldEditException { - List> chunkLoadings = submitChunkLoadTasks(region, serverWorld); - - // drive executor until loading finishes - BlockableEventLoop executor = serverWorld.getChunkSource().mainThreadProcessor; - executor.managedBlock(() -> { - // bail out early if a future fails - if (chunkLoadings.stream().anyMatch(ftr -> - ftr.isDone() && Futures.getUnchecked(ftr) == null - )) { - return false; - } - return chunkLoadings.stream().allMatch(CompletableFuture::isDone); - }); - - Map chunks = new HashMap<>(); - for (CompletableFuture future : chunkLoadings) { - @Nullable - ChunkAccess chunk = future.getNow(null); - checkState(chunk != null, "Failed to generate a chunk, regen failed."); - chunks.put(chunk.getPos(), chunk); - } - - for (BlockVector3 vec : region) { - BlockPos pos = NeoForgeAdapter.toBlockPos(vec); - ChunkAccess chunk = chunks.get(ChunkPos.containing(pos)); - BlockStateHolder state = NeoForgeAdapter.adapt(chunk.getBlockState(pos)); - BlockEntity blockEntity = chunk.getBlockEntity(pos); - if (blockEntity != null) { - net.minecraft.nbt.CompoundTag tag = NeoForgeLoggingProblemReporter.with( - () -> "serializing block entity at " + pos, - reporter -> { - var tagValueOutput = TagValueOutput.createWithContext(reporter, getWorld().registryAccess()); - blockEntity.saveWithId(tagValueOutput); - return tagValueOutput.buildResult(); - } - ); - state = state.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))); - } - extent.setBlock(vec, state.toBaseBlock()); - - if (options.shouldRegenBiomes()) { - BiomeType biome = getBiomeInChunk(vec, chunk); - extent.setBiome(vec, biome); - } - } - } - - private List> submitChunkLoadTasks(Region region, ServerLevel world) { - List> chunkLoadings = new ArrayList<>(); - // Pre-gen all the chunks - for (BlockVector2 chunk : region.getChunks()) { - chunkLoadings.add( - world.getChunkSource().getChunkFuture(chunk.x(), chunk.z(), ChunkStatus.FEATURES, true) - .thenApply(either -> either.orElse(null)) - ); - } - return chunkLoadings; - } - - @SuppressWarnings("deprecation") - @Nullable - private static ResourceKey createTreeFeatureGenerator(com.sk89q.worldedit.util.TreeGenerator.TreeType type) { - return switch (type) { - // Based off of the SaplingGenerator class, as well as uses of DefaultBiomeFeatures fields - case TREE -> TreePlacements.OAK_CHECKED; - case BIG_TREE -> TreePlacements.FANCY_OAK_CHECKED; - case REDWOOD -> TreePlacements.SPRUCE_CHECKED; - case TALL_REDWOOD -> TreePlacements.MEGA_SPRUCE_CHECKED; - case MEGA_REDWOOD -> TreePlacements.MEGA_PINE_CHECKED; - case BIRCH -> TreePlacements.BIRCH_CHECKED; - case JUNGLE -> TreePlacements.MEGA_JUNGLE_TREE_CHECKED; - case SMALL_JUNGLE -> TreePlacements.JUNGLE_TREE_CHECKED; - case SHORT_JUNGLE -> TreePlacements.JUNGLE_TREE_CHECKED; - case JUNGLE_BUSH -> TreePlacements.JUNGLE_BUSH; - case SWAMP -> TreePlacements.OAK_CHECKED; - case ACACIA -> TreePlacements.ACACIA_CHECKED; - case DARK_OAK -> TreePlacements.DARK_OAK_CHECKED; - case TALL_BIRCH -> TreePlacements.SUPER_BIRCH_BEES_0002; - case WARPED_FUNGUS -> TreePlacements.WARPED_FUNGI; - case CRIMSON_FUNGUS -> TreePlacements.CRIMSON_FUNGI; - case CHORUS_PLANT -> EndPlacements.CHORUS_PLANT; - case MANGROVE -> TreePlacements.MANGROVE_CHECKED; - case TALL_MANGROVE -> TreePlacements.TALL_MANGROVE_CHECKED; - case CHERRY -> TreePlacements.CHERRY_CHECKED; - case PALE_OAK -> TreePlacements.PALE_OAK_CHECKED; - case PALE_OAK_CREAKING -> TreePlacements.PALE_OAK_CREAKING_CHECKED; - case RANDOM -> { - // We're intentionally using index here to get a random tree type - @SuppressWarnings("EnumOrdinal") - com.sk89q.worldedit.util.TreeGenerator.TreeType randomTreeType = com.sk89q.worldedit.util.TreeGenerator.TreeType.values()[ThreadLocalRandom.current().nextInt(com.sk89q.worldedit.util.TreeGenerator.TreeType.values().length)]; - yield createTreeFeatureGenerator(randomTreeType); - } - default -> null; - }; - } - - @SuppressWarnings("deprecation") - @Override - public boolean generateTree(com.sk89q.worldedit.util.TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { - ServerLevel world = getWorld(); - PlacedFeature generator = Optional.ofNullable(createTreeFeatureGenerator(type)) - .map(k -> world.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE).getValue(k)) - .orElse(null); - ServerChunkCache chunkManager = world.getChunkSource(); - if (type == com.sk89q.worldedit.util.TreeGenerator.TreeType.CHORUS_PLANT) { - position = position.add(0, 1, 0); - } - try (NeoForgeServerLevelDelegateProxy.LevelAndProxy proxyLevel = NeoForgeServerLevelDelegateProxy.newInstance(editSession, world)) { - return generator != null && generator.place( - proxyLevel.level(), chunkManager.getGenerator(), random, - NeoForgeAdapter.toBlockPos(position) - ); - } - } - - @Override - public boolean generateTree(com.sk89q.worldedit.world.generation.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { - Boolean customResult = WorldEditTreeGeneration.handleWorldEditTrees(this, type, editSession, position); - if (customResult != null) { - return customResult; - } - ServerLevel world = getWorld(); - PlacedFeature generator = world.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE).getValue(Identifier.tryParse(type.id())); - ServerChunkCache chunkManager = world.getChunkSource(); - try (NeoForgeServerLevelDelegateProxy.LevelAndProxy proxyLevel = NeoForgeServerLevelDelegateProxy.newInstance(editSession, world)) { - return generator != null && generator.place( - proxyLevel.level(), chunkManager.getGenerator(), random, - NeoForgeAdapter.toBlockPos(position) - ); - } - } - - @Override - public boolean generateFeature(ConfiguredFeatureType type, EditSession editSession, BlockVector3 position) { - ServerLevel world = getWorld(); - ConfiguredFeature feature = world.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(Identifier.tryParse(type.id())); - ServerChunkCache chunkManager = world.getChunkSource(); - try (NeoForgeServerLevelDelegateProxy.LevelAndProxy levelProxy = - NeoForgeServerLevelDelegateProxy.newInstance(editSession, world)) { - return feature != null && feature.place(levelProxy.level(), chunkManager.getGenerator(), random, NeoForgeAdapter.toBlockPos(position)); - } catch (MaxChangedBlocksException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean generateStructure(StructureType type, EditSession editSession, BlockVector3 position) { - ServerLevel world = getWorld(); - Registry structureRegistry = world.registryAccess().lookupOrThrow(Registries.STRUCTURE); - Structure structure = structureRegistry.getValue(Identifier.tryParse(type.id())); - if (structure == null) { - return false; - } - - ServerChunkCache chunkManager = world.getChunkSource(); - try (NeoForgeServerLevelDelegateProxy.LevelAndProxy levelProxy = - NeoForgeServerLevelDelegateProxy.newInstance(editSession, world)) { - ChunkPos chunkPos = ChunkPos.containing(new BlockPos(position.x(), position.y(), position.z())); - StructureStart structureStart = structure.generate( - structureRegistry.wrapAsHolder(structure), world.dimension(), world.registryAccess(), - chunkManager.getGenerator(), chunkManager.getGenerator().getBiomeSource(), chunkManager.randomState(), - world.getStructureManager(), world.getSeed(), chunkPos, 0, levelProxy.level(), - biome -> true - ); - - if (!structureStart.isValid()) { - return false; - } else { - BoundingBox boundingBox = structureStart.getBoundingBox(); - ChunkPos min = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ())); - ChunkPos max = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ())); - ChunkPos.rangeClosed(min, max).forEach((chunkPosx) -> - structureStart.placeInChunk( - levelProxy.level(), world.structureManager(), chunkManager.getGenerator(), world.getRandom(), - new BoundingBox( - chunkPosx.getMinBlockX(), world.getMinY(), chunkPosx.getMinBlockZ(), - chunkPosx.getMaxBlockX(), world.getMaxY(), chunkPosx.getMaxBlockZ() - ), - chunkPosx - ) - ); - return true; - } - } catch (MaxChangedBlocksException e) { - throw new RuntimeException(e); - } - } - - @Override - public void checkLoadedChunk(BlockVector3 pt) { - getWorld().getChunk(NeoForgeAdapter.toBlockPos(pt)); - } - - @Override - public void fixAfterFastMode(Iterable chunks) { - fixLighting(chunks); - } - - @Override - public void sendBiomeUpdates(Iterable chunks) { - List nativeChunks = chunks instanceof Collection chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList(); - for (BlockVector2 chunk : chunks) { - nativeChunks.add(getWorld().getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false)); - } - getWorld().getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks); - } - - @Override - public void fixLighting(Iterable chunks) { - ServerLevel world = getWorld(); - for (BlockVector2 chunk : chunks) { - // Fetch the chunk after light initialization at least - // We'll be doing a full relight anyways, so we don't need to be LIGHT yet - world.getChunkSource().getLightEngine().lightChunk(world.getChunk( - chunk.x(), chunk.z(), ChunkStatus.INITIALIZE_LIGHT - ), false).exceptionally(t -> { - WorldEdit.logger.warn("Failed to relight chunk at " + chunk, t); - return null; - }); - } - } - - @Override - public WeatherType getWeather() { - WeatherData weatherData = getWorld().getServer().getWeatherData(); - if (weatherData.isThundering()) { - return WeatherTypes.THUNDER_STORM; - } - if (weatherData.isRaining()) { - return WeatherTypes.RAIN; - } - return WeatherTypes.CLEAR; - } - - @Override - public long getRemainingWeatherDuration() { - WeatherData weatherData = getWorld().getServer().getWeatherData(); - if (weatherData.isThundering()) { - return weatherData.getThunderTime(); - } - if (weatherData.isRaining()) { - return weatherData.getRainTime(); - } - return weatherData.getClearWeatherTime(); - } - - @Override - public void setWeather(WeatherType weatherType) { - setWeather(weatherType, 0); - } - - @Override - public void setWeather(WeatherType weatherType, long duration) { - WeatherData weatherData = getWorld().getServer().getWeatherData(); - if (weatherType == WeatherTypes.THUNDER_STORM) { - weatherData.setClearWeatherTime(0); - weatherData.setThundering(true); - weatherData.setThunderTime((int) duration); - } else if (weatherType == WeatherTypes.RAIN) { - weatherData.setClearWeatherTime(0); - weatherData.setRaining(true); - weatherData.setRainTime((int) duration); - } else if (weatherType == WeatherTypes.CLEAR) { - weatherData.setRaining(false); - weatherData.setThundering(false); - weatherData.setClearWeatherTime((int) duration); - } - } - - @Override - public int getMinY() { - return getWorld().getMinY(); - } - - @Override - public int getMaxY() { - return getWorld().getMaxY(); - } - - @Override - public BlockVector3 getSpawnPosition() { - return NeoForgeAdapter.adapt(getWorld().getLevelData().getRespawnData().pos()); - } - - @Override - public BlockState getBlock(BlockVector3 position) { - net.minecraft.world.level.block.state.BlockState mcState = getWorld() - .getChunk(position.x() >> 4, position.z() >> 4) - .getBlockState(NeoForgeAdapter.toBlockPos(position)); - - return NeoForgeAdapter.adapt(mcState); - } - - @Override - public BaseBlock getFullBlock(BlockVector3 position) { - BlockPos pos = new BlockPos(position.x(), position.y(), position.z()); - BlockEntity tile = getWorld().getChunk(pos).getBlockEntity(pos); - - if (tile != null) { - net.minecraft.nbt.CompoundTag tag = NeoForgeLoggingProblemReporter.with( - () -> "serializing block entity at " + pos, - reporter -> { - var tagValueOutput = TagValueOutput.createWithContext(reporter, getWorld().registryAccess()); - tile.saveWithId(tagValueOutput); - return tagValueOutput.buildResult(); - } - ); - return getBlock(position).toBaseBlock( - LazyReference.from(() -> NBTConverter.fromNative(tag)) - ); - } else { - return getBlock(position).toBaseBlock(); - } - } - - @Override - public int hashCode() { - return getWorld().hashCode(); - } - - @Override - public boolean equals(Object o) { - return switch (o) { - case NeoForgeWorld other -> { - Level otherWorld = other.worldRef.get(); - Level thisWorld = worldRef.get(); - yield otherWorld != null && otherWorld.equals(thisWorld); - } - case com.sk89q.worldedit.world.World world -> world.getName().equals(getName()); - case null, default -> false; - }; - } - - @Override - public List getEntities(Region region) { - final ServerLevel world = getWorld(); - AABB box = new AABB( - NeoForgeAdapter.toVec3(region.getMinimumPoint()), - NeoForgeAdapter.toVec3(region.getMaximumPoint().add(BlockVector3.ONE)) - ); - List nmsEntities = world.getEntities( - (net.minecraft.world.entity.Entity) null, - box, - e -> region.contains(NeoForgeAdapter.adapt(e.blockPosition())) - ); - return nmsEntities.stream().map(NeoForgeEntity::new).collect(ImmutableList.toImmutableList()); - } - - @Override - public List getEntities() { - final ServerLevel world = getWorld(); - return Streams.stream(world.getAllEntities()) - .map(NeoForgeEntity::new) - .collect(ImmutableList.toImmutableList()); - } - - @Nullable - @Override - public Entity createEntity(Location location, BaseEntity entity) { - ServerLevel world = getWorld(); - String entityId = entity.getType().id(); - final Optional> entityType = EntityType.byString(entityId); - if (entityType.isEmpty()) { - return null; - } - LinCompoundTag nativeTag = entity.getNbt(); - net.minecraft.nbt.CompoundTag tag; - if (nativeTag != null) { - tag = NBTConverter.toNative(nativeTag); - removeUnwantedEntityTagsRecursively(tag); - } else { - tag = new net.minecraft.nbt.CompoundTag(); - } - tag.putString("id", entityId); - - net.minecraft.world.entity.Entity createdEntity = EntityType.loadEntityRecursive(tag, world, EntitySpawnReason.COMMAND, (loadedEntity) -> { - loadedEntity.absSnapTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - return loadedEntity; - }); - if (createdEntity != null) { - world.addFreshEntityWithPassengers(createdEntity); - return new NeoForgeEntity(createdEntity); - } - return null; - } - - private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) { - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - - // Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive - tag.getList("Passengers").ifPresent(nbttaglist -> { - for (int i = 0; i < nbttaglist.size(); ++i) { - removeUnwantedEntityTagsRecursively(nbttaglist.getCompoundOrEmpty(i)); - } - }); - } - - @Override - public Mask createLiquidMask() { - return new AbstractExtentMask(this) { - @Override - public boolean test(BlockVector3 vector) { - return NeoForgeAdapter.adapt(getExtent().getBlock(vector)).getBlock() instanceof LiquidBlock; - } - }; - } - - @Override - public boolean isValid() { - return worldRef.get() != null; - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java index f460cdab4e..7c4ab8d987 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java @@ -19,53 +19,9 @@ package com.sk89q.worldedit.neoforge; -import com.mojang.brigadier.ParseResults; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.util.PermissionCondition; -import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; -import com.sk89q.worldedit.event.platform.PlatformReadyEvent; -import com.sk89q.worldedit.event.platform.PlatformUnreadyEvent; -import com.sk89q.worldedit.event.platform.PlatformsRegisteredEvent; -import com.sk89q.worldedit.event.platform.SessionIdleEvent; -import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.Platform; -import com.sk89q.worldedit.extension.platform.PlatformManager; -import com.sk89q.worldedit.internal.anvil.ChunkDeleter; -import com.sk89q.worldedit.internal.event.InteractionDebouncer; +import com.sk89q.worldedit.coremc.internal.CoreMcMod; +import com.sk89q.worldedit.coremc.internal.ThreadSafeCache; import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.registry.CommonRegistries; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.world.biome.BiomeCategory; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockCategory; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.generation.ConfiguredFeatureType; -import com.sk89q.worldedit.world.generation.StructureType; -import com.sk89q.worldedit.world.generation.TreeType; -import com.sk89q.worldedit.world.item.ItemCategory; -import com.sk89q.worldedit.world.item.ItemType; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.feature.CoralTreeFeature; -import net.minecraft.world.level.levelgen.feature.FallenTreeFeature; -import net.minecraft.world.level.levelgen.feature.TreeFeature; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; @@ -74,427 +30,120 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.CommandEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.server.ServerAboutToStartEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; +import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.apache.logging.log4j.Logger; -import org.enginehub.piston.Command; -import org.enginehub.worldeditcui.protocol.CUIPacket; import org.enginehub.worldeditcui.protocol.CUIPacketHandler; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME; -import static com.sk89q.worldedit.neoforge.NeoForgeAdapter.adaptCommandSource; -import static com.sk89q.worldedit.neoforge.NeoForgeAdapter.adaptPlayer; /** - * The Forge implementation of WorldEdit. + * The NeoForge implementation of WorldEdit. */ @Mod(NeoForgeWorldEdit.MOD_ID) -public class NeoForgeWorldEdit { +public class NeoForgeWorldEdit extends CoreMcMod { private static final Logger LOGGER = LogManagerCompat.getLogger(); public static final String MOD_ID = "worldedit"; - private NeoForgePermissionsProvider provider; - public static NeoForgeWorldEdit inst; - private InteractionDebouncer debouncer; - private NeoForgePlatform platform; - private NeoForgeConfiguration config; - private Path workingDir; - private ModContainer container; public NeoForgeWorldEdit(IEventBus modBus) { inst = this; - modBus.addListener(this::init); + modBus.addListener(this::onFMLCommonSetup); - NeoForge.EVENT_BUS.register(ThreadSafeCache.getInstance()); - NeoForge.EVENT_BUS.register(this); + NeoForge.EVENT_BUS.register(new EventHandler(this)); } - private void init(FMLCommonSetupEvent event) { + private void onFMLCommonSetup(FMLCommonSetupEvent event) { this.container = ModLoadingContext.get().getActiveContainer(); - // Setup working directory - workingDir = FMLPaths.CONFIGDIR.get().resolve("worldedit"); - if (!Files.exists(workingDir)) { - try { - Files.createDirectory(workingDir); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } + init(new NeoForgePlatform(this), FMLPaths.CONFIGDIR.get()); CUIPacketHandler.instance().registerServerboundHandler(this::onCuiPacket); - setupPlatform(); - LOGGER.info("WorldEdit for NeoForge (version {}) is loaded", getInternalVersion()); } - private void setupPlatform() { - this.platform = new NeoForgePlatform(this); - debouncer = new InteractionDebouncer(platform); - - WorldEdit.getInstance().getPlatformManager().register(platform); - - config = new NeoForgeConfiguration(this); - - this.provider = new NeoForgePermissionsProvider.VanillaPermissionsProvider(platform); - } - - private void setupRegistries(MinecraftServer server) { - // Blocks - for (Identifier name : BuiltInRegistries.BLOCK.keySet()) { - String key = name.toString(); - if (BlockType.REGISTRY.get(key) == null) { - BlockType.REGISTRY.register(key, new BlockType(key, - input -> NeoForgeAdapter.adapt(NeoForgeAdapter.adapt(input.getBlockType()).defaultBlockState()))); - } - } - // Items - for (Identifier name : BuiltInRegistries.ITEM.keySet()) { - String key = name.toString(); - if (ItemType.REGISTRY.get(key) == null) { - ItemType.REGISTRY.register(key, new ItemType(key)); - } - } - // Entities - for (Identifier name : BuiltInRegistries.ENTITY_TYPE.keySet()) { - String key = name.toString(); - if (EntityType.REGISTRY.get(key) == null) { - EntityType.REGISTRY.register(key, new EntityType(key)); - } - } - // Biomes - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.BIOME).keySet()) { - String key = name.toString(); - if (BiomeType.REGISTRY.get(key) == null) { - BiomeType.REGISTRY.register(key, new BiomeType(key)); - } - } - // Tags - server.registryAccess().lookupOrThrow(Registries.BLOCK).getTags().map(t -> t.key().location()).forEach(name -> { - String key = name.toString(); - if (BlockCategory.REGISTRY.get(key) == null) { - BlockCategory.REGISTRY.register(key, new BlockCategory(key)); - } - }); - server.registryAccess().lookupOrThrow(Registries.ITEM).getTags().map(t -> t.key().location()).forEach(name -> { - String key = name.toString(); - if (ItemCategory.REGISTRY.get(key) == null) { - ItemCategory.REGISTRY.register(key, new ItemCategory(key)); - } - }); - Registry biomeRegistry = server.registryAccess().lookupOrThrow(Registries.BIOME); - biomeRegistry.getTags().forEach(tag -> { - String key = tag.key().location().toString(); - if (BiomeCategory.REGISTRY.get(key) == null) { - BiomeCategory.REGISTRY.register(key, new BiomeCategory( - key, - () -> biomeRegistry.get(tag.key()) - .stream() - .flatMap(HolderSet.Named::stream) - .map(Holder::value) - .map(NeoForgeAdapter::adapt) - .collect(Collectors.toSet())) - ); - } - }); - // Features - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).keySet()) { - String key = name.toString(); - if (ConfiguredFeatureType.REGISTRY.get(key) == null) { - ConfiguredFeatureType.REGISTRY.register(key, new ConfiguredFeatureType(key)); - } - } - // Structures - for (Identifier name : server.registryAccess().lookupOrThrow(Registries.STRUCTURE).keySet()) { - String key = name.toString(); - if (StructureType.REGISTRY.get(key) == null) { - StructureType.REGISTRY.register(key, new StructureType(key)); - } - } - // Trees - Registry placedFeatureRegistry = server.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE); - for (Identifier name : placedFeatureRegistry.keySet()) { - // Do some hackery to make sure this is a tree - var underlyingFeature = placedFeatureRegistry.get(name).get().value().feature().value().feature(); - if (underlyingFeature instanceof TreeFeature || underlyingFeature instanceof FallenTreeFeature || underlyingFeature instanceof CoralTreeFeature) { - String key = name.toString(); - if (TreeType.REGISTRY.get(key) == null) { - TreeType.REGISTRY.register(key, new TreeType(key)); - } - } - } - - // Common registries - CommonRegistries.init(); - } - - @SubscribeEvent - public void registerCommands(RegisterCommandsEvent event) { - WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent()); - - PlatformManager manager = WorldEdit.getInstance().getPlatformManager(); - Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS); - if (commandsPlatform != platform || !platform.isHookingEvents()) { - // We're not in control of commands/events -- do not register. - return; - } - - List commands = manager.getPlatformCommandManager().getCommandManager() - .getAllCommands().toList(); - for (Command command : commands) { - CommandWrapper.register(event.getDispatcher(), command); - Set perms = command.getCondition().as(PermissionCondition.class) - .map(PermissionCondition::getPermissions) - .orElseGet(Collections::emptySet); - if (!perms.isEmpty()) { - perms.forEach(getPermissionsProvider()::registerPermission); - } - } - } - - @SubscribeEvent - public void serverAboutToStart(ServerAboutToStartEvent event) { - final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME); - if (Files.exists(delChunks)) { - ChunkDeleter.runFromFile(delChunks, true); - } - } - - @SubscribeEvent - public void serverStopping(ServerStoppingEvent event) { - WorldEdit worldEdit = WorldEdit.getInstance(); - worldEdit.getSessionManager().unload(); - WorldEdit.getInstance().getEventBus().post(new PlatformUnreadyEvent(platform)); - } - - @SubscribeEvent - public void serverStarted(ServerStartedEvent event) { - setupRegistries(event.getServer()); - - config.load(); - WorldEdit.getInstance().getEventBus().post(new ConfigurationLoadEvent(config)); - WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent(platform)); - } - - private boolean skipEvents() { - return platform == null || !platform.isHookingEvents(); - } - - private boolean skipInteractionEvent(Player player, InteractionHand hand) { - return skipEvents() || hand != InteractionHand.MAIN_HAND || player.level().isClientSide() || !(player instanceof ServerPlayer); + @Override + protected String getInternalVersion() { + return container.getModInfo().getVersion().toString(); } - @SubscribeEvent - public void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) { - if (skipInteractionEvent(event.getEntity(), event.getHand()) || event.getUseItem().isFalse()) { - return; - } - - ServerPlayer playerEntity = (ServerPlayer) event.getEntity(); - WorldEdit we = WorldEdit.getInstance(); - NeoForgePlayer player = adaptPlayer(playerEntity); - NeoForgeWorld world = getWorld(playerEntity.level()); - Direction direction = NeoForgeAdapter.adaptEnumFacing(event.getFace()); - - BlockPos blockPos = event.getPos(); - Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); - - boolean result = we.handleBlockLeftClick(player, pos, direction) || we.handleArmSwing(player); - debouncer.setLastInteraction(player, result); + // Proxy all events through a separate class to avoid loading all of CoreMcMod's methods immediately + // It causes some weird classloader issue + public static final class EventHandler { + private final NeoForgeWorldEdit mod; - if (result) { - event.setCanceled(true); + public EventHandler(NeoForgeWorldEdit mod) { + this.mod = mod; } - } - @SubscribeEvent - public void onRightClickBlock(PlayerInteractEvent.RightClickBlock event) { - if (skipInteractionEvent(event.getEntity(), event.getHand()) || event.getUseItem().isFalse()) { - return; + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event) { + mod.registerCommands(event.getDispatcher()); } - ServerPlayer playerEntity = (ServerPlayer) event.getEntity(); - WorldEdit we = WorldEdit.getInstance(); - NeoForgePlayer player = adaptPlayer(playerEntity); - NeoForgeWorld world = getWorld(playerEntity.level()); - Direction direction = NeoForgeAdapter.adaptEnumFacing(event.getFace()); - - BlockPos blockPos = event.getPos(); - Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); - - boolean result = we.handleBlockRightClick(player, pos, direction) || we.handleRightClick(player); - debouncer.setLastInteraction(player, result); - - if (result) { - event.setCanceled(true); + @SubscribeEvent + public void serverAboutToStart(ServerAboutToStartEvent event) { + mod.serverAboutToStart(); } - } - public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { - if (skipInteractionEvent(playerEntity, hand)) { - return; + @SubscribeEvent + public void serverStarted(ServerStartedEvent event) { + mod.serverStarted(event.getServer()); } - WorldEdit we = WorldEdit.getInstance(); - NeoForgePlayer player = adaptPlayer(playerEntity); - - Optional previousResult = debouncer.getDuplicateInteractionResult(player); - if (previousResult.isPresent()) { - return; + @SubscribeEvent + public void serverStopping(ServerStoppingEvent event) { + mod.serverStopping(); } - boolean result = we.handleArmSwing(player); - debouncer.setLastInteraction(player, result); - } - - @SubscribeEvent - public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { - if (skipInteractionEvent(event.getEntity(), event.getHand())) { - return; + @SubscribeEvent + public void onServerTick(ServerTickEvent.Post event) { + ThreadSafeCache.getInstance().onEndTick(ServerLifecycleHooks.getCurrentServer()); } - ServerPlayer playerEntity = (ServerPlayer) event.getEntity(); - WorldEdit we = WorldEdit.getInstance(); - NeoForgePlayer player = adaptPlayer(playerEntity); - - Optional previousResult = debouncer.getDuplicateInteractionResult(player); - if (previousResult.isPresent()) { - if (previousResult.get()) { + @SubscribeEvent + public void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) { + if (event.getUseItem().isFalse()) { + return; + } + if (mod.onLeftClickBlock(event.getEntity(), event.getHand(), event.getPos(), event.getFace())) { event.setCanceled(true); } - return; } - boolean result = we.handleRightClick(player); - debouncer.setLastInteraction(player, result); - - if (result) { - event.setCanceled(true); + @SubscribeEvent + public void onRightClickBlock(PlayerInteractEvent.RightClickBlock event) { + if (event.getUseItem().isFalse()) { + return; + } + if (mod.onRightClickBlock(event.getEntity(), event.getHand(), event.getPos(), event.getFace())) { + event.setCanceled(true); + } } - } - @SubscribeEvent - public void onCommandEvent(CommandEvent event) throws CommandSyntaxException { - ParseResults parseResults = event.getParseResults(); - if (parseResults.getContext().getSource().getEntity() instanceof ServerPlayer player && player.level().isClientSide()) { - return; - } - if (parseResults.getContext().getCommand() != CommandWrapper.FAKE_COMMAND) { - return; - } - event.setCanceled(true); - WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent( - adaptCommandSource(parseResults.getContext().getSource()), - "/" + parseResults.getReader().getString() - )); - } - - @SubscribeEvent - public void onPlayerLogOut(PlayerEvent.PlayerLoggedOutEvent event) { - if (event.getEntity() instanceof ServerPlayer player) { - debouncer.clearInteraction(adaptPlayer(player)); - - WorldEdit.getInstance().getEventBus() - .post(new SessionIdleEvent(new NeoForgePlayer.SessionKeyImpl(player))); + @SubscribeEvent + public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { + Optional result = mod.onRightClickItem(event.getEntity(), event.getHand()); + if (result.isPresent() && result.get()) { + event.setCanceled(true); + } } - } - private void onCuiPacket(CUIPacket payload, CUIPacketHandler.PacketContext context) { - if (!(context.player() instanceof ServerPlayer player)) { - // Ignore - this is not a server-bound packet - return; + @SubscribeEvent + public void onPlayerLogOut(PlayerEvent.PlayerLoggedOutEvent event) { + mod.onPlayerDisconnect(event.getEntity()); } - NeoForgePlayer actor = NeoForgeAdapter.adaptPlayer(player); - LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); - session.handleCUIInitializationMessage(payload.eventType(), payload.args(), actor); - } - - /** - * Get the configuration. - * - * @return the Forge configuration - */ - NeoForgeConfiguration getConfig() { - return this.config; - } - - /** - * Get the session for a player. - * - * @param player the player - * @return the session - */ - public LocalSession getSession(ServerPlayer player) { - checkNotNull(player); - return WorldEdit.getInstance().getSessionManager().get(adaptPlayer(player)); } - - /** - * Get the WorldEdit proxy for the given world. - * - * @param world the world - * @return the WorldEdit world - */ - public NeoForgeWorld getWorld(ServerLevel world) { - checkNotNull(world); - return new NeoForgeWorld(world); - } - - /** - * Get the WorldEdit proxy for the platform. - * - * @return the WorldEdit platform - */ - public Platform getPlatform() { - return this.platform; - } - - /** - * Get the working directory where WorldEdit's files are stored. - * - * @return the working directory - */ - public Path getWorkingDir() { - return this.workingDir; - } - - /** - * Get the version of the WorldEdit-for-Forge implementation. - * - * @return a version string - */ - String getInternalVersion() { - return container.getModInfo().getVersion().toString(); - } - - public void setPermissionsProvider(NeoForgePermissionsProvider provider) { - this.provider = provider; - } - - public NeoForgePermissionsProvider getPermissionsProvider() { - return provider; - } - } diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/ThreadSafeCache.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/ThreadSafeCache.java deleted file mode 100644 index e47b7e5091..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/ThreadSafeCache.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge; - -import com.google.common.collect.Sets; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; -import net.neoforged.neoforge.server.ServerLifecycleHooks; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CopyOnWriteArraySet; - -/** - * Caches data that cannot be accessed from another thread safely. - */ -public class ThreadSafeCache { - - private static final long REFRESH_DELAY = 1000 * 30; - private static final ThreadSafeCache INSTANCE = new ThreadSafeCache(); - private Set onlineIds = Sets.newHashSet(); - private long lastRefresh = 0; - - /** - * Get an concurrent-safe set of UUIDs of online players. - * - * @return a set of UUIDs - */ - public Set getOnlineIds() { - return onlineIds; - } - - @SubscribeEvent - public void onEndTick(ServerTickEvent.Post event) { - long now = System.currentTimeMillis(); - - if (now - lastRefresh > REFRESH_DELAY) { - Set onlineIds = new HashSet<>(); - - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if (server == null) { - return; - } - for (ServerPlayer player : server.getPlayerList().getPlayers()) { - if (player != null) { - onlineIds.add(player.getUUID()); - } - } - - this.onlineIds = new CopyOnWriteArraySet<>(onlineIds); - - lastRefresh = now; - } - } - - public static ThreadSafeCache getInstance() { - return INSTANCE; - } - -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/ComponentConverter.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/ComponentConverter.java deleted file mode 100644 index 099f04d8a5..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/ComponentConverter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge.internal; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.Strictness; -import com.google.gson.stream.JsonReader; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.HolderLookup; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.ComponentSerialization; -import net.minecraft.network.chat.MutableComponent; - -import java.io.StringReader; -import javax.annotation.Nullable; - -public class ComponentConverter { - - public static class Serializer { - private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); - - private Serializer() { - } - - static MutableComponent deserialize(JsonElement json, HolderLookup.Provider registries) { - return (MutableComponent) ComponentSerialization.CODEC.parse(registries.createSerializationContext(JsonOps.INSTANCE), json).getOrThrow(JsonParseException::new); - } - - static JsonElement serialize(Component text, HolderLookup.Provider registries) { - return ComponentSerialization.CODEC.encodeStart(registries.createSerializationContext(JsonOps.INSTANCE), text).getOrThrow(JsonParseException::new); - } - - public static String toJson(Component text, HolderLookup.Provider registries) { - return GSON.toJson(serialize(text, registries)); - } - - @Nullable - public static MutableComponent fromJson(String json, HolderLookup.Provider registries) { - JsonElement jsonelement = JsonParser.parseString(json); - return jsonelement == null ? null : deserialize(jsonelement, registries); - } - - @Nullable - public static MutableComponent fromJson(@Nullable JsonElement json, HolderLookup.Provider registries) { - return json == null ? null : deserialize(json, registries); - } - - @Nullable - public static MutableComponent fromJsonLenient(String json, HolderLookup.Provider registries) { - JsonReader jsonreader = new JsonReader(new StringReader(json)); - jsonreader.setStrictness(Strictness.LENIENT); - JsonElement jsonelement = JsonParser.parseReader(jsonreader); - return jsonelement == null ? null : deserialize(jsonelement, registries); - } - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeEntity.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeEntity.java deleted file mode 100644 index 7f0ac7470f..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeEntity.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge.internal; - -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.entity.metadata.EntityProperties; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.neoforge.NeoForgeAdapter; -import com.sk89q.worldedit.neoforge.NeoForgeEntityProperties; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.world.NullWorld; -import com.sk89q.worldedit.world.entity.EntityTypes; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.Identifier; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.storage.TagValueOutput; - -import java.lang.ref.WeakReference; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class NeoForgeEntity implements Entity { - - private final WeakReference entityRef; - - public NeoForgeEntity(net.minecraft.world.entity.Entity entity) { - checkNotNull(entity); - this.entityRef = new WeakReference<>(entity); - } - - @Override - public BaseEntity getState() { - net.minecraft.world.entity.Entity entity = entityRef.get(); - if (entity == null) { - return null; - } - - net.minecraft.nbt.CompoundTag tag = NeoForgeLoggingProblemReporter.with( - () -> "serializing entity " + entity.getStringUUID(), - reporter -> { - TagValueOutput tagValueOutput = TagValueOutput.createWithContext(reporter, entity.registryAccess()); - if (!entity.save(tagValueOutput)) { - return null; - } - return tagValueOutput.buildResult(); - } - ); - - if (tag == null) { - return null; - } - - Identifier id = BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()); - return new BaseEntity( - EntityTypes.get(id.toString()), - LazyReference.from(() -> NBTConverter.fromNative(tag)) - ); - } - - @Override - public Location getLocation() { - net.minecraft.world.entity.Entity entity = entityRef.get(); - if (entity != null) { - Vector3 position = Vector3.at(entity.getX(), entity.getY(), entity.getZ()); - float yaw = entity.getYRot(); - float pitch = entity.getXRot(); - - return new Location(NeoForgeAdapter.adapt((ServerLevel) entity.level()), position, yaw, pitch); - } else { - return new Location(NullWorld.getInstance()); - } - } - - @Override - public boolean setLocation(Location location) { - // TODO unused atm - return false; - } - - @Override - public Extent getExtent() { - net.minecraft.world.entity.Entity entity = entityRef.get(); - if (entity != null) { - return NeoForgeAdapter.adapt((ServerLevel) entity.level()); - } else { - return NullWorld.getInstance(); - } - } - - @Override - public boolean remove() { - net.minecraft.world.entity.Entity entity = entityRef.get(); - if (entity != null) { - entity.remove(net.minecraft.world.entity.Entity.RemovalReason.KILLED); - } - return true; - } - - @SuppressWarnings("unchecked") - @Nullable - @Override - public T getFacet(Class cls) { - net.minecraft.world.entity.Entity entity = entityRef.get(); - if (entity != null) { - if (EntityProperties.class.isAssignableFrom(cls)) { - return (T) new NeoForgeEntityProperties(entity); - } else { - return null; - } - } else { - return null; - } - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeLoggingProblemReporter.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeLoggingProblemReporter.java deleted file mode 100644 index 3d28207ea8..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeLoggingProblemReporter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge.internal; - -import net.minecraft.util.ProblemReporter; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.function.Function; -import java.util.function.Supplier; - -public final class NeoForgeLoggingProblemReporter implements ProblemReporter, AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - - public static T with(Supplier contextSupplier, Function consumer) { - try (var problemReporter = new NeoForgeLoggingProblemReporter(contextSupplier)) { - return consumer.apply(problemReporter); - } - } - - NeoForgeLoggingProblemReporter(Supplier contextSupplier) { - this.contextSupplier = contextSupplier; - } - - private final Collector delegate = new Collector(); - private final Supplier contextSupplier; - - @Override - public ProblemReporter forChild(PathElement child) { - return delegate.forChild(child); - } - - @Override - public void report(Problem problem) { - delegate.report(problem); - } - - @Override - public void close() { - if (!delegate.isEmpty()) { - LOGGER.warn("Problems were reported during {}: {}", contextSupplier.get(), delegate.getTreeReport()); - } - } -} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePropertyAdapter.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePropertyAdapter.java deleted file mode 100644 index 659e331548..0000000000 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePropertyAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.neoforge.internal; - -import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.registry.state.Property; - -import java.util.List; -import java.util.Optional; - -import static com.google.common.base.Preconditions.checkArgument; - -class NeoForgePropertyAdapter> implements Property { - - private final net.minecraft.world.level.block.state.properties.Property property; - private final List values; - - NeoForgePropertyAdapter(net.minecraft.world.level.block.state.properties.Property property) { - this.property = property; - this.values = ImmutableList.copyOf(property.getPossibleValues()); - } - - @Override - public String name() { - return property.getName(); - } - - @Override - public List values() { - return values; - } - - @Override - public T getValueFor(String string) throws IllegalArgumentException { - Optional val = property.getValue(string); - checkArgument(val.isPresent(), "%s has no value for %s", name(), string); - return val.get(); - } - - @Override - public int hashCode() { - return name().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Property)) { - return false; - } - return name().equals(((Property) obj).name()); - } - -} diff --git a/worldedit-neoforge/src/main/resources/META-INF/accesstransformer.cfg b/worldedit-neoforge/src/main/resources/META-INF/accesstransformer.cfg deleted file mode 100644 index fc19f2fdff..0000000000 --- a/worldedit-neoforge/src/main/resources/META-INF/accesstransformer.cfg +++ /dev/null @@ -1,7 +0,0 @@ -public net.minecraft.server.MinecraftServer nextTickTimeNanos - -# For regen -public net.minecraft.server.MinecraftServer storageSource -public net.minecraft.server.level.ServerChunkCache mainThreadProcessor - -public net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket (Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V diff --git a/worldedit-neoforge/src/main/resources/META-INF/neoforge.mods.toml b/worldedit-neoforge/src/main/resources/META-INF/neoforge.mods.toml index 0f42fe20dd..ef0cae7ae9 100644 --- a/worldedit-neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/worldedit-neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -12,14 +12,11 @@ description = ''' WorldEdit is an easy-to-use in-game world editor for Minecraft, supporting both single- and multi-player. ''' authors = "EngineHub" -logoFile = "worldedit-icon.png" +logoFile = "assets/worldedit/icon.png" displayTest = "IGNORE_SERVER_VERSION" [[mixins]] -config = "worldedit-neoforge.mixins.json" - -[[accessTransformers]] -file = "META-INF/accesstransformer.cfg" +config = "worldedit-coremc.mixins.json" [[dependencies.worldedit]] modId = "minecraft" diff --git a/worldedit-neoforge/src/main/resources/defaults/worldedit.properties b/worldedit-neoforge/src/main/resources/defaults/worldedit.properties deleted file mode 100644 index 531c12927c..0000000000 --- a/worldedit-neoforge/src/main/resources/defaults/worldedit.properties +++ /dev/null @@ -1,33 +0,0 @@ -#Don't put comments; they get removed -default-max-polygon-points=-1 -schematic-save-dir=schematics -super-pickaxe-many-drop-items=true -register-help=true -nav-wand-item=minecraft:compass -profile=false -trace-unflushed-sessions=false -super-pickaxe-drop-items=true -disallowed-blocks=minecraft:oak_sapling,minecraft:jungle_sapling,minecraft:dark_oak_sapling,minecraft:spruce_sapling,minecraft:birch_sapling,minecraft:acacia_sapling,minecraft:black_bed,minecraft:blue_bed,minecraft:brown_bed,minecraft:cyan_bed,minecraft:gray_bed,minecraft:green_bed,minecraft:light_blue_bed,minecraft:light_gray_bed,minecraft:lime_bed,minecraft:magenta_bed,minecraft:orange_bed,minecraft:pink_bed,minecraft:purple_bed,minecraft:red_bed,minecraft:white_bed,minecraft:yellow_bed,minecraft:powered_rail,minecraft:detector_rail,minecraft:short_grass,minecraft:dead_bush,minecraft:moving_piston,minecraft:piston_head,minecraft:sunflower,minecraft:rose_bush,minecraft:dandelion,minecraft:poppy,minecraft:brown_mushroom,minecraft:red_mushroom,minecraft:tnt,minecraft:torch,minecraft:fire,minecraft:redstone_wire,minecraft:wheat,minecraft:potatoes,minecraft:carrots,minecraft:melon_stem,minecraft:pumpkin_stem,minecraft:beetroots,minecraft:rail,minecraft:lever,minecraft:redstone_torch,minecraft:redstone_wall_torch,minecraft:repeater,minecraft:comparator,minecraft:stone_button,minecraft:birch_button,minecraft:acacia_button,minecraft:dark_oak_button,minecraft:jungle_button,minecraft:oak_button,minecraft:spruce_button,minecraft:cactus,minecraft:sugar_cane,minecraft:bedrock -max-super-pickaxe-size=5 -max-brush-radius=10 -craftscript-dir=craftscripts -wand-item=minecraft:wooden_axe -shell-save-type= -scripting-timeout=3000 -snapshots-dir= -use-inventory-creative-override=false -log-file=worldedit.log -log-format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s]: %5$s%6$s%n -max-changed-blocks=-1 -default-vertical-height=256 -nav-wand-distance=50 -butcher-default-radius=-1 -default-max-changed-blocks=-1 -history-size=15 -use-inventory=false -allow-symbolic-links=false -use-inventory-override=false -log-commands=false -butcher-max-radius=-1 -max-polygon-points=20 -max-radius=-1 diff --git a/worldedit-neoforge/src/main/resources/pack.mcmeta b/worldedit-neoforge/src/main/resources/pack.mcmeta deleted file mode 100644 index 0a39f614ad..0000000000 --- a/worldedit-neoforge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "WorldEdit Resources", - "pack_format": 8 - } -} \ No newline at end of file diff --git a/worldedit-neoforge/src/main/resources/worldedit-icon.png b/worldedit-neoforge/src/main/resources/worldedit-icon.png deleted file mode 100644 index dc269dcf7b17ffb3d5b4ba950c2dda74a3b5c26b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5636 zcmV+f7W?UmP)3LSnB__s;iHVxjB^FVQ(UfOILyRbTLPRu*MnpA= zz;UXFQ4mp1Jz}CRiAg9mR!a3wtBj{9qnfB-1O?fDv+V3l_xHVY&wS0R?yqO3cNSo# z+|PQ|-K=?+We4X@XyYK&%M9^1Mtwp8I1He-VXkP#jo@_;c z-${boY{U=7XDqN#-++JzpU3@d_YU%;z?U{O;3!J^hD)?kAWp^-Ck&qDR8NjTfQtcW z5dhrei31HZM5DnNaMf9Tj`|e>Ocnqj&=+JW|5+OVF3dUV=LFEyNI>jHgVFD(RThFJ zu&fz~Y}u$J=m`aybW(3o{(MZ6bsBn?qZ+akWl*Yb^cU4C;ln7Yw$=tuuq^tTe`X6M>;%oo zIUWpzZ1C12!|>0;gES%r;|W1t(p*JyLVJ_-!+JJfqV64dvE;zB0(}_lGX!c)fry|M ztw|R6f+dheNz;1^vaTJysC%CQ+DvKVBuJkVJ9DfggzR6a49HQQPbm(|r;GwA_&&pt zzL~NxWTJQ=G7Jp;2P`}j3u#k9mVCnKhUbp^v= z7?>~(L{&&(%r$FH*{AdrwWA*e!e+{cfv90%<%dtC&nX0j!Nfz-niichYba8k*jsk= zqb92${h&{-4Z(=`2BI<~3J?&oO$xyygoTib2x(vKk!){NdVj4V%M z`7LJ{IY_*w%9qVzy} zfC3OE5KWgDvIbLmI#5*V#GV4&?Lj%afq^9V8NQhkJ2ZoxE>ZZQ;h6EV<@oQY^k>9nih0uYuU1lp`h zSIA^^vb5c{SVMNV&tNlUPH!oI@#&+Tjvp`zWr~=14 zww`d7Jz3cBKnhC7861JL%EmbJ=3`HBt?`qF6*Z?0_@@-?`mw;14?MZ60V8#W z;U@|)NEC+B<2*=fs4QSt2SLQkN3$tCd7CEtdgMYHP%2v_7(U0gm%vELaKlUi%IkhP&xqnSb^-Re+Um+`4HD0NhsP3(W?nQGzZhR}v_r;1uDvHS`WsW?4V9d;)WZ0f27rE^N)xGR;>Ae1O zDu`1EpbG$Q+XFz@XY^{HA<%#kmWXBu&rEe(wVdoJ2UgWmwY?AIhwm3?AeWOLZMKWA z|4|g4U*8P*ft1h?qFEE}i03RG5ktv*{@B5eA1%tDuxj$7&Reev4~7to5?n?9G2p76 z7F*oEJAp8aVmatTs65Dk0c98qR{EMz6^7jMK6Kr10mw}o(g2X=iXs~MFcVDt=ShF& zOZkpVZfQc>u00Mzp^-CuK(cbKyjMThRl5O*>A)dy;55|w7dBI3{0cPOd;O9YvT}xu@24I zRE246*k^RiPv$e+_uqxC>t~fhMgq(R=NfdOl`+se=phl9#|d52k%kWbu$45`r=D0RbBwn zAe1N2+78gxPWFL^^^Uvdt`s)6BnmwH9=Nqo_|ps3sj=_mzGDrD0IpX+7wlw{#g)Du zr`%Ckp_ajKXZbJKrA&u})prMhpJg{o_daSyWt#TTd-VyN3CbbBCYnB!JA6=F1n0rfMXcov?f^53DTui74?vOy10K9!C0pUuY zKn+7n)OjjTM8^b`ojzA(zW8+k!m@@1{gwZf-8at>G?+J7kWpQXZ)9lu-W=I_(m7TP zO_3n3px&Qd=L|gcSd%79RaBC-gu?yC6aXtjxzz=lB(Qqr(N5gniD-#P-xL9bVhd~P zL9*kTyFiQ?#}Jajc=*hH&6bl#t;AtvVu1gccYCC;qvGwHd*Baze&ysoW;0wQR zLP$1H3-=uJU@gW#Q|1%FUKYYk08mMRm`eg&e@$NyXCU7q0tHejHFn-oVi>~`A|ZOm z&b>uzeQhKC&tL3-+6MJ5zt&+G$!oP51Pd}2BH|8wAdm#-N}_HH@UjFz%w=Syl}iAj z#^+EM1@Rl&dg^(uwfEFoGqspG{HRaBo*C44?-D2f^g0bA8Ib@ScTs8>1flpu0cl&Q zp#aQN9u$H2(*(0DhS5`$k0U@f)XonTs(wuw*)r`+3mS0rtzKH(-g#dM2FvgU2EtQc z7Cn>H)O&581It|$Q+l&Yn-=sx7b;B|N*8)*8F&^3bEy4iN#c%{&2+OhqA zmgCNWVEPi&Vwn6gbZ!{e$3a&u+*)uCu|3T=!$RB#S#3Gk0btcLvZ-Oym0NX-7#<^AwV5tJLQrqKn#!$OT+Ggxm#S8QbKd^5)3^M( z3_3+bE-)no5}!LGAMz7|#JGut%;&$79@133_L7rZzR+fEH*HKJ7ZTrDKjc3jjli0H zu}gG}4FLbh;eY%uLret9D#^-{|Mde+%a35M#~R_MOrVjEot1tLeXiJ+J@ z7QpgRH)^Bv<|~6k0V(|d|K+-`o7INW#rQc@LKp!J3`4;x+M>b5n}32&+K5$eA0^I& z(VS_>t(#$}A-lE=P}i0YYlp95pT%$tFlO};SnW~6k(j6!?}COgQs2P~Q4t6k#|Xr= zNx^G`aHy_Y#1S@sLeYvDfe6%(5?0v)7^YaDvKKBW zQgqoik-lciRH4}e7z|i|Pl;CBTB``&4}(Z+==O?<4-9ne%pEw6Q$L8jo^G^hC)F4so1y-@*7qSBdSvpOPwASUkPG=Fv4umauIvo03hPj@PB z2%!zUBI0y>1cV}A2o&fe0ayqNEX0j=d%5|dGmmO!&Q(7{0zn8+k^qibHf5nrOtlZKTut$dBFEvU&M(Xh1v zD>!s}@_sd`nHWDw%6HyK5hD8zG~*>j3`N6uSd_cy$tX~@+M?7)G$7TDCG$l90wcRw zkTC=V6ZB^Y1@C!mAP|2QTmCXr+u%IR)0@=BTX|TiRbHy;G2QU~&1d2e|nse0M zfFwZg#KzO&cvVksvRH;a7vOuFDGAb&kOW86Oos%L=$PQt&_L+NUjo>vvxmHv#zpGXNkl;r_fQH!$y#XU0xT}AMOs&vqaT#uQU%AhU)2Z z-FM!yEwf`X+F;Hw*i2O^;WCs}Eta@k1&%1Zlz;_TcE+fU>B#TVcJ`dX=C7Tch8o89 z&NYBaBE~4Jf{4!`VxN(?$$`z+Vg)oYFKJ#72@Aws@&Ic|JP`45Bv4vUol$7}_BqY9 zz;NGrL*+ZySfT=OMZ_8cuwEdt�v@D{EVq36fj3OY$AQ03_h`Fl*CG)v2XGC^PGR=7O z{$l^i#c2V&AD3yLVqie&B=8xu%U4jf+165lxYgek4iT(jrc#V-Ck8NxjE#~Ra0MX1 zNxCHW_h2+9hq0tdHwv;w#PNt^ZV|vRQ@aibo3H!*qYnjup;TwWRW^mhIWp8iXK-!S zr%Wgmzz9Jm7~vT3U~KncaMy^rQz}qYGZ+RijNJr;p(sV;a;{o79GFT408r!M>~DY+ ztHlp&8bF1n!c-Fw){Hgz{uPUx1+w{!ZCaqHrW1hSGj=BsHedg#04DUiYQ8mbZ<+o6 zoFP-!sr?Tg+kWn)#r}Jjr9iqUfhPy3okubtW`#3#*k|45<48O9^`4fd~G>cI#X z%`nV?nTKJlw>aqAvpYGo+tyWXbKB`L&M0|&0Z(=gh_XJFt!4~8c$MHZ#?yYR;ZJ) z{g?OU`|nxOtQ~j+hN&G~Xad85*9Q=mwVt$jvJx6(%KGUL zhEcB@nBC*arTii5Q8;bhd+W6s)`colTNeL}6NL@13FZ<{HfcDSdIch~?F7;lp`K>M z2nbU%z}F1+84a^5>4TnZ^W;%an(IyqG zVi?@jA`FeecwfU0u>=Nnx24+fm-OI=OWseq4$Y_fD6r z)qf94wXN5cYY8BWm3n-+DVtfu#tax*Zzur6Cd~w3!XTX}WS{Zz`j)ngC4P&DC-ge* zZxmshz;KHv`ciRq6$=rQR2ruOhCmF5L4=kEn3cYd?H5a?1wPZBvc5||vQlatjn!8e z5`ksm^(DN~i_ky?#uXqd`;3nv5SEM(k7sS`Tt%Ri5u6cF1O~)zgkx%xF|DrH=fyr_ z^vj949DFYjpx@vfWWoh6g9z=n7#$cBPO5NK&zu18ZmB+ulMSEovD6R~%Br-5rzn5{ z#SL-Bwy(7f);Ps59yVZ%0x|qWClP&1DGy4}RTBA9Vyc3Lp;cN+2L4!X#k6;hnyktR z$?r*mhlxn=GA`7oyyg+BG(Z3a*W5b=l(5n_sv#^E!XpCU0tKK{c=@mv3SApJS#t`6 zwWGwstn`g)NMa~>msGS(0o@M-%{mhpPC{xFrimhB2{KXbmA+9REWc0$IYM|0h%!D7 zp*tQcG&{3)7;F02OpO8=nXDHCXG?&GfCz(}3O8nB$ekOSQ40ECC&Cy70s?U@5lxT) zw~-HpgFt@H5f~cIdR}^Lj!~yRGAMTdz-$RXQZJ(PMS+&!nmgis7&|}C7}XFK1h`EA ze54etM4;x-N-hnD09+!vLkRpa01PsKQ6RfSY{Ulz!gGU)W-EXbkl+A~WTS7Qi0F13 e@il_R8-E89rZjGhc4GJd0000 Date: Sun, 19 Apr 2026 22:23:51 -0700 Subject: [PATCH 3/4] [coremc] Keep a Platform instance in most places This also makes Adapter an abstract class implemented by the platforms, which expose their adapter back to coremc and also to other mods. --- .../sk89q/worldedit/coremc/CoreMcAdapter.java | 83 +++++++++-------- .../coremc/CoreMcPermissionsProvider.java | 12 ++- .../internal/CoreMcBlockCategoryRegistry.java | 11 ++- .../internal/CoreMcBlockCommandSender.java | 10 ++- .../coremc/internal/CoreMcBlockRegistry.java | 16 ++-- .../coremc/internal/CoreMcCommandWrapper.java | 25 +++--- .../coremc/internal/CoreMcDataFixer.java | 89 +++++++++---------- .../coremc/internal/CoreMcEntity.java | 9 +- .../internal/CoreMcItemCategoryRegistry.java | 12 ++- .../coremc/internal/CoreMcItemRegistry.java | 14 ++- .../worldedit/coremc/internal/CoreMcMod.java | 28 +++--- .../coremc/internal/CoreMcPlatform.java | 73 ++++++--------- .../coremc/internal/CoreMcPlayer.java | 24 ++--- .../coremc/internal/CoreMcRegistries.java | 15 +++- .../CoreMcServerLevelDelegateProxy.java | 25 +++--- .../coremc/internal/CoreMcTransmogrifier.java | 34 +++---- .../coremc/internal/CoreMcWorld.java | 70 ++++++++------- .../internal/CoreMcWorldNativeAccess.java | 9 +- .../MixinServerGamePacketListenerImpl.java | 19 +++- .../sk89q/worldedit/fabric/FabricAdapter.java | 47 ++++++++++ .../fabric/{ => internal}/FabricPlatform.java | 8 +- .../{ => internal}/FabricWorldEdit.java | 15 +++- .../LuckoFabricPermissionsProvider.java | 2 +- .../src/main/resources/fabric.mod.json | 2 +- .../worldedit/neoforge/NeoForgeAdapter.java | 47 ++++++++++ .../{ => internal}/NeoForgePlatform.java | 8 +- .../NeoForgeResourceLoader.java | 2 +- .../{ => internal}/NeoForgeWorldEdit.java | 18 ++-- 28 files changed, 450 insertions(+), 277 deletions(-) create mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/{ => internal}/FabricPlatform.java (91%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/{ => internal}/FabricWorldEdit.java (92%) rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/{ => internal}/LuckoFabricPermissionsProvider.java (97%) create mode 100644 worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/{ => internal}/NeoForgePlatform.java (93%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/{ => internal}/NeoForgeResourceLoader.java (97%) rename worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/{ => internal}/NeoForgeWorldEdit.java (91%) diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java index eeb71104f2..eb1d05cec9 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java @@ -20,13 +20,11 @@ package com.sk89q.worldedit.coremc; import com.mojang.serialization.Codec; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.coremc.internal.CoreMcBlockCommandSender; import com.sk89q.worldedit.coremc.internal.CoreMcCommandSender; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.coremc.internal.CoreMcPlayer; -import com.sk89q.worldedit.coremc.internal.CoreMcTransmogrifier; import com.sk89q.worldedit.coremc.internal.CoreMcWorld; import com.sk89q.worldedit.coremc.internal.NBTConverter; import com.sk89q.worldedit.coremc.mixin.AccessorCommandSourceStack; @@ -68,18 +66,25 @@ import static com.google.common.base.Preconditions.checkNotNull; /** - * Common adapter methods for platforms sharing native Minecraft code. + * Adapter for platforms sharing native Minecraft code. + * + * @implNote This is not intended to be implemented by non-platforms. Only extend this in platform-specific code. */ -public final class CoreMcAdapter { +public abstract class CoreMcAdapter { - private CoreMcAdapter() { + protected CoreMcAdapter() { } - public static World fromNativeWorld(Level level) { - return new CoreMcWorld((ServerLevel) level); + /** + * {@return the platform that owns this adapter} + */ + protected abstract CoreMcPlatform getPlatform(); + + public World fromNativeWorld(Level level) { + return new CoreMcWorld(getPlatform(), (ServerLevel) level); } - public static ServerLevel toNativeWorld(World world) { + public ServerLevel toNativeWorld(World world) { checkNotNull(world); if (world instanceof CoreMcWorld coreMcWorld) { return coreMcWorld.getWorld(); @@ -90,31 +95,31 @@ public static ServerLevel toNativeWorld(World world) { // Available as API, but not used by WorldEdit itself. @SuppressWarnings("unused") - public static Biome toNativeBiome(BiomeType biomeType) { - return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BIOME) + public Biome toNativeBiome(BiomeType biomeType) { + return getPlatform().serverRegistryAccess().lookupOrThrow(Registries.BIOME) .getOptional(Identifier.parse(biomeType.id())) .orElseThrow(() -> new IllegalStateException("No biome for " + biomeType.id())); } - public static BiomeType fromNativeBiome(Biome biome) { - Identifier id = CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BIOME).getKey(biome); + public BiomeType fromNativeBiome(Biome biome) { + Identifier id = getPlatform().serverRegistryAccess().lookupOrThrow(Registries.BIOME).getKey(biome); Objects.requireNonNull(id, "biome is not registered"); return BiomeTypes.get(id.toString()); } - public static Vector3 adapt(Vec3 vector) { + public Vector3 adapt(Vec3 vector) { return Vector3.at(vector.x, vector.y, vector.z); } - public static BlockVector3 adapt(BlockPos pos) { + public BlockVector3 adapt(BlockPos pos) { return BlockVector3.at(pos.getX(), pos.getY(), pos.getZ()); } - public static Vec3 toVec3(BlockVector3 vector) { + public Vec3 toVec3(BlockVector3 vector) { return new Vec3(vector.x(), vector.y(), vector.z()); } - public static net.minecraft.core.Direction adapt(Direction face) { + public net.minecraft.core.Direction adapt(Direction face) { return switch (face) { case NORTH -> net.minecraft.core.Direction.NORTH; case SOUTH -> net.minecraft.core.Direction.SOUTH; @@ -125,7 +130,7 @@ public static net.minecraft.core.Direction adapt(Direction face) { }; } - public static Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction face) { + public Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction face) { if (face == null) { return null; } @@ -139,46 +144,46 @@ public static Direction adaptEnumFacing(@Nullable net.minecraft.core.Direction f }; } - public static BlockPos toBlockPos(BlockVector3 vector) { + public BlockPos toBlockPos(BlockVector3 vector) { return new BlockPos(vector.x(), vector.y(), vector.z()); } - public static net.minecraft.world.level.block.state.BlockState toNativeBlockState(BlockState blockState) { + public net.minecraft.world.level.block.state.BlockState toNativeBlockState(BlockState blockState) { int blockStateId = BlockStateIdAccess.getBlockStateId(blockState); if (!BlockStateIdAccess.isValidInternalId(blockStateId)) { - return CoreMcTransmogrifier.transmogToMinecraft(blockState); + return getPlatform().getTransmogrifier().transmogToMinecraft(blockState); } return Block.stateById(blockStateId); } - public static BlockState fromNativeBlockState(net.minecraft.world.level.block.state.BlockState blockState) { + public BlockState fromNativeBlockState(net.minecraft.world.level.block.state.BlockState blockState) { int blockStateId = Block.getId(blockState); BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId); if (worldEdit == null) { - return CoreMcTransmogrifier.transmogToWorldEdit(blockState); + return getPlatform().getTransmogrifier().transmogToWorldEdit(blockState); } return worldEdit; } - public static Block toNativeBlock(BlockType blockType) { - return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK) + public Block toNativeBlock(BlockType blockType) { + return getPlatform().serverRegistryAccess().lookupOrThrow(Registries.BLOCK) .getValue(Identifier.parse(blockType.id())); } - public static BlockType fromNativeBlock(Block block) { + public BlockType fromNativeBlock(Block block) { return BlockTypes.get( - CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK).getKey(block).toString() + getPlatform().serverRegistryAccess().lookupOrThrow(Registries.BLOCK).getKey(block).toString() ); } - public static Item toNativeItem(ItemType itemType) { - return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM) + public Item toNativeItem(ItemType itemType) { + return getPlatform().serverRegistryAccess().lookupOrThrow(Registries.ITEM) .getValue(Identifier.parse(itemType.id())); } - public static ItemType fromNativeItem(Item item) { + public ItemType fromNativeItem(Item item) { return ItemTypes.get( - CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM).getKey(item).toString() + getPlatform().serverRegistryAccess().lookupOrThrow(Registries.ITEM).getKey(item).toString() ); } @@ -189,7 +194,7 @@ public static ItemType fromNativeItem(Item item) { "components", DataComponentPatch.EMPTY ).codec(); - public static ItemStack toNativeItemStack(BaseItemStack baseItemStack) { + public ItemStack toNativeItemStack(BaseItemStack baseItemStack) { final ItemStack itemStack = new ItemStack( toNativeItem(baseItemStack.getType()), baseItemStack.getAmount() @@ -197,7 +202,7 @@ public static ItemStack toNativeItemStack(BaseItemStack baseItemStack) { LinCompoundTag nbt = baseItemStack.getNbt(); if (nbt != null) { DataComponentPatch componentPatch = COMPONENTS_CODEC.parse( - CoreMcPlatform.getRegistryAccess().createSerializationContext(NbtOps.INSTANCE), + getPlatform().serverRegistryAccess().createSerializationContext(NbtOps.INSTANCE), NBTConverter.toNative(nbt) ).getOrThrow(); itemStack.applyComponents(componentPatch); @@ -205,9 +210,9 @@ public static ItemStack toNativeItemStack(BaseItemStack baseItemStack) { return itemStack; } - public static BaseItemStack fromNativeItemStack(ItemStack itemStack) { + public BaseItemStack fromNativeItemStack(ItemStack itemStack) { CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart( - CoreMcPlatform.getRegistryAccess().createSerializationContext(NbtOps.INSTANCE), + getPlatform().serverRegistryAccess().createSerializationContext(NbtOps.INSTANCE), itemStack.getComponentsPatch() ).getOrThrow(); return new BaseItemStack( @@ -223,9 +228,9 @@ public static BaseItemStack fromNativeItemStack(ItemStack itemStack) { * @param player the player * @return the WorldEdit player */ - public static CoreMcPlayer fromNativePlayer(ServerPlayer player) { + public CoreMcPlayer fromNativePlayer(ServerPlayer player) { checkNotNull(player); - return new CoreMcPlayer(player); + return new CoreMcPlayer(getPlatform(), player); } /** @@ -234,15 +239,15 @@ public static CoreMcPlayer fromNativePlayer(ServerPlayer player) { * @param commandSourceStack the command source * @return the WorldEdit actor */ - public static Actor adaptCommandSource(CommandSourceStack commandSourceStack) { + public Actor adaptCommandSource(CommandSourceStack commandSourceStack) { checkNotNull(commandSourceStack); if (commandSourceStack.isPlayer()) { return fromNativePlayer(commandSourceStack.getPlayer()); } - if (WorldEdit.getInstance().getPlatformManager().getConfiguration().commandBlockSupport + if (getPlatform().getConfiguration().commandBlockSupport && ((AccessorCommandSourceStack) commandSourceStack).getSource() instanceof BaseCommandBlock commandBlock) { return new CoreMcBlockCommandSender( - commandBlock, commandSourceStack.getLevel(), commandSourceStack.getPosition() + getPlatform(), commandBlock, commandSourceStack.getLevel(), commandSourceStack.getPosition() ); } return new CoreMcCommandSender(commandSourceStack); diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java index 88258efccf..0c7c758985 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java @@ -41,11 +41,21 @@ public interface CoreMcPermissionsProvider { return coreMcPlatform; } + /** + * Public API for other mods to get the current permissions provider. + * + * @return the current permissions provider + */ + @SuppressWarnings("unused") static CoreMcPermissionsProvider current() { return getCoreMcPlatform().getPermissionsProvider(); } - // API for other mods to set a custom permissions provider. + /** + * Public API for other mods to set the current permissions provider. + * + * @param provider the provider to set + */ @SuppressWarnings("unused") static void setCurrent(CoreMcPermissionsProvider provider) { getCoreMcPlatform().setPermissionsProvider(provider); diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java index 3fdc5b6625..5d5c32f354 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCategoryRegistry.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; import net.minecraft.core.Holder; @@ -33,14 +32,20 @@ public final class CoreMcBlockCategoryRegistry implements BlockCategoryRegistry { + private final CoreMcPlatform platform; + + public CoreMcBlockCategoryRegistry(CoreMcPlatform platform) { + this.platform = platform; + } + @Override public Set getCategorisedByName(String category) { - return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.BLOCK) + return platform.serverRegistryAccess().lookupOrThrow(Registries.BLOCK) .get(TagKey.create(Registries.BLOCK, Identifier.parse(category))) .stream() .flatMap(HolderSet.Named::stream) .map(Holder::value) - .map(CoreMcAdapter::fromNativeBlock) + .map(platform.getAdapter()::fromNativeBlock) .collect(Collectors.toSet()); } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java index b4fe01f97f..6cd528f03a 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockCommandSender.java @@ -44,13 +44,19 @@ import static com.google.common.base.Preconditions.checkNotNull; public final class CoreMcBlockCommandSender extends AbstractCommandBlockActor { + + private static Location createLocation(CoreMcPlatform platform, ServerLevel level, Vec3 pos) { + CoreMcAdapter adapter = platform.getAdapter(); + return new Location(adapter.fromNativeWorld(checkNotNull(level)), adapter.adapt(pos)); + } + private final BaseCommandBlock sender; private final UUID uuid; private final ServerLevel level; private final Vec3 pos; - public CoreMcBlockCommandSender(BaseCommandBlock sender, ServerLevel level, Vec3 pos) { - super(new Location(CoreMcAdapter.fromNativeWorld(checkNotNull(level)), CoreMcAdapter.adapt(pos))); + public CoreMcBlockCommandSender(CoreMcPlatform platform, BaseCommandBlock sender, ServerLevel level, Vec3 pos) { + super(createLocation(platform, level, pos)); this.sender = sender; this.level = level; diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java index 5853630dc5..6d6119d0a4 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcBlockRegistry.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -40,16 +39,21 @@ */ public final class CoreMcBlockRegistry implements BlockRegistry { + private final CoreMcPlatform platform; private final Map materialMap = new HashMap<>(); + public CoreMcBlockRegistry(CoreMcPlatform platform) { + this.platform = platform; + } + @Override public Component getRichName(BlockType blockType) { - return TranslatableComponent.of(CoreMcAdapter.toNativeBlock(blockType).getDescriptionId()); + return TranslatableComponent.of(platform.getAdapter().toNativeBlock(blockType).getDescriptionId()); } @Override public BlockMaterial getMaterial(BlockType blockType) { - Block block = CoreMcAdapter.toNativeBlock(blockType); + Block block = platform.getAdapter().toNativeBlock(blockType); return materialMap.computeIfAbsent( block.defaultBlockState(), CoreMcBlockMaterial::new @@ -58,20 +62,20 @@ public BlockMaterial getMaterial(BlockType blockType) { @Override public Map> getProperties(BlockType blockType) { - Block block = CoreMcAdapter.toNativeBlock(blockType); + Block block = platform.getAdapter().toNativeBlock(blockType); Map> map = new TreeMap<>(); Collection> propertyKeys = block .defaultBlockState() .getProperties(); for (net.minecraft.world.level.block.state.properties.Property key : propertyKeys) { - map.put(key.getName(), CoreMcTransmogrifier.transmogToWorldEditProperty(key)); + map.put(key.getName(), platform.getTransmogrifier().transmogToWorldEditProperty(key)); } return map; } @Override public OptionalInt getInternalBlockStateId(BlockState state) { - net.minecraft.world.level.block.state.BlockState equivalent = CoreMcAdapter.toNativeBlockState(state); + net.minecraft.world.level.block.state.BlockState equivalent = platform.getAdapter().toNativeBlockState(state); return OptionalInt.of(Block.getId(equivalent)); } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java index 75b64bed72..e5e897db47 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcCommandWrapper.java @@ -30,7 +30,6 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extension.platform.Actor; @@ -50,11 +49,13 @@ /** * Shared command wrapper logic for registering WorldEdit commands with Brigadier. - * Platform modules only need to provide the {@code adaptCommandSource} function. */ public final class CoreMcCommandWrapper { - private CoreMcCommandWrapper() { + private final CoreMcPlatform platform; + + public CoreMcCommandWrapper(CoreMcPlatform platform) { + this.platform = platform; } /** @@ -63,14 +64,14 @@ private CoreMcCommandWrapper() { * @param dispatcher the Brigadier dispatcher * @param command the WorldEdit command to register */ - public static void register(CommandDispatcher dispatcher, - org.enginehub.piston.Command command) { + public void register(CommandDispatcher dispatcher, + org.enginehub.piston.Command command) { Command commandRunner = ctx -> { if (ctx.getSource().getLevel().isClientSide()) { return 0; } WorldEdit.getInstance().getEventBus().post(new CommandEvent( - CoreMcAdapter.adaptCommandSource(ctx.getSource()), + platform.getAdapter().adaptCommandSource(ctx.getSource()), "/" + ctx.getInput() )); return 0; @@ -82,7 +83,7 @@ public static void register(CommandDispatcher dispatcher, for (String alias : aliases.build()) { LiteralArgumentBuilder base = literal(alias).executes(commandRunner) .then(argument("args", StringArgumentType.greedyString()) - .suggests(CoreMcCommandWrapper::suggest) + .suggests(this::suggest) .executes(commandRunner)); if (command.getCondition() != org.enginehub.piston.Command.Condition.TRUE) { base.requires(requirementsFor(command)); @@ -91,19 +92,19 @@ public static void register(CommandDispatcher dispatcher, } } - private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { + private Predicate requirementsFor(org.enginehub.piston.Command mapping) { return ctx -> { InjectedValueStore store = MapBackedValueStore.create(); - final Actor actor = CoreMcAdapter.adaptCommandSource(ctx); + final Actor actor = platform.getAdapter().adaptCommandSource(ctx); store.injectValue(Key.of(Actor.class), _ -> Optional.of(actor)); return mapping.getCondition().satisfied(store); }; } - private static CompletableFuture suggest(CommandContext context, - SuggestionsBuilder builder) { + private CompletableFuture suggest(CommandContext context, + SuggestionsBuilder builder) { CommandSuggestionEvent event = new CommandSuggestionEvent( - CoreMcAdapter.adaptCommandSource(context.getSource()), + platform.getAdapter().adaptCommandSource(context.getSource()), builder.getInput() ); WorldEdit.getInstance().getEventBus().post(event); diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java index 2f982365b5..1499a5151e 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcDataFixer.java @@ -86,11 +86,9 @@ *

*/ @SuppressWarnings({ - "UnnecessarilyQualifiedStaticUsage", "StringSplitter", "ImmutableEnumChecker", "MissingOverride", - "StaticAssignmentInConstructor", "EffectivelyPrivate", "FallThrough", "MutablePublicArray", @@ -139,7 +137,7 @@ private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) { private String fixBlockState(String blockState, int srcVer) { net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState); Dynamic dynamic = new Dynamic<>(OPS_NBT, stateNBT); - net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue(); + net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) fixer.update(References.BLOCK_STATE, dynamic, srcVer, dataVersion).getValue(); return nbtToState(fixed); } @@ -181,16 +179,15 @@ private String fixItemType(String key, int srcVer) { return fixName(key, srcVer, References.ITEM_NAME); } - private static String fixName(String key, int srcVer, TypeReference type) { - return INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, DATA_VERSION) + private String fixName(String key, int srcVer, TypeReference type) { + return fixer.update(type, new Dynamic<>(OPS_NBT, StringTag.valueOf(key)), srcVer, dataVersion) .asString().result().orElse(key); } private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final int LEGACY_VERSION = 1343; - private static int DATA_VERSION; - private static CoreMcDataFixer INSTANCE; + private final int dataVersion; private final Map> converters = new EnumMap<>(LegacyType.class); private final Map> inspectors = new EnumMap<>(LegacyType.class); @@ -220,9 +217,11 @@ public TypeReference getDFUType() { } } - public CoreMcDataFixer(int dataVersion) { - DATA_VERSION = dataVersion; - INSTANCE = this; + private final CoreMcPlatform platform; + + public CoreMcDataFixer(CoreMcPlatform platform, int dataVersion) { + this.platform = platform; + this.dataVersion = dataVersion; registerConverters(); registerInspectors(); this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); @@ -276,32 +275,32 @@ public Schema getSchema(int i) { } } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { + public net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { return convert(type.getDFUType(), cmp); } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + public net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { return convert(type.getDFUType(), cmp, sourceVer); } - public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { return convert(type.getDFUType(), cmp, sourceVer, targetVer); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { + public net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp) { int i = cmp.getIntOr("DataVersion", -1); return convert(type, cmp, i); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { - return convert(type, cmp, sourceVer, DATA_VERSION); + public net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer) { + return convert(type, cmp, sourceVer, dataVersion); } - public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { + public net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (sourceVer >= targetVer) { return cmp; } - return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); + return (net.minecraft.nbt.CompoundTag) fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue(); } @@ -591,17 +590,17 @@ private static Identifier getKey(String type) { return key; } - private static void convertCompound(LegacyType type, net.minecraft.nbt.CompoundTag cmp, String key, int sourceVer, int targetVer) { + private void convertCompound(LegacyType type, net.minecraft.nbt.CompoundTag cmp, String key, int sourceVer, int targetVer) { cmp.put(key, convert(type, cmp.getCompoundOrEmpty(key), sourceVer, targetVer)); } - private static void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + private void convertItem(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { if (nbttagcompound.getCompound(key).isPresent()) { convertCompound(LegacyType.ITEM_INSTANCE, nbttagcompound, key, sourceVer, targetVer); } } - private static void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { + private void convertItems(net.minecraft.nbt.CompoundTag nbttagcompound, String key, int sourceVer, int targetVer) { nbttagcompound.getList(key).ifPresent(nbttaglist -> { for (int j = 0; j < nbttaglist.size(); ++j) { nbttaglist.set(j, convert(LegacyType.ITEM_INSTANCE, nbttaglist.getCompoundOrEmpty(j), sourceVer, targetVer)); @@ -666,7 +665,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) } } - private static class DataInspectorBlockEntity implements DataInspector { + private class DataInspectorBlockEntity implements DataInspector { private static final Map b = Maps.newHashMap(); private static final Map c = Maps.newHashMap(); @@ -808,7 +807,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorEntity implements DataInspector { + private class DataInspectorEntity implements DataInspector { private static final Logger a = LogManager.getLogger(CoreMcDataFixer.class); @@ -871,7 +870,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, abstract net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer); } - private static class DataInspectorItemList extends DataInspectorTagged { + private class DataInspectorItemList extends DataInspectorTagged { private final String[] keys; @@ -882,14 +881,14 @@ private static class DataInspectorItemList extends DataInspectorTagged { net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String s : this.keys) { - CoreMcDataFixer.convertItems(nbttagcompound, s, sourceVer, targetVer); + convertItems(nbttagcompound, s, sourceVer, targetVer); } return nbttagcompound; } } - private static class DataInspectorItem extends DataInspectorTagged { + private class DataInspectorItem extends DataInspectorTagged { private final String[] keys; @@ -900,7 +899,7 @@ private static class DataInspectorItem extends DataInspectorTagged { net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer) { for (String key : this.keys) { - CoreMcDataFixer.convertItem(nbttagcompound, key, sourceVer, targetVer); + convertItem(nbttagcompound, key, sourceVer, targetVer); } return nbttagcompound; @@ -1822,7 +1821,7 @@ protected net.minecraft.nbt.CompoundTag b(net.minecraft.nbt.CompoundTag nbttagco } } - private static class DataConverterBook implements DataConverter { + private class DataConverterBook implements DataConverter { DataConverterBook() { } @@ -1855,7 +1854,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (object == null) { try { - object = ComponentConverter.Serializer.fromJson(s, CoreMcPlatform.getRegistryAccess()); + object = ComponentConverter.Serializer.fromJson(s, platform.serverRegistryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -1863,7 +1862,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) if (object == null) { try { - object = ComponentConverter.Serializer.fromJsonLenient(s, CoreMcPlatform.getRegistryAccess()); + object = ComponentConverter.Serializer.fromJsonLenient(s, platform.serverRegistryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -1877,7 +1876,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) object = Component.literal(""); } - nbttaglist.set(i, StringTag.valueOf(ComponentConverter.Serializer.toJson((Component) object, CoreMcPlatform.getRegistryAccess()))); + nbttaglist.set(i, StringTag.valueOf(ComponentConverter.Serializer.toJson((Component) object, platform.serverRegistryAccess()))); } nbttagcompound1.put("pages", nbttaglist); @@ -2448,7 +2447,7 @@ public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) } } - private static class DataConverterSignText implements DataConverter { + private class DataConverterSignText implements DataConverter { public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { @@ -2518,7 +2517,7 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { if (object == null) { try { - object = ComponentConverter.Serializer.fromJson(s1, CoreMcPlatform.getRegistryAccess()); + object = ComponentConverter.Serializer.fromJson(s1, platform.serverRegistryAccess()); } catch (JsonParseException jsonparseexception1) { ; } @@ -2526,7 +2525,7 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { if (object == null) { try { - object = ComponentConverter.Serializer.fromJsonLenient(s1, CoreMcPlatform.getRegistryAccess()); + object = ComponentConverter.Serializer.fromJsonLenient(s1, platform.serverRegistryAccess()); } catch (JsonParseException jsonparseexception2) { ; } @@ -2540,11 +2539,11 @@ private void convert(net.minecraft.nbt.CompoundTag nbttagcompound, String s) { object = Component.literal(""); } - nbttagcompound.putString(s, ComponentConverter.Serializer.toJson((Component) object, CoreMcPlatform.getRegistryAccess())); + nbttagcompound.putString(s, ComponentConverter.Serializer.toJson((Component) object, platform.serverRegistryAccess())); } } - private static class DataInspectorPlayerVehicle implements DataInspector { + private class DataInspectorPlayerVehicle implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { cmp.getCompound("RootVehicle").ifPresent(nbttagcompound1 -> { @@ -2557,7 +2556,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorLevelPlayer implements DataInspector { + private class DataInspectorLevelPlayer implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { if (cmp.getCompound("Player").isPresent()) { @@ -2568,7 +2567,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorStructure implements DataInspector { + private class DataInspectorStructure implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { cmp.getList("entities").ifPresent(nbttaglist -> { @@ -2593,7 +2592,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorChunks implements DataInspector { + private class DataInspectorChunks implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { cmp.getCompound("Level").ifPresent(nbttagcompound1 -> { @@ -2614,7 +2613,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorEntityPassengers implements DataInspector { + private class DataInspectorEntityPassengers implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { cmp.getList("Passengers").ifPresent(nbttaglist -> { @@ -2627,7 +2626,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorPlayer implements DataInspector { + private class DataInspectorPlayer implements DataInspector { @Override public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { convertItems(cmp, "Inventory", sourceVer, targetVer); @@ -2644,7 +2643,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorVillagers implements DataInspector { + private class DataInspectorVillagers implements DataInspector { Identifier entityVillager = getKey("EntityVillager"); @Override @@ -2666,7 +2665,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorMobSpawnerMinecart implements DataInspector { + private class DataInspectorMobSpawnerMinecart implements DataInspector { Identifier entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @@ -2683,7 +2682,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorMobSpawnerMobs implements DataInspector { + private class DataInspectorMobSpawnerMobs implements DataInspector { Identifier tileEntityMobSpawner = getKey("TileEntityMobSpawner"); @Override @@ -2704,7 +2703,7 @@ public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, } } - private static class DataInspectorCommandBlock implements DataInspector { + private class DataInspectorCommandBlock implements DataInspector { Identifier tileEntityCommand = getKey("TileEntityCommand"); @Override diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java index cc4de5c80e..33b1399612 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcEntity.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityProperties; @@ -40,10 +39,12 @@ public final class CoreMcEntity implements Entity { + private final CoreMcPlatform platform; private final WeakReference entityRef; - public CoreMcEntity(net.minecraft.world.entity.Entity entity) { + public CoreMcEntity(CoreMcPlatform platform, net.minecraft.world.entity.Entity entity) { checkNotNull(entity); + this.platform = platform; this.entityRef = new WeakReference<>(entity); } @@ -87,7 +88,7 @@ public Location getLocation() { float yaw = entity.getYRot(); float pitch = entity.getXRot(); - return new Location(CoreMcAdapter.fromNativeWorld(entity.level()), position, yaw, pitch); + return new Location(platform.getAdapter().fromNativeWorld(entity.level()), position, yaw, pitch); } else { return new Location(NullWorld.getInstance()); } @@ -103,7 +104,7 @@ public boolean setLocation(Location location) { public Extent getExtent() { net.minecraft.world.entity.Entity entity = entityRef.get(); if (entity != null) { - return CoreMcAdapter.fromNativeWorld(entity.level()); + return platform.getAdapter().fromNativeWorld(entity.level()); } else { return NullWorld.getInstance(); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java index 97884aed65..de8edf2d04 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemCategoryRegistry.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; import net.minecraft.core.Holder; @@ -32,14 +31,21 @@ import java.util.stream.Collectors; public final class CoreMcItemCategoryRegistry implements ItemCategoryRegistry { + + private final CoreMcPlatform platform; + + public CoreMcItemCategoryRegistry(CoreMcPlatform platform) { + this.platform = platform; + } + @Override public Set getCategorisedByName(String category) { - return CoreMcPlatform.getRegistryAccess().lookupOrThrow(Registries.ITEM) + return platform.serverRegistryAccess().lookupOrThrow(Registries.ITEM) .get(TagKey.create(Registries.ITEM, Identifier.parse(category))) .stream() .flatMap(HolderSet.Named::stream) .map(Holder::value) - .map(CoreMcAdapter::fromNativeItem) + .map(platform.getAdapter()::fromNativeItem) .collect(Collectors.toSet()); } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java index b920fdba41..cc4066ac16 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcItemRegistry.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; @@ -29,10 +28,17 @@ @SuppressWarnings("removal") public final class CoreMcItemRegistry extends BundledItemRegistry { + + private final CoreMcPlatform platform; + + public CoreMcItemRegistry(CoreMcPlatform platform) { + this.platform = platform; + } + @Override public Component getRichName(ItemType itemType) { return TranslatableComponent.of( - CoreMcAdapter.toNativeItem(itemType).getDescriptionId() + platform.getAdapter().toNativeItem(itemType).getDescriptionId() ); } @@ -40,8 +46,8 @@ public Component getRichName(ItemType itemType) { public Component getRichName(BaseItemStack itemStack) { return GsonComponentSerializer.INSTANCE.deserialize( ComponentConverter.Serializer.toJson( - CoreMcAdapter.toNativeItemStack(itemStack).getItemName(), - CoreMcPlatform.getRegistryAccess() + platform.getAdapter().toNativeItemStack(itemStack).getItemName(), + platform.serverRegistryAccess() ) ); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java index f65cbf54b6..709f769a80 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java @@ -23,7 +23,6 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.PermissionCondition; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; @@ -123,7 +122,7 @@ protected void setupRegistries(MinecraftServer server) { String key = name.toString(); if (BlockType.REGISTRY.get(key) == null) { BlockType.REGISTRY.register(key, new BlockType(key, - input -> CoreMcAdapter.fromNativeBlockState(CoreMcAdapter.toNativeBlock(input.getBlockType()).defaultBlockState()))); + input -> platform.getAdapter().fromNativeBlockState(platform.getAdapter().toNativeBlock(input.getBlockType()).defaultBlockState()))); } } // Items @@ -170,7 +169,7 @@ protected void setupRegistries(MinecraftServer server) { .stream() .flatMap(HolderSet.Named::stream) .map(Holder::value) - .map(CoreMcAdapter::fromNativeBiome) + .map(platform.getAdapter()::fromNativeBiome) .collect(Collectors.toSet())) ); } @@ -218,8 +217,9 @@ protected void registerCommands(CommandDispatcher dispatcher List commands = manager.getPlatformCommandManager().getCommandManager() .getAllCommands().toList(); + CoreMcCommandWrapper commandWrapper = new CoreMcCommandWrapper(platform); for (Command command : commands) { - CoreMcCommandWrapper.register(dispatcher, command); + commandWrapper.register(dispatcher, command); Set perms = command.getCondition().as(PermissionCondition.class) .map(PermissionCondition::getPermissions) .orElseGet(Collections::emptySet); @@ -264,7 +264,7 @@ public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { } WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(playerEntity); + CoreMcPlayer player = platform.getAdapter().fromNativePlayer(playerEntity); Optional previousResult = debouncer.getDuplicateInteractionResult(player); if (previousResult.isPresent()) { @@ -282,9 +282,9 @@ protected boolean onLeftClickBlock(Player playerEntity, InteractionHand hand, Bl ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); - CoreMcWorld world = (CoreMcWorld) CoreMcAdapter.fromNativeWorld(serverPlayer.level()); - Direction direction = CoreMcAdapter.adaptEnumFacing(face); + CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); + CoreMcWorld world = (CoreMcWorld) platform.getAdapter().fromNativeWorld(serverPlayer.level()); + Direction direction = platform.getAdapter().adaptEnumFacing(face); Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); @@ -301,9 +301,9 @@ protected boolean onRightClickBlock(Player playerEntity, InteractionHand hand, B ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); - CoreMcWorld world = (CoreMcWorld) CoreMcAdapter.fromNativeWorld(serverPlayer.level()); - Direction direction = CoreMcAdapter.adaptEnumFacing(face); + CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); + CoreMcWorld world = (CoreMcWorld) platform.getAdapter().fromNativeWorld(serverPlayer.level()); + Direction direction = platform.getAdapter().adaptEnumFacing(face); Location pos = new Location(world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); @@ -320,7 +320,7 @@ protected Optional onRightClickItem(Player playerEntity, InteractionHan ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = CoreMcAdapter.fromNativePlayer(serverPlayer); + CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); Optional previousResult = debouncer.getDuplicateInteractionResult(player); if (previousResult.isPresent()) { @@ -337,7 +337,7 @@ protected void onPlayerDisconnect(Player playerEntity) { if (!(playerEntity instanceof ServerPlayer player)) { return; } - debouncer.clearInteraction(CoreMcAdapter.fromNativePlayer(player)); + debouncer.clearInteraction(platform.getAdapter().fromNativePlayer(player)); WorldEdit.getInstance().getEventBus() .post(new SessionIdleEvent(new CoreMcPlayer.SessionKeyImpl(player))); @@ -347,7 +347,7 @@ protected void onCuiPacket(CUIPacket payload, CUIPacketHandler.PacketContext con if (!(context.player() instanceof ServerPlayer player)) { return; } - CoreMcPlayer actor = CoreMcAdapter.fromNativePlayer(player); + CoreMcPlayer actor = platform.getAdapter().fromNativePlayer(player); LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); session.handleCUIInitializationMessage(payload.eventType(), payload.args(), actor); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java index dc07bbb2d1..ca5edb90b1 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlatform.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.coremc.internal; import com.google.common.collect.Sets; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; import com.sk89q.worldedit.entity.Player; @@ -58,52 +57,12 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; public abstract class CoreMcPlatform extends AbstractPlatform implements MultiUserPlatform { - private static final Lifecycled WORLD_EDITING_PLATFORM = WorldEdit.getInstance().getPlatformManager() - .getPreferred(Capability.WORLD_EDITING) - .flatMap(platform -> { - if (platform instanceof CoreMcPlatform coreMcPlatform) { - return new ConstantLifecycled<>(coreMcPlatform); - } else { - return SimpleLifecycled.invalid(); - } - }); - - public static CoreMcPlatform forWorldEditing() { - return WORLD_EDITING_PLATFORM.valueOrThrow(); - } - - public static Optional optionallyForWorldEditing() { - return WORLD_EDITING_PLATFORM.value(); - } - - private static final Lifecycled REGISTRY_ACCESS = WORLD_EDITING_PLATFORM - .flatMap(platform -> platform.server.map(MinecraftServer::registryAccess)); - - public static RegistryAccess getRegistryAccess() { - return REGISTRY_ACCESS.valueOrThrow(); - } - - private static final Lifecycled CUI_PLATFORM = WorldEdit.getInstance().getPlatformManager() - .getPreferred(Capability.WORLDEDIT_CUI) - .flatMap(platform -> { - if (platform instanceof CoreMcPlatform coreMcPlatform) { - return new ConstantLifecycled<>(coreMcPlatform); - } else { - return SimpleLifecycled.invalid(); - } - }); - - public static CoreMcPlatform forCui() { - return CUI_PLATFORM.valueOrThrow(); - } - - protected static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( SideEffect.VALIDATION, SideEffect.ENTITY_AI, SideEffect.LIGHTING, @@ -114,6 +73,7 @@ public static CoreMcPlatform forCui() { private final CoreMcMod mod; private final CoreMcDataFixer dataFixer; private final CoreMcRegistries registries; + private final CoreMcTransmogrifier transmogrifier; private final Lifecycled server; private final Lifecycled watchdog; private boolean hookingEvents = false; @@ -121,8 +81,9 @@ public static CoreMcPlatform forCui() { protected CoreMcPlatform(CoreMcMod mod, Lifecycled server) { this.mod = mod; - this.dataFixer = new CoreMcDataFixer(getDataVersion()); - this.registries = new CoreMcRegistries(); + this.dataFixer = new CoreMcDataFixer(this, getDataVersion()); + this.registries = new CoreMcRegistries(this); + this.transmogrifier = new CoreMcTransmogrifier(this); this.server = server; this.watchdog = server.flatMap(s -> { if (s instanceof DedicatedServer dedicatedServer) { @@ -142,6 +103,18 @@ protected void extraOnBlockStateChange(ServerLevel level, BlockPos pos, BlockSta // endregion + /** + * {@return the platform-specific {@link CoreMcAdapter}} + */ + public abstract CoreMcAdapter getAdapter(); + + /** + * {@return the registry access of this platform's server} + */ + public RegistryAccess serverRegistryAccess() { + return server.valueOrThrow().registryAccess(); + } + public CoreMcMod getMod() { return mod; } @@ -173,6 +146,10 @@ public Registries getRegistries() { return registries; } + public CoreMcTransmogrifier getTransmogrifier() { + return transmogrifier; + } + @Override public int getDataVersion() { return SharedConstants.getCurrentVersion().dataVersion().version(); @@ -205,7 +182,7 @@ public List getWorlds() { Iterable worlds = server.valueOrThrow().getAllLevels(); List ret = new ArrayList<>(); for (ServerLevel world : worlds) { - ret.add(new CoreMcWorld(world)); + ret.add(new CoreMcWorld(this, world)); } return ret; } @@ -217,7 +194,7 @@ public Player matchPlayer(Player player) { return player; } else { ServerPlayer entity = server.valueOrThrow().getPlayerList().getPlayerByName(player.getName()); - return entity != null ? CoreMcAdapter.fromNativePlayer(entity) : null; + return entity != null ? getAdapter().fromNativePlayer(entity) : null; } } @@ -229,7 +206,7 @@ public World matchWorld(World world) { } else { for (ServerLevel ws : server.valueOrThrow().getAllLevels()) { if (((ServerLevelData) ws.getLevelData()).getLevelName().equals(world.getName())) { - return new CoreMcWorld(ws); + return new CoreMcWorld(this, ws); } } @@ -289,7 +266,7 @@ public Collection getConnectedUsers() { List users = new ArrayList<>(); PlayerList scm = server.valueOrThrow().getPlayerList(); for (ServerPlayer entity : scm.getPlayers()) { - users.add(CoreMcAdapter.fromNativePlayer(entity)); + users.add(getAdapter().fromNativePlayer(entity)); } return users; } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java index 469b4c4fb0..96b9b58cfb 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcPlayer.java @@ -20,8 +20,6 @@ package com.sk89q.worldedit.coremc.internal; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.coremc.CoreMcAdapter; -import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; import com.sk89q.worldedit.coremc.mixin.AccessorClientboundBlockEntityDataPacket; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; @@ -61,9 +59,11 @@ */ public class CoreMcPlayer extends AbstractPlayerActor { + private final CoreMcPlatform platform; private final ServerPlayer player; - public CoreMcPlayer(ServerPlayer player) { + public CoreMcPlayer(CoreMcPlatform platform, ServerPlayer player) { + this.platform = platform; this.player = player; if (getUniqueId() == null) { @@ -85,7 +85,7 @@ public BaseItemStack getItemInHand(HandSide handSide) { ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND ); - return CoreMcAdapter.fromNativeItemStack(is); + return platform.getAdapter().fromNativeItemStack(is); } @Override @@ -102,7 +102,7 @@ public BaseEntity getState() { public Location getLocation() { Vector3 position = Vector3.at(this.player.getX(), this.player.getY(), this.player.getZ()); return new Location( - CoreMcAdapter.fromNativeWorld(this.player.level()), + platform.getAdapter().fromNativeWorld(this.player.level()), position, this.player.getYRot(), this.player.getXRot() @@ -111,7 +111,7 @@ public Location getLocation() { @Override public boolean setLocation(Location location) { - ServerLevel level = CoreMcAdapter.toNativeWorld((World) location.getExtent()); + ServerLevel level = platform.getAdapter().toNativeWorld((World) location.getExtent()); this.player.teleportTo( level, location.getX(), location.getY(), location.getZ(), @@ -125,17 +125,17 @@ public boolean setLocation(Location location) { @Override public World getWorld() { - return CoreMcAdapter.fromNativeWorld(this.player.level()); + return platform.getAdapter().fromNativeWorld(this.player.level()); } @Override public void giveItem(BaseItemStack itemStack) { - this.player.getInventory().add(CoreMcAdapter.toNativeItemStack(itemStack)); + this.player.getInventory().add(platform.getAdapter().toNativeItemStack(itemStack)); } @Override public void dispatchCUIEvent(CUIEvent event) { - CoreMcPlatform.forCui().sendCUIPacket(this.player, new CUIPacket(event.getTypeId(), event.getParameters())); + platform.sendCUIPacket(this.player, new CUIPacket(event.getTypeId(), event.getParameters())); } public ServerPlayer getPlayer() { @@ -210,7 +210,7 @@ public BlockBag getInventoryBlockBag() { @Override public boolean hasPermission(String perm) { - return CoreMcPermissionsProvider.current().hasPermission(player, perm); + return platform.getPermissionsProvider().hasPermission(player, perm); } @Nullable @@ -238,7 +238,7 @@ public > void sendFakeBlock(BlockVector3 pos, B bl if (!(world instanceof CoreMcWorld coreMcWorld)) { return; } - BlockPos loc = CoreMcAdapter.toBlockPos(pos); + BlockPos loc = platform.getAdapter().toBlockPos(pos); if (block == null) { final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( coreMcWorld.getWorld(), loc @@ -247,7 +247,7 @@ public > void sendFakeBlock(BlockVector3 pos, B bl } else { final ClientboundBlockUpdatePacket packetOut = new ClientboundBlockUpdatePacket( loc, - CoreMcAdapter.toNativeBlockState(block.toImmutableState()) + platform.getAdapter().toNativeBlockState(block.toImmutableState()) ); player.connection.send(packetOut); if (block instanceof BaseBlock baseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) { diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java index d4801c2bee..e18feec9fb 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcRegistries.java @@ -31,11 +31,18 @@ */ public final class CoreMcRegistries extends BundledRegistries { - private final BlockRegistry blockRegistry = new CoreMcBlockRegistry(); + private final BlockRegistry blockRegistry; private final BiomeRegistry biomeRegistry = new CoreMcBiomeRegistry(); - private final ItemRegistry itemRegistry = new CoreMcItemRegistry(); - private final BlockCategoryRegistry blockCategoryRegistry = new CoreMcBlockCategoryRegistry(); - private final ItemCategoryRegistry itemCategoryRegistry = new CoreMcItemCategoryRegistry(); + private final ItemRegistry itemRegistry; + private final BlockCategoryRegistry blockCategoryRegistry; + private final ItemCategoryRegistry itemCategoryRegistry; + + public CoreMcRegistries(CoreMcPlatform platform) { + this.blockRegistry = new CoreMcBlockRegistry(platform); + this.itemRegistry = new CoreMcItemRegistry(platform); + this.blockCategoryRegistry = new CoreMcBlockCategoryRegistry(platform); + this.itemCategoryRegistry = new CoreMcItemCategoryRegistry(platform); + } @Override public BlockRegistry getBlockRegistry() { diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java index b0bd60bfea..9d36009e8b 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcServerLevelDelegateProxy.java @@ -21,7 +21,6 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; @@ -47,11 +46,13 @@ public final class CoreMcServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { + private final CoreMcPlatform platform; private final EditSession editSession; private final ServerLevel serverLevel; private final Map createdBlockEntities = new HashMap<>(); - private CoreMcServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel) { + private CoreMcServerLevelDelegateProxy(CoreMcPlatform platform, EditSession editSession, ServerLevel serverLevel) { + this.platform = platform; this.editSession = editSession; this.serverLevel = serverLevel; } @@ -63,8 +64,8 @@ public void close() throws MaxChangedBlocksException { } } - public static LevelAndProxy newInstance(EditSession editSession, ServerLevel serverLevel) { - CoreMcServerLevelDelegateProxy proxy = new CoreMcServerLevelDelegateProxy(editSession, serverLevel); + public static LevelAndProxy newInstance(CoreMcPlatform platform, EditSession editSession, ServerLevel serverLevel) { + CoreMcServerLevelDelegateProxy proxy = new CoreMcServerLevelDelegateProxy(platform, editSession, serverLevel); return new LevelAndProxy( (WorldGenLevel) Proxy.newProxyInstance( serverLevel.getClass().getClassLoader(), @@ -79,18 +80,18 @@ public static LevelAndProxy newInstance(EditSession editSession, ServerLevel ser private BlockEntity getBlockEntity(BlockPos blockPos) { // This doesn't synthesize or load from world. I think editing existing block entities without setting the block // (in the context of features) should not be supported in the first place. - BlockVector3 pos = CoreMcAdapter.adapt(blockPos); + BlockVector3 pos = platform.getAdapter().adapt(blockPos); return createdBlockEntities.get(pos); } private BlockState getBlockState(BlockPos blockPos) { - return CoreMcAdapter.toNativeBlockState(this.editSession.getBlockWithBuffer(CoreMcAdapter.adapt(blockPos))); + return platform.getAdapter().toNativeBlockState(this.editSession.getBlockWithBuffer(platform.getAdapter().adapt(blockPos))); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { try { handleBlockEntity(blockPos, blockState); - return editSession.setBlock(CoreMcAdapter.adapt(blockPos), CoreMcAdapter.fromNativeBlockState(blockState)); + return editSession.setBlock(platform.getAdapter().adapt(blockPos), platform.getAdapter().fromNativeBlockState(blockState)); } catch (MaxChangedBlocksException e) { throw new RuntimeException(e); } @@ -99,7 +100,7 @@ private boolean setBlock(BlockPos blockPos, BlockState blockState) { // For BlockEntity#setBlockState, not sure why it's deprecated @SuppressWarnings("deprecation") private void handleBlockEntity(BlockPos blockPos, BlockState blockState) { - BlockVector3 pos = CoreMcAdapter.adapt(blockPos); + BlockVector3 pos = platform.getAdapter().adapt(blockPos); if (blockState.hasBlockEntity()) { if (!(blockState.getBlock() instanceof EntityBlock entityBlock)) { // This will probably never happen, as Mojang's own code assumes that @@ -124,9 +125,9 @@ private boolean removeBlock(BlockPos blockPos) { } private boolean addEntity(Entity entity) { - Vector3 pos = CoreMcAdapter.adapt(entity.getPosition(0.0f)); - Location location = new Location(CoreMcAdapter.fromNativeWorld(serverLevel), pos.x(), pos.y(), pos.z()); - BaseEntity baseEntity = new CoreMcEntity(entity).getState(); + Vector3 pos = platform.getAdapter().adapt(entity.getPosition(0.0f)); + Location location = new Location(platform.getAdapter().fromNativeWorld(serverLevel), pos.x(), pos.y(), pos.z()); + BaseEntity baseEntity = new CoreMcEntity(platform, entity).getState(); return editSession.createEntity(location, baseEntity) != null; } @@ -146,7 +147,7 @@ public void close() throws MaxChangedBlocksException { ); editSession.setBlock( blockPos, - CoreMcAdapter.fromNativeBlockState(blockEntity.getBlockState()) + platform.getAdapter().fromNativeBlockState(blockEntity.getBlockState()) .toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(tag))) ); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java index c07252f016..e1945d8b4a 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcTransmogrifier.java @@ -23,7 +23,6 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.registry.state.BooleanProperty; import com.sk89q.worldedit.registry.state.DirectionalProperty; import com.sk89q.worldedit.registry.state.EnumProperty; @@ -44,7 +43,8 @@ * Raw, un-cached transformations. */ public final class CoreMcTransmogrifier { - private static final LoadingCache, Property> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<>() { + private final CoreMcPlatform platform; + private final LoadingCache, Property> propertyCache = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override public Property load(net.minecraft.world.level.block.state.properties.Property property) { return switch (property) { @@ -55,7 +55,7 @@ public Property load(net.minecraft.world.level.block.state.properties.Propert case net.minecraft.world.level.block.state.properties.EnumProperty enumProperty -> { if (property.getValueClass() == net.minecraft.core.Direction.class) { yield new DirectionalProperty(property.getName(), property.getPossibleValues().stream() - .map(v -> CoreMcAdapter.adaptEnumFacing((net.minecraft.core.Direction) v)) + .map(v -> CoreMcTransmogrifier.this.platform.getAdapter().adaptEnumFacing((net.minecraft.core.Direction) v)) .collect(ImmutableList.toImmutableList())); } yield new EnumProperty(property.getName(), enumProperty.getPossibleValues().stream() @@ -67,17 +67,21 @@ yield new EnumProperty(property.getName(), enumProperty.getPossibleValues().stre } }); - public static Property transmogToWorldEditProperty(net.minecraft.world.level.block.state.properties.Property property) { - return PROPERTY_CACHE.getUnchecked(property); + public CoreMcTransmogrifier(CoreMcPlatform platform) { + this.platform = platform; } - public static Map, Object> transmogToWorldEditProperties(BlockType block, net.minecraft.world.level.block.state.BlockState blockState) { + public Property transmogToWorldEditProperty(net.minecraft.world.level.block.state.properties.Property property) { + return propertyCache.getUnchecked(property); + } + + public Map, Object> transmogToWorldEditProperties(BlockType block, net.minecraft.world.level.block.state.BlockState blockState) { Map, Object> props = new TreeMap<>(Comparator.comparing(Property::name)); for (net.minecraft.world.level.block.state.properties.Property property : blockState.getProperties()) { Object value = blockState.getValue(property); if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { if (property.getValueClass() == net.minecraft.core.Direction.class) { - value = CoreMcAdapter.adaptEnumFacing((net.minecraft.core.Direction) value); + value = platform.getAdapter().adaptEnumFacing((net.minecraft.core.Direction) value); } else { value = ((StringRepresentable) value).getSerializedName(); } @@ -88,7 +92,7 @@ public static Map, Object> transmogToWorldEditProperties(BlockType b } @SuppressWarnings({"rawtypes", "unchecked"}) - private static net.minecraft.world.level.block.state.BlockState transmogToMinecraftProperties( + private net.minecraft.world.level.block.state.BlockState transmogToMinecraftProperties( StateDefinition stateContainer, net.minecraft.world.level.block.state.BlockState newState, Map, Object> states @@ -100,7 +104,7 @@ private static net.minecraft.world.level.block.state.BlockState transmogToMinecr if (property instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { if (property.getValueClass() == net.minecraft.core.Direction.class) { Direction dir = (Direction) value; - value = CoreMcAdapter.adapt(dir); + value = platform.getAdapter().adapt(dir); } else { String enumName = (String) value; value = ((net.minecraft.world.level.block.state.properties.EnumProperty) property).getValue((String) value).orElseThrow(() -> @@ -114,19 +118,15 @@ private static net.minecraft.world.level.block.state.BlockState transmogToMinecr return newState; } - public static net.minecraft.world.level.block.state.BlockState transmogToMinecraft(BlockState blockState) { - Block mcBlock = CoreMcAdapter.toNativeBlock(blockState.getBlockType()); + public net.minecraft.world.level.block.state.BlockState transmogToMinecraft(BlockState blockState) { + Block mcBlock = platform.getAdapter().toNativeBlock(blockState.getBlockType()); net.minecraft.world.level.block.state.BlockState newState = mcBlock.defaultBlockState(); Map, Object> states = blockState.getStates(); return transmogToMinecraftProperties(mcBlock.getStateDefinition(), newState, states); } - public static BlockState transmogToWorldEdit(net.minecraft.world.level.block.state.BlockState blockState) { - BlockType blockType = CoreMcAdapter.fromNativeBlock(blockState.getBlock()); + public BlockState transmogToWorldEdit(net.minecraft.world.level.block.state.BlockState blockState) { + BlockType blockType = platform.getAdapter().fromNativeBlock(blockState.getBlock()); return blockType.getState(transmogToWorldEditProperties(blockType, blockState)); } - - private CoreMcTransmogrifier() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java index b3a27ddda3..d8c9f7b4b1 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorld.java @@ -33,7 +33,6 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.coremc.mixin.AccessorChunkMap; import com.sk89q.worldedit.coremc.mixin.AccessorMinecraftServer; import com.sk89q.worldedit.entity.BaseEntity; @@ -145,18 +144,21 @@ private static Identifier getDimensionRegistryKey(ServerLevel world) { .getKey(world.dimensionType()); } + private final CoreMcPlatform platform; private final WeakReference worldRef; private final CoreMcWorldNativeAccess worldNativeAccess; /** * Construct a new world. * + * @param platform the owning platform * @param world the world */ - public CoreMcWorld(ServerLevel world) { + public CoreMcWorld(CoreMcPlatform platform, ServerLevel world) { checkNotNull(world); + this.platform = platform; this.worldRef = new WeakReference<>(world); - this.worldNativeAccess = new CoreMcWorldNativeAccess(worldRef); + this.worldNativeAccess = new CoreMcWorldNativeAccess(platform, worldRef); } /** @@ -199,19 +201,19 @@ public > boolean setBlock(BlockVector3 position, B @Override public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) { worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); - return Sets.intersection(CoreMcPlatform.SUPPORTED_SIDE_EFFECTS, sideEffectSet.getSideEffectsToApply()); + return Sets.intersection(platform.getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } @Override public int getBlockLightLevel(BlockVector3 position) { checkNotNull(position); - return getWorld().getMaxLocalRawBrightness(CoreMcAdapter.toBlockPos(position)); + return getWorld().getMaxLocalRawBrightness(platform.getAdapter().toBlockPos(position)); } @Override public boolean clearContainerBlockContents(BlockVector3 position) { checkNotNull(position); - BlockEntity tile = getWorld().getBlockEntity(CoreMcAdapter.toBlockPos(position)); + BlockEntity tile = getWorld().getBlockEntity(platform.getAdapter().toBlockPos(position)); if (tile instanceof Clearable clearable) { clearable.clearContent(); return true; @@ -227,7 +229,7 @@ public BiomeType getBiome(BlockVector3 position) { } private BiomeType getBiomeInChunk(BlockVector3 position, ChunkAccess chunk) { - return CoreMcAdapter.fromNativeBiome( + return platform.getAdapter().fromNativeBiome( chunk.getNoiseBiome(position.x() >> 2, position.y() >> 2, position.z() >> 2).value() ); } @@ -254,7 +256,7 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - ItemStack stack = CoreMcAdapter.toNativeItemStack(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); + ItemStack stack = platform.getAdapter().toNativeItemStack(new BaseItemStack(item.getType(), item.getNbtReference(), 1)); ServerLevel world = getWorld(); final CoreMcFakePlayer fakePlayer; try { @@ -265,9 +267,9 @@ public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); fakePlayer.absSnapTo(position.x(), position.y(), position.z(), (float) face.toVector().toYaw(), (float) face.toVector().toPitch()); - final BlockPos blockPos = CoreMcAdapter.toBlockPos(position); - final BlockHitResult rayTraceResult = new BlockHitResult(CoreMcAdapter.toVec3(position), - CoreMcAdapter.adapt(face), blockPos, false); + final BlockPos blockPos = platform.getAdapter().toBlockPos(position); + final BlockHitResult rayTraceResult = new BlockHitResult(platform.getAdapter().toVec3(position), + platform.getAdapter().adapt(face), blockPos, false); UseOnContext itemUseContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTraceResult); InteractionResult used = stack.useOn(itemUseContext); if (!used.consumesAction()) { @@ -288,20 +290,20 @@ public void dropItem(Vector3 position, BaseItemStack item) { return; } - ItemEntity entity = new ItemEntity(getWorld(), position.x(), position.y(), position.z(), CoreMcAdapter.toNativeItemStack(item)); + ItemEntity entity = new ItemEntity(getWorld(), position.x(), position.y(), position.z(), platform.getAdapter().toNativeItemStack(item)); entity.setPickUpDelay(10); getWorld().addFreshEntity(entity); } @Override public void simulateBlockMine(BlockVector3 position) { - BlockPos pos = CoreMcAdapter.toBlockPos(position); + BlockPos pos = platform.getAdapter().toBlockPos(position); getWorld().destroyBlock(pos, true); } @Override public boolean canPlaceAt(BlockVector3 position, BlockState blockState) { - return CoreMcAdapter.toNativeBlockState(blockState).canSurvive(getWorld(), CoreMcAdapter.toBlockPos(position)); + return platform.getAdapter().toNativeBlockState(blockState).canSurvive(getWorld(), platform.getAdapter().toBlockPos(position)); } @Override @@ -376,9 +378,9 @@ private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld } for (BlockVector3 vec : region) { - BlockPos pos = CoreMcAdapter.toBlockPos(vec); + BlockPos pos = platform.getAdapter().toBlockPos(vec); ChunkAccess chunk = chunks.get(ChunkPos.containing(pos)); - BlockStateHolder state = CoreMcAdapter.fromNativeBlockState(chunk.getBlockState(pos)); + BlockStateHolder state = platform.getAdapter().fromNativeBlockState(chunk.getBlockState(pos)); BlockEntity blockEntity = chunk.getBlockEntity(pos); if (blockEntity != null) { CompoundTag tag = CoreMcLoggingProblemReporter.with( @@ -460,10 +462,10 @@ public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession if (type == TreeGenerator.TreeType.CHORUS_PLANT) { position = position.add(0, 1, 0); } - try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(platform, editSession, world)) { return generator != null && generator.place( proxyLevel.level(), chunkManager.getGenerator(), random, - CoreMcAdapter.toBlockPos(position) + platform.getAdapter().toBlockPos(position) ); } } @@ -477,10 +479,10 @@ public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 ServerLevel world = getWorld(); PlacedFeature generator = world.registryAccess().lookupOrThrow(Registries.PLACED_FEATURE).getValue(Identifier.tryParse(type.id())); ServerChunkCache chunkManager = world.getChunkSource(); - try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(platform, editSession, world)) { return generator != null && generator.place( proxyLevel.level(), chunkManager.getGenerator(), random, - CoreMcAdapter.toBlockPos(position) + platform.getAdapter().toBlockPos(position) ); } } @@ -490,10 +492,10 @@ public boolean generateFeature(ConfiguredFeatureType type, EditSession editSessi ServerLevel world = getWorld(); ConfiguredFeature feature = world.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(Identifier.tryParse(type.id())); ServerChunkCache chunkManager = world.getChunkSource(); - try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(platform, editSession, world)) { return feature != null && feature.place( proxyLevel.level(), chunkManager.getGenerator(), random, - CoreMcAdapter.toBlockPos(position) + platform.getAdapter().toBlockPos(position) ); } catch (MaxChangedBlocksException e) { throw new RuntimeException(e); @@ -510,7 +512,7 @@ public boolean generateStructure(StructureType type, EditSession editSession, Bl } ServerChunkCache chunkManager = world.getChunkSource(); - try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(editSession, world)) { + try (CoreMcServerLevelDelegateProxy.LevelAndProxy proxyLevel = CoreMcServerLevelDelegateProxy.newInstance(platform, editSession, world)) { ChunkPos chunkPos = ChunkPos.containing(new BlockPos(position.x(), position.y(), position.z())); StructureStart structureStart = structure.generate( structureRegistry.wrapAsHolder(structure), world.dimension(), world.registryAccess(), @@ -542,7 +544,7 @@ public boolean generateStructure(StructureType type, EditSession editSession, Bl @Override public void checkLoadedChunk(BlockVector3 pt) { - getWorld().getChunk(CoreMcAdapter.toBlockPos(pt)); + getWorld().getChunk(platform.getAdapter().toBlockPos(pt)); } @Override @@ -633,15 +635,15 @@ public int getMaxY() { @Override public BlockVector3 getSpawnPosition() { - return CoreMcAdapter.adapt(getWorld().getLevelData().getRespawnData().pos()); + return platform.getAdapter().adapt(getWorld().getLevelData().getRespawnData().pos()); } @Override public BlockState getBlock(BlockVector3 position) { net.minecraft.world.level.block.state.BlockState mcState = getWorld() .getChunk(position.x() >> 4, position.z() >> 4) - .getBlockState(CoreMcAdapter.toBlockPos(position)); - return CoreMcAdapter.fromNativeBlockState(mcState); + .getBlockState(platform.getAdapter().toBlockPos(position)); + return platform.getAdapter().fromNativeBlockState(mcState); } @Override @@ -687,16 +689,16 @@ public boolean equals(Object o) { public List getEntities(Region region) { final ServerLevel world = getWorld(); AABB box = new AABB( - CoreMcAdapter.toVec3(region.getMinimumPoint()), - CoreMcAdapter.toVec3(region.getMaximumPoint().add(BlockVector3.ONE)) + platform.getAdapter().toVec3(region.getMinimumPoint()), + platform.getAdapter().toVec3(region.getMaximumPoint().add(BlockVector3.ONE)) ); List nmsEntities = world.getEntities( (net.minecraft.world.entity.Entity) null, box, - e -> region.contains(CoreMcAdapter.adapt(e.blockPosition())) + e -> region.contains(platform.getAdapter().adapt(e.blockPosition())) ); return nmsEntities.stream() - .map(CoreMcEntity::new) + .map(e -> new CoreMcEntity(platform, e)) .collect(ImmutableList.toImmutableList()); } @@ -704,7 +706,7 @@ public List getEntities(Region region) { public List getEntities() { final ServerLevel world = getWorld(); return Streams.stream(world.getAllEntities()) - .map(entity -> new CoreMcEntity(entity)) + .map(entity -> new CoreMcEntity(platform, entity)) .collect(ImmutableList.toImmutableList()); } @@ -733,7 +735,7 @@ public Entity createEntity(Location location, BaseEntity entity) { }); if (createdEntity != null) { world.addFreshEntityWithPassengers(createdEntity); - return new CoreMcEntity(createdEntity); + return new CoreMcEntity(platform, createdEntity); } return null; } @@ -756,7 +758,7 @@ public Mask createLiquidMask() { return new AbstractExtentMask(this) { @Override public boolean test(BlockVector3 vector) { - return CoreMcAdapter.toNativeBlockState(getExtent().getBlock(vector)).getBlock() instanceof LiquidBlock; + return platform.getAdapter().toNativeBlockState(getExtent().getBlock(vector)).getBlock() instanceof LiquidBlock; } }; } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java index f1e34f8a3d..63466108b1 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcWorldNativeAccess.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.coremc.internal; -import com.sk89q.worldedit.coremc.CoreMcAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.util.SideEffect; @@ -40,10 +39,12 @@ import javax.annotation.Nullable; public final class CoreMcWorldNativeAccess implements WorldNativeAccess { + private final CoreMcPlatform platform; private final WeakReference world; private SideEffectSet sideEffectSet; - public CoreMcWorldNativeAccess(WeakReference world) { + public CoreMcWorldNativeAccess(CoreMcPlatform platform, WeakReference world) { + this.platform = platform; this.world = world; } @@ -66,7 +67,7 @@ public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { int stateId = BlockStateIdAccess.getBlockStateId(state); return BlockStateIdAccess.isValidInternalId(stateId) ? Block.stateById(stateId) - : CoreMcAdapter.toNativeBlockState(state); + : platform.getAdapter().toNativeBlockState(state); } @Override @@ -174,6 +175,6 @@ public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newSta @Override public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { getWorld().updatePOIOnBlockStateChange(pos, oldState, newState); - CoreMcPlatform.forWorldEditing().extraOnBlockStateChange(getWorld(), pos, oldState, newState); + platform.extraOnBlockStateChange(getWorld(), pos, oldState, newState); } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java index 1287dd73a4..3cfb931060 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/mixin/MixinServerGamePacketListenerImpl.java @@ -20,7 +20,12 @@ package com.sk89q.worldedit.coremc.mixin; import com.google.errorprone.annotations.Keep; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.util.lifecycle.ConstantLifecycled; +import com.sk89q.worldedit.util.lifecycle.Lifecycled; +import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.network.protocol.game.ServerboundSwingPacket; import net.minecraft.server.level.ServerPlayer; @@ -34,6 +39,18 @@ @Mixin(ServerGamePacketListenerImpl.class) public class MixinServerGamePacketListenerImpl { + + @Unique + private static final Lifecycled WORLD_EDITING_PLATFORM = WorldEdit.getInstance().getPlatformManager() + .getPreferred(Capability.WORLD_EDITING) + .flatMap(platform -> { + if (platform instanceof CoreMcPlatform coreMcPlatform) { + return new ConstantLifecycled<>(coreMcPlatform); + } else { + return SimpleLifecycled.invalid(); + } + }); + @Shadow public ServerPlayer player; @@ -50,7 +67,7 @@ private void onAnimate(ServerboundSwingPacket packet, @SuppressWarnings("UnusedV if (this.ignoreSwingPackets > 0) { this.ignoreSwingPackets--; } else { - CoreMcPlatform.optionallyForWorldEditing().ifPresent(platform -> + WORLD_EDITING_PLATFORM.value().ifPresent(platform -> platform.getMod().onLeftClickAir(this.player, packet.getHand()) ); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java new file mode 100644 index 0000000000..5d6481d8ea --- /dev/null +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java @@ -0,0 +1,47 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.fabric; + +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.fabric.internal.FabricWorldEdit; + +/** + * Public API to adapt between WorldEdit and Fabric. + */ +public final class FabricAdapter extends CoreMcAdapter { + + private static final FabricAdapter INSTANCE = new FabricAdapter(); + + /** + * {@return the Fabric adapter} + */ + public static FabricAdapter get() { + return INSTANCE; + } + + private FabricAdapter() { + } + + @Override + protected CoreMcPlatform getPlatform() { + return FabricWorldEdit.getPlatform(); + } +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPlatform.java similarity index 91% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPlatform.java index a340aaddb6..a27de5a38e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricPlatform.java @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.fabric.FabricAdapter; import com.sk89q.worldedit.util.lifecycle.Lifecycled; import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -41,6 +42,11 @@ private static Lifecycled createMinecraftServerLifecycled() { super(mod, createMinecraftServerLifecycled()); } + @Override + public FabricAdapter getAdapter() { + return FabricAdapter.get(); + } + @Override public void sendCUIPacket(ServerPlayer player, CUIPacket packet) { ServerPlayNetworking.send(player, packet); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java similarity index 92% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java index f647bcc339..22e33022f3 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorldEdit.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; import com.sk89q.worldedit.coremc.internal.CoreMcMod; @@ -52,6 +52,16 @@ public class FabricWorldEdit extends CoreMcMod implements ModInitializer { public static FabricWorldEdit inst; + private static volatile CoreMcPlatform PLATFORM; + + public static CoreMcPlatform getPlatform() { + CoreMcPlatform platform = PLATFORM; + if (platform == null) { + throw new IllegalStateException("FabricWorldEdit is not initialized"); + } + return platform; + } + private ModContainer container; public FabricWorldEdit() { @@ -64,7 +74,8 @@ public void onInitialize() { () -> new IllegalStateException("WorldEdit mod missing in Fabric") ); - init(new FabricPlatform(this), FabricLoader.getInstance().getConfigDir()); + PLATFORM = new FabricPlatform(this); + init(PLATFORM, FabricLoader.getInstance().getConfigDir()); CUIPacketHandler.instance().registerServerboundHandler(this::onCuiPacket); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java similarity index 97% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java index f1234c1dcc..5fb3aee351 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/LuckoFabricPermissionsProvider.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; diff --git a/worldedit-fabric/src/main/resources/fabric.mod.json b/worldedit-fabric/src/main/resources/fabric.mod.json index 8a7e826f9d..b3c5080b90 100644 --- a/worldedit-fabric/src/main/resources/fabric.mod.json +++ b/worldedit-fabric/src/main/resources/fabric.mod.json @@ -26,7 +26,7 @@ "environment": "*", "entrypoints": { "main": [ - "com.sk89q.worldedit.fabric.FabricWorldEdit" + "com.sk89q.worldedit.fabric.internal.FabricWorldEdit" ] }, diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java new file mode 100644 index 0000000000..39a5dca62d --- /dev/null +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeAdapter.java @@ -0,0 +1,47 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.neoforge; + +import com.sk89q.worldedit.coremc.CoreMcAdapter; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.neoforge.internal.NeoForgeWorldEdit; + +/** + * Public API to adapt between WorldEdit and NeoForge. + */ +public final class NeoForgeAdapter extends CoreMcAdapter { + + private static final NeoForgeAdapter INSTANCE = new NeoForgeAdapter(); + + /** + * {@return the NeoForge adapter} + */ + public static NeoForgeAdapter get() { + return INSTANCE; + } + + private NeoForgeAdapter() { + } + + @Override + protected CoreMcPlatform getPlatform() { + return NeoForgeWorldEdit.getPlatform(); + } +} diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePlatform.java similarity index 93% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java rename to worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePlatform.java index 86fd6fbe4f..257e418e42 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgePlatform.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgePlatform.java @@ -17,10 +17,11 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.neoforge.internal; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; +import com.sk89q.worldedit.neoforge.NeoForgeAdapter; import com.sk89q.worldedit.util.io.ResourceLoader; import com.sk89q.worldedit.util.lifecycle.Lifecycled; import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled; @@ -52,6 +53,11 @@ private static Lifecycled createMinecraftServerLifecycled() { super(mod, createMinecraftServerLifecycled()); } + @Override + public NeoForgeAdapter getAdapter() { + return NeoForgeAdapter.get(); + } + @Override public void sendCUIPacket(ServerPlayer player, CUIPacket packet) { PacketDistributor.sendToPlayer(player, packet); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeResourceLoader.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeResourceLoader.java similarity index 97% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeResourceLoader.java rename to worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeResourceLoader.java index 57dda7565f..dc944ea693 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeResourceLoader.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeResourceLoader.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.neoforge.internal; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.util.io.WorldEditResourceLoader; diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldEdit.java similarity index 91% rename from worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java rename to worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldEdit.java index 7c4ab8d987..5050da61a4 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/NeoForgeWorldEdit.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeWorldEdit.java @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.neoforge; +package com.sk89q.worldedit.neoforge.internal; import com.sk89q.worldedit.coremc.internal.CoreMcMod; +import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.coremc.internal.ThreadSafeCache; import com.sk89q.worldedit.internal.util.LogManagerCompat; import net.neoforged.bus.api.IEventBus; @@ -52,13 +53,19 @@ public class NeoForgeWorldEdit extends CoreMcMod { private static final Logger LOGGER = LogManagerCompat.getLogger(); public static final String MOD_ID = "worldedit"; - public static NeoForgeWorldEdit inst; + private static volatile CoreMcPlatform PLATFORM; + + public static CoreMcPlatform getPlatform() { + CoreMcPlatform platform = PLATFORM; + if (platform == null) { + throw new IllegalStateException("NeoForgeWorldEdit is not initialized"); + } + return platform; + } private ModContainer container; public NeoForgeWorldEdit(IEventBus modBus) { - inst = this; - modBus.addListener(this::onFMLCommonSetup); NeoForge.EVENT_BUS.register(new EventHandler(this)); @@ -67,7 +74,8 @@ public NeoForgeWorldEdit(IEventBus modBus) { private void onFMLCommonSetup(FMLCommonSetupEvent event) { this.container = ModLoadingContext.get().getActiveContainer(); - init(new NeoForgePlatform(this), FMLPaths.CONFIGDIR.get()); + PLATFORM = new NeoForgePlatform(this); + init(PLATFORM, FMLPaths.CONFIGDIR.get()); CUIPacketHandler.instance().registerServerboundHandler(this::onCuiPacket); From a143c971e2bfddf1f73e64cf455b1160671764b3 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Mon, 20 Apr 2026 00:26:40 -0700 Subject: [PATCH 4/4] [coremc] Clean up exposure of internals --- .../sk89q/worldedit/coremc/CoreMcAdapter.java | 3 +- .../coremc/CoreMcPermissionsProvider.java | 23 ---------- .../worldedit/coremc/internal/CoreMcMod.java | 24 +++++----- .../internal/VanillaPermissionsProvider.java | 44 +++++++++++++++++++ .../fabric/internal/FabricWorldEdit.java | 6 ++- .../LuckoFabricPermissionsProvider.java | 14 +++--- 6 files changed, 71 insertions(+), 43 deletions(-) create mode 100644 worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/VanillaPermissionsProvider.java diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java index eb1d05cec9..913701596d 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcAdapter.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.coremc.internal.CoreMcWorld; import com.sk89q.worldedit.coremc.internal.NBTConverter; import com.sk89q.worldedit.coremc.mixin.AccessorCommandSourceStack; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector3; @@ -228,7 +229,7 @@ public BaseItemStack fromNativeItemStack(ItemStack itemStack) { * @param player the player * @return the WorldEdit player */ - public CoreMcPlayer fromNativePlayer(ServerPlayer player) { + public Player fromNativePlayer(ServerPlayer player) { checkNotNull(player); return new CoreMcPlayer(getPlatform(), player); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java index 0c7c758985..b8f6619150 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/CoreMcPermissionsProvider.java @@ -20,12 +20,10 @@ package com.sk89q.worldedit.coremc; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.coremc.internal.CoreMcConfiguration; import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.GameType; import org.jspecify.annotations.NonNull; public interface CoreMcPermissionsProvider { @@ -64,25 +62,4 @@ static void setCurrent(CoreMcPermissionsProvider provider) { boolean hasPermission(ServerPlayer player, String permission); void registerPermission(String permission); - - class VanillaPermissionsProvider implements CoreMcPermissionsProvider { - - private final CoreMcPlatform platform; - - public VanillaPermissionsProvider(CoreMcPlatform platform) { - this.platform = platform; - } - - @Override - public boolean hasPermission(ServerPlayer player, String permission) { - CoreMcConfiguration configuration = platform.getConfiguration(); - return configuration.cheatMode - || player.level().getServer().getPlayerList().isOp(player.nameAndId()) - || (configuration.creativeEnable && player.gameMode.getGameModeForPlayer() == GameType.CREATIVE); - } - - @Override - public void registerPermission(String permission) { - } - } } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java index 709f769a80..e86bd55427 100644 --- a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/CoreMcMod.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.event.platform.PlatformUnreadyEvent; @@ -57,7 +58,6 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.feature.CoralTreeFeature; import net.minecraft.world.level.levelgen.feature.FallenTreeFeature; @@ -89,7 +89,7 @@ public abstract class CoreMcMod { protected abstract String getInternalVersion(); protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform platform) { - return new CoreMcPermissionsProvider.VanillaPermissionsProvider(platform); + return new VanillaPermissionsProvider(platform); } protected final void init(CoreMcPlatform platform, Path gameConfigDir) { @@ -254,7 +254,7 @@ private boolean skipEvents() { return platform == null || !platform.isHookingEvents(); } - private boolean skipInteractionEvent(Player player, InteractionHand hand) { + private boolean skipInteractionEvent(net.minecraft.world.entity.player.Player player, InteractionHand hand) { return skipEvents() || hand != InteractionHand.MAIN_HAND || player.level().isClientSide() || !(player instanceof ServerPlayer); } @@ -264,7 +264,7 @@ public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { } WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = platform.getAdapter().fromNativePlayer(playerEntity); + Player player = platform.getAdapter().fromNativePlayer(playerEntity); Optional previousResult = debouncer.getDuplicateInteractionResult(player); if (previousResult.isPresent()) { @@ -275,14 +275,14 @@ public void onLeftClickAir(ServerPlayer playerEntity, InteractionHand hand) { debouncer.setLastInteraction(player, result); } - protected boolean onLeftClickBlock(Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { + protected boolean onLeftClickBlock(net.minecraft.world.entity.player.Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { if (skipInteractionEvent(playerEntity, hand)) { return false; } ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); + Player player = platform.getAdapter().fromNativePlayer(serverPlayer); CoreMcWorld world = (CoreMcWorld) platform.getAdapter().fromNativeWorld(serverPlayer.level()); Direction direction = platform.getAdapter().adaptEnumFacing(face); @@ -294,14 +294,14 @@ protected boolean onLeftClickBlock(Player playerEntity, InteractionHand hand, Bl return result; } - protected boolean onRightClickBlock(Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { + protected boolean onRightClickBlock(net.minecraft.world.entity.player.Player playerEntity, InteractionHand hand, BlockPos blockPos, net.minecraft.core.Direction face) { if (skipInteractionEvent(playerEntity, hand)) { return false; } ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); + Player player = platform.getAdapter().fromNativePlayer(serverPlayer); CoreMcWorld world = (CoreMcWorld) platform.getAdapter().fromNativeWorld(serverPlayer.level()); Direction direction = platform.getAdapter().adaptEnumFacing(face); @@ -313,14 +313,14 @@ protected boolean onRightClickBlock(Player playerEntity, InteractionHand hand, B return result; } - protected Optional onRightClickItem(Player playerEntity, InteractionHand hand) { + protected Optional onRightClickItem(net.minecraft.world.entity.player.Player playerEntity, InteractionHand hand) { if (skipInteractionEvent(playerEntity, hand)) { return Optional.empty(); } ServerPlayer serverPlayer = (ServerPlayer) playerEntity; WorldEdit we = WorldEdit.getInstance(); - CoreMcPlayer player = platform.getAdapter().fromNativePlayer(serverPlayer); + Player player = platform.getAdapter().fromNativePlayer(serverPlayer); Optional previousResult = debouncer.getDuplicateInteractionResult(player); if (previousResult.isPresent()) { @@ -333,7 +333,7 @@ protected Optional onRightClickItem(Player playerEntity, InteractionHan return Optional.of(result); } - protected void onPlayerDisconnect(Player playerEntity) { + protected void onPlayerDisconnect(net.minecraft.world.entity.player.Player playerEntity) { if (!(playerEntity instanceof ServerPlayer player)) { return; } @@ -347,7 +347,7 @@ protected void onCuiPacket(CUIPacket payload, CUIPacketHandler.PacketContext con if (!(context.player() instanceof ServerPlayer player)) { return; } - CoreMcPlayer actor = platform.getAdapter().fromNativePlayer(player); + Player actor = platform.getAdapter().fromNativePlayer(player); LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); session.handleCUIInitializationMessage(payload.eventType(), payload.args(), actor); } diff --git a/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/VanillaPermissionsProvider.java b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/VanillaPermissionsProvider.java new file mode 100644 index 0000000000..d26b84c55c --- /dev/null +++ b/worldedit-core-mc/src/main/java/com/sk89q/worldedit/coremc/internal/VanillaPermissionsProvider.java @@ -0,0 +1,44 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.coremc.internal; + +import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.GameType; + +final class VanillaPermissionsProvider implements CoreMcPermissionsProvider { + private final CoreMcPlatform platform; + + VanillaPermissionsProvider(CoreMcPlatform platform) { + this.platform = platform; + } + + @Override + public boolean hasPermission(ServerPlayer player, String permission) { + CoreMcConfiguration configuration = platform.getConfiguration(); + return configuration.cheatMode + || player.level().getServer().getPlayerList().isOp(player.nameAndId()) + || (configuration.creativeEnable && player.gameMode.getGameModeForPlayer() == GameType.CREATIVE); + } + + @Override + public void registerPermission(String permission) { + } +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java index 22e33022f3..0a16849f99 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldEdit.java @@ -112,6 +112,8 @@ protected String getInternalVersion() { @Override protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform platform) { + CoreMcPermissionsProvider provider = super.createPermissionsProvider(platform); + try { Class.forName("me.lucko.fabric.api.permissions.v0.Permissions", false, getClass().getClassLoader()); Optional version = FabricLoader.getInstance().getModContainer("fabric-permissions-api-v0") @@ -122,7 +124,7 @@ protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform pla throw new RuntimeException("Fabric permissions version " + version.get() + " is not supported. Please update Fabric Permissions API"); } - return new LuckoFabricPermissionsProvider(platform); + provider = new LuckoFabricPermissionsProvider(provider); } catch (ClassNotFoundException ignored) { // fallback to vanilla } catch (Exception e) { @@ -130,6 +132,6 @@ protected CoreMcPermissionsProvider createPermissionsProvider(CoreMcPlatform pla LOGGER.warn("Failed to load Fabric permissions provider. Falling back to Minecraft", e); } - return super.createPermissionsProvider(platform); + return provider; } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java index 5fb3aee351..a018a9e575 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/LuckoFabricPermissionsProvider.java @@ -20,19 +20,23 @@ package com.sk89q.worldedit.fabric.internal; import com.sk89q.worldedit.coremc.CoreMcPermissionsProvider; -import com.sk89q.worldedit.coremc.internal.CoreMcPlatform; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.level.ServerPlayer; -final class LuckoFabricPermissionsProvider extends CoreMcPermissionsProvider.VanillaPermissionsProvider { +final class LuckoFabricPermissionsProvider implements CoreMcPermissionsProvider { + private final CoreMcPermissionsProvider fallback; - LuckoFabricPermissionsProvider(CoreMcPlatform platform) { - super(platform); + LuckoFabricPermissionsProvider(CoreMcPermissionsProvider fallback) { + this.fallback = fallback; } @Override public boolean hasPermission(ServerPlayer player, String permission) { return Permissions.getPermissionValue(player, permission) - .orElseGet(() -> super.hasPermission(player, permission)); + .orElseGet(() -> fallback.hasPermission(player, permission)); + } + + @Override + public void registerPermission(String permission) { } }