Merge branch 'IntellectualSites:main' into main

This commit is contained in:
Telesphoreo 2024-05-20 10:40:17 -05:00 committed by GitHub
commit eb204998e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 1888 additions and 1457 deletions

View File

@ -27,10 +27,9 @@ body:
description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first.
multiple: false multiple: false
options: options:
- '1.20.4' - '1.20.5/6'
- '1.20' - '1.20'
- '1.19.4' - '1.19.4'
- '1.18.2'
validations: validations:
required: true required: true

View File

@ -17,7 +17,7 @@ jobs:
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
java-version: 17 java-version: 21
- name: Build on ${{ matrix.os }} - name: Build on ${{ matrix.os }}
run: ./gradlew build -s run: ./gradlew build -s
- name: Archive artifacts - name: Archive artifacts

View File

@ -17,7 +17,7 @@ jobs:
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
java-version: 17 java-version: 21
- name: Clean Build - name: Clean Build
run: ./gradlew clean build --no-daemon run: ./gradlew clean build --no-daemon
- name: Determine release status - name: Determine release status

View File

@ -25,7 +25,7 @@ jobs:
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
java-version: 17 java-version: 21
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3
with: with:

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Label conflicting PRs - name: Label conflicting PRs
uses: eps1lon/actions-label-merge-conflict@v3.0.0 uses: eps1lon/actions-label-merge-conflict@v3.0.1
with: with:
dirtyLabel: "unresolved-merge-conflict" dirtyLabel: "unresolved-merge-conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}" repoToken: "${{ secrets.GITHUB_TOKEN }}"

View File

@ -15,7 +15,7 @@ jobs:
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
java-version: 17 java-version: 21
- name: Clean Build - name: Clean Build
run: ./gradlew clean build --no-daemon run: ./gradlew clean build --no-daemon
- name: Upload Release Assets - name: Upload Release Assets

View File

@ -3,12 +3,12 @@
= Compiling = Compiling
You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed, You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 21 installed. Gradle will download JDK 21 specifically if needed,
but it needs some version of Java to bootstrap from. but it needs some version of Java to bootstrap from.
Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 17. Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 21.
You can get the JDK 17 link:https://adoptium.net/[here] from Adoptium. You can get the JDK 21 link:https://adoptium.net/[here] from Adoptium.
The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules: The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules:

2
Jenkinsfile vendored
View File

@ -7,7 +7,7 @@ pipeline {
stage('Build') { stage('Build') {
steps { steps {
withEnv([ withEnv([
"PATH+JAVA=${tool 'Temurin-17.0.7_7'}/bin" "PATH+JAVA=${tool 'Temurin-21.0.3_9'}/bin"
]) { ]) {
sh './gradlew clean build' sh './gradlew clean build'
} }

View File

@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer
plugins { plugins {
id("io.github.gradle-nexus.publish-plugin") version "2.0.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
id("xyz.jpenilla.run-paper") version "2.2.3" id("xyz.jpenilla.run-paper") version "2.3.0"
} }
if (!File("$rootDir/.git").exists()) { if (!File("$rootDir/.git").exists()) {
@ -34,7 +34,7 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("2.9.3") var rootVersion by extra("2.10.1")
var snapshot by extra("SNAPSHOT") var snapshot by extra("SNAPSHOT")
var revision: String by extra("") var revision: String by extra("")
var buildNumber by extra("") var buildNumber by extra("")
@ -83,7 +83,7 @@ allprojects {
} }
applyCommonConfiguration() applyCommonConfiguration()
val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") val supportedVersions = listOf("1.19.4", "1.20", "1.20.4", "1.20.5", "1.20.6")
tasks { tasks {
supportedVersions.forEach { supportedVersions.forEach {

View File

@ -28,11 +28,23 @@ dependencies {
implementation(gradleApi()) implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
implementation("com.github.johnrengelman:shadow:8.1.1") implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.15") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.1")
constraints {
val asmVersion = "[9.7,)"
implementation("org.ow2.asm:asm:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.ow2.asm:asm-commons:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.vafer:jdependency:[2.10,)") {
because("Need Java 21 support in shadow")
}
}
} }
kotlin { kotlin {
jvmToolchain { jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17)) (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(21))
} }
} }

View File

@ -37,7 +37,7 @@ fun Project.applyCommonConfiguration() {
plugins.withId("java") { plugins.withId("java") {
the<JavaPluginExtension>().toolchain { the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(17)) languageVersion.set(JavaLanguageVersion.of(21))
} }
} }

View File

@ -21,7 +21,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
.matching { it.name == "compileJava" || it.name == "compileTestJava" } .matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach { .configureEach {
val disabledLint = listOf( val disabledLint = listOf(
"processing", "path", "fallthrough", "serial" "processing", "path", "fallthrough", "serial", "overloads", "this-escape",
) )
options.release.set(17) options.release.set(17)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
@ -31,7 +31,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
} }
configurations.all { configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
} }
tasks.withType<Test>().configureEach { tasks.withType<Test>().configureEach {
@ -61,7 +61,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
"https://jd.advntr.dev/api/latest/", "https://jd.advntr.dev/api/latest/",
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
"https://www.antlr.org/api/Java/", "https://www.antlr.org/api/Java/",
"https://jd.papermc.io/paper/1.20/", "https://jd.papermc.io/paper/1.20.6/",
"https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/"
) )
docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}"

View File

@ -122,7 +122,7 @@ fun Project.applyLibrariesConfiguration() {
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
} }
outgoing.artifact(tasks.named("jar")) outgoing.artifact(tasks.named("jar"))
} }
@ -137,7 +137,7 @@ fun Project.applyLibrariesConfiguration() {
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
} }
outgoing.artifact(tasks.named("jar")) outgoing.artifact(tasks.named("jar"))
} }

View File

@ -1,6 +1,6 @@
[versions] [versions]
# Minecraft expectations # Minecraft expectations
paper = "1.20.4-R0.1-SNAPSHOT" paper = "1.20.6-R0.1-SNAPSHOT"
fastutil = "8.5.9" fastutil = "8.5.9"
guava = "31.1-jre" guava = "31.1-jre"
log4j = "2.19.0" log4j = "2.19.0"
@ -9,25 +9,25 @@ snakeyaml = "2.0"
# Plugins # Plugins
dummypermscompat = "1.10" dummypermscompat = "1.10"
worldguard-bukkit = "7.0.9" worldguard-bukkit = "7.0.10"
mapmanager = "1.8.0-SNAPSHOT" mapmanager = "1.8.0-SNAPSHOT"
griefprevention = "17.0.0" griefprevention = "17.0.0"
griefdefender = "2.1.0-SNAPSHOT" griefdefender = "2.1.0-SNAPSHOT"
residence = "4.5._13.1" residence = "4.5._13.1"
towny = "0.100.2.3" towny = "0.100.2.9"
plotsquared = "7.3.8" plotsquared = "7.3.8"
# Third party # Third party
bstats = "3.0.2" bstats = "3.0.2"
sparsebitset = "1.3" sparsebitset = "1.3"
parallelgzip = "1.0.5" parallelgzip = "1.0.5"
adventure = "4.16.0" adventure = "4.17.0"
adventure-bukkit = "4.3.2" adventure-bukkit = "4.3.2"
checkerqual = "3.42.0" checkerqual = "3.43.0"
truezip = "6.8.4" truezip = "6.8.4"
auto-value = "1.10.4" auto-value = "1.10.4"
findbugs = "3.0.2" findbugs = "3.0.2"
rhino-runtime = "1.7.14" rhino-runtime = "1.7.15"
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
antlr4 = "4.13.1" antlr4 = "4.13.1"
json-simple = "1.1.1" json-simple = "1.1.1"
@ -35,7 +35,7 @@ jlibnoise = "1.0.0"
jchronic = "0.2.4a" jchronic = "0.2.4a"
lz4-java = "1.8.0" lz4-java = "1.8.0"
lz4-stream = "1.0.0" lz4-stream = "1.0.0"
commons-cli = "1.6.0" commons-cli = "1.7.0"
paperlib = "1.0.8" paperlib = "1.0.8"
paster = "1.1.6" paster = "1.1.6"
vault = "1.7.1" vault = "1.7.1"
@ -46,7 +46,7 @@ text = "3.0.4"
piston = "0.5.10" piston = "0.5.10"
# Tests # Tests
mockito = "5.11.0" mockito = "5.12.0"
# Gradle plugins # Gradle plugins
pluginyml = "0.6.0" pluginyml = "0.6.0"

View File

@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit"
include("worldedit-libs") include("worldedit-libs")
listOf("1_18_2", "1_19_4", "1_20", "1_20_2", "1_20_4").forEach { listOf("1_19_4", "1_20", "1_20_2", "1_20_4", "1_20_5").forEach {
include("worldedit-bukkit:adapters:adapter-$it") include("worldedit-bukkit:adapters:adapter-$it")
} }

View File

@ -12,6 +12,6 @@ repositories {
dependencies { dependencies {
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240420.200855-173") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240424.165410-174")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

View File

@ -58,7 +58,6 @@ import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_20_R3.CraftChunk; import org.bukkit.craftbukkit.v1_20_R3.CraftChunk;
import sun.misc.Unsafe;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@ -11,7 +11,7 @@ repositories {
} }
dependencies { dependencies {
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.18.2-R0.1-SNAPSHOT // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.18.2-R0.1-20220920.010157-167") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240520.005421-60")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

View File

@ -17,24 +17,23 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightPlatformAdapter;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
@ -81,14 +80,20 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Holder;
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.nbt.Tag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.level.progress.ChunkProgressListener;
@ -112,10 +117,10 @@ import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@ -124,13 +129,13 @@ import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R2.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
@ -155,7 +160,6 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -166,33 +170,28 @@ import static com.google.common.base.Preconditions.checkState;
public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> { public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> {
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( private static final Codec<DataComponentPatch> COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf(
SideEffect.NEIGHBORS, "components", DataComponentPatch.EMPTY
SideEffect.LIGHTING, ).codec();
SideEffect.VALIDATION,
SideEffect.ENTITY_AI, private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
SideEffect.EVENTS,
SideEffect.UPDATE
);
private final Field serverWorldsField; private final Field serverWorldsField;
private final Method getChunkFutureMethod; private final Method getChunkFutureMethod;
private final Field chunkProviderExecutorField; private final Field chunkProviderExecutorField;
private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName()); private final Watchdog watchdog;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // Code that may break between versions of Minecraft
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
private final Watchdog watchdog;
private final LoadingCache<ServerLevel, PaperweightFakePlayer> fakePlayers
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException { public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException {
// A simple test // A simple test
CraftServer.class.cast(Bukkit.getServer()); CraftServer.class.cast(Bukkit.getServer());
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
if (dataVersion != 2975) { if (dataVersion != 3837 && dataVersion != 3839) {
throw new UnsupportedClassVersionError("Not 1.18.2!"); throw new UnsupportedClassVersionError("Not 1.20.(5/6)!");
} }
serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField = CraftServer.class.getDeclaredField("worlds");
@ -209,7 +208,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
); );
chunkProviderExecutorField.setAccessible(true); chunkProviderExecutorField.setAccessible(true);
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized();
Watchdog watchdog; Watchdog watchdog;
try { try {
@ -231,6 +230,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
} }
@Override
public DataFixer getDataFixer() {
return PaperweightDataConverters.INSTANCE;
}
/** /**
* Read the given NBT data into the given tile entity. * Read the given NBT data into the given tile entity.
* *
@ -238,7 +242,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @param tag the tag * @param tag the tag
*/ */
static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) { static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) {
tileEntity.load(tag); tileEntity.loadWithComponents(tag, MinecraftServer.getServer().registryAccess());
tileEntity.setChanged(); tileEntity.setChanged();
} }
@ -271,9 +275,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @param tag the tag * @param tag the tag
*/ */
private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) {
//FAWE start - avoid villager async catcher entity.load(tag);
PaperweightPlatformAdapter.readEntityIntoTag(entity, tag);
//FAWE end
} }
/** /**
@ -287,34 +289,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
private static Block getBlockFromType(BlockType blockType) { private static Block getBlockFromType(BlockType blockType) {
return Registry.BLOCK.get(ResourceLocation.tryParse(blockType.getId()));
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(
blockType.getId()));
} }
private static Item getItemFromType(ItemType itemType) { private static Item getItemFromType(ItemType itemType) {
return Registry.ITEM.get(ResourceLocation.tryParse(itemType.getId())); return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(
} itemType.getId()));
private static net.minecraft.core.Direction adapt(Direction face) {
switch (face) {
case NORTH:
return net.minecraft.core.Direction.NORTH;
case SOUTH:
return net.minecraft.core.Direction.SOUTH;
case WEST:
return net.minecraft.core.Direction.WEST;
case EAST:
return net.minecraft.core.Direction.EAST;
case DOWN:
return net.minecraft.core.Direction.DOWN;
case UP:
default:
return net.minecraft.core.Direction.UP;
}
}
@Override
public DataFixer getDataFixer() {
return PaperweightDataConverters.INSTANCE;
} }
@Override @Override
@ -334,6 +316,25 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
} }
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
int internalId = Block.getId(blockState);
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
if (state == null) {
state = BukkitAdapter.adapt(CraftBlockData.createData(blockState));
}
return state;
}
public BiomeType adapt(Biome biome) {
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(
biome);
if (mcBiome == null) {
return null;
}
return BiomeType.REGISTRY.get(mcBiome.toString());
}
@Override @Override
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
checkNotNull(location); checkNotNull(location);
@ -373,21 +374,37 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
// Read the NBT data // Read the NBT data
BlockEntity te = chunk.getBlockEntity(blockPos); BlockEntity te = chunk.getBlockEntity(blockPos);
if (te != null) { if (te != null) {
net.minecraft.nbt.CompoundTag tag = te.saveWithId(); net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess());
//FAWE start - BinaryTag
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
//FAWE end
} }
return state.toBaseBlock(); return state.toBaseBlock();
} }
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightWorldNativeAccess( return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
this, }
new WeakReference<>(((CraftWorld) world).getHandle())
); private static net.minecraft.core.Direction adapt(Direction face) {
switch (face) {
case NORTH:
return net.minecraft.core.Direction.NORTH;
case SOUTH:
return net.minecraft.core.Direction.SOUTH;
case WEST:
return net.minecraft.core.Direction.WEST;
case EAST:
return net.minecraft.core.Direction.EAST;
case DOWN:
return net.minecraft.core.Direction.DOWN;
case UP:
default:
return net.minecraft.core.Direction.UP;
}
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@ -429,16 +446,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
CraftEntity craftEntity = ((CraftEntity) entity); CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle(); Entity mcEntity = craftEntity.getHandle();
// Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity
if (mcEntity.isPassenger()) {
return null;
}
String id = getEntityId(mcEntity); String id = getEntityId(mcEntity);
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, tag);
//FAWE start - CompoundBinaryTag
return new BaseEntity( return new BaseEntity(
com.sk89q.worldedit.world.entity.EntityTypes.get(id), com.sk89q.worldedit.world.entity.EntityTypes.get(id),
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)) LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
); );
//FAWE end
} }
@Nullable @Nullable
@ -471,6 +491,22 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
} }
// This removes all unwanted tags from the main entity and all its passengers
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
if (tag.contains("Passengers", NBTConstants.TYPE_LIST)) {
net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", NBTConstants.TYPE_COMPOUND);
for (int i = 0; i < nbttaglist.size(); ++i) {
removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i));
}
}
}
@Override @Override
public Component getRichBlockName(BlockType blockType) { public Component getRichBlockName(BlockType blockType) {
return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId());
@ -487,26 +523,44 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() { private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
@Override .newBuilder()
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception { .build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) { @Override
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
} else if (state instanceof DirectionProperty) { if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
return new DirectionalProperty(state.getName(), return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
(List<Direction>) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList())); } else if (state instanceof DirectionProperty) {
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) { return new DirectionalProperty(
return new EnumProperty(state.getName(), state.getName(),
(List<String>) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList())); (List<Direction>) state
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { .getPossibleValues()
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); .stream()
} else { .map(e -> Direction.valueOf(((StringRepresentable) e)
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName()); .getSerializedName()
} .toUpperCase(Locale.ROOT)))
} .collect(Collectors.toList())
}); );
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
return new EnumProperty(
state.getName(),
(List<String>) state
.getPossibleValues()
.stream()
.map(e -> ((StringRepresentable) e).getSerializedName())
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
} else {
throw new IllegalArgumentException("WorldEdit needs an update to support " + state
.getClass()
.getSimpleName());
}
}
});
@SuppressWarnings({ "rawtypes" }) @SuppressWarnings({"rawtypes"})
@Override @Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) { public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
Map<String, Property<?>> properties = new TreeMap<>(); Map<String, Property<?>> properties = new TreeMap<>();
@ -520,50 +574,68 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return properties; return properties;
} }
//FAWE start - CompoundBinaryTag > CompoundTag
@Override @Override
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) { public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
((CraftPlayer) player).getHandle().networkManager.send(ClientboundBlockEntityDataPacket.create( var structureBlock = new StructureBlockEntity(
new StructureBlockEntity( new BlockPos(pos.getX(), pos.getY(), pos.getZ()),
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()), Blocks.STRUCTURE_BLOCK.defaultBlockState()
Blocks.STRUCTURE_BLOCK.defaultBlockState() );
), structureBlock.setLevel(((CraftPlayer) player).getHandle().level());
__ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData) ((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
structureBlock,
(blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
)); ));
} }
//FAWE end
@Override @Override
public void sendFakeOP(Player player) { public void sendFakeOP(Player player) {
((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket( ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
((CraftPlayer) player).getHandle(), (byte) 28 ((CraftPlayer) player).getHandle(), (byte) 28
)); ));
} }
@Override @Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); ItemStack stack = new ItemStack(
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())),
item.getAmount()
);
final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData());
final DataComponentPatch patch = COMPONENTS_CODEC
.parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt)
.getOrThrow();
stack.applyComponents(patch);
return CraftItemStack.asCraftMirror(stack); return CraftItemStack.asCraftMirror(stack);
} }
@Override @Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); final Tag tag = COMPONENTS_CODEC.encodeStart(
//FAWE start - CBT > CT registryAccess.createSerializationContext(NbtOps.INSTANCE),
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); nmsStack.getComponentsPatch()
//FAWE end ).getOrThrow();
return weStack; return new BaseItemStack(
BukkitAdapter.asItemType(itemStack.getType()),
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)),
itemStack.getAmount()
);
} }
private final LoadingCache<ServerLevel, PaperweightFakePlayer> fakePlayers
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
@Override @Override
public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) { public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) {
CraftWorld craftWorld = (CraftWorld) world; CraftWorld craftWorld = (CraftWorld) world;
ServerLevel worldServer = craftWorld.getHandle(); ServerLevel worldServer = craftWorld.getHandle();
ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack ItemStack stack = CraftItemStack.asNMSCopy(adapt(
? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1))); item instanceof BaseItemStack
stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())); ? ((BaseItemStack) item)
: new BaseItemStack(item.getType(), item.getNbtReference(), 1)
));
PaperweightFakePlayer fakePlayer; PaperweightFakePlayer fakePlayer;
try { try {
@ -572,20 +644,20 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return false; return false;
} }
fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack);
fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(), fakePlayer.absMoveTo(position.getX(), position.getY(), position.getZ(),
(float) face.toVector().toYaw(), (float) face.toVector().toPitch() (float) face.toVector().toYaw(), (float) face.toVector().toPitch()
); );
final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); final BlockPos blockPos = new BlockPos(position.getX(), position.getY(), position.getZ());
final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos); final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos);
final net.minecraft.core.Direction enumFacing = adapt(face); final net.minecraft.core.Direction enumFacing = adapt(face);
BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false); BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false);
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace); UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
InteractionResult result = stack.useOn(context, InteractionHand.MAIN_HAND); InteractionResult result = stack.useOn(context);
if (result != InteractionResult.SUCCESS) { if (result != InteractionResult.SUCCESS) {
if (worldServer if (worldServer
.getBlockState(blockPos) .getBlockState(blockPos)
.use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace) .useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace)
.consumesAction()) { .consumesAction()) {
result = InteractionResult.SUCCESS; result = InteractionResult.SUCCESS;
} else { } else {
@ -621,18 +693,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
Environment env = bukkitWorld.getEnvironment(); Environment env = bukkitWorld.getEnvironment();
ChunkGenerator gen = bukkitWorld.getGenerator(); ChunkGenerator gen = bukkitWorld.getGenerator();
Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen"); Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env); ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) {
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
.getWorldData().overworldData(); .getWorldData().overworldData();
WorldGenSettings originalOpts = levelProperties.worldGenSettings(); WorldOptions originalOpts = levelProperties.worldGenOptions();
long seed = options.getSeed().orElse(originalWorld.getSeed()); long seed = options.getSeed().orElse(originalWorld.getSeed());
WorldGenSettings newOpts = options.getSeed().isPresent() WorldOptions newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
@ -642,23 +714,40 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
levelProperties.settings.difficulty(), levelProperties.settings.difficulty(),
levelProperties.settings.allowCommands(), levelProperties.settings.allowCommands(),
levelProperties.settings.gameRules(), levelProperties.settings.gameRules(),
levelProperties.settings.getDataPackConfig() levelProperties.settings.getDataConfiguration()
);
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
levelProperties.isFlatWorld()
? PrimaryLevelData.SpecialWorldProperty.FLAT
: levelProperties.isDebugWorld()
? PrimaryLevelData.SpecialWorldProperty.DEBUG
: PrimaryLevelData.SpecialWorldProperty.NONE;
PrimaryLevelData newWorldData = new PrimaryLevelData(
newWorldSettings,
newOpts,
specialWorldProperty,
Lifecycle.stable()
); );
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
ServerLevel freshWorld = new ServerLevel( ServerLevel freshWorld = new ServerLevel(
originalWorld.getServer(), originalWorld.getServer(),
originalWorld.getServer().executor, originalWorld.getServer().executor,
session, newWorldData, session, newWorldData,
originalWorld.dimension(), originalWorld.dimension(),
originalWorld.dimensionTypeRegistration(), new LevelStem(
originalWorld.dimensionTypeRegistration(),
originalWorld.getChunkSource().getGenerator()
),
new NoOpWorldLoadListener(), new NoOpWorldLoadListener(),
newOpts.dimensions().get(worldDimKey).generator(),
originalWorld.isDebug(), originalWorld.isDebug(),
seed, seed,
ImmutableList.of(), ImmutableList.of(),
false, false,
env, gen, originalWorld.getRandomSequences(),
env,
gen,
bukkitWorld.getBiomeProvider() bukkitWorld.getBiomeProvider()
); );
try { try {
@ -678,7 +767,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) {
ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome); ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registries.BIOME).getKey(origBiome);
if (key == null) { if (key == null) {
return null; return null;
} }
@ -721,10 +810,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
Objects.requireNonNull(state); Objects.requireNonNull(state);
BlockEntity blockEntity = chunk.getBlockEntity(pos); BlockEntity blockEntity = chunk.getBlockEntity(pos);
if (blockEntity != null) { if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess());
//FAWE start - BinaryTag
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag))); state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
//FAWE end
} }
extent.setBlock(vec, state.toBaseBlock()); extent.setBlock(vec, state.toBaseBlock());
if (options.shouldRegenBiomes()) { if (options.shouldRegenBiomes()) {
@ -746,9 +833,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
try { try {
//noinspection unchecked //noinspection unchecked
chunkLoadings.add( chunkLoadings.add(
((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>) ((CompletableFuture<ChunkResult<ChunkAccess>>)
getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true))
.thenApply(either -> either.left().orElse(null)) .thenApply(either -> either.orElse(null))
); );
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("Couldn't load chunk for regen.", e); throw new IllegalStateException("Couldn't load chunk for regen.", e);
@ -769,6 +856,15 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
} }
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.NEIGHBORS,
SideEffect.LIGHTING,
SideEffect.VALIDATION,
SideEffect.ENTITY_AI,
SideEffect.EVENTS,
SideEffect.UPDATE
);
@Override @Override
public Set<SideEffect> getSupportedSideEffects() { public Set<SideEffect> getSupportedSideEffects() {
return SUPPORTED_SIDE_EFFECTS; return SUPPORTED_SIDE_EFFECTS;
@ -797,7 +893,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @param foreign non-native NMS NBT structure * @param foreign non-native NMS NBT structure
* @return native WorldEdit NBT structure * @return native WorldEdit NBT structure
*/ */
//FAWE start - BinaryTag
@Override @Override
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
if (foreign == null) { if (foreign == null) {
@ -830,7 +925,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
try { try {
return toNativeList((net.minecraft.nbt.ListTag) foreign); return toNativeList((net.minecraft.nbt.ListTag) foreign);
} catch (Throwable e) { } catch (Throwable e) {
LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
return ListBinaryTag.empty(); return ListBinaryTag.empty();
} }
} else if (foreign instanceof net.minecraft.nbt.LongTag) { } else if (foreign instanceof net.minecraft.nbt.LongTag) {
@ -855,7 +950,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @throws IllegalArgumentException on error * @throws IllegalArgumentException on error
*/ */
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException { private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
ListBinaryTag.Builder<BinaryTag> values = ListBinaryTag.builder(); ListBinaryTag.Builder values = ListBinaryTag.builder();
for (net.minecraft.nbt.Tag tag : foreign) { for (net.minecraft.nbt.Tag tag : foreign) {
values.add(toNativeBinary(tag)); values.add(toNativeBinary(tag));
@ -895,8 +990,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
} else if (foreign instanceof LongArrayBinaryTag) { } else if (foreign instanceof LongArrayBinaryTag) {
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
} else if (foreign instanceof ListBinaryTag foreignList) { } else if (foreign instanceof ListBinaryTag) {
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
ListBinaryTag foreignList = (ListBinaryTag) foreign;
for (BinaryTag t : foreignList) { for (BinaryTag t : foreignList) {
tag.add(fromNativeBinary(t)); tag.add(fromNativeBinary(t));
} }
@ -913,7 +1009,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
} }
} }
//FAWE end
@Override @Override
public boolean supportsWatchdog() { public boolean supportsWatchdog() {
@ -925,54 +1020,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
watchdog.tick(); watchdog.tick();
} }
private static class MojangWatchdog implements Watchdog {
private final DedicatedServer server;
private final Field tickField;
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
this.server = server;
Field tickField = MinecraftServer.class.getDeclaredField(
Refraction.pickName("nextTickTime", "ao")
);
tickField.setAccessible(true);
this.tickField = tickField;
}
@Override
public void tick() {
try {
tickField.set(server, Util.getMillis());
} catch (IllegalAccessException ignored) {
}
}
}
private static class NoOpWorldLoadListener implements ChunkProgressListener {
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public void setChunkRadius(int radius) {
}
}
private class SpigotWatchdog implements Watchdog { private class SpigotWatchdog implements Watchdog {
private final Field instanceField; private final Field instanceField;
@ -996,10 +1043,61 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
WatchdogThread.tick(); WatchdogThread.tick();
} }
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
LOGGER.log(Level.WARNING, "Failed to tick watchdog", e); logger.log(Level.WARNING, "Failed to tick watchdog", e);
} }
} }
} }
private static class MojangWatchdog implements Watchdog {
private final DedicatedServer server;
private final Field tickField;
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
this.server = server;
Field tickField = MinecraftServer.class.getDeclaredField(
Refraction.pickName("nextTickTime", "ah")
);
if (tickField.getType() != long.class) {
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
}
tickField.setAccessible(true);
this.tickField = tickField;
}
@Override
public void tick() {
try {
tickField.set(server, Util.getMillis());
} catch (IllegalAccessException ignored) {
}
}
}
private static class NoOpWorldLoadListener implements ChunkProgressListener {
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(
final ChunkPos pos,
@org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status
) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
}
} }

View File

@ -17,18 +17,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket; import net.minecraft.server.level.ClientInformation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stat; import net.minecraft.stats.Stat;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.player.ChatVisiblity;
import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
@ -37,15 +38,14 @@ import java.util.OptionalInt;
import java.util.UUID; import java.util.UUID;
class PaperweightFakePlayer extends ServerPlayer { class PaperweightFakePlayer extends ServerPlayer {
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]");
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
UUID.nameUUIDFromBytes("worldedit".getBytes()),
"[WorldEdit]"
);
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D); private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation(
"en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false
);
PaperweightFakePlayer(ServerLevel world) { PaperweightFakePlayer(ServerLevel world) {
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE); super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO);
} }
@Override @Override
@ -72,17 +72,13 @@ class PaperweightFakePlayer extends ServerPlayer {
} }
@Override @Override
public void updateOptions(ServerboundClientInformationPacket packet) { public void updateOptions(ClientInformation clientOptions) {
} }
@Override @Override
public void displayClientMessage(Component message, boolean actionBar) { public void displayClientMessage(Component message, boolean actionBar) {
} }
@Override
public void sendMessage(Component message, ChatType type, UUID sender) {
}
@Override @Override
public void awardStat(Stat<?> stat, int amount) { public void awardStat(Stat<?> stat, int amount) {
} }
@ -97,7 +93,6 @@ class PaperweightFakePlayer extends ServerPlayer {
} }
@Override @Override
public void openTextEdit(SignBlockEntity sign) { public void openTextEdit(SignBlockEntity sign, boolean front) {
} }
} }

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
@ -27,21 +27,19 @@ import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPhysicsEvent;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class PaperweightWorldNativeAccess implements public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1; private static final int UPDATE = 1;
private static final int NOTIFY = 2; private static final int NOTIFY = 2;
@ -83,19 +81,12 @@ public class PaperweightWorldNativeAccess implements
@Nullable @Nullable
@Override @Override
public net.minecraft.world.level.block.state.BlockState setBlockState( public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) {
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState state
) {
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE)); return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
} }
@Override @Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition( public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) {
net.minecraft.world.level.block.state.BlockState block,
BlockPos position
) {
return Block.updateFromNeighbourShapes(block, getWorld(), position); return Block.updateFromNeighbourShapes(block, getWorld(), position);
} }
@ -115,12 +106,7 @@ public class PaperweightWorldNativeAccess implements
} }
@Override @Override
public void notifyBlockUpdate( public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) { if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
} }
@ -128,7 +114,7 @@ public class PaperweightWorldNativeAccess implements
@Override @Override
public boolean isChunkTicking(LevelChunk chunk) { public boolean isChunkTicking(LevelChunk chunk) {
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
} }
@Override @Override
@ -139,11 +125,7 @@ public class PaperweightWorldNativeAccess implements
} }
@Override @Override
public void notifyNeighbors( public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
ServerLevel world = getWorld(); ServerLevel world = getWorld();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
world.updateNeighborsAt(pos, oldState.getBlock()); world.updateNeighborsAt(pos, oldState.getBlock());
@ -162,27 +144,20 @@ public class PaperweightWorldNativeAccess implements
} }
} }
// Not sure why neighborChanged is deprecated
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) { private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false); world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false);
} }
@Override @Override
public void updateNeighbors( public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) {
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
ServerLevel world = getWorld(); ServerLevel world = getWorld();
// a == updateNeighbors // a == updateNeighbors
// b == updateDiagonalNeighbors // b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = world.getWorld(); CraftWorld craftWorld = world.getWorld();
BlockPhysicsEvent event = new BlockPhysicsEvent( BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState));
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
CraftBlockData.fromData(newState)
);
world.getCraftServer().getPluginManager().callEvent(event); world.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
@ -193,19 +168,13 @@ public class PaperweightWorldNativeAccess implements
} }
@Override @Override
public void onBlockStateChange( public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getWorld().onBlockStateChange(pos, oldState, newState); getWorld().onBlockStateChange(pos, oldState, newState);
} }
//FAWE start
@Override @Override
public void flush() { public void flush() {
} }
//FAWE end
} }

View File

@ -1,28 +1,24 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial { public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block; private final Block block;
private final BlockState blockState; private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData; private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial; private final org.bukkit.Material craftMaterial;
private final int opacity; private final int opacity;
@ -35,22 +31,16 @@ public class PaperweightBlockMaterial implements BlockMaterial {
public PaperweightBlockMaterial(Block block, BlockState blockState) { public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block; this.block = block;
this.blockState = blockState; this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState); this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial(); this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aO"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO, BlockPos.ZERO,
blockState blockState
); );
tile = tileEntity == null tile = tileEntity == null ? null : new PaperweightLazyCompoundTag(
? null Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); );
} }
public Block getBlock() { public Block getBlock() {
@ -65,10 +55,6 @@ public class PaperweightBlockMaterial implements BlockMaterial {
return craftBlockData; return craftBlockData;
} }
public Material getMaterial() {
return material;
}
@Override @Override
public boolean isAir() { public boolean isAir() {
return blockState.isAir(); return blockState.isAir();
@ -81,7 +67,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isOpaque() { public boolean isOpaque() {
return material.isSolidBlocking(); return blockState.canOcclude();
} }
@Override @Override
@ -91,12 +77,13 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isLiquid() { public boolean isLiquid() {
return material.isLiquid(); return !blockState.getFluidState().is(Fluids.EMPTY);
} }
@Override @Override
public boolean isSolid() { public boolean isSolid() {
return material.isSolid(); // No access to world -> EmptyBlockGetter
return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
} }
@Override @Override
@ -126,27 +113,27 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isFragileWhenPushed() { public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY; return blockState.getPistonPushReaction() == PushReaction.DESTROY;
} }
@Override @Override
public boolean isUnpushable() { public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK; return blockState.getPistonPushReaction() == PushReaction.BLOCK;
} }
@Override @Override
public boolean isTicksRandomly() { public boolean isTicksRandomly() {
return block.isRandomlyTicking(blockState); return blockState.isRandomlyTicking();
} }
@Override @Override
public boolean isMovementBlocker() { public boolean isMovementBlocker() {
return material.isSolid(); return craftMaterial.isSolid();
} }
@Override @Override
public boolean isBurnable() { public boolean isBurnable() {
return material.isFlammable(); return craftMaterial.isBurnable();
} }
@Override @Override
@ -157,12 +144,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isReplacedDuringPlacement() { public boolean isReplacedDuringPlacement() {
return material.isReplaceable(); return blockState.canBeReplaced();
} }
@Override @Override
public boolean isTranslucent() { public boolean isTranslucent() {
return isTranslucent; return !blockState.canOcclude();
} }
@Override @Override
@ -183,7 +170,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public int getMapColor() { public int getMapColor() {
// rgb field // rgb field
return material.getColor().col; return block.defaultMapColor().col;
} }
} }

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
@ -12,14 +12,13 @@ import com.fastasyncworldedit.core.util.NbtUtils;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.Codec;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen.PaperweightRegen;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen.PaperweightRegen;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
@ -35,6 +34,7 @@ import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -45,7 +45,6 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
@ -53,44 +52,48 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.WritableRegistry; import net.minecraft.core.WritableRegistry;
import net.minecraft.nbt.IntTag; 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.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable; import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v1_18_R2.util.CraftNamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -104,11 +107,24 @@ import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static net.minecraft.core.registries.Registries.BIOME;
public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> { public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
private static final Codec<DataComponentPatch> COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf(
"components", DataComponentPatch.EMPTY
).codec();
private final PaperweightAdapter parent; static {
try {
CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave");
} catch (NoSuchMethodException ignored) { // may not be present in newer paper versions
}
}
private final com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter parent;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // Code that may break between versions of Minecraft
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -119,7 +135,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
private Map<String, List<Property<?>>> allBlockProperties = null; private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter(); this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter();
} }
@Nullable @Nullable
@ -128,6 +144,10 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return resourceLocation == null ? null : resourceLocation.toString(); return resourceLocation == null ? null : resourceLocation.toString();
} }
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override @Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() { public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent; return parent;
@ -219,7 +239,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
} }
public Block getBlock(BlockType blockType) { public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK)
.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
} }
@Deprecated @Deprecated
@ -264,7 +285,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
// Read the NBT data // Read the NBT data
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) { if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(); net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess());
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
} }
} }
@ -277,54 +298,6 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return SideEffectSet.defaults().getSideEffectsToApply(); return SideEffectSet.defaults().getSideEffectsToApply();
} }
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world))); return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
@ -343,7 +316,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> { Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag); final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
@ -474,7 +447,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = getServerLevel(world); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) { if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false;
// PlayerChunk.d players = map.players; // PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
*/ Stream.empty(); */ Stream.empty();
@ -516,11 +490,18 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
@Override @Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
ItemStack stack = new ItemStack( ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount() baseItemStack.getAmount()
); );
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData());
if (nbt != null) {
final DataComponentPatch patch = COMPONENTS_CODEC
.parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt)
.getOrThrow();
stack.applyComponents(patch);
}
return CraftItemStack.asCraftMirror(stack); return CraftItemStack.asCraftMirror(stack);
} }
@ -547,29 +528,19 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return ((CraftWorld) world).getHandle(); return ((CraftWorld) world).getHandle();
} }
@Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
// Quickly add each entity to a list copy.
List<Entity> mcEntities = new ArrayList<>();
getServerLevel(world).entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>();
mcEntities.forEach((mcEnt) -> {
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity();
if (bukkitEntity.isValid()) {
list.add(bukkitEntity);
}
});
return list;
}
@Override @Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart(
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag()))); registryAccess.createSerializationContext(NbtOps.INSTANCE),
return weStack; nmsStack.getComponentsPatch()
).getOrThrow();
return new BaseItemStack(
BukkitAdapter.asItemType(itemStack.getType()),
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)),
itemStack.getAmount()
);
} }
@Override @Override
@ -577,17 +548,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return parent.toNative(foreign); return parent.toNative(foreign);
} }
@Override
public BinaryTag toNativeBinary(final net.minecraft.nbt.Tag foreign) {
return parent.toNativeBinary(foreign);
}
@Override @Override
public net.minecraft.nbt.Tag fromNative(Tag foreign) { public net.minecraft.nbt.Tag fromNative(Tag foreign) {
if (foreign instanceof PaperweightLazyCompoundTag) { if (foreign instanceof PaperweightLazyCompoundTag) {
return ((PaperweightLazyCompoundTag) foreign).get(); return ((PaperweightLazyCompoundTag) foreign).get();
} }
return (net.minecraft.nbt.Tag) parent.fromNative(foreign); return parent.fromNative(foreign);
} }
@Override @Override
@ -605,7 +571,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
final Registry<Biome> registry = MinecraftServer final Registry<Biome> registry = MinecraftServer
.getServer() .getServer()
.registryAccess() .registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY); .registryOrThrow(BIOME);
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
Biome biome = registry.get(resourceLocation); Biome biome = registry.get(resourceLocation);
return registry.getId(biome); return registry.getId(biome);
@ -616,8 +582,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer()) WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
.getServer() .getServer()
.registryAccess() .registryAccess()
.ownedRegistryOrThrow( .registryOrThrow(BIOME);
Registry.BIOME_REGISTRY);
List<ResourceLocation> keys = biomeRegistry.stream() List<ResourceLocation> keys = biomeRegistry.stream()
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); .map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
List<NamespacedKey> namespacedKeys = new ArrayList<>(); List<NamespacedKey> namespacedKeys = new ArrayList<>();
@ -659,4 +624,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return new PaperweightPostProcessor(); return new PaperweightPostProcessor();
} }
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
try {
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException ignored) {
// fall-through
}
}
// Papers new chunk system has no related replacement - therefor we assume true.
return true;
}
} }

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
@ -15,14 +15,15 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -102,7 +103,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
} }
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ())); cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ));
boolean nextTick = lastTick.get() > currentTick; boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) { if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) { if (nextTick) {
@ -140,7 +141,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
return false; return false;
} }
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag); net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
blockEntity.load((CompoundTag) nativeTag); blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess());
return true; return true;
} }
@ -157,7 +158,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
@Override @Override
public boolean isChunkTicking(LevelChunk levelChunk) { public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
} }
@Override @Override
@ -181,7 +182,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
// Un-nest neighbour updating // Un-nest neighbour updating
for (Direction direction : NEIGHBOUR_ORDER) { for (Direction direction : NEIGHBOUR_ORDER) {
BlockPos shifted = blockPos.relative(direction); BlockPos shifted = blockPos.relative(direction);
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false); level.getBlockState(shifted).handleNeighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
} }
} }
if (newState.hasAnalogOutputSignal()) { if (newState.hasAnalogOutputSignal()) {

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks; import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
@ -20,7 +20,7 @@ import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -29,12 +29,9 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import io.papermc.paper.event.block.BeaconDeactivatedEvent; import io.papermc.paper.event.block.BeaconDeactivatedEvent;
import net.minecraft.core.BlockPos; import net.minecraft.core.*;
import net.minecraft.core.Holder;
import net.minecraft.core.IdMap;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.IntTag; import net.minecraft.nbt.IntTag;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.BitStorage; import net.minecraft.util.BitStorage;
@ -46,33 +43,17 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BeaconBlockEntity; import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.DataLayer; import net.minecraft.world.level.chunk.*;
import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.lighting.LevelLightEngine; import net.minecraft.world.level.lighting.LevelLightEngine;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock; import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.AbstractSet; import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -83,13 +64,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.minecraft.core.registries.Registries.BIOME;
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ());
private static final Function<BlockEntity, CompoundTag> nmsTile2We = private static final Function<BlockEntity, CompoundTag> nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag(
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
);
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance() .getInstance()
.getBukkitImplAdapter()); .getBukkitImplAdapter());
@ -130,7 +114,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
this.maxSectionPosition = maxHeight >> 4; this.maxSectionPosition = maxHeight >> 4;
this.skyLight = new DataLayer[getSectionCount()]; this.skyLight = new DataLayer[getSectionCount()];
this.blockLight = new DataLayer[getSectionCount()]; this.blockLight = new DataLayer[getSectionCount()];
this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME);
this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap();
} }
@ -260,7 +244,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (blockEntity == null) { if (blockEntity == null) {
return null; return null;
} }
return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())));
} }
@Override @Override
@ -289,8 +273,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
LightLayer.BLOCK, LightLayer.BLOCK,
sectionPos, sectionPos,
dataLayer, dataLayer
true
); );
} }
skyLight[alayer] = dataLayer; skyLight[alayer] = dataLayer;
@ -317,7 +300,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
Arrays.fill(LAYER_COUNT, (byte) 15); Arrays.fill(LAYER_COUNT, (byte) 15);
dataLayer = new DataLayer(LAYER_COUNT); dataLayer = new DataLayer(LAYER_COUNT);
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos,
dataLayer, true dataLayer
); );
} }
blockLight[alayer] = dataLayer; blockLight[alayer] = dataLayer;
@ -334,7 +317,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
public CompoundTag getEntity(UUID uuid) { public CompoundTag getEntity(UUID uuid) {
Entity entity = serverLevel.getEntity(uuid); ensureLoaded(serverLevel, chunkX, chunkZ);
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
Entity entity = null;
for (Entity e : entities) {
if (e.getUUID().equals(uuid)) {
entity = e;
break;
}
}
if (entity != null) { if (entity != null) {
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
@ -349,6 +340,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
public Set<CompoundTag> getEntities() { public Set<CompoundTag> getEntities() {
ensureLoaded(serverLevel, chunkX, chunkZ);
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk()); List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
if (entities.isEmpty()) { if (entities.isEmpty()) {
return Collections.emptySet(); return Collections.emptySet();
@ -385,7 +377,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
public Iterator<CompoundTag> iterator() { public Iterator<CompoundTag> iterator() {
Iterable<CompoundTag> result = entities.stream().map(input -> { Iterable<CompoundTag> result = entities.stream().map(input -> {
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
PaperweightPlatformAdapter.readEntityIntoTag(input, tag); input.save(tag);
return (CompoundTag) adapter.toNative(tag); return (CompoundTag) adapter.toNative(tag);
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return result.iterator(); return result.iterator();
@ -474,7 +466,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
synchronized (super.sectionLocks[getSectionIndex]) { synchronized (super.sectionLocks[getSectionIndex]) {
LevelChunkSection existingSection = levelChunkSections[getSectionIndex]; LevelChunkSection existingSection = levelChunkSections[getSectionIndex];
if (createCopy && existingSection != null) { if (createCopy && existingSection != null) {
copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
} }
if (existingSection == null) { if (existingSection == null) {
@ -507,8 +499,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
} else { } else {
PalettedContainer<Holder<Biome>> biomeData = existingSection.getBiomes(); setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData);
} }
} }
} }
@ -543,7 +534,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
copy.storeSection(getSectionIndex, copyArr); copy.storeSection(getSectionIndex, copyArr);
if (biomes != null && existingSection != null) { if (biomes != null && existingSection != null) {
copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy()); copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
} }
} }
@ -555,8 +546,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
.getBukkitImplAdapter() .getBukkitImplAdapter()
.getInternalBiomeId( .getInternalBiomeId(
BiomeTypes.PLAINS)), BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES, PalettedContainer.Strategy.SECTION_BIOMES
null
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap); ) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
newSection = PaperweightPlatformAdapter.newChunkSection( newSection = PaperweightPlatformAdapter.newChunkSection(
layerNo, layerNo,
@ -616,11 +606,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
sectionLock.writeLock().unlock(); sectionLock.writeLock().unlock();
} }
PalettedContainer<Holder<Biome>> biomeData = existingSection.getBiomes(); PalettedContainer<Holder<Biome>> biomeData = setBiomesToPalettedContainer(
biomes,
if (biomes != null && biomes[setSectionIndex] != null) { setSectionIndex,
setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData); existingSection.getBiomes()
} );
newSection = newSection =
PaperweightPlatformAdapter.newChunkSection( PaperweightPlatformAdapter.newChunkSection(
@ -705,7 +695,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
for (UUID uuid : entityRemoves) { for (UUID uuid : entityRemoves) {
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); Entity entity = nmsWorld.getEntities().get(uuid);
if (entity != null) { if (entity != null) {
removeEntity(entity); removeEntity(entity);
} }
@ -800,7 +790,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
tag.put("x", IntTag.valueOf(x)); tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y)); tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z)); tag.put("z", IntTag.valueOf(z));
tileEntity.load(tag); tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess());
} }
} }
} }
@ -1076,8 +1066,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
lightLayer, lightLayer,
sectionPos, sectionPos,
dataLayer, dataLayer
true
); );
} }
synchronized (dataLayer) { synchronized (dataLayer) {
@ -1095,22 +1084,35 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
private void setBiomesToPalettedContainer( private PalettedContainer<Holder<Biome>> setBiomesToPalettedContainer(
final BiomeType[] biomes, final BiomeType[][] biomes,
PalettedContainer<Holder<Biome>> data final int sectionIndex,
final PalettedContainerRO<Holder<Biome>> data
) { ) {
int index = 0; PalettedContainer<Holder<Biome>> biomeData;
if (biomes == null) { if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
return; biomeData = palettedContainer;
} else {
LOGGER.warn(
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
"type {} but got {}",
PalettedContainer.class.getSimpleName(),
data.getClass().getSimpleName()
);
biomeData = data.recreate();
} }
for (int y = 0; y < 4; y++) { BiomeType[] sectionBiomes;
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
return biomeData;
}
for (int y = 0, index = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) { for (int z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, index++) { for (int x = 0; x < 4; x++, index++) {
BiomeType biomeType = biomes[index]; BiomeType biomeType = sectionBiomes[index];
if (biomeType == null) { if (biomeType == null) {
continue; continue;
} }
data.set( biomeData.set(
x, x,
y, y,
z, z,
@ -1122,6 +1124,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
} }
return biomeData;
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
@ -8,19 +8,23 @@ import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.PalettedContainerRO;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
@ -33,6 +37,8 @@ import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet { public class PaperweightGetBlocks_Copy implements IChunkGet {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>(); private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks; private final char[][] blocks;
@ -57,7 +63,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ() blockEntity.getBlockPos().getZ()
), ),
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())))
); );
} }
@ -76,7 +82,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
protected void storeEntity(Entity entity) { protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag); entity.save(compoundTag);
entities.add((CompoundTag) adapter.toNative(compoundTag)); entities.add((CompoundTag) adapter.toNative(compoundTag));
} }
@ -166,11 +172,19 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
blocks[layer] = data; blocks[layer] = data;
} }
protected void storeBiomes(int layer, PalettedContainer<Holder<Biome>> biomeData) { protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
if (biomes == null) { if (biomes == null) {
biomes = new PalettedContainer[getSectionCount()]; biomes = new PalettedContainer[getSectionCount()];
} }
biomes[layer] = biomeData; if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
biomes[layer] = palettedContainer.copy();
} else {
LOGGER.error(
"Cannot correctly save biomes to history. Expected class type {} but got {}",
PalettedContainer.class.getSimpleName(),
biomeData.getClass().getSimpleName()
);
}
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil; import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.Refraction;
@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkW
public PaperweightMapChunkUtil() throws NoSuchFieldException { public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a")); fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a")); fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "b"));
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b")); fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "c"));
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b")); fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c")); fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "d"));
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c")); fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d")); fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
fieldX.setAccessible(true); fieldX.setAccessible(true);

View File

@ -1,5 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.destroystokyo.paper.util.maplist.EntityList;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
@ -19,6 +20,7 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import io.papermc.paper.world.ChunkEntitySlices;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IdMap; import net.minecraft.core.IdMap;
@ -30,19 +32,19 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import net.minecraft.util.BitStorage; import net.minecraft.util.BitStorage;
import net.minecraft.util.ExceptionCollector;
import net.minecraft.util.SimpleBitStorage; import net.minecraft.util.SimpleBitStorage;
import net.minecraft.util.ThreadingDetector; import net.minecraft.util.ThreadingDetector;
import net.minecraft.util.Unit; import net.minecraft.util.Unit;
import net.minecraft.util.ZeroBitStorage; import net.minecraft.util.ZeroBitStorage;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.item.trading.MerchantOffers;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.GlobalPalette; import net.minecraft.world.level.chunk.GlobalPalette;
import net.minecraft.world.level.chunk.HashMapPalette; import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
@ -51,15 +53,17 @@ import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette; import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.chunk.SingleValuePalette;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; import org.bukkit.craftbukkit.CraftChunk;
import sun.misc.Unsafe;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -79,6 +83,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.function.Function; import java.util.function.Function;
import static java.lang.invoke.MethodType.methodType;
import static net.minecraft.core.registries.Registries.BIOME;
public final class PaperweightPlatformAdapter extends NMSAdapter { public final class PaperweightPlatformAdapter extends NMSAdapter {
public static final Field fieldData; public static final Field fieldData;
@ -100,14 +107,23 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
private static final MethodHandle methodRemoveGameEventListener; private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity; private static final MethodHandle methodremoveTickingBlockEntity;
private static final Field fieldOffers; /*
private static final MerchantOffers OFFERS = new MerchantOffers(); * This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java
* and is only needed to support 1.19.4 versions before *and* after this change.
*/
private static final MethodHandle CRAFT_CHUNK_GET_HANDLE;
private static final Field fieldRemove; private static final Field fieldRemove;
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
static final boolean POST_CHUNK_REWRITE;
private static Method PAPER_CHUNK_GEN_ALL_ENTITIES;
private static Field LEVEL_CHUNK_ENTITIES;
private static Field SERVER_LEVEL_ENTITY_MANAGER;
static { static {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try { try {
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d")); fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
fieldData.setAccessible(true); fieldData.setAccessible(true);
@ -121,11 +137,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c")); fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
fieldPalette.setAccessible(true); fieldPalette.setAccessible(true);
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h")); fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "g"));
fieldTickingFluidCount.setAccessible(true); fieldTickingFluidCount.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g")); fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
fieldTickingBlockCount.setAccessible(true); fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f")); fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
fieldNonEmptyBlockCount.setAccessible(true); fieldNonEmptyBlockCount.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName( Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
@ -133,7 +149,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
"b" "b"
), long.class); ), long.class);
getVisibleChunkIfPresent.setAccessible(true); getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent); methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
if (!PaperLib.isPaper()) { if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f")); fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
@ -147,31 +163,66 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod( Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Refraction.pickName("removeGameEventListener", "d"), Refraction.pickName("removeGameEventListener", "a"),
BlockEntity.class BlockEntity.class,
ServerLevel.class
); );
removeGameEventListener.setAccessible(true); removeGameEventListener.setAccessible(true);
methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener); methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod( Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName( Refraction.pickName(
"removeBlockEntityTicker", "removeBlockEntityTicker",
"l" "k"
), BlockPos.class ), BlockPos.class
); );
removeBlockEntityTicker.setAccessible(true); removeBlockEntityTicker.setAccessible(true);
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker); methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true); fieldRemove.setAccessible(true);
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bW")); boolean chunkRewrite;
fieldOffers.setAccessible(true); try {
} catch (RuntimeException e) { ServerLevel.class.getDeclaredMethod("getEntityLookup");
chunkRewrite = true;
PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities");
PAPER_CHUNK_GEN_ALL_ENTITIES.setAccessible(true);
} catch (NoSuchMethodException ignored) {
chunkRewrite = false;
}
try {
// Paper - Pre-Chunk-Update
LEVEL_CHUNK_ENTITIES = LevelChunk.class.getDeclaredField("entities");
LEVEL_CHUNK_ENTITIES.setAccessible(true);
} catch (NoSuchFieldException ignored) {
}
try {
// Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "N"));
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) {
}
POST_CHUNK_REWRITE = chunkRewrite;
} catch (RuntimeException | Error e) {
throw e; throw e;
} catch (Throwable rethrow) { } catch (Exception e) {
rethrow.printStackTrace(); throw new RuntimeException(e);
throw new RuntimeException(rethrow);
} }
MethodHandle craftChunkGetHandle;
final MethodType type = methodType(LevelChunk.class);
try {
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", type);
} catch (NoSuchMethodException | IllegalAccessException e) {
try {
final MethodType newType = methodType(ChunkAccess.class, ChunkStatus.class);
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", newType);
craftChunkGetHandle = MethodHandles.insertArguments(craftChunkGetHandle, 1, ChunkStatus.FULL);
} catch (NoSuchMethodException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
CRAFT_CHUNK_GET_HANDLE = craftChunkGetHandle;
} }
static boolean setSectionAtomic( static boolean setSectionAtomic(
@ -255,7 +306,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!");
} }
} }
return chunk.getHandle(); addTicket(serverLevel, chunkX, chunkZ);
return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -265,9 +317,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
// Ensure chunk is definitely loaded before applying a ticket // Ensure chunk is definitely loaded before applying a ticket
net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
.getChunkSource() .getChunkSource()
.addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
} }
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
@ -286,20 +338,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
return; return;
} }
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ); ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
// UNLOADED_CHUNK LevelChunk levelChunk;
Optional<LevelChunk> optional = ((Either) chunkHolder
.getTickingChunkFuture()
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only // getChunkAtIfLoadedImmediately is paper only
optional = optional.or(() -> Optional.ofNullable(nmsWorld levelChunk = nmsWorld
.getChunkSource() .getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ))); .getChunkAtIfLoadedImmediately(chunkX, chunkZ);
} else {
levelChunk = ((Optional<LevelChunk>) ((Either) chunkHolder
.getTickingChunkFuture() // method is not present with new paper chunk system
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left())
.orElse(null);
} }
if (optional.isEmpty()) { if (levelChunk == null) {
return; return;
} }
LevelChunk levelChunk = optional.get();
TaskManager.taskManager().task(() -> { TaskManager.taskManager().task(() -> {
ClientboundLevelChunkWithLightPacket packet; ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
@ -307,9 +360,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
levelChunk, levelChunk,
nmsWorld.getChunkSource().getLightEngine(), nmsWorld.getChunkSource().getLightEngine(),
null, null,
null, null
true, // last false is to not bother with x-ray
false // last false is to not bother with x-ray
); );
} else { } else {
// deprecated on paper - deprecation suppressed // deprecated on paper - deprecation suppressed
@ -317,8 +369,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
levelChunk, levelChunk,
nmsWorld.getChunkSource().getLightEngine(), nmsWorld.getChunkSource().getLightEngine(),
null, null,
null, null
true
); );
} }
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
@ -424,12 +475,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
.getBukkitImplAdapter() .getBukkitImplAdapter()
.getInternalBiomeId( .getInternalBiomeId(
BiomeTypes.PLAINS)), BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES, PalettedContainer.Strategy.SECTION_BIOMES
null
); );
} }
return new LevelChunkSection(layer, blockStatePalettedContainer, biomes); return new LevelChunkSection(blockStatePalettedContainer, biomes);
} catch (final Throwable e) { } catch (final Throwable e) {
throw e; throw e;
} finally { } finally {
@ -447,15 +497,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
@Nullable PalettedContainer<Holder<Biome>> biomes @Nullable PalettedContainer<Holder<Biome>> biomes
) { ) {
if (biomes == null) { if (biomes == null) {
return new LevelChunkSection(layer, biomeRegistry); return new LevelChunkSection(biomeRegistry);
} }
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>( PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY, Block.BLOCK_STATE_REGISTRY,
Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(),
PalettedContainer.Strategy.SECTION_STATES, PalettedContainer.Strategy.SECTION_STATES
null
); );
return new LevelChunkSection(layer, dataPaletteBlocks, biomes); return new LevelChunkSection(dataPaletteBlocks, biomes);
} }
/** /**
@ -492,8 +541,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
PalettedContainer<Holder<Biome>> biomePalettedContainer = new PalettedContainer<>( PalettedContainer<Holder<Biome>> biomePalettedContainer = new PalettedContainer<>(
biomeRegistry, biomeRegistry,
biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)), biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES, PalettedContainer.Strategy.SECTION_BIOMES
null
); );
final Palette<Holder<Biome>> biomePalette; final Palette<Holder<Biome>> biomePalette;
@ -571,7 +619,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
public static BiomeType adapt(Holder<Biome> biome, LevelAccessor levelAccessor) { public static BiomeType adapt(Holder<Biome> biome, LevelAccessor levelAccessor) {
final Registry<Biome> biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY); final Registry<Biome> biomeRegistry = levelAccessor.registryAccess().registryOrThrow(BIOME);
if (biomeRegistry.getKey(biome.value()) == null) { if (biomeRegistry.getKey(biome.value()) == null) {
return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN
: null; : null;
@ -581,13 +629,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) { static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try { try {
// Do the method ourselves to avoid trying to reflect generic method parameters
// similar to removeGameEventListener
if (levelChunk.loaded || levelChunk.level.isClientSide()) { if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos()); BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) { if (blockEntity != null) {
if (!levelChunk.level.isClientSide) { if (!levelChunk.level.isClientSide) {
methodRemoveGameEventListener.invoke(levelChunk, beacon); methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level);
} }
fieldRemove.set(beacon, true); fieldRemove.set(beacon, true);
} }
@ -599,30 +645,32 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
static List<Entity> getEntities(LevelChunk chunk) { static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(chunk.getPos()); ExceptionCollector<RuntimeException> collector = new ExceptionCollector<>();
} if (PaperLib.isPaper()) {
if (POST_CHUNK_REWRITE) {
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) { try {
boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread(); //noinspection unchecked
boolean unset = false; return (List<Entity>) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ));
if (isVillager) { } catch (IllegalAccessException | InvocationTargetException e) {
try { throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e);
if (fieldOffers.get(entity) != null) {
fieldOffers.set(entity, OFFERS);
unset = true;
} }
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to set offers field to villager to avoid async catcher.", e);
} }
}
entity.save(compoundTag);
if (unset) {
try { try {
fieldOffers.set(entity, null); EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk);
return List.of(entityList.getRawData());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new RuntimeException("Failed to set offers field to null again on villager.", e); collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e));
// fall through
} }
} }
try {
//noinspection unchecked
return ((PersistentEntitySectionManager<Entity>) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos());
} catch (IllegalAccessException e) {
collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e));
}
collector.throwIfPresent();
return List.of();
} }
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> { record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.extent.processor.ProcessorScope;

View File

@ -1,14 +1,14 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.IQueueExtent;
import net.minecraft.server.MCUtil; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import net.minecraft.util.Unit; import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -18,7 +18,7 @@ import java.util.function.IntConsumer;
public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> { public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> {
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) { public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) {
super(serverLevel, queue); super(serverLevel, queue);

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
@ -7,7 +7,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.LazyCompoundTag; import com.sk89q.jnbt.LazyCompoundTag;

View File

@ -1,17 +1,15 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightGetBlocks; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.PaperweightGetBlocks;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -20,14 +18,19 @@ import com.sk89q.worldedit.world.RegenOptions;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.thread.ProcessorHandle;
import net.minecraft.util.thread.ProcessorMailbox;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelHeightAccessor;
@ -37,31 +40,34 @@ import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource; import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.Chunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.generator.CustomChunkGenerator; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
@ -74,6 +80,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import java.util.function.Supplier; import java.util.function.Supplier;
import static net.minecraft.core.registries.Registries.BIOME;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> { public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
@ -85,6 +93,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private static final Field generatorSettingBaseSupplierField; private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField; private static final Field delegateField;
private static final Field chunkSourceField; private static final Field chunkSourceField;
private static final Field generatorStructureStateField;
private static final Field ringPositionsField; private static final Field ringPositionsField;
private static final Field hasGeneratedPositionsField; private static final Field hasGeneratedPositionsField;
@ -96,23 +105,22 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
chunkStati.put( chunkStati.put(
ChunkStatus.STRUCTURE_REFERENCES, ChunkStatus.STRUCTURE_REFERENCES,
Concurrency.FULL Concurrency.NONE
); // structure refs: radius 8, but only writes to current chunk ); // structure refs: radius 8, but only writes to current chunk
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 chunkStati.put(ChunkStatus.BIOMES, Concurrency.NONE); // biomes: radius 0
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(
ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
chunkStati.put(
ChunkStatus.INITIALIZE_LIGHT,
Concurrency.FULL
); // initialize_light: radius 0
chunkStati.put( chunkStati.put(
ChunkStatus.LIGHT, ChunkStatus.LIGHT,
Concurrency.FULL Concurrency.FULL
); // light: radius 1, but no writes to other chunks, only current chunk ); // light: radius 1, but no writes to other chunks, only current chunk
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 chunkStati.put(ChunkStatus.SPAWN, Concurrency.NONE); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try { try {
serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField = CraftServer.class.getDeclaredField("worlds");
@ -134,22 +142,27 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
flatBedrockField = tmpFlatBedrockField; flatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "h")); "settings", "e"));
generatorSettingBaseSupplierField.setAccessible(true); generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "g")); generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d"));
generatorSettingFlatField.setAccessible(true); generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true); delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "K")); chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
chunkSourceField.setAccessible(true); chunkSourceField.setAccessible(true);
ringPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("ringPositions", "h")); generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v"));
generatorStructureStateField.setAccessible(true);
ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g"));
ringPositionsField.setAccessible(true); ringPositionsField.setAccessible(true);
hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "i")); hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(
Refraction.pickName("hasGeneratedPositions", "h")
);
hasGeneratedPositionsField.setAccessible(true); hasGeneratedPositionsField.setAccessible(true);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -162,9 +175,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private ServerLevel freshWorld; private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider; private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session; private LevelStorageSource.LevelStorageAccess session;
private StructureManager structureManager; private StructureTemplateManager structureTemplateManager;
private ThreadedLevelLightEngine threadedLevelLightEngine; private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator; private ChunkGenerator chunkGenerator;
private WorldGenContext worldGenContext;
private Path tempDir; private Path tempDir;
@ -207,12 +221,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
WorldGenSettings originalOpts = originalWorldData.worldGenSettings(); WorldOptions originalOpts = originalWorldData.worldGenOptions();
WorldGenSettings newOpts = options.getSeed().isPresent() WorldOptions newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld", "faweregentempworld",
@ -221,9 +233,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
originalWorldData.settings.difficulty(), originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(), originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(), originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig() originalWorldData.settings.getDataConfiguration()
); );
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
originalWorldData.isFlatWorld()
? PrimaryLevelData.SpecialWorldProperty.FLAT
: originalWorldData.isDebugWorld()
? PrimaryLevelData.SpecialWorldProperty.DEBUG
: PrimaryLevelData.SpecialWorldProperty.NONE;
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable());
BiomeProvider biomeProvider = getBiomeProvider();
//init world //init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel( freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
@ -232,66 +254,70 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
session, session,
newWorldData, newWorldData,
originalServerWorld.dimension(), originalServerWorld.dimension(),
originalServerWorld.dimensionTypeRegistration(), DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow()
.getOrThrow(levelStemResourceKey),
new RegenNoOpWorldLoadListener(), new RegenNoOpWorldLoadListener(),
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
newOpts.dimensions().getOrThrow(levelStemResourceKey).generator(),
originalServerWorld.isDebug(), originalServerWorld.isDebug(),
seed, seed,
ImmutableList.of(), ImmutableList.of(),
false, false,
originalServerWorld.getRandomSequences(),
environment, environment,
generator, generator,
biomeProvider biomeProvider
) { ) {
private final Holder<Biome> singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) private final Holder<Biome> singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess()
) : null; .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
) : null;
@Override @Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking public void tick(@NotNull BooleanSupplier shouldKeepTicking) { //no ticking
} }
@Override @Override
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { public @NotNull Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) { if (options.hasBiomeType()) {
return singleBiome; return singleBiome;
} }
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ, return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(
PaperweightRegen.this.chunkGenerator.climateSampler() biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
); );
} }
}).get(); }).get();
freshWorld.noSave = true; freshWorld.noSave = true;
removeWorldFromWorldsMap(); removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) { if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig); paperConfigField.set(freshWorld, originalServerWorld.paperConfig());
} }
//generator
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator(); ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
if (originalGenerator instanceof FlatLevelSource flatLevelSource) { if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings(); FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat); chunkGenerator = new FlatLevelSource(generatorSettingFlat);
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>)
(Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator);
.get(originalGenerator);
BiomeSource biomeSource; BiomeSource biomeSource;
if (options.hasBiomeType()) { if (options.hasBiomeType()) {
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME biomeSource = new FixedBiomeSource(
.asHolderIdMap() DedicatedServer.getServer().registryAccess()
.byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()))); .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
)
);
} else { } else {
biomeSource = originalGenerator.getBiomeSource(); biomeSource = originalGenerator.getBiomeSource();
} }
chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, noiseBasedChunkGenerator.noises, chunkGenerator = new NoiseBasedChunkGenerator(
biomeSource, seed, biomeSource,
generatorSettingBaseSupplier generatorSettingBaseSupplier
); );
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
chunkGenerator = customChunkGenerator.delegate; chunkGenerator = customChunkGenerator.getDelegate();
} else { } else {
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
return false; return false;
@ -300,22 +326,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable(); generateConcurrent = generator.isParallelCapable();
} }
// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
// Optimisation for needless ring position calculation when the seed and biome is the same.
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator);
if (hasGeneratedPositions) {
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> ringPositions =
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(
originalGenerator);
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(ringPositions);
ringPositionsField.set(chunkGenerator, copy);
hasGeneratedPositionsField.setBoolean(chunkGenerator, true);
}
}
chunkGenerator.conf = originalServerWorld.spigotConfig;
freshChunkProvider = new ServerChunkCache( freshChunkProvider = new ServerChunkCache(
freshWorld, freshWorld,
session, session,
@ -333,7 +345,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
) { ) {
// redirect to LevelChunks created in #createChunks // redirect to LevelChunks created in #createChunks
@Override @Override
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { public ChunkAccess getChunk(int x, int z, @NotNull ChunkStatus chunkstatus, boolean create) {
ChunkAccess chunkAccess = getChunkAt(x, z); ChunkAccess chunkAccess = getChunkAt(x, z);
if (chunkAccess == null && create) { if (chunkAccess == null && create) {
chunkAccess = createChunk(getProtoChunkAt(x, z)); chunkAccess = createChunk(getProtoChunkAt(x, z));
@ -342,11 +354,32 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
}; };
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
// Optimisation for needless ring position calculation when the seed and biome is the same.
ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(
originalChunkProvider.chunkMap);
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state);
if (hasGeneratedPositions) {
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> origPositions =
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(state);
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(
origPositions);
ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(
freshChunkProvider.chunkMap);
ringPositionsField.set(newState, copy);
hasGeneratedPositionsField.setBoolean(newState, true);
}
}
chunkSourceField.set(freshWorld, freshChunkProvider); chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then //let's start then
structureManager = server.getStructureManager(); structureTemplateManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine(); threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
this.worldGenContext = new WorldGenContext(freshWorld, chunkGenerator, structureTemplateManager,
threadedLevelLightEngine
);
return true; return true;
} }
@ -362,7 +395,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
Fawe.instance().getQueueHandler().sync(() -> { Fawe.instance().getQueueHandler().sync(() -> {
try { try {
freshChunkProvider.close(false); freshChunkProvider.close(false);
} catch (IOException e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}); });
@ -385,7 +418,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
protected ProtoChunk createProtoChunk(int x, int z) { protected ProtoChunk createProtoChunk(int x, int z) {
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null this.freshWorld.registryAccess().registryOrThrow(BIOME), null
); );
} }
@ -411,7 +444,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access // BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); TaskManager.taskManager().task(() -> {
final CraftWorld world = freshWorld.getWorld();
final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ);
blockPopulator.populate(world, random, chunk);
});
} }
@Override @Override
@ -427,14 +464,12 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
//util //util
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void removeWorldFromWorldsMap() { private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> { try {
try { Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer()); map.remove("faweregentempworld");
map.remove("faweregentempworld"); } catch (IllegalAccessException e) {
} catch (IllegalAccessException e) { throw new RuntimeException(e);
throw new RuntimeException(e); }
}
});
} }
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) { private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
@ -451,11 +486,15 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
@Override @Override
public void updateSpawnPos(ChunkPos spawnPos) { public void updateSpawnPos(@NotNull ChunkPos spawnPos) {
} }
@Override @Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) { public void onStatusChange(
final @NotNull ChunkPos pos,
@org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status
) {
} }
@Override @Override
@ -487,15 +526,14 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
// avoid warning on paper // avoid warning on paper
// compatibility with spigot @SuppressWarnings("unused") // compatibility with spigot
public boolean generateFlatBedrock() { public boolean generateFlatBedrock() {
return generateFlatBedrock; return generateFlatBedrock;
} }
// no one will ever see the entities! // no one will ever see the entities!
@Override @Override
public List<CompoundTag> getEntities() { public @NotNull List<CompoundTag> getEntities() {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -516,23 +554,41 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
public String name() { public String name() {
return chunkStatus.getName(); return chunkStatus.toString();
} }
@Override @Override
public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) { public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) {
return chunkStatus.generate( return chunkStatus.generate(
Runnable::run, // TODO revisit, we might profit from this somehow? worldGenContext,
freshWorld, Runnable::run,
chunkGenerator, CompletableFuture::completedFuture,
structureManager, accessibleChunks
threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks,
true
); );
} }
} }
/**
* A light engine that does nothing. As light is calculated after pasting anyway, we can avoid
* work this way.
*/
static class NoOpLightEngine extends ThreadedLevelLightEngine {
private static final ProcessorMailbox<Runnable> MAILBOX = ProcessorMailbox.create(task -> {
}, "fawe-no-op");
private static final ProcessorHandle<Message<Runnable>> HANDLE = ProcessorHandle.of("fawe-no-op", m -> {
});
public NoOpLightEngine(final ServerChunkCache chunkProvider) {
super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE);
}
@Override
public @NotNull CompletableFuture<ChunkAccess> lightChunk(final @NotNull ChunkAccess chunk, final boolean excludeBlocks) {
return CompletableFuture.completedFuture(chunk);
}
}
} }

View File

@ -40,6 +40,7 @@ repositories {
name = "Glaremasters" name = "Glaremasters"
url = uri("https://repo.glaremasters.me/repository/towny/") url = uri("https://repo.glaremasters.me/repository/towny/")
} }
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO Remove when 4.17.0 is released
flatDir { dir(File("src/main/resources")) } flatDir { dir(File("src/main/resources")) }
} }
@ -182,7 +183,7 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("org.lz4:lz4-java:1.8.0")) include(dependency("org.lz4:lz4-java:1.8.0"))
} }
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") { relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
include(dependency("net.kyori:adventure-nbt:4.16.0")) include(dependency("net.kyori:adventure-nbt:4.17.0"))
} }
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") { relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
include(dependency("com.zaxxer:SparseBitSet:1.3")) include(dependency("com.zaxxer:SparseBitSet:1.3"))
@ -214,7 +215,7 @@ tasks {
versionNumber.set("${project.version}") versionNumber.set("${project.version}")
versionType.set("release") versionType.set("release")
uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar")) uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar"))
gameVersions.addAll(listOf("1.20.4", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4", "1.18.2")) gameVersions.addAll(listOf("1.20.6", "1.20.5", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4"))
loaders.addAll(listOf("paper", "spigot")) loaders.addAll(listOf("paper", "spigot"))
changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" + changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" +
"FastAsyncWorldEdit/releases/tag/${project.version}") "FastAsyncWorldEdit/releases/tag/${project.version}")

View File

@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent; import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
@ -24,11 +25,16 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList; import it.unimi.dsi.fastutil.longs.LongList;
import jdk.jfr.Category;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.WorldInfo; import org.bukkit.generator.WorldInfo;
import java.util.AbstractList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -36,6 +42,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -62,7 +69,7 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
protected final RegenOptions options; protected final RegenOptions options;
//runtime //runtime
protected final Map<ChunkStatus, Concurrency> chunkStatuses = new LinkedHashMap<>(); protected final LinkedHashMap<ChunkStatus, Concurrency> chunkStatuses = new LinkedHashMap<>(); // TODO (j21): use SequencedMap
private final Long2ObjectLinkedOpenHashMap<ProtoChunk> protoChunks = new Long2ObjectLinkedOpenHashMap<>(); private final Long2ObjectLinkedOpenHashMap<ProtoChunk> protoChunks = new Long2ObjectLinkedOpenHashMap<>();
private final Long2ObjectOpenHashMap<Chunk> chunks = new Long2ObjectOpenHashMap<>(); private final Long2ObjectOpenHashMap<Chunk> chunks = new Long2ObjectOpenHashMap<>();
protected boolean generateConcurrent = true; protected boolean generateConcurrent = true;
@ -172,51 +179,70 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
//TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)? //TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)?
//for now it is working well and fast, if we are bored in the future we could do the research (a lot of it) to reduce the border radius //for now it is working well and fast, if we are bored in the future we could do the research (a lot of it) to reduce the border radius
//generate chunk coords lists with a certain radius // to get the chunks we need to generate in the nth chunk status, we need to know how many chunks
Int2ObjectOpenHashMap<long[]> chunkCoordsForRadius = new Int2ObjectOpenHashMap<>(); // we need to generate in the n + 1 th chunk status. Summing up the margin solves that
chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { LinkedHashMap<ChunkStatus, long[]> chunkCoordsForChunkStatus = new LinkedHashMap<>();
if (radius == -1) { //ignore ChunkStatus.EMPTY int borderSum = 1;
return; // TODO (j21): use SequencedMap#sequencedKeySet().reversed()
} final List<ChunkStatus> reversedKeys = Lists.reverse(new ArrayList<>(chunkStatuses.keySet()));
int border = 10 - radius; //9 = 8 + 1, 8: max border radius used in chunk stages, 1: need 1 extra chunk for chunk for (final ChunkStatus status : reversedKeys) {
// features to generate at the border of the region chunkCoordsForChunkStatus.put(status, getChunkCoordsRegen(region, borderSum));
chunkCoordsForRadius.put(radius, getChunkCoordsRegen(region, border)); borderSum += status.requiredNeighborChunkRadius();
}); }
//create chunks //create chunks
for (long xz : chunkCoordsForRadius.get(0)) { // TODO (j21): use SequencedMap#firstEntry().getKey()
for (long xz : chunkCoordsForChunkStatus.get(chunkStatuses.keySet().iterator().next())) {
ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz)); ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz));
protoChunks.put(xz, chunk); protoChunks.put(xz, chunk);
} }
//generate lists for RegionLimitedWorldAccess, need to be square with odd length (e.g. 17x17), 17 = 1 middle chunk + 8 border chunks * 2 // a memory-efficient, lightweight "list" that calculates index -> ChunkAccess
Int2ObjectOpenHashMap<Long2ObjectOpenHashMap<List<IChunkAccess>>> worldLimits = new Int2ObjectOpenHashMap<>(); // as needed when accessed
chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> { class LazyChunkList extends AbstractList<IChunkAccess> {
if (radius == -1) { //ignore ChunkStatus.EMPTY private final int size;
return; private final int minX;
private final int minZ;
private final int sizeSqrt;
LazyChunkList(int radius, int centerX, int centerZ) {
this.sizeSqrt = radius + 1 + radius; // length of one side
this.size = this.sizeSqrt * this.sizeSqrt;
this.minX = centerX - radius;
this.minZ = centerZ - radius;
} }
Long2ObjectOpenHashMap<List<IChunkAccess>> map = new Long2ObjectOpenHashMap<>(); @Override
for (long xz : chunkCoordsForRadius.get(radius)) { public IChunkAccess get(final int index) {
int x = MathMan.unpairIntX(xz); Objects.checkIndex(index, size);
int z = MathMan.unpairIntY(xz); int absX = (index % sizeSqrt) + minX;
List<IChunkAccess> l = new ArrayList<>((radius + 1 + radius) * (radius + 1 + radius)); int absZ = (index / sizeSqrt) + minZ;
for (int zz = z - radius; zz <= z + radius; zz++) { //order is important, first z then x return protoChunks.get(MathMan.pairInt(absX, absZ));
for (int xx = x - radius; xx <= x + radius; xx++) {
l.add(protoChunks.get(MathMan.pairInt(xx, zz)));
}
}
map.put(xz, l);
} }
worldLimits.put(radius, map);
}); @Override
public int size() {
return size;
}
}
@Label("Regeneration")
@Category("FAWE")
@Name("fawe.regen")
class RegenerationEvent extends Event {
private String chunkStatus;
private int chunksToProcess;
}
//run generation tasks excluding FULL chunk status //run generation tasks excluding FULL chunk status
for (Map.Entry<ChunkStatus, Concurrency> entry : chunkStatuses.entrySet()) { for (Map.Entry<ChunkStatus, Concurrency> entry : chunkStatuses.entrySet()) {
ChunkStatus chunkStatus = entry.getKey(); ChunkStatus chunkStatus = entry.getKey();
int radius = chunkStatus.requiredNeighborChunkRadius0(); final RegenerationEvent event = new RegenerationEvent();
event.begin();
event.chunkStatus = chunkStatus.name();
int radius = Math.max(1, chunkStatus.requiredNeighborChunkRadius0());
long[] coords = chunkCoordsForRadius.get(radius); long[] coords = chunkCoordsForChunkStatus.get(chunkStatus);
Long2ObjectOpenHashMap<List<IChunkAccess>> limitsForRadius = worldLimits.get(radius); event.chunksToProcess = coords.length;
if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) { if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) {
SequentialTasks<ConcurrentTasks<LongList>> tasks = getChunkStatusTaskRows(coords, radius); SequentialTasks<ConcurrentTasks<LongList>> tasks = getChunkStatusTaskRows(coords, radius);
for (ConcurrentTasks<LongList> para : tasks) { for (ConcurrentTasks<LongList> para : tasks) {
@ -224,7 +250,8 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
for (LongList row : para) { for (LongList row : para) {
scheduled.add(() -> { scheduled.add(() -> {
for (long xz : row) { for (long xz : row) {
chunkStatus.processChunkSave(xz, limitsForRadius.get(xz)); chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz),
MathMan.unpairIntY(xz)));
} }
}); });
} }
@ -234,7 +261,8 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
// every chunk can be processed individually // every chunk can be processed individually
List<Runnable> scheduled = new ArrayList<>(coords.length); List<Runnable> scheduled = new ArrayList<>(coords.length);
for (long xz : coords) { for (long xz : coords) {
scheduled.add(() -> chunkStatus.processChunkSave(xz, limitsForRadius.get(xz))); scheduled.add(() -> chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz),
MathMan.unpairIntY(xz))));
} }
runAndWait(scheduled); runAndWait(scheduled);
} else { // Concurrency.NONE or generateConcurrent == false } else { // Concurrency.NONE or generateConcurrent == false
@ -242,28 +270,33 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
// running regen on the main thread otherwise triggers async-only events on the main thread // running regen on the main thread otherwise triggers async-only events on the main thread
executor.submit(() -> { executor.submit(() -> {
for (long xz : coords) { for (long xz : coords) {
chunkStatus.processChunkSave(xz, limitsForRadius.get(xz)); chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz),
MathMan.unpairIntY(xz)));
} }
}).get(); // wait until finished this step }).get(); // wait until finished this step
} }
event.commit();
} }
//convert to proper chunks //convert to proper chunks
for (long xz : chunkCoordsForRadius.get(0)) { // TODO (j21): use SequencedMap#firstEntry().getValue()
for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) {
ProtoChunk proto = protoChunks.get(xz); ProtoChunk proto = protoChunks.get(xz);
chunks.put(xz, createChunk(proto)); chunks.put(xz, createChunk(proto));
} }
//final chunkstatus //final chunkstatus
ChunkStatus FULL = getFullChunkStatus(); ChunkStatus FULL = getFullChunkStatus();
for (long xz : chunkCoordsForRadius.get(0)) { //FULL.requiredNeighbourChunkRadius() == 0! // TODO (j21): use SequencedMap#firstEntry().getValue()
for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { //FULL.requiredNeighbourChunkRadius() == 0!
Chunk chunk = chunks.get(xz); Chunk chunk = chunks.get(xz);
FULL.processChunkSave(xz, List.of(chunk)); FULL.processChunkSave(xz, List.of(chunk));
} }
//populate //populate
List<BlockPopulator> populators = getBlockPopulators(); List<BlockPopulator> populators = getBlockPopulators();
for (long xz : chunkCoordsForRadius.get(0)) { // TODO (j21): use SequencedMap#firstEntry().getValue()
for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) {
int x = MathMan.unpairIntX(xz); int x = MathMan.unpairIntX(xz);
int z = MathMan.unpairIntY(xz); int z = MathMan.unpairIntY(xz);
@ -277,8 +310,10 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
}); });
} }
source = new SingleThreadQueueExtent(BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, source = new SingleThreadQueueExtent(
BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256); BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0,
BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256
);
source.init(target, initSourceQueueCache(), null); source.init(target, initSourceQueueCache(), null);
return true; return true;
} }
@ -503,7 +538,7 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
int numlists = Math.min(requiredNeighbors * 2 + 1, maxZ - minZ + 1); int numlists = Math.min(requiredNeighbors * 2 + 1, maxZ - minZ + 1);
Int2ObjectOpenHashMap<LongList> byZ = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<LongList> byZ = new Int2ObjectOpenHashMap<>();
int expectedListLength = (coordsCount + 1) / (maxZ - minZ); int expectedListLength = (coordsCount + 1) / (maxZ - minZ + 2);
//init lists //init lists
for (int i = minZ; i <= maxZ; i++) { for (int i = minZ; i <= maxZ; i++) {
@ -581,13 +616,16 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
try { try {
processChunk(accessibleChunks).get(); processChunk(accessibleChunks).get();
} catch (Exception e) { } catch (Exception e) {
LOGGER.error( LOGGER.error("Error while running {} on chunk {}/{}",
"Error while running " + name() + " on chunk " + MathMan.unpairIntX(xz) + "/" + MathMan.unpairIntY(xz), name(), MathMan.unpairIntX(xz), MathMan.unpairIntY(xz), e);
e
);
} }
} }
@Override
public String toString() {
return name();
}
} }
public static class SequentialTasks<T> extends Tasks<T> { public static class SequentialTasks<T> extends Tasks<T> {

View File

@ -135,7 +135,7 @@ public abstract class ChunkListener implements Listener {
@Deprecated(since = "2.0.0") @Deprecated(since = "2.0.0")
public void cleanup(Chunk chunk) { public void cleanup(Chunk chunk) {
for (Entity entity : chunk.getEntities()) { for (Entity entity : chunk.getEntities()) {
if (entity.getType() == EntityType.DROPPED_ITEM) { if (entity.getType() == EntityType.ITEM) {
entity.remove(); entity.remove();
} }
} }

View File

@ -20,6 +20,7 @@
package com.sk89q.bukkit.util; package com.sk89q.bukkit.util;
import com.sk89q.util.ReflectionUtil; import com.sk89q.util.ReflectionUtil;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -96,12 +97,11 @@ public class CommandRegistration {
return fallbackCommands; return fallbackCommands;
} }
CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); CommandMap commandMap = PaperLib.isPaper() ? Bukkit.getCommandMap() : ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap");
if (commandMap == null) { if (commandMap == null) {
Bukkit.getServer().getLogger().severe(plugin.getDescription().getName() Bukkit.getServer().getLogger().severe(plugin.getDescription().getName()
+ ": Could not retrieve server CommandMap, using fallback instead!"); + ": Could not retrieve server CommandMap");
fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer()); throw new IllegalStateException("Failed to retrieve command map, make sure you are running supported server software");
Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin);
} else { } else {
serverCommandMap = commandMap; serverCommandMap = commandMap;
} }

View File

@ -1,16 +1,12 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.8.20" kotlin("jvm") version "1.9.23"
application application
} }
applyCommonConfiguration() applyCommonConfiguration()
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "17"
}
application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter") application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter")
tasks.named<JavaExec>("run") { tasks.named<JavaExec>("run") {
workingDir = rootProject.projectDir workingDir = rootProject.projectDir

View File

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.configuration;
import com.fastasyncworldedit.core.configuration.file.YamlConfiguration; import com.fastasyncworldedit.core.configuration.file.YamlConfiguration;
import com.fastasyncworldedit.core.util.StringMan; import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -14,8 +15,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -27,6 +30,9 @@ public class Config {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private final Map<String, Object> removedKeyVals = new HashMap<>();
private List<String> existingMigrateNodes = null;
public Config() { public Config() {
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0); save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
} }
@ -43,7 +49,8 @@ public class Config {
try { try {
return (T) field.get(instance); return (T) field.get(instance);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
e.printStackTrace(); LOGGER.error("Failed to get config option: {}", key, e);
return null;
} }
} }
} }
@ -67,6 +74,10 @@ public class Config {
if (field.getAnnotation(Final.class) != null) { if (field.getAnnotation(Final.class) != null) {
return; return;
} }
Migrate migrate = field.getAnnotation(Migrate.class);
if (existingMigrateNodes != null && migrate != null) {
existingMigrateNodes.add(migrate.value());
}
if (field.getType() == String.class && !(value instanceof String)) { if (field.getType() == String.class && !(value instanceof String)) {
value = value + ""; value = value + "";
} }
@ -74,17 +85,22 @@ public class Config {
field.set(instance, value); field.set(instance, value);
return; return;
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Failed to set config option: {}", key);
} }
} }
} }
LOGGER.error("Failed to set config option: {}: {} | {} | {}.yml", key, value, instance, root.getSimpleName()); removedKeyVals.put(key, value);
LOGGER.error(
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed.",
key,
value,
instance,
root.getSimpleName()
);
} }
public boolean load(File file) { public boolean load(File file) {
if (!file.exists()) { existingMigrateNodes = new ArrayList<>();
return false;
}
YamlConfiguration yml = YamlConfiguration.loadConfiguration(file); YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
for (String key : yml.getKeys(true)) { for (String key : yml.getKeys(true)) {
Object value = yml.get(key); Object value = yml.get(key);
@ -93,6 +109,10 @@ public class Config {
} }
set(key, value, getClass()); set(key, value, getClass());
} }
for (String node : existingMigrateNodes) {
removedKeyVals.remove(node);
}
existingMigrateNodes = null;
return true; return true;
} }
@ -113,7 +133,7 @@ public class Config {
save(writer, getClass(), instance, 0); save(writer, getClass(), instance, 0);
writer.close(); writer.close();
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Failed to save config file: {}", file, e);
} }
} }
@ -166,6 +186,19 @@ public class Config {
} }
/**
* Indicates that a field should be instantiated / created.
*
* @since 2.10.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Migrate {
String value();
}
@Ignore // This is not part of the config @Ignore // This is not part of the config
public static class ConfigBlock<T> { public static class ConfigBlock<T> {
@ -222,7 +255,6 @@ public class Config {
try { try {
String CTRF = System.lineSeparator(); String CTRF = System.lineSeparator();
String spacing = StringMan.repeat(" ", indent); String spacing = StringMan.repeat(" ", indent);
HashMap<Class<?>, Object> instances = new HashMap<>();
for (Field field : clazz.getFields()) { for (Field field : clazz.getFields()) {
if (field.getAnnotation(Ignore.class) != null) { if (field.getAnnotation(Ignore.class) != null) {
continue; continue;
@ -239,31 +271,14 @@ public class Config {
} }
if (current == ConfigBlock.class) { if (current == ConfigBlock.class) {
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0]; current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
comment = current.getAnnotation(Comment.class); handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current);
if (comment != null) {
for (String commentLine : comment.value()) {
writer.write(spacing + "# " + commentLine + CTRF);
}
}
BlockName blockNames = current.getAnnotation(BlockName.class);
if (blockNames != null) {
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
ConfigBlock configBlock = (ConfigBlock) field.get(instance);
if (configBlock == null || configBlock.getInstances().isEmpty()) {
configBlock = new ConfigBlock();
field.set(instance, configBlock);
for (String blockName : blockNames.value()) {
configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
}
}
// Save each instance
for (Map.Entry<String, Object> entry : ((Map<String, Object>) configBlock.getRaw()).entrySet()) {
String key = entry.getKey();
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
save(writer, current, entry.getValue(), indent + 4);
}
}
continue; continue;
} else if (!removedKeyVals.isEmpty()) {
Migrate migrate = field.getAnnotation(Migrate.class);
Object value;
if (migrate != null && (value = removedKeyVals.remove(migrate.value())) != null) {
field.set(instance, value);
}
} }
Create create = field.getAnnotation(Create.class); Create create = field.getAnnotation(Create.class);
if (create != null) { if (create != null) {
@ -281,7 +296,6 @@ public class Config {
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
if (value == null) { if (value == null) {
field.set(instance, value = current.getDeclaredConstructor().newInstance()); field.set(instance, value = current.getDeclaredConstructor().newInstance());
instances.put(current, value);
} }
save(writer, current, value, indent + 2); save(writer, current, value, indent + 2);
} else { } else {
@ -292,7 +306,42 @@ public class Config {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Failed to save config file", e);
}
}
private <T> void handleConfigBlockSave(
PrintWriter writer,
Object instance,
int indent,
Field field,
String spacing,
String CTRF,
Class<T> current
) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Comment comment = current.getAnnotation(Comment.class);
if (comment != null) {
for (String commentLine : comment.value()) {
writer.write(spacing + "# " + commentLine + CTRF);
}
}
BlockName blockNames = current.getAnnotation(BlockName.class);
if (blockNames != null) {
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
ConfigBlock<T> configBlock = (ConfigBlock<T>) field.get(instance);
if (configBlock == null || configBlock.getInstances().isEmpty()) {
configBlock = new ConfigBlock<>();
field.set(instance, configBlock);
for (String blockName : blockNames.value()) {
configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
}
}
// Save each instance
for (Map.Entry<String, T> entry : configBlock.getRaw().entrySet()) {
String key = entry.getKey();
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
save(writer, current, entry.getValue(), indent + 4);
}
} }
} }
@ -311,7 +360,7 @@ public class Config {
return field; return field;
} catch (Throwable ignored) { } catch (Throwable ignored) {
LOGGER.warn( LOGGER.warn(
"Invalid config field: {} for {}", "Invalid config field: {} for {}. It is possible this is because it has been removed.",
StringMan.join(split, "."), StringMan.join(split, "."),
toNodeName(instance.getClass().getSimpleName()) toNodeName(instance.getClass().getSimpleName())
); );
@ -379,7 +428,7 @@ public class Config {
return null; return null;
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Failed retrieving instance for config node: {}", StringUtil.joinString(split, "."), e);
} }
return null; return null;
} }

View File

@ -79,6 +79,8 @@ public class Settings extends Config {
@Create @Create
public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS; public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS;
@Create @Create
public GENERAL GENERAL;
@Create
public ConfigBlock<LIMITS> LIMITS; public ConfigBlock<LIMITS> LIMITS;
private Settings() { private Settings() {
@ -145,6 +147,14 @@ public class Settings extends Config {
limit.MAX_HISTORY, limit.MAX_HISTORY,
newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE
); );
limit.SCHEM_FILE_NUM_LIMIT = Math.max(
limit.SCHEM_FILE_NUM_LIMIT,
newLimit.SCHEM_FILE_NUM_LIMIT != -1 ? newLimit.SCHEM_FILE_NUM_LIMIT : Integer.MAX_VALUE
);
limit.SCHEM_FILE_SIZE_LIMIT = Math.max(
limit.SCHEM_FILE_SIZE_LIMIT,
newLimit.SCHEM_FILE_SIZE_LIMIT != -1 ? newLimit.SCHEM_FILE_SIZE_LIMIT : Integer.MAX_VALUE
);
limit.MAX_EXPRESSION_MS = Math.max( limit.MAX_EXPRESSION_MS = Math.max(
limit.MAX_EXPRESSION_MS, limit.MAX_EXPRESSION_MS,
newLimit.MAX_EXPRESSION_MS != -1 ? newLimit.MAX_EXPRESSION_MS : Integer.MAX_VALUE newLimit.MAX_EXPRESSION_MS != -1 ? newLimit.MAX_EXPRESSION_MS : Integer.MAX_VALUE
@ -353,6 +363,18 @@ public class Settings extends Config {
" - History on disk or memory will be deleted", " - History on disk or memory will be deleted",
}) })
public int MAX_HISTORY_MB = -1; public int MAX_HISTORY_MB = -1;
@Comment({
"Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)",
"Set to -1 to disable"
})
@Migrate("experimental.per-player-file-size-limit")
public int SCHEM_FILE_SIZE_LIMIT = -1;
@Comment({
"Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)",
"Set to -1 to disable"
})
@Migrate("experimental.per-player-file-num-limit")
public int SCHEM_FILE_NUM_LIMIT = -1;
@Comment("Maximum time in milliseconds //calc can execute") @Comment("Maximum time in milliseconds //calc can execute")
public int MAX_EXPRESSION_MS = 50; public int MAX_EXPRESSION_MS = 50;
@Comment({ @Comment({
@ -615,18 +637,6 @@ public class Settings extends Config {
}) })
public boolean ALLOW_TICK_FLUIDS = false; public boolean ALLOW_TICK_FLUIDS = false;
@Comment({
"Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)",
"Set to -1 to disable"
})
public int PER_PLAYER_FILE_SIZE_LIMIT = -1;
@Comment({
"Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)",
"Set to -1 to disable"
})
public int PER_PLAYER_FILE_NUM_LIMIT = -1;
} }
@Comment({"Web/HTTP connection related settings"}) @Comment({"Web/HTTP connection related settings"})
@ -744,4 +754,13 @@ public class Settings extends Config {
} }
public static class GENERAL {
@Comment({
"If the player should be relocated/unstuck when a generation command would bury them",
})
public boolean UNSTUCK_ON_GENERATE = true;
}
} }

View File

@ -15,6 +15,8 @@ public class FaweLimit {
public int MAX_BLOCKSTATES = 0; public int MAX_BLOCKSTATES = 0;
public int MAX_ENTITIES = 0; public int MAX_ENTITIES = 0;
public int MAX_HISTORY = 0; public int MAX_HISTORY = 0;
public int SCHEM_FILE_SIZE_LIMIT = 0;
public int SCHEM_FILE_NUM_LIMIT = 0;
public int MAX_EXPRESSION_MS = 0; public int MAX_EXPRESSION_MS = 0;
public int INVENTORY_MODE = Integer.MAX_VALUE; public int INVENTORY_MODE = Integer.MAX_VALUE;
public int SPEED_REDUCTION = Integer.MAX_VALUE; public int SPEED_REDUCTION = Integer.MAX_VALUE;
@ -111,6 +113,8 @@ public class FaweLimit {
MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE; MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE;
MAX.MAX_ENTITIES = Integer.MAX_VALUE; MAX.MAX_ENTITIES = Integer.MAX_VALUE;
MAX.MAX_HISTORY = Integer.MAX_VALUE; MAX.MAX_HISTORY = Integer.MAX_VALUE;
MAX.SCHEM_FILE_NUM_LIMIT = Integer.MAX_VALUE;
MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE;
MAX.MAX_EXPRESSION_MS = 50; MAX.MAX_EXPRESSION_MS = 50;
MAX.FAST_PLACEMENT = true; MAX.FAST_PLACEMENT = true;
MAX.CONFIRM_LARGE = true; MAX.CONFIRM_LARGE = true;
@ -237,6 +241,8 @@ public class FaweLimit {
&& MAX_BLOCKSTATES == Integer.MAX_VALUE && MAX_BLOCKSTATES == Integer.MAX_VALUE
&& MAX_ENTITIES == Integer.MAX_VALUE && MAX_ENTITIES == Integer.MAX_VALUE
&& MAX_HISTORY == Integer.MAX_VALUE && MAX_HISTORY == Integer.MAX_VALUE
&& SCHEM_FILE_SIZE_LIMIT == Integer.MAX_VALUE
&& SCHEM_FILE_NUM_LIMIT == Integer.MAX_VALUE
&& INVENTORY_MODE == 0 && INVENTORY_MODE == 0
&& SPEED_REDUCTION == 0 && SPEED_REDUCTION == 0
&& FAST_PLACEMENT && FAST_PLACEMENT
@ -256,6 +262,8 @@ public class FaweLimit {
MAX_FAILS = limit.MAX_FAILS; MAX_FAILS = limit.MAX_FAILS;
MAX_ITERATIONS = limit.MAX_ITERATIONS; MAX_ITERATIONS = limit.MAX_ITERATIONS;
MAX_HISTORY = limit.MAX_HISTORY; MAX_HISTORY = limit.MAX_HISTORY;
SCHEM_FILE_NUM_LIMIT = limit.SCHEM_FILE_NUM_LIMIT;
SCHEM_FILE_SIZE_LIMIT = limit.SCHEM_FILE_SIZE_LIMIT;
INVENTORY_MODE = limit.INVENTORY_MODE; INVENTORY_MODE = limit.INVENTORY_MODE;
SPEED_REDUCTION = limit.SPEED_REDUCTION; SPEED_REDUCTION = limit.SPEED_REDUCTION;
FAST_PLACEMENT = limit.FAST_PLACEMENT; FAST_PLACEMENT = limit.FAST_PLACEMENT;
@ -279,6 +287,8 @@ public class FaweLimit {
limit.MAX_FAILS = MAX_FAILS; limit.MAX_FAILS = MAX_FAILS;
limit.MAX_ITERATIONS = MAX_ITERATIONS; limit.MAX_ITERATIONS = MAX_ITERATIONS;
limit.MAX_HISTORY = MAX_HISTORY; limit.MAX_HISTORY = MAX_HISTORY;
limit.SCHEM_FILE_SIZE_LIMIT = SCHEM_FILE_SIZE_LIMIT;
limit.SCHEM_FILE_NUM_LIMIT = SCHEM_FILE_NUM_LIMIT;
limit.FAST_PLACEMENT = FAST_PLACEMENT; limit.FAST_PLACEMENT = FAST_PLACEMENT;
limit.CONFIRM_LARGE = CONFIRM_LARGE; limit.CONFIRM_LARGE = CONFIRM_LARGE;
limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS; limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS;

View File

@ -23,7 +23,7 @@ import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.net.JarURLConnection; import java.net.JarURLConnection;
import java.net.URL; import java.net.URI;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.jar.Attributes; import java.util.jar.Attributes;
import java.util.jar.Manifest; import java.util.jar.Manifest;
@ -73,8 +73,7 @@ public class WorldEditManifest {
} }
try { try {
URL url = new URL(classPath); JarURLConnection jarConnection = (JarURLConnection) URI.create(classPath).toURL().openConnection();
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
Manifest manifest = jarConnection.getManifest(); Manifest manifest = jarConnection.getManifest();
return manifest.getMainAttributes(); return manifest.getMainAttributes();
} catch (IOException e) { } catch (IOException e) {

View File

@ -184,6 +184,9 @@ public class GenerationCommands {
BlockVector3 pos = session.getPlacementPosition(actor); BlockVector3 pos = session.getPlacementPosition(actor);
int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow); int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow);
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition();
}
actor.print(Caption.of("worldedit.cyl.created", TextComponent.of(affected))); actor.print(Caption.of("worldedit.cyl.created", TextComponent.of(affected)));
return affected; return affected;
} }
@ -227,6 +230,9 @@ public class GenerationCommands {
BlockVector3 pos = session.getPlacementPosition(actor); BlockVector3 pos = session.getPlacementPosition(actor);
int affected = editSession.makeCone(pos, pattern, radiusX, radiusZ, height, !hollow, thickness); int affected = editSession.makeCone(pos, pattern, radiusX, radiusZ, height, !hollow, thickness);
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition();
}
actor.printInfo(Caption.of("worldedit.cone.created", TextComponent.of(affected))); actor.printInfo(Caption.of("worldedit.cone.created", TextComponent.of(affected)));
return affected; return affected;
} }
@ -293,7 +299,7 @@ public class GenerationCommands {
} }
int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow); int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow);
if (actor instanceof Player) { if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition(); ((Player) actor).findFreePosition();
} }
actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected)));
@ -379,7 +385,7 @@ public class GenerationCommands {
worldEdit.checkMaxRadius(size); worldEdit.checkMaxRadius(size);
BlockVector3 pos = session.getPlacementPosition(actor); BlockVector3 pos = session.getPlacementPosition(actor);
int affected = editSession.makePyramid(pos, pattern, size, !hollow); int affected = editSession.makePyramid(pos, pattern, size, !hollow);
if (actor instanceof Player) { if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition(); ((Player) actor).findFreePosition();
} }
actor.print(Caption.of("worldedit.pyramid.created", TextComponent.of(affected))); actor.print(Caption.of("worldedit.pyramid.created", TextComponent.of(affected)));
@ -457,7 +463,7 @@ public class GenerationCommands {
hollow, hollow,
session.getTimeout() session.getTimeout()
); );
if (actor instanceof Player) { if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition(); ((Player) actor).findFreePosition();
} }
actor.print(Caption.of("worldedit.generate.created", TextComponent.of(affected))); actor.print(Caption.of("worldedit.generate.created", TextComponent.of(affected)));
@ -741,7 +747,7 @@ public class GenerationCommands {
radius.divide(max), radius.divide(max),
sphericity / 100 sphericity / 100
); );
if (actor instanceof Player) { if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition(); ((Player) actor).findFreePosition();
} }
actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected))); actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected)));

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.FaweAPI; import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode; import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.limit.FaweLimit;
import com.fastasyncworldedit.core.util.MaskTraverser; import com.fastasyncworldedit.core.util.MaskTraverser;
@ -715,6 +716,9 @@ public class RegionCommands {
session.setSourceMask(mask); session.setSourceMask(mask);
//FAWE end //FAWE end
} }
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition();
}
if (success) { if (success) {
actor.print(Caption.of("worldedit.regen.regenerated")); actor.print(Caption.of("worldedit.regen.regenerated"));
} else { } else {
@ -788,7 +792,7 @@ public class RegionCommands {
String.join(" ", expression), String.join(" ", expression),
session.getTimeout() session.getTimeout()
); );
if (actor instanceof Player) { if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
((Player) actor).findFreePosition(); ((Player) actor).findFreePosition();
} }
actor.print(Caption.of("worldedit.deform.deformed", TextComponent.of(affected))); actor.print(Caption.of("worldedit.deform.deformed", TextComponent.of(affected)));

View File

@ -26,6 +26,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder; import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure; import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MainUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -60,15 +61,19 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.util.io.file.FilenameException; import com.sk89q.worldedit.util.io.file.FilenameException;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.sk89q.worldedit.util.paste.EngineHubPaste;
import com.sk89q.worldedit.util.paste.PasteMetadata;
import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.StopExecutionException; import org.enginehub.piston.exception.StopExecutionException;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -79,9 +84,12 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -525,6 +533,42 @@ public class SchematicCommands {
.buildAndExec(worldEdit.getExecutorService()); .buildAndExec(worldEdit.getExecutorService());
} }
@Command(
name = "share",
desc = "Share your clipboard as a schematic online"
)
@CommandPermissions({ "worldedit.clipboard.share", "worldedit.schematic.share" })
public void share(Actor actor, LocalSession session,
@Arg(desc = "Schematic name. Defaults to name-millis", def = "")
String schematicName,
@Arg(desc = "Format name.", def = "sponge")
String formatName) throws WorldEditException {
if (true) {
throw new UnsupportedOperationException("This feature is currently not implemented");
}
if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) {
actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version"));
return;
}
ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) {
actor.printError(TranslatableComponent.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
return;
}
ClipboardHolder holder = session.getClipboard();
SchematicShareTask task = new SchematicShareTask(actor, format, holder, schematicName);
AsyncCommandBuilder.wrap(task, actor)
.registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic")
.setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving"))
.setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving"))
.onSuccess("Shared", (url -> actor.printInfo(TextComponent.of(url.toExternalForm() + ".schem").clickEvent(ClickEvent.openUrl(url.toExternalForm() + ".schem")))))
.onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
.buildAndExec(worldEdit.getExecutorService());
}
@Command( @Command(
name = "formats", name = "formats",
aliases = {"listformats", "f"}, aliases = {"listformats", "f"},
@ -689,10 +733,10 @@ public class SchematicCommands {
String headerBytesElem = String.format("%.1fkb", totalBytes / 1000.0); String headerBytesElem = String.format("%.1fkb", totalBytes / 1000.0);
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1) { if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1) {
headerBytesElem += String.format( headerBytesElem += String.format(
" / %dkb", " / %dkb",
Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT actor.getLimit().SCHEM_FILE_SIZE_LIMIT
); );
} }
@ -793,14 +837,48 @@ public class SchematicCommands {
} }
private static class SchematicSaveTask implements Callable<Void> { private abstract static class SchematicOutputTask<T> implements Callable<T> {
protected final Actor actor;
protected final ClipboardFormat format;
protected final ClipboardHolder holder;
private final Actor actor; SchematicOutputTask(
private final ClipboardFormat format; Actor actor,
private final ClipboardHolder holder; ClipboardFormat format,
ClipboardHolder holder
) {
this.actor = actor;
this.format = format;
this.holder = holder;
}
protected void writeToOutputStream(OutputStream outputStream) throws Exception {
Clipboard clipboard = holder.getClipboard();
Transform transform = holder.getTransform();
Clipboard target;
// If we have a transform, bake it into the copy
if (transform.isIdentity()) {
target = clipboard;
} else {
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform);
target = new BlockArrayClipboard(result.getTransformedRegion());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
}
try (Closer closer = Closer.create()) {
OutputStream stream = closer.register(outputStream);
BufferedOutputStream bos = closer.register(new BufferedOutputStream(stream));
ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target);
}
}
}
private static class SchematicSaveTask extends SchematicOutputTask<Void> {
private File file;
private final boolean overwrite; private final boolean overwrite;
private final File rootDir; private final File rootDir;
private File file;
SchematicSaveTask( SchematicSaveTask(
Actor actor, Actor actor,
@ -810,11 +888,9 @@ public class SchematicCommands {
ClipboardHolder holder, ClipboardHolder holder,
boolean overwrite boolean overwrite
) { ) {
this.actor = actor; super(actor, format, holder);
this.file = file; this.file = file;
this.rootDir = rootDir; this.rootDir = rootDir;
this.format = format;
this.holder = holder;
this.overwrite = overwrite; this.overwrite = overwrite;
} }
@ -826,7 +902,7 @@ public class SchematicCommands {
//FAWE start //FAWE start
boolean checkFilesize = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS boolean checkFilesize = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS
&& Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT > -1; && actor.getLimit().SCHEM_FILE_SIZE_LIMIT > -1;
double directorysizeKb = 0; double directorysizeKb = 0;
String curFilepath = file.getAbsolutePath(); String curFilepath = file.getAbsolutePath();
@ -856,7 +932,7 @@ public class SchematicCommands {
} }
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) {
if (numFiles == -1) { if (numFiles == -1) {
numFiles = 0; numFiles = 0;
@ -869,7 +945,7 @@ public class SchematicCommands {
} }
} }
} }
int limit = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT; int limit = actor.getLimit().SCHEM_FILE_NUM_LIMIT;
if (numFiles >= limit) { if (numFiles >= limit) {
TextComponent noSlotsErr = TextComponent.of( //TODO - to be moved into captions/translatablecomponents TextComponent noSlotsErr = TextComponent.of( //TODO - to be moved into captions/translatablecomponents
@ -920,7 +996,7 @@ public class SchematicCommands {
if (checkFilesize) { if (checkFilesize) {
double curKb = filesizeKb + directorysizeKb; double curKb = filesizeKb + directorysizeKb;
int allocatedKb = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT; int allocatedKb = actor.getLimit().SCHEM_FILE_SIZE_LIMIT;
if (overwrite) { if (overwrite) {
curKb -= oldKbOverwritten; curKb -= oldKbOverwritten;
@ -955,11 +1031,11 @@ public class SchematicCommands {
actor.print(kbRemainingNotif); actor.print(kbRemainingNotif);
} }
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT > -1) { if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && actor.getLimit().SCHEM_FILE_NUM_LIMIT > -1) {
TextComponent slotsRemainingNotif = TextComponent.of( TextComponent slotsRemainingNotif = TextComponent.of(
//TODO - to be moved into captions/translatablecomponents //TODO - to be moved into captions/translatablecomponents
"You have " + (Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_NUM_LIMIT - numFiles) "You have " + (actor.getLimit().SCHEM_FILE_NUM_LIMIT - numFiles)
+ " schematic file slots left.", + " schematic file slots left.",
TextColor.GRAY TextColor.GRAY
); );
@ -973,7 +1049,32 @@ public class SchematicCommands {
//FAWE end //FAWE end
return null; return null;
} }
}
private static class SchematicShareTask extends SchematicOutputTask<URL> {
private final String name;
SchematicShareTask(Actor actor, ClipboardFormat format, ClipboardHolder holder, String name) {
super(actor, format, holder);
this.name = name;
}
@Override
public URL call() throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
writeToOutputStream(baos);
} catch (Exception e) {
throw new CommandException(TextComponent.of(e.getMessage()), e, ImmutableList.of());
}
EngineHubPaste pasteService = new EngineHubPaste();
PasteMetadata metadata = new PasteMetadata();
metadata.author = this.actor.getName();
metadata.extension = "schem";
metadata.name = name == null ? actor.getName() + "-" + System.currentTimeMillis() : name;
return pasteService.paste(new String(Base64.getEncoder().encode(baos.toByteArray()), StandardCharsets.UTF_8), metadata).call();
}
} }
private static class SchematicListTask implements Callable<Component> { private static class SchematicListTask implements Callable<Component> {

View File

@ -56,6 +56,7 @@ public class BaseEntity implements NbtValued {
* @param nbtData NBT data * @param nbtData NBT data
* @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)} * @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)}
*/ */
@SuppressWarnings("this-escape")
@Deprecated @Deprecated
public BaseEntity(EntityType type, CompoundTag nbtData) { public BaseEntity(EntityType type, CompoundTag nbtData) {
this(type); this(type);
@ -87,6 +88,7 @@ public class BaseEntity implements NbtValued {
* *
* @param other the object to clone * @param other the object to clone
*/ */
@SuppressWarnings("this-escape")
public BaseEntity(BaseEntity other) { public BaseEntity(BaseEntity other) {
checkNotNull(other); checkNotNull(other);
this.type = other.getType(); this.type = other.getType();

View File

@ -62,6 +62,7 @@ public class BlockChangeLimiter extends AbstractDelegateExtent {
* *
* @param limit the limit (&gt;= 0) or -1 for no limit * @param limit the limit (&gt;= 0) or -1 for no limit
*/ */
@SuppressWarnings("this-escape") // Unlikely anyone is extending this in practice
public void setLimit(int limit) { public void setLimit(int limit) {
checkArgument(limit >= -1, "limit >= -1 required"); checkArgument(limit >= -1, "limit >= -1 required");
this.limit = limit; this.limit = limit;

View File

@ -19,11 +19,16 @@
package com.sk89q.worldedit.util.io; package com.sk89q.worldedit.util.io;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
public class ForwardSeekableInputStream extends InputStream { public class ForwardSeekableInputStream extends InputStream {
private static final Logger LOGGER = LogManager.getLogger();
protected InputStream parent; protected InputStream parent;
protected long position = 0; protected long position = 0;
@ -60,7 +65,7 @@ public class ForwardSeekableInputStream extends InputStream {
@Override @Override
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
int read = super.read(b, off, len); int read = parent.read(b, off, len);
position += read; position += read;
return read; return read;
} }
@ -86,6 +91,7 @@ public class ForwardSeekableInputStream extends InputStream {
public void seek(long n) throws IOException { public void seek(long n) throws IOException {
long diff = n - position; long diff = n - position;
LOGGER.error("Seek to {} from {} using {}", n, position, diff);
if (diff < 0) { if (diff < 0) {
throw new IOException("Can't seek backwards"); throw new IOException("Can't seek backwards");

View File

@ -357,7 +357,7 @@ public class HttpRequest implements Closeable {
*/ */
public static URL url(String url) { public static URL url(String url) {
try { try {
return new URL(url); return URI.create(url).toURL();
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -371,13 +371,7 @@ public class HttpRequest implements Closeable {
*/ */
private static URL reformat(URL existing) { private static URL reformat(URL existing) {
try { try {
URL url = new URL(existing.toString()); return existing.toURI().toURL();
URI uri = new URI(
url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(),
url.getPath(), url.getQuery(), url.getRef()
);
url = uri.toURL();
return url;
} catch (MalformedURLException | URISyntaxException e) { } catch (MalformedURLException | URISyntaxException e) {
return existing; return existing;
} }

View File

@ -83,4 +83,26 @@ public final class ActorCallbackPaste {
.buildAndExec(Pasters.getExecutor()); .buildAndExec(Pasters.getExecutor());
} }
/**
* Submit data to a pastebin service and inform the sender of
* success or failure.
*
* @param supervisor The supervisor instance
* @param sender The sender
* @param content The content
* @param pasteMetadata The paste metadata
* @param successMessage The message builder, given the URL as an arg
*/
public static void pastebin(Supervisor supervisor, final Actor sender, String content, PasteMetadata pasteMetadata, final TranslatableComponent.Builder successMessage) {
Callable<URL> task = paster.paste(content, pasteMetadata);
AsyncCommandBuilder.wrap(task, sender)
.registerWithSupervisor(supervisor, "Submitting content to a pastebin service.")
.setDelayMessage(TranslatableComponent.of("worldedit.pastebin.uploading"))
.onSuccess((String) null, url -> sender.printInfo(successMessage.args(TextComponent.of(url.toString())).build()))
.onFailure("Failed to submit paste", null)
.buildAndExec(Pasters.getExecutor());
}
} }

View File

@ -24,6 +24,7 @@ import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.util.net.HttpRequest; import com.sk89q.worldedit.util.net.HttpRequest;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -33,23 +34,38 @@ public class EngineHubPaste implements Paster {
private static final Gson GSON = new Gson(); private static final Gson GSON = new Gson();
@Override @Override
public Callable<URL> paste(String content) { public Callable<URL> paste(String content, PasteMetadata metadata) {
return new PasteTask(content); return new PasteTask(content, metadata);
} }
private static final class PasteTask implements Callable<URL> { private static final class PasteTask implements Callable<URL> {
private final String content; private final String content;
private final PasteMetadata metadata;
private PasteTask(String content) { private PasteTask(String content, PasteMetadata metadata) {
this.content = content; this.content = content;
this.metadata = metadata;
} }
@Override @Override
public URL call() throws IOException, InterruptedException { public URL call() throws IOException, InterruptedException {
URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste"); URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste");
SignedPasteResponse response = GSON.fromJson(HttpRequest.get(initialUrl) HttpRequest requestBuilder = HttpRequest.get(initialUrl);
requestBuilder.header("x-paste-meta-from", "EngineHub");
if (metadata.name != null) {
requestBuilder.header("x-paste-meta-name", metadata.name);
}
if (metadata.author != null) {
requestBuilder.header("x-paste-meta-author", metadata.author);
}
if (metadata.extension != null) {
requestBuilder.header("x-paste-meta-extension", metadata.extension);
}
SignedPasteResponse response = GSON.fromJson(requestBuilder
.execute() .execute()
.expectResponseCode(200) .expectResponseCode(200)
.returnContent() .returnContent()
@ -68,7 +84,7 @@ public class EngineHubPaste implements Paster {
.execute() .execute()
.expectResponseCode(200, 204); .expectResponseCode(200, 204);
return new URL(response.viewUrl); return URI.create(response.viewUrl).toURL();
} }
} }

View File

@ -0,0 +1,26 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.paste;
public class PasteMetadata {
public String name;
public String extension;
public String author;
}

View File

@ -24,6 +24,10 @@ import java.util.concurrent.Callable;
public interface Paster { public interface Paster {
Callable<URL> paste(String content); default Callable<URL> paste(String content) {
return paste(content, new PasteMetadata());
}
Callable<URL> paste(String content, PasteMetadata metadata);
} }

View File

@ -82,21 +82,22 @@ public class FutureForwardingTask<V> extends AbstractTask<V> {
return future.get(timeout, unit); return future.get(timeout, unit);
} }
// TODO: consider deprecating in favor of Future.State?
@Override @Override
public State getState() { public Task.State getState() {
if (isCancelled()) { if (isCancelled()) {
return State.CANCELLED; return Task.State.CANCELLED;
} else if (isDone()) { } else if (isDone()) {
try { try {
get(); get();
return State.SUCCEEDED; return Task.State.SUCCEEDED;
} catch (InterruptedException e) { } catch (InterruptedException e) {
return State.CANCELLED; return Task.State.CANCELLED;
} catch (ExecutionException e) { } catch (ExecutionException e) {
return State.FAILED; return Task.State.FAILED;
} }
} else { } else {
return State.RUNNING; return Task.State.RUNNING;
} }
} }

View File

@ -33,8 +33,10 @@ public final class BlockCategories {
public static final BlockCategory ANCIENT_CITY_REPLACEABLE = get("minecraft:ancient_city_replaceable"); public static final BlockCategory ANCIENT_CITY_REPLACEABLE = get("minecraft:ancient_city_replaceable");
public static final BlockCategory ANIMALS_SPAWNABLE_ON = get("minecraft:animals_spawnable_on"); public static final BlockCategory ANIMALS_SPAWNABLE_ON = get("minecraft:animals_spawnable_on");
public static final BlockCategory ANVIL = get("minecraft:anvil"); public static final BlockCategory ANVIL = get("minecraft:anvil");
public static final BlockCategory ARMADILLO_SPAWNABLE_ON = get("minecraft:armadillo_spawnable_on");
public static final BlockCategory AXOLOTLS_SPAWNABLE_ON = get("minecraft:axolotls_spawnable_on"); public static final BlockCategory AXOLOTLS_SPAWNABLE_ON = get("minecraft:axolotls_spawnable_on");
public static final BlockCategory AZALEA_GROWS_ON = get("minecraft:azalea_grows_on"); public static final BlockCategory AZALEA_GROWS_ON = get("minecraft:azalea_grows_on");
public static final BlockCategory BADLANDS_TERRACOTTA = get("minecraft:badlands_terracotta");
public static final BlockCategory AZALEA_ROOT_REPLACEABLE = get("minecraft:azalea_root_replaceable"); public static final BlockCategory AZALEA_ROOT_REPLACEABLE = get("minecraft:azalea_root_replaceable");
public static final BlockCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final BlockCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks");
public static final BlockCategory BAMBOO_PLANTABLE_ON = get("minecraft:bamboo_plantable_on"); public static final BlockCategory BAMBOO_PLANTABLE_ON = get("minecraft:bamboo_plantable_on");
@ -78,6 +80,7 @@ public final class BlockCategories {
public static final BlockCategory DIRT = get("minecraft:dirt"); public static final BlockCategory DIRT = get("minecraft:dirt");
@Deprecated @Deprecated
public static final BlockCategory DIRT_LIKE = get("minecraft:dirt_like"); public static final BlockCategory DIRT_LIKE = get("minecraft:dirt_like");
public static final BlockCategory DOES_NOT_BLOCK_HOPPERS = get("minecraft:does_not_block_hoppers");
public static final BlockCategory DOORS = get("minecraft:doors"); public static final BlockCategory DOORS = get("minecraft:doors");
public static final BlockCategory DRAGON_IMMUNE = get("minecraft:dragon_immune"); public static final BlockCategory DRAGON_IMMUNE = get("minecraft:dragon_immune");
public static final BlockCategory DRAGON_TRANSPARENT = get("minecraft:dragon_transparent"); public static final BlockCategory DRAGON_TRANSPARENT = get("minecraft:dragon_transparent");
@ -103,6 +106,12 @@ public final class BlockCategories {
public static final BlockCategory HOGLIN_REPELLENTS = get("minecraft:hoglin_repellents"); public static final BlockCategory HOGLIN_REPELLENTS = get("minecraft:hoglin_repellents");
public static final BlockCategory ICE = get("minecraft:ice"); public static final BlockCategory ICE = get("minecraft:ice");
public static final BlockCategory IMPERMEABLE = get("minecraft:impermeable"); public static final BlockCategory IMPERMEABLE = get("minecraft:impermeable");
public static final BlockCategory INCORRECT_FOR_DIAMOND_TOOL = get("minecraft:incorrect_for_diamond_tool");
public static final BlockCategory INCORRECT_FOR_GOLD_TOOL = get("minecraft:incorrect_for_gold_tool");
public static final BlockCategory INCORRECT_FOR_IRON_TOOL = get("minecraft:incorrect_for_iron_tool");
public static final BlockCategory INCORRECT_FOR_NETHERITE_TOOL = get("minecraft:incorrect_for_netherite_tool");
public static final BlockCategory INCORRECT_FOR_STONE_TOOL = get("minecraft:incorrect_for_stone_tool");
public static final BlockCategory INCORRECT_FOR_WOODEN_TOOL = get("minecraft:incorrect_for_wooden_tool");
public static final BlockCategory INFINIBURN_END = get("minecraft:infiniburn_end"); public static final BlockCategory INFINIBURN_END = get("minecraft:infiniburn_end");
public static final BlockCategory INFINIBURN_NETHER = get("minecraft:infiniburn_nether"); public static final BlockCategory INFINIBURN_NETHER = get("minecraft:infiniburn_nether");
public static final BlockCategory INFINIBURN_OVERWORLD = get("minecraft:infiniburn_overworld"); public static final BlockCategory INFINIBURN_OVERWORLD = get("minecraft:infiniburn_overworld");

View File

@ -60,6 +60,7 @@ public class BlockType implements Keyed, Pattern {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private final String id; private final String id;
@SuppressWarnings("this-escape")
private final LazyReference<FuzzyBlockState> emptyFuzzy private final LazyReference<FuzzyBlockState> emptyFuzzy
= LazyReference.from(() -> new FuzzyBlockState(this)); = LazyReference.from(() -> new FuzzyBlockState(this));
//FAWE start //FAWE start

View File

@ -483,6 +483,10 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType COPPER_GRATE = init(); public static final BlockType COPPER_GRATE = init();
@Nullable @Nullable
public static final BlockType COPPER_ORE = init();
@Nullable
public static final BlockType COPPER_TRAPDOOR = init();
@Nullable
public static final BlockType CORNFLOWER = init(); public static final BlockType CORNFLOWER = init();
@Nullable @Nullable
public static final BlockType CRACKED_DEEPSLATE_BRICKS = init(); public static final BlockType CRACKED_DEEPSLATE_BRICKS = init();
@ -495,6 +499,8 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType CRACKED_STONE_BRICKS = init(); public static final BlockType CRACKED_STONE_BRICKS = init();
@Nullable @Nullable
public static final BlockType CRAFTER = init();
@Nullable
public static final BlockType CRAFTING_TABLE = init(); public static final BlockType CRAFTING_TABLE = init();
@Nullable @Nullable
public static final BlockType CREEPER_HEAD = init(); public static final BlockType CREEPER_HEAD = init();
@ -685,8 +691,6 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType DEEPSLATE_COPPER_ORE = init(); public static final BlockType DEEPSLATE_COPPER_ORE = init();
@Nullable @Nullable
public static final BlockType COPPER_TRAPDOOR = init();
@Nullable
public static final BlockType DEEPSLATE_DIAMOND_ORE = init(); public static final BlockType DEEPSLATE_DIAMOND_ORE = init();
@Nullable @Nullable
public static final BlockType DEEPSLATE_EMERALD_ORE = init(); public static final BlockType DEEPSLATE_EMERALD_ORE = init();
@ -747,8 +751,6 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType ENDER_CHEST = init(); public static final BlockType ENDER_CHEST = init();
@Nullable @Nullable
public static final BlockType EXPOSED_CHISELED_COPPER = init();
@Nullable
public static final BlockType END_GATEWAY = init(); public static final BlockType END_GATEWAY = init();
@Nullable @Nullable
public static final BlockType END_PORTAL = init(); public static final BlockType END_PORTAL = init();
@ -767,6 +769,8 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType END_STONE_BRICK_WALL = init(); public static final BlockType END_STONE_BRICK_WALL = init();
@Nullable @Nullable
public static final BlockType EXPOSED_CHISELED_COPPER = init();
@Nullable
public static final BlockType EXPOSED_COPPER = init(); public static final BlockType EXPOSED_COPPER = init();
@Nullable @Nullable
public static final BlockType EXPOSED_COPPER_BULB = init(); public static final BlockType EXPOSED_COPPER_BULB = init();
@ -836,6 +840,9 @@ public final class BlockTypes {
public static final BlockType GRASS = init(); public static final BlockType GRASS = init();
@Nullable @Nullable
public static final BlockType GRASS_BLOCK = init(); public static final BlockType GRASS_BLOCK = init();
@Deprecated
@Nullable
public static final BlockType GRASS_PATH = init();
@Nullable @Nullable
public static final BlockType GRAVEL = init(); public static final BlockType GRAVEL = init();
@Nullable @Nullable
@ -901,6 +908,8 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType HAY_BLOCK = init(); public static final BlockType HAY_BLOCK = init();
@Nullable @Nullable
public static final BlockType HEAVY_CORE = init();
@Nullable
public static final BlockType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); public static final BlockType HEAVY_WEIGHTED_PRESSURE_PLATE = init();
@Nullable @Nullable
public static final BlockType HONEYCOMB_BLOCK = init(); public static final BlockType HONEYCOMB_BLOCK = init();
@ -925,8 +934,6 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType INFESTED_CRACKED_STONE_BRICKS = init(); public static final BlockType INFESTED_CRACKED_STONE_BRICKS = init();
@Nullable @Nullable
public static final BlockType CRAFTER = init();
@Nullable
public static final BlockType INFESTED_DEEPSLATE = init(); public static final BlockType INFESTED_DEEPSLATE = init();
@Nullable @Nullable
public static final BlockType INFESTED_MOSSY_STONE_BRICKS = init(); public static final BlockType INFESTED_MOSSY_STONE_BRICKS = init();
@ -1954,10 +1961,12 @@ public final class BlockTypes {
@Nullable @Nullable
public static final BlockType TWISTING_VINES = init(); public static final BlockType TWISTING_VINES = init();
@Nullable @Nullable
public static final BlockType VERDANT_FROGLIGHT = init();
@Nullable
public static final BlockType TWISTING_VINES_PLANT = init(); public static final BlockType TWISTING_VINES_PLANT = init();
@Nullable @Nullable
public static final BlockType VAULT = init();
@Nullable
public static final BlockType VERDANT_FROGLIGHT = init();
@Nullable
public static final BlockType VINE = init(); public static final BlockType VINE = init();
@Nullable @Nullable
public static final BlockType VOID_AIR = init(); public static final BlockType VOID_AIR = init();
@ -2026,7 +2035,7 @@ public final class BlockTypes {
public static final BlockType WAXED_CUT_COPPER_SLAB = init(); public static final BlockType WAXED_CUT_COPPER_SLAB = init();
@Nullable @Nullable
public static final BlockType WAXED_CUT_COPPER_STAIRS = init(); public static final BlockType WAXED_CUT_COPPER_STAIRS = init();
@ Nullable @Nullable
public static final BlockType WAXED_EXPOSED_CHISELED_COPPER = init(); public static final BlockType WAXED_EXPOSED_CHISELED_COPPER = init();
@Nullable @Nullable
public static final BlockType WAXED_EXPOSED_COPPER = init(); public static final BlockType WAXED_EXPOSED_COPPER = init();

View File

@ -163,7 +163,7 @@ public class AnvilChunk13 implements Chunk {
throw new InvalidFormatException("Too short block state table"); throw new InvalidFormatException("Too short block state table");
} }
currentSerializedValue = blockStatesSerialized[nextSerializedItem++]; currentSerializedValue = blockStatesSerialized[nextSerializedItem++];
localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits; localBlockId |= (int) ((currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits);
currentSerializedValue >>>= bitsNextLong; currentSerializedValue >>>= bitsNextLong;
remainingBits = 64 - bitsNextLong; remainingBits = 64 - bitsNextLong;
} else { } else {

View File

@ -35,6 +35,8 @@ public final class EntityTypes {
@Nullable @Nullable
public static final EntityType AREA_EFFECT_CLOUD = get("minecraft:area_effect_cloud"); public static final EntityType AREA_EFFECT_CLOUD = get("minecraft:area_effect_cloud");
@Nullable @Nullable
public static final EntityType ARMADILLO = get("minecraft:armadillo");
@Nullable
public static final EntityType ARMOR_STAND = get("minecraft:armor_stand"); public static final EntityType ARMOR_STAND = get("minecraft:armor_stand");
@Nullable @Nullable
public static final EntityType ARROW = get("minecraft:arrow"); public static final EntityType ARROW = get("minecraft:arrow");
@ -51,8 +53,12 @@ public final class EntityTypes {
@Nullable @Nullable
public static final EntityType BOAT = get("minecraft:boat"); public static final EntityType BOAT = get("minecraft:boat");
@Nullable @Nullable
public static final EntityType BOGGED = get("minecraft:bogged");
@Nullable
public static final EntityType BREEZE = get("minecraft:breeze"); public static final EntityType BREEZE = get("minecraft:breeze");
@Nullable @Nullable
public static final EntityType BREEZE_WIND_CHARGE = get("minecraft:breeze_wind_charge");
@Nullable
public static final EntityType CAMEL = get("minecraft:camel"); public static final EntityType CAMEL = get("minecraft:camel");
@Nullable @Nullable
public static final EntityType CAT = get("minecraft:cat"); public static final EntityType CAT = get("minecraft:cat");
@ -171,6 +177,8 @@ public final class EntityTypes {
@Nullable @Nullable
public static final EntityType OCELOT = get("minecraft:ocelot"); public static final EntityType OCELOT = get("minecraft:ocelot");
@Nullable @Nullable
public static final EntityType OMINOUS_ITEM_SPAWNER = get("minecraft:ominous_item_spawner");
@Nullable
public static final EntityType PAINTING = get("minecraft:painting"); public static final EntityType PAINTING = get("minecraft:painting");
@Nullable @Nullable
public static final EntityType PANDA = get("minecraft:panda"); public static final EntityType PANDA = get("minecraft:panda");

View File

@ -29,28 +29,36 @@ public final class ItemCategories {
public static final ItemCategory ACACIA_LOGS = get("minecraft:acacia_logs"); public static final ItemCategory ACACIA_LOGS = get("minecraft:acacia_logs");
public static final ItemCategory ANVIL = get("minecraft:anvil"); public static final ItemCategory ANVIL = get("minecraft:anvil");
public static final ItemCategory ARMADILLO_FOOD = get("minecraft:armadillo_food");
public static final ItemCategory ARROWS = get("minecraft:arrows"); public static final ItemCategory ARROWS = get("minecraft:arrows");
public static final ItemCategory AXES = get("minecraft:axes"); public static final ItemCategory AXES = get("minecraft:axes");
public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items"); public static final ItemCategory AXOLOTL_FOOD = get("minecraft:axolotl_food");
@Deprecated public static final ItemCategory AXOLOTL_TEMPT_ITEMS = get("minecraft:axolotl_tempt_items");
public static final ItemCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks"); public static final ItemCategory BAMBOO_BLOCKS = get("minecraft:bamboo_blocks");
public static final ItemCategory BANNERS = get("minecraft:banners"); public static final ItemCategory BANNERS = get("minecraft:banners");
public static final ItemCategory BEACON_PAYMENT_ITEMS = get("minecraft:beacon_payment_items"); public static final ItemCategory BEACON_PAYMENT_ITEMS = get("minecraft:beacon_payment_items");
public static final ItemCategory BEDS = get("minecraft:beds"); public static final ItemCategory BEDS = get("minecraft:beds");
public static final ItemCategory BEE_FOOD = get("minecraft:bee_food");
public static final ItemCategory BIRCH_LOGS = get("minecraft:birch_logs"); public static final ItemCategory BIRCH_LOGS = get("minecraft:birch_logs");
public static final ItemCategory BOATS = get("minecraft:boats"); public static final ItemCategory BOATS = get("minecraft:boats");
public static final ItemCategory BOOKSHELF_BOOKS = get("minecraft:bookshelf_books"); public static final ItemCategory BOOKSHELF_BOOKS = get("minecraft:bookshelf_books");
public static final ItemCategory BREAKS_DECORATED_POTS = get("minecraft:breaks_decorated_pots"); public static final ItemCategory BREAKS_DECORATED_POTS = get("minecraft:breaks_decorated_pots");
public static final ItemCategory BUTTONS = get("minecraft:buttons"); public static final ItemCategory BUTTONS = get("minecraft:buttons");
public static final ItemCategory CAMEL_FOOD = get("minecraft:camel_food");
public static final ItemCategory CANDLES = get("minecraft:candles"); public static final ItemCategory CANDLES = get("minecraft:candles");
@Deprecated public static final ItemCategory CARPETS = get("minecraft:carpets"); @Deprecated public static final ItemCategory CARPETS = get("minecraft:carpets");
public static final ItemCategory CAT_FOOD = get("minecraft:cat_food");
public static final ItemCategory CHERRY_LOGS = get("minecraft:cherry_logs"); public static final ItemCategory CHERRY_LOGS = get("minecraft:cherry_logs");
public static final ItemCategory CHEST_ARMOR = get("minecraft:chest_armor");
public static final ItemCategory CHEST_BOATS = get("minecraft:chest_boats"); public static final ItemCategory CHEST_BOATS = get("minecraft:chest_boats");
public static final ItemCategory CHICKEN_FOOD = get("minecraft:chicken_food");
public static final ItemCategory CLUSTER_MAX_HARVESTABLES = get("minecraft:cluster_max_harvestables"); public static final ItemCategory CLUSTER_MAX_HARVESTABLES = get("minecraft:cluster_max_harvestables");
public static final ItemCategory COAL_ORES = get("minecraft:coal_ores"); public static final ItemCategory COAL_ORES = get("minecraft:coal_ores");
public static final ItemCategory COALS = get("minecraft:coals"); public static final ItemCategory COALS = get("minecraft:coals");
public static final ItemCategory COMPASSES = get("minecraft:compasses"); public static final ItemCategory COMPASSES = get("minecraft:compasses");
public static final ItemCategory COMPLETES_FIND_TREE_TUTORIAL = get("minecraft:completes_find_tree_tutorial"); public static final ItemCategory COMPLETES_FIND_TREE_TUTORIAL = get("minecraft:completes_find_tree_tutorial");
public static final ItemCategory COPPER_ORES = get("minecraft:copper_ores"); public static final ItemCategory COPPER_ORES = get("minecraft:copper_ores");
public static final ItemCategory COW_FOOD = get("minecraft:cow_food");
public static final ItemCategory CREEPER_DROP_MUSIC_DISCS = get("minecraft:creeper_drop_music_discs"); public static final ItemCategory CREEPER_DROP_MUSIC_DISCS = get("minecraft:creeper_drop_music_discs");
public static final ItemCategory CREEPER_IGNITERS = get("minecraft:creeper_igniters"); public static final ItemCategory CREEPER_IGNITERS = get("minecraft:creeper_igniters");
public static final ItemCategory CRIMSON_STEMS = get("minecraft:crimson_stems"); public static final ItemCategory CRIMSON_STEMS = get("minecraft:crimson_stems");
@ -61,44 +69,82 @@ public final class ItemCategories {
public static final ItemCategory DIAMOND_ORES = get("minecraft:diamond_ores"); public static final ItemCategory DIAMOND_ORES = get("minecraft:diamond_ores");
public static final ItemCategory DIRT = get("minecraft:dirt"); public static final ItemCategory DIRT = get("minecraft:dirt");
public static final ItemCategory DOORS = get("minecraft:doors"); public static final ItemCategory DOORS = get("minecraft:doors");
public static final ItemCategory DYEABLE = get("minecraft:dyeable");
public static final ItemCategory EMERALD_ORES = get("minecraft:emerald_ores"); public static final ItemCategory EMERALD_ORES = get("minecraft:emerald_ores");
public static final ItemCategory ENCHANTABLE_ARMOR = get("minecraft:enchantable/armor");
public static final ItemCategory ENCHANTABLE_BOW = get("minecraft:enchantable/bow");
public static final ItemCategory ENCHANTABLE_CHEST_ARMOR = get("minecraft:enchantable/chest_armor");
public static final ItemCategory ENCHANTABLE_CROSSBOW = get("minecraft:enchantable/crossbow");
public static final ItemCategory ENCHANTABLE_DURABILITY = get("minecraft:enchantable/durability");
public static final ItemCategory ENCHANTABLE_EQUIPPABLE = get("minecraft:enchantable/equippable");
public static final ItemCategory ENCHANTABLE_FIRE_ASPECT = get("minecraft:enchantable/fire_aspect");
public static final ItemCategory ENCHANTABLE_FISHING = get("minecraft:enchantable/fishing");
public static final ItemCategory ENCHANTABLE_FOOT_ARMOR = get("minecraft:enchantable/foot_armor");
public static final ItemCategory ENCHANTABLE_HEAD_ARMOR = get("minecraft:enchantable/head_armor");
public static final ItemCategory ENCHANTABLE_LEG_ARMOR = get("minecraft:enchantable/leg_armor");
public static final ItemCategory ENCHANTABLE_MINING = get("minecraft:enchantable/mining");
public static final ItemCategory ENCHANTABLE_MINING_LOOT = get("minecraft:enchantable/mining_loot");
public static final ItemCategory ENCHANTABLE_SHARP_WEAPON = get("minecraft:enchantable/sharp_weapon");
public static final ItemCategory ENCHANTABLE_SWORD = get("minecraft:enchantable/sword");
public static final ItemCategory ENCHANTABLE_TRIDENT = get("minecraft:enchantable/trident");
public static final ItemCategory ENCHANTABLE_VANISHING = get("minecraft:enchantable/vanishing");
public static final ItemCategory ENCHANTABLE_WEAPON = get("minecraft:enchantable/weapon");
public static final ItemCategory FENCE_GATES = get("minecraft:fence_gates"); public static final ItemCategory FENCE_GATES = get("minecraft:fence_gates");
public static final ItemCategory FENCES = get("minecraft:fences"); public static final ItemCategory FENCES = get("minecraft:fences");
public static final ItemCategory FISHES = get("minecraft:fishes"); public static final ItemCategory FISHES = get("minecraft:fishes");
public static final ItemCategory FLOWERS = get("minecraft:flowers"); public static final ItemCategory FLOWERS = get("minecraft:flowers");
public static final ItemCategory FOOT_ARMOR = get("minecraft:foot_armor");
public static final ItemCategory FOX_FOOD = get("minecraft:fox_food"); public static final ItemCategory FOX_FOOD = get("minecraft:fox_food");
public static final ItemCategory FREEZE_IMMUNE_WEARABLES = get("minecraft:freeze_immune_wearables"); public static final ItemCategory FREEZE_IMMUNE_WEARABLES = get("minecraft:freeze_immune_wearables");
public static final ItemCategory FROG_FOOD = get("minecraft:frog_food");
@Deprecated @Deprecated
public static final ItemCategory FURNACE_MATERIALS = get("minecraft:furnace_materials"); public static final ItemCategory FURNACE_MATERIALS = get("minecraft:furnace_materials");
public static final ItemCategory GOAT_FOOD = get("minecraft:goat_food");
public static final ItemCategory GOLD_ORES = get("minecraft:gold_ores"); public static final ItemCategory GOLD_ORES = get("minecraft:gold_ores");
public static final ItemCategory HANGING_SIGNS = get("minecraft:hanging_signs"); public static final ItemCategory HANGING_SIGNS = get("minecraft:hanging_signs");
public static final ItemCategory HEAD_ARMOR = get("minecraft:head_armor");
public static final ItemCategory HOES = get("minecraft:hoes"); public static final ItemCategory HOES = get("minecraft:hoes");
public static final ItemCategory HOGLIN_FOOD = get("minecraft:hoglin_food");
public static final ItemCategory HORSE_FOOD = get("minecraft:horse_food");
public static final ItemCategory HORSE_TEMPT_ITEMS = get("minecraft:horse_tempt_items");
public static final ItemCategory IGNORED_BY_PIGLIN_BABIES = get("minecraft:ignored_by_piglin_babies"); public static final ItemCategory IGNORED_BY_PIGLIN_BABIES = get("minecraft:ignored_by_piglin_babies");
public static final ItemCategory IRON_ORES = get("minecraft:iron_ores"); public static final ItemCategory IRON_ORES = get("minecraft:iron_ores");
public static final ItemCategory JUNGLE_LOGS = get("minecraft:jungle_logs"); public static final ItemCategory JUNGLE_LOGS = get("minecraft:jungle_logs");
public static final ItemCategory LAPIS_ORES = get("minecraft:lapis_ores"); public static final ItemCategory LAPIS_ORES = get("minecraft:lapis_ores");
public static final ItemCategory LEAVES = get("minecraft:leaves"); public static final ItemCategory LEAVES = get("minecraft:leaves");
public static final ItemCategory LECTERN_BOOKS = get("minecraft:lectern_books"); public static final ItemCategory LECTERN_BOOKS = get("minecraft:lectern_books");
public static final ItemCategory LEG_ARMOR = get("minecraft:leg_armor");
public static final ItemCategory LLAMA_FOOD = get("minecraft:llama_food");
public static final ItemCategory LLAMA_TEMPT_ITEMS = get("minecraft:llama_tempt_items");
public static final ItemCategory LOGS = get("minecraft:logs"); public static final ItemCategory LOGS = get("minecraft:logs");
public static final ItemCategory LOGS_THAT_BURN = get("minecraft:logs_that_burn"); public static final ItemCategory LOGS_THAT_BURN = get("minecraft:logs_that_burn");
public static final ItemCategory MANGROVE_LOGS = get("minecraft:mangrove_logs"); public static final ItemCategory MANGROVE_LOGS = get("minecraft:mangrove_logs");
public static final ItemCategory MEAT = get("minecraft:meat");
public static final ItemCategory MUSIC_DISCS = get("minecraft:music_discs"); public static final ItemCategory MUSIC_DISCS = get("minecraft:music_discs");
public static final ItemCategory NON_FLAMMABLE_WOOD = get("minecraft:non_flammable_wood"); public static final ItemCategory NON_FLAMMABLE_WOOD = get("minecraft:non_flammable_wood");
public static final ItemCategory NOTEBLOCK_TOP_INSTRUMENTS = get("minecraft:noteblock_top_instruments"); public static final ItemCategory NOTEBLOCK_TOP_INSTRUMENTS = get("minecraft:noteblock_top_instruments");
public static final ItemCategory OAK_LOGS = get("minecraft:oak_logs"); public static final ItemCategory OAK_LOGS = get("minecraft:oak_logs");
@Deprecated public static final ItemCategory OCCLUDES_VIBRATION_SIGNALS = get("minecraft:occludes_vibration_signals"); @Deprecated public static final ItemCategory OCCLUDES_VIBRATION_SIGNALS = get("minecraft:occludes_vibration_signals");
public static final ItemCategory OCELOT_FOOD = get("minecraft:ocelot_food");
@Deprecated public static final ItemCategory OVERWORLD_NATURAL_LOGS = get("minecraft:overworld_natural_logs"); @Deprecated public static final ItemCategory OVERWORLD_NATURAL_LOGS = get("minecraft:overworld_natural_logs");
public static final ItemCategory PANDA_FOOD = get("minecraft:panda_food");
public static final ItemCategory PARROT_FOOD = get("minecraft:parrot_food");
public static final ItemCategory PARROT_POISONOUS_FOOD = get("minecraft:parrot_poisonous_food");
public static final ItemCategory PICKAXES = get("minecraft:pickaxes"); public static final ItemCategory PICKAXES = get("minecraft:pickaxes");
public static final ItemCategory PIG_FOOD = get("minecraft:pig_food");
public static final ItemCategory PIGLIN_FOOD = get("minecraft:piglin_food"); public static final ItemCategory PIGLIN_FOOD = get("minecraft:piglin_food");
public static final ItemCategory PIGLIN_LOVED = get("minecraft:piglin_loved"); public static final ItemCategory PIGLIN_LOVED = get("minecraft:piglin_loved");
public static final ItemCategory PIGLIN_REPELLENTS = get("minecraft:piglin_repellents"); public static final ItemCategory PIGLIN_REPELLENTS = get("minecraft:piglin_repellents");
public static final ItemCategory PLANKS = get("minecraft:planks"); public static final ItemCategory PLANKS = get("minecraft:planks");
public static final ItemCategory RABBIT_FOOD = get("minecraft:rabbit_food");
public static final ItemCategory RAILS = get("minecraft:rails"); public static final ItemCategory RAILS = get("minecraft:rails");
public static final ItemCategory REDSTONE_ORES = get("minecraft:redstone_ores"); public static final ItemCategory REDSTONE_ORES = get("minecraft:redstone_ores");
public static final ItemCategory SAND = get("minecraft:sand"); public static final ItemCategory SAND = get("minecraft:sand");
public static final ItemCategory SAPLINGS = get("minecraft:saplings"); public static final ItemCategory SAPLINGS = get("minecraft:saplings");
public static final ItemCategory SHEEP_FOOD = get("minecraft:sheep_food");
public static final ItemCategory SHOVELS = get("minecraft:shovels"); public static final ItemCategory SHOVELS = get("minecraft:shovels");
public static final ItemCategory SIGNS = get("minecraft:signs"); public static final ItemCategory SIGNS = get("minecraft:signs");
public static final ItemCategory SKULLS = get("minecraft:skulls");
public static final ItemCategory SLABS = get("minecraft:slabs"); public static final ItemCategory SLABS = get("minecraft:slabs");
public static final ItemCategory SMALL_FLOWERS = get("minecraft:small_flowers"); public static final ItemCategory SMALL_FLOWERS = get("minecraft:small_flowers");
public static final ItemCategory SMELTS_TO_GLASS = get("minecraft:smelts_to_glass"); public static final ItemCategory SMELTS_TO_GLASS = get("minecraft:smelts_to_glass");
@ -110,18 +156,22 @@ public final class ItemCategories {
public static final ItemCategory STONE_BUTTONS = get("minecraft:stone_buttons"); public static final ItemCategory STONE_BUTTONS = get("minecraft:stone_buttons");
public static final ItemCategory STONE_CRAFTING_MATERIALS = get("minecraft:stone_crafting_materials"); public static final ItemCategory STONE_CRAFTING_MATERIALS = get("minecraft:stone_crafting_materials");
public static final ItemCategory STONE_TOOL_MATERIALS = get("minecraft:stone_tool_materials"); public static final ItemCategory STONE_TOOL_MATERIALS = get("minecraft:stone_tool_materials");
public static final ItemCategory STRIDER_FOOD = get("minecraft:strider_food");
public static final ItemCategory STRIDER_TEMPT_ITEMS = get("minecraft:strider_tempt_items");
public static final ItemCategory SWORDS = get("minecraft:swords"); public static final ItemCategory SWORDS = get("minecraft:swords");
public static final ItemCategory TALL_FLOWERS = get("minecraft:tall_flowers"); public static final ItemCategory TALL_FLOWERS = get("minecraft:tall_flowers");
public static final ItemCategory TERRACOTTA = get("minecraft:terracotta"); public static final ItemCategory TERRACOTTA = get("minecraft:terracotta");
public static final ItemCategory TOOLS = get("minecraft:tools"); @Deprecated public static final ItemCategory TOOLS = get("minecraft:tools");
public static final ItemCategory TRAPDOORS = get("minecraft:trapdoors"); public static final ItemCategory TRAPDOORS = get("minecraft:trapdoors");
public static final ItemCategory TRIM_MATERIALS = get("minecraft:trim_materials"); public static final ItemCategory TRIM_MATERIALS = get("minecraft:trim_materials");
public static final ItemCategory TRIM_TEMPLATES = get("minecraft:trim_templates"); public static final ItemCategory TRIM_TEMPLATES = get("minecraft:trim_templates");
public static final ItemCategory TRIMMABLE_ARMOR = get("minecraft:trimmable_armor"); public static final ItemCategory TRIMMABLE_ARMOR = get("minecraft:trimmable_armor");
public static final ItemCategory TURTLE_FOOD = get("minecraft:turtle_food");
public static final ItemCategory VILLAGER_PLANTABLE_SEEDS = get("minecraft:villager_plantable_seeds"); public static final ItemCategory VILLAGER_PLANTABLE_SEEDS = get("minecraft:villager_plantable_seeds");
public static final ItemCategory WALLS = get("minecraft:walls"); public static final ItemCategory WALLS = get("minecraft:walls");
public static final ItemCategory WARPED_STEMS = get("minecraft:warped_stems"); public static final ItemCategory WARPED_STEMS = get("minecraft:warped_stems");
public static final ItemCategory WART_BLOCKS = get("minecraft:wart_blocks"); public static final ItemCategory WART_BLOCKS = get("minecraft:wart_blocks");
public static final ItemCategory WOLF_FOOD = get("minecraft:wolf_food");
public static final ItemCategory WOODEN_BUTTONS = get("minecraft:wooden_buttons"); public static final ItemCategory WOODEN_BUTTONS = get("minecraft:wooden_buttons");
public static final ItemCategory WOODEN_DOORS = get("minecraft:wooden_doors"); public static final ItemCategory WOODEN_DOORS = get("minecraft:wooden_doors");
public static final ItemCategory WOODEN_FENCES = get("minecraft:wooden_fences"); public static final ItemCategory WOODEN_FENCES = get("minecraft:wooden_fences");

View File

@ -42,7 +42,7 @@ public class ItemType implements RegistryItem, Keyed {
public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type", true); public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type", true);
private final String id; private final String id;
@SuppressWarnings("deprecation") @SuppressWarnings({"deprecation", "this-escape"})
private transient final LazyReference<String> name = LazyReference.from(() -> { private transient final LazyReference<String> name = LazyReference.from(() -> {
String name = GuavaUtil.firstNonNull( String name = GuavaUtil.firstNonNull(
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
@ -51,10 +51,12 @@ public class ItemType implements RegistryItem, Keyed {
); );
return name.isEmpty() ? getId() : name; return name.isEmpty() ? getId() : name;
}); });
@SuppressWarnings("this-escape")
private transient final LazyReference<Component> richName = LazyReference.from(() -> private transient final LazyReference<Component> richName = LazyReference.from(() ->
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getRegistries().getItemRegistry().getRichName(this) .getRegistries().getItemRegistry().getRichName(this)
); );
@SuppressWarnings("this-escape")
private transient final LazyReference<ItemMaterial> itemMaterial = LazyReference.from(() -> private transient final LazyReference<ItemMaterial> itemMaterial = LazyReference.from(() ->
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS) WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getRegistries().getItemRegistry().getMaterial(this) .getRegistries().getItemRegistry().getMaterial(this)

View File

@ -105,6 +105,10 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType ARMOR_STAND = init(); public static final ItemType ARMOR_STAND = init();
@Nullable @Nullable
public static final ItemType ARMADILLO_SCUTE = init();
@Nullable
public static final ItemType ARMADILLO_SPAWN_EGG = init();
@Nullable
public static final ItemType ARMS_UP_POTTERY_SHERD = init(); public static final ItemType ARMS_UP_POTTERY_SHERD = init();
@Nullable @Nullable
public static final ItemType ARROW = init(); public static final ItemType ARROW = init();
@ -297,6 +301,10 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType BLUE_WOOL = init(); public static final ItemType BLUE_WOOL = init();
@Nullable @Nullable
public static final ItemType BOGGED_SPAWN_EGG = init();
@Nullable
public static final ItemType BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = init();
@Nullable
public static final ItemType BONE = init(); public static final ItemType BONE = init();
@Nullable @Nullable
public static final ItemType BONE_BLOCK = init(); public static final ItemType BONE_BLOCK = init();
@ -319,6 +327,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType BREAD = init(); public static final ItemType BREAD = init();
@Nullable @Nullable
public static final ItemType BREEZE_ROD = init();
@Nullable
public static final ItemType BREEZE_SPAWN_EGG = init(); public static final ItemType BREEZE_SPAWN_EGG = init();
@Nullable @Nullable
public static final ItemType BREWER_POTTERY_SHERD = init(); public static final ItemType BREWER_POTTERY_SHERD = init();
@ -971,6 +981,12 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType FLINT_AND_STEEL = init(); public static final ItemType FLINT_AND_STEEL = init();
@Nullable @Nullable
public static final ItemType FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = init();
@Nullable
public static final ItemType FLOW_BANNER_PATTERN = init();
@Nullable
public static final ItemType FLOW_POTTERY_SHERD = init();
@Nullable
public static final ItemType FLOWER_BANNER_PATTERN = init(); public static final ItemType FLOWER_BANNER_PATTERN = init();
@Nullable @Nullable
public static final ItemType FLOWER_POT = init(); public static final ItemType FLOWER_POT = init();
@ -1132,6 +1148,10 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType GUNPOWDER = init(); public static final ItemType GUNPOWDER = init();
@Nullable @Nullable
public static final ItemType GUSTER_BANNER_PATTERN = init();
@Nullable
public static final ItemType GUSTER_POTTERY_SHERD = init();
@Nullable
public static final ItemType HANGING_ROOTS = init(); public static final ItemType HANGING_ROOTS = init();
@Nullable @Nullable
public static final ItemType HAY_BLOCK = init(); public static final ItemType HAY_BLOCK = init();
@ -1142,6 +1162,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType HEARTBREAK_POTTERY_SHERD = init(); public static final ItemType HEARTBREAK_POTTERY_SHERD = init();
@Nullable @Nullable
public static final ItemType HEAVY_CORE = init();
@Nullable
public static final ItemType HEAVY_WEIGHTED_PRESSURE_PLATE = init(); public static final ItemType HEAVY_WEIGHTED_PRESSURE_PLATE = init();
@Nullable @Nullable
public static final ItemType HOGLIN_SPAWN_EGG = init(); public static final ItemType HOGLIN_SPAWN_EGG = init();
@ -1404,6 +1426,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType LOOM = init(); public static final ItemType LOOM = init();
@Nullable @Nullable
public static final ItemType MACE = init();
@Nullable
public static final ItemType MAGENTA_BANNER = init(); public static final ItemType MAGENTA_BANNER = init();
@Nullable @Nullable
public static final ItemType MAGENTA_BED = init(); public static final ItemType MAGENTA_BED = init();
@ -1668,6 +1692,10 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType OCHRE_FROGLIGHT = init(); public static final ItemType OCHRE_FROGLIGHT = init();
@Nullable @Nullable
public static final ItemType OMINOUS_BOTTLE = init();
@Nullable
public static final ItemType OMINOUS_TRIAL_KEY = init();
@Nullable
public static final ItemType ORANGE_BANNER = init(); public static final ItemType ORANGE_BANNER = init();
@Nullable @Nullable
public static final ItemType ORANGE_BED = init(); public static final ItemType ORANGE_BED = init();
@ -2075,6 +2103,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType SCAFFOLDING = init(); public static final ItemType SCAFFOLDING = init();
@Nullable @Nullable
public static final ItemType SCRAPE_POTTERY_SHERD = init();
@Nullable
public static final ItemType SCULK = init(); public static final ItemType SCULK = init();
@Nullable @Nullable
public static final ItemType SCULK_CATALYST = init(); public static final ItemType SCULK_CATALYST = init();
@ -2085,6 +2115,7 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType SCULK_VEIN = init(); public static final ItemType SCULK_VEIN = init();
@Nullable @Nullable
@Deprecated
public static final ItemType SCUTE = init(); public static final ItemType SCUTE = init();
@Nullable @Nullable
public static final ItemType SEA_LANTERN = init(); public static final ItemType SEA_LANTERN = init();
@ -2424,10 +2455,14 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType TURTLE_HELMET = init(); public static final ItemType TURTLE_HELMET = init();
@Nullable @Nullable
public static final ItemType TURTLE_SCUTE = init();
@Nullable
public static final ItemType TURTLE_SPAWN_EGG = init(); public static final ItemType TURTLE_SPAWN_EGG = init();
@Nullable @Nullable
public static final ItemType TWISTING_VINES = init(); public static final ItemType TWISTING_VINES = init();
@Nullable @Nullable
public static final ItemType VAULT = init();
@Nullable
public static final ItemType VERDANT_FROGLIGHT = init(); public static final ItemType VERDANT_FROGLIGHT = init();
@Nullable @Nullable
public static final ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = init(); public static final ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = init();
@ -2614,6 +2649,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = init(); public static final ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = init();
@Nullable @Nullable
public static final ItemType WIND_CHARGE = init();
@Nullable
public static final ItemType WITCH_SPAWN_EGG = init(); public static final ItemType WITCH_SPAWN_EGG = init();
@Nullable @Nullable
public static final ItemType WITHER_ROSE = init(); public static final ItemType WITHER_ROSE = init();
@ -2624,6 +2661,8 @@ public final class ItemTypes {
@Nullable @Nullable
public static final ItemType WITHER_SPAWN_EGG = init(); public static final ItemType WITHER_SPAWN_EGG = init();
@Nullable @Nullable
public static final ItemType WOLF_ARMOR = init();
@Nullable
public static final ItemType WOLF_SPAWN_EGG = init(); public static final ItemType WOLF_SPAWN_EGG = init();
@Nullable @Nullable
public static final ItemType WOODEN_AXE = init(); public static final ItemType WOODEN_AXE = init();

View File

@ -28,7 +28,7 @@ dependencies {
}) })
api("org.apache.logging.log4j:log4j-api") api("org.apache.logging.log4j:log4j-api")
api("org.bstats:bstats-sponge:1.7") api("org.bstats:bstats-sponge:1.7")
testImplementation("org.mockito:mockito-core:5.11.0") testImplementation("org.mockito:mockito-core:5.12.0")
} }
<<<<<<< HEAD <<<<<<< HEAD