Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-19 17:30:08 +01:00
Merge branch 'main' into feat/improved-entity-operations
# Conflicts: # worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java
Dieser Commit ist enthalten in:
Commit
ef071fad20
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -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.
|
||||
multiple: false
|
||||
options:
|
||||
- '1.20.4'
|
||||
- '1.20.5/6'
|
||||
- '1.20'
|
||||
- '1.19.4'
|
||||
- '1.18.2'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
3
.github/renovate.json
vendored
3
.github/renovate.json
vendored
@ -2,7 +2,8 @@
|
||||
"$schema" : "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends" : [
|
||||
"config:recommended",
|
||||
":semanticCommitsDisabled"
|
||||
":semanticCommitsDisabled",
|
||||
"schedule:earlyMondays"
|
||||
],
|
||||
"automerge" : true,
|
||||
"ignoreDeps" : [
|
||||
|
4
.github/workflows/build-pr.yml
vendored
4
.github/workflows/build-pr.yml
vendored
@ -11,13 +11,13 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
- name: Build on ${{ matrix.os }}
|
||||
run: ./gradlew build -s
|
||||
- name: Archive artifacts
|
||||
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -11,13 +11,13 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
- name: Clean Build
|
||||
run: ./gradlew clean build --no-daemon
|
||||
- name: Determine release status
|
||||
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
|
4
.github/workflows/upload-release-assets.yml
vendored
4
.github/workflows/upload-release-assets.yml
vendored
@ -9,13 +9,13 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
- name: Clean Build
|
||||
run: ./gradlew clean build --no-daemon
|
||||
- name: Upload Release Assets
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
= 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.
|
||||
|
||||
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:
|
||||
|
||||
|
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -7,7 +7,7 @@ pipeline {
|
||||
stage('Build') {
|
||||
steps {
|
||||
withEnv([
|
||||
"PATH+JAVA=${tool 'Temurin-17.0.7_7'}/bin"
|
||||
"PATH+JAVA=${tool 'Temurin-21.0.3_9'}/bin"
|
||||
]) {
|
||||
sh './gradlew clean build'
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import java.time.format.DateTimeFormatter
|
||||
import xyz.jpenilla.runpaper.task.RunServer
|
||||
|
||||
plugins {
|
||||
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.2.3"
|
||||
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.2.4"
|
||||
}
|
||||
|
||||
if (!File("$rootDir/.git").exists()) {
|
||||
@ -83,7 +83,7 @@ allprojects {
|
||||
}
|
||||
|
||||
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 {
|
||||
supportedVersions.forEach {
|
||||
|
@ -24,11 +24,23 @@ dependencies {
|
||||
implementation(gradleApi())
|
||||
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
|
||||
implementation("com.github.johnrengelman:shadow:8.1.1")
|
||||
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.13")
|
||||
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 {
|
||||
jvmToolchain {
|
||||
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
|
||||
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ fun Project.applyCommonConfiguration() {
|
||||
|
||||
plugins.withId("java") {
|
||||
the<JavaPluginExtension>().toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
||||
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
|
||||
.configureEach {
|
||||
val disabledLint = listOf(
|
||||
"processing", "path", "fallthrough", "serial"
|
||||
"processing", "path", "fallthrough", "serial", "overloads", "this-escape",
|
||||
)
|
||||
options.release.set(17)
|
||||
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
|
||||
@ -31,7 +31,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
|
@ -122,7 +122,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
|
||||
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"))
|
||||
}
|
||||
@ -137,7 +137,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
|
||||
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"))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
# Minecraft expectations
|
||||
paper = "1.20.4-R0.1-SNAPSHOT"
|
||||
paper = "1.20.6-R0.1-SNAPSHOT"
|
||||
fastutil = "8.5.9"
|
||||
guava = "31.1-jre"
|
||||
log4j = "2.19.0"
|
||||
@ -9,13 +9,13 @@ snakeyaml = "2.0"
|
||||
|
||||
# Plugins
|
||||
dummypermscompat = "1.10"
|
||||
worldguard-bukkit = "7.0.9"
|
||||
worldguard-bukkit = "7.0.10"
|
||||
mapmanager = "1.8.0-SNAPSHOT"
|
||||
griefprevention = "17.0.0"
|
||||
griefdefender = "2.1.0-SNAPSHOT"
|
||||
residence = "4.5._13.1"
|
||||
towny = "0.100.2.0"
|
||||
plotsquared = "7.3.7"
|
||||
towny = "0.100.2.9"
|
||||
plotsquared = "7.3.8"
|
||||
|
||||
# Third party
|
||||
bstats = "3.0.2"
|
||||
@ -23,11 +23,11 @@ sparsebitset = "1.3"
|
||||
parallelgzip = "1.0.5"
|
||||
adventure = "4.16.0"
|
||||
adventure-bukkit = "4.3.2"
|
||||
checkerqual = "3.42.0"
|
||||
checkerqual = "3.43.0"
|
||||
truezip = "6.8.4"
|
||||
auto-value = "1.10.4"
|
||||
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
|
||||
antlr4 = "4.13.1"
|
||||
json-simple = "1.1.1"
|
||||
@ -35,11 +35,11 @@ jlibnoise = "1.0.0"
|
||||
jchronic = "0.2.4a"
|
||||
lz4-java = "1.8.0"
|
||||
lz4-stream = "1.0.0"
|
||||
commons-cli = "1.6.0"
|
||||
commons-cli = "1.7.0"
|
||||
paperlib = "1.0.8"
|
||||
paster = "1.1.5"
|
||||
paster = "1.1.6"
|
||||
vault = "1.7.1"
|
||||
serverlib = "2.3.4"
|
||||
serverlib = "2.3.6"
|
||||
## Internal
|
||||
text-adapter = "3.0.6"
|
||||
text = "3.0.4"
|
||||
|
@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit"
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,6 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
// 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-20240405.071722-146")
|
||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240424.165410-174")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftChunk;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -11,7 +11,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.18.2-R0.1-SNAPSHOT
|
||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.18.2-R0.1-20220920.010157-167")
|
||||
// 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.20.6-R0.1-20240516.001739-55")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
@ -17,24 +17,23 @@
|
||||
* 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.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
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.sk89q.jnbt.NBTConstants;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
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.extension.platform.Watchdog;
|
||||
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 net.minecraft.Util;
|
||||
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.ClientboundEntityEventPacket;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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.ServerLevel;
|
||||
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.properties.DirectionProperty;
|
||||
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.status.ChunkStatus;
|
||||
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.PrimaryLevelData;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
@ -124,13 +129,13 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.util.CraftMagicNumbers;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
@ -155,7 +160,6 @@ import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
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> {
|
||||
|
||||
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
|
||||
SideEffect.NEIGHBORS,
|
||||
SideEffect.LIGHTING,
|
||||
SideEffect.VALIDATION,
|
||||
SideEffect.ENTITY_AI,
|
||||
SideEffect.EVENTS,
|
||||
SideEffect.UPDATE
|
||||
);
|
||||
private static final Codec<DataComponentPatch> COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf(
|
||||
"components", DataComponentPatch.EMPTY
|
||||
).codec();
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
|
||||
|
||||
private final Field serverWorldsField;
|
||||
private final Method getChunkFutureMethod;
|
||||
private final Field chunkProviderExecutorField;
|
||||
private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName());
|
||||
private final Watchdog watchdog;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 {
|
||||
// A simple test
|
||||
CraftServer.class.cast(Bukkit.getServer());
|
||||
|
||||
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
|
||||
if (dataVersion != 2975) {
|
||||
throw new UnsupportedClassVersionError("Not 1.18.2!");
|
||||
if (dataVersion != 3837 && dataVersion != 3839) {
|
||||
throw new UnsupportedClassVersionError("Not 1.20.(5/6)!");
|
||||
}
|
||||
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
@ -209,7 +208,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
);
|
||||
chunkProviderExecutorField.setAccessible(true);
|
||||
|
||||
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool());
|
||||
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized();
|
||||
|
||||
Watchdog watchdog;
|
||||
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.
|
||||
*
|
||||
@ -238,7 +242,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @param tag the tag
|
||||
*/
|
||||
static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) {
|
||||
tileEntity.load(tag);
|
||||
tileEntity.loadWithComponents(tag, MinecraftServer.getServer().registryAccess());
|
||||
tileEntity.setChanged();
|
||||
}
|
||||
|
||||
@ -271,9 +275,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @param tag the tag
|
||||
*/
|
||||
private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) {
|
||||
//FAWE start - avoid villager async catcher
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, tag);
|
||||
//FAWE end
|
||||
entity.load(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -287,34 +289,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
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) {
|
||||
return Registry.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;
|
||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(
|
||||
itemType.getId()));
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
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
|
||||
public BlockState getBlock(Location location) {
|
||||
checkNotNull(location);
|
||||
@ -373,21 +374,37 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
// Read the NBT data
|
||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||
if (te != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
||||
//FAWE start - BinaryTag
|
||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess());
|
||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
|
||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightWorldNativeAccess(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"})
|
||||
@ -429,16 +446,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
CraftEntity craftEntity = ((CraftEntity) entity);
|
||||
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);
|
||||
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
readEntityIntoTag(mcEntity, tag);
|
||||
//FAWE start - CompoundBinaryTag
|
||||
return new BaseEntity(
|
||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
||||
);
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
@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
|
||||
public Component getRichBlockName(BlockType blockType) {
|
||||
return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId());
|
||||
@ -487,26 +523,44 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
@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
|
||||
.newBuilder()
|
||||
.build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
|
||||
@Override
|
||||
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
|
||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
||||
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||
} else if (state instanceof DirectionProperty) {
|
||||
return new DirectionalProperty(state.getName(),
|
||||
(List<Direction>) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList()));
|
||||
return new DirectionalProperty(
|
||||
state.getName(),
|
||||
(List<Direction>) state
|
||||
.getPossibleValues()
|
||||
.stream()
|
||||
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
||||
.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()));
|
||||
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("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName());
|
||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state
|
||||
.getClass()
|
||||
.getSimpleName());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
@Override
|
||||
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
||||
Map<String, Property<?>> properties = new TreeMap<>();
|
||||
@ -520,50 +574,68 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
return properties;
|
||||
}
|
||||
|
||||
//FAWE start - CompoundBinaryTag > CompoundTag
|
||||
@Override
|
||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
||||
((CraftPlayer) player).getHandle().networkManager.send(ClientboundBlockEntityDataPacket.create(
|
||||
new StructureBlockEntity(
|
||||
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()),
|
||||
var structureBlock = new StructureBlockEntity(
|
||||
new BlockPos(pos.getX(), pos.getY(), pos.getZ()),
|
||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
||||
),
|
||||
__ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
|
||||
);
|
||||
structureBlock.setLevel(((CraftPlayer) player).getHandle().level());
|
||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
||||
structureBlock,
|
||||
(blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
|
||||
));
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
@Override
|
||||
public void sendFakeOP(Player player) {
|
||||
((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket(
|
||||
((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
|
||||
((CraftPlayer) player).getHandle(), (byte) 28
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
|
||||
ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount());
|
||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())));
|
||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||
//FAWE start - CBT > CT
|
||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
||||
//FAWE end
|
||||
return weStack;
|
||||
final Tag tag = COMPONENTS_CODEC.encodeStart(
|
||||
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||
nmsStack.getComponentsPatch()
|
||||
).getOrThrow();
|
||||
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
|
||||
public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) {
|
||||
CraftWorld craftWorld = (CraftWorld) world;
|
||||
ServerLevel worldServer = craftWorld.getHandle();
|
||||
ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack
|
||||
? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1)));
|
||||
stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()));
|
||||
ItemStack stack = CraftItemStack.asNMSCopy(adapt(
|
||||
item instanceof BaseItemStack
|
||||
? ((BaseItemStack) item)
|
||||
: new BaseItemStack(item.getType(), item.getNbtReference(), 1)
|
||||
));
|
||||
|
||||
PaperweightFakePlayer fakePlayer;
|
||||
try {
|
||||
@ -572,20 +644,20 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
return false;
|
||||
}
|
||||
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()
|
||||
);
|
||||
|
||||
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 net.minecraft.core.Direction enumFacing = adapt(face);
|
||||
BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false);
|
||||
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 (worldServer
|
||||
.getBlockState(blockPos)
|
||||
.use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace)
|
||||
.useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace)
|
||||
.consumesAction()) {
|
||||
result = InteractionResult.SUCCESS;
|
||||
} else {
|
||||
@ -621,18 +693,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
Environment env = bukkitWorld.getEnvironment();
|
||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||
|
||||
Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen");
|
||||
Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
|
||||
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
|
||||
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
|
||||
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) {
|
||||
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
|
||||
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
|
||||
.getWorldData().overworldData();
|
||||
WorldGenSettings originalOpts = levelProperties.worldGenSettings();
|
||||
WorldOptions originalOpts = levelProperties.worldGenOptions();
|
||||
|
||||
long seed = options.getSeed().orElse(originalWorld.getSeed());
|
||||
WorldGenSettings newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed))
|
||||
WorldOptions newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(OptionalLong.of(seed))
|
||||
: originalOpts;
|
||||
|
||||
LevelSettings newWorldSettings = new LevelSettings(
|
||||
@ -642,23 +714,40 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
levelProperties.settings.difficulty(),
|
||||
levelProperties.settings.allowCommands(),
|
||||
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(
|
||||
originalWorld.getServer(),
|
||||
originalWorld.getServer().executor,
|
||||
session, newWorldData,
|
||||
originalWorld.dimension(),
|
||||
new LevelStem(
|
||||
originalWorld.dimensionTypeRegistration(),
|
||||
originalWorld.getChunkSource().getGenerator()
|
||||
),
|
||||
new NoOpWorldLoadListener(),
|
||||
newOpts.dimensions().get(worldDimKey).generator(),
|
||||
originalWorld.isDebug(),
|
||||
seed,
|
||||
ImmutableList.of(),
|
||||
false,
|
||||
env, gen,
|
||||
originalWorld.getRandomSequences(),
|
||||
env,
|
||||
gen,
|
||||
bukkitWorld.getBiomeProvider()
|
||||
);
|
||||
try {
|
||||
@ -678,7 +767,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
@ -721,10 +810,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
Objects.requireNonNull(state);
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||
if (blockEntity != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||
//FAWE start - BinaryTag
|
||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess());
|
||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
||||
//FAWE end
|
||||
}
|
||||
extent.setBlock(vec, state.toBaseBlock());
|
||||
if (options.shouldRegenBiomes()) {
|
||||
@ -746,9 +833,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
try {
|
||||
//noinspection unchecked
|
||||
chunkLoadings.add(
|
||||
((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>)
|
||||
((CompletableFuture<ChunkResult<ChunkAccess>>)
|
||||
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) {
|
||||
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
|
||||
public Set<SideEffect> getSupportedSideEffects() {
|
||||
return SUPPORTED_SIDE_EFFECTS;
|
||||
@ -797,7 +893,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @param foreign non-native NMS NBT structure
|
||||
* @return native WorldEdit NBT structure
|
||||
*/
|
||||
//FAWE start - BinaryTag
|
||||
@Override
|
||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
||||
if (foreign == null) {
|
||||
@ -830,7 +925,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
try {
|
||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
||||
} 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();
|
||||
}
|
||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||
@ -855,7 +950,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @throws IllegalArgumentException on error
|
||||
*/
|
||||
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) {
|
||||
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());
|
||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
||||
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();
|
||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
||||
for (BinaryTag t : foreignList) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
@Override
|
||||
public boolean supportsWatchdog() {
|
||||
@ -925,54 +1020,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
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 final Field instanceField;
|
||||
@ -996,10 +1043,61 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
WatchdogThread.tick();
|
||||
}
|
||||
} 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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -17,18 +17,19 @@
|
||||
* 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 net.minecraft.network.chat.ChatType;
|
||||
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.ServerPlayer;
|
||||
import net.minecraft.stats.Stat;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
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.phys.Vec3;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
@ -37,15 +38,14 @@ import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
|
||||
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 ClientInformation FAKE_CLIENT_INFO = new ClientInformation(
|
||||
"en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false
|
||||
);
|
||||
|
||||
PaperweightFakePlayer(ServerLevel world) {
|
||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
|
||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,17 +72,13 @@ class PaperweightFakePlayer extends ServerPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOptions(ServerboundClientInformationPacket packet) {
|
||||
public void updateOptions(ClientInformation clientOptions) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayClientMessage(Component message, boolean actionBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message, ChatType type, UUID sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void awardStat(Stat<?> stat, int amount) {
|
||||
}
|
||||
@ -97,7 +93,6 @@ class PaperweightFakePlayer extends ServerPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openTextEdit(SignBlockEntity sign) {
|
||||
public void openTextEdit(SignBlockEntity sign, boolean front) {
|
||||
}
|
||||
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
* 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.internal.block.BlockStateIdAccess;
|
||||
@ -27,21 +27,19 @@ import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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.world.level.block.Block;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PaperweightWorldNativeAccess implements
|
||||
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
|
||||
|
||||
public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
|
||||
private static final int UPDATE = 1;
|
||||
private static final int NOTIFY = 2;
|
||||
|
||||
@ -83,19 +81,12 @@ public class PaperweightWorldNativeAccess implements
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public net.minecraft.world.level.block.state.BlockState setBlockState(
|
||||
LevelChunk chunk,
|
||||
BlockPos position,
|
||||
net.minecraft.world.level.block.state.BlockState state
|
||||
) {
|
||||
public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) {
|
||||
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
|
||||
net.minecraft.world.level.block.state.BlockState block,
|
||||
BlockPos position
|
||||
) {
|
||||
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) {
|
||||
return Block.updateFromNeighbourShapes(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@ -115,12 +106,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(
|
||||
LevelChunk chunk,
|
||||
BlockPos position,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void notifyBlockUpdate(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) {
|
||||
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
@ -128,7 +114,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(LevelChunk chunk) {
|
||||
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
||||
return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,11 +125,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||
ServerLevel world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
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) {
|
||||
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
|
||||
world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState,
|
||||
int recursionLimit
|
||||
) {
|
||||
public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) {
|
||||
ServerLevel world = getWorld();
|
||||
// a == updateNeighbors
|
||||
// b == updateDiagonalNeighbors
|
||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
CraftWorld craftWorld = world.getWorld();
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(
|
||||
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
|
||||
CraftBlockData.fromData(newState)
|
||||
);
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState));
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
@ -193,19 +168,13 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||
getWorld().onBlockStateChange(pos, oldState, newState);
|
||||
}
|
||||
|
||||
//FAWE start
|
||||
@Override
|
||||
public void flush() {
|
||||
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
}
|
@ -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.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.util.ReflectionUtil;
|
||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
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.world.registry.BlockMaterial;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.EmptyBlockGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
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 org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
|
||||
public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
private final Block block;
|
||||
private final BlockState blockState;
|
||||
private final Material material;
|
||||
private final boolean isTranslucent;
|
||||
private final CraftBlockData craftBlockData;
|
||||
private final org.bukkit.Material craftMaterial;
|
||||
private final int opacity;
|
||||
@ -35,22 +31,16 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
public PaperweightBlockMaterial(Block block, BlockState blockState) {
|
||||
this.block = block;
|
||||
this.blockState = blockState;
|
||||
this.material = blockState.getMaterial();
|
||||
this.craftBlockData = CraftBlockData.fromData(blockState);
|
||||
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);
|
||||
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
|
||||
BlockPos.ZERO,
|
||||
blockState
|
||||
);
|
||||
tile = tileEntity == null
|
||||
? null
|
||||
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
||||
tile = tileEntity == null ? null : new PaperweightLazyCompoundTag(
|
||||
Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
|
||||
);
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
@ -65,10 +55,6 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
return craftBlockData;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return blockState.isAir();
|
||||
@ -81,7 +67,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return material.isSolidBlocking();
|
||||
return blockState.canOcclude();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,12 +77,13 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isLiquid() {
|
||||
return material.isLiquid();
|
||||
return !blockState.getFluidState().is(Fluids.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return material.isSolid();
|
||||
// No access to world -> EmptyBlockGetter
|
||||
return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,27 +113,27 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isFragileWhenPushed() {
|
||||
return material.getPushReaction() == PushReaction.DESTROY;
|
||||
return blockState.getPistonPushReaction() == PushReaction.DESTROY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnpushable() {
|
||||
return material.getPushReaction() == PushReaction.BLOCK;
|
||||
return blockState.getPistonPushReaction() == PushReaction.BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTicksRandomly() {
|
||||
return block.isRandomlyTicking(blockState);
|
||||
return blockState.isRandomlyTicking();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovementBlocker() {
|
||||
return material.isSolid();
|
||||
return craftMaterial.isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBurnable() {
|
||||
return material.isFlammable();
|
||||
return craftMaterial.isBurnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,12 +144,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isReplacedDuringPlacement() {
|
||||
return material.isReplaceable();
|
||||
return blockState.canBeReplaced();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTranslucent() {
|
||||
return isTranslucent;
|
||||
return !blockState.canOcclude();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,7 +170,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
@Override
|
||||
public int getMapColor() {
|
||||
// rgb field
|
||||
return material.getColor().col;
|
||||
return block.defaultMapColor().col;
|
||||
}
|
||||
|
||||
}
|
@ -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.NMSRelighterFactory;
|
||||
@ -12,14 +12,13 @@ import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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_18_R2.nbt.PaperweightLazyCompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen.PaperweightRegen;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.regen.PaperweightRegen;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.BlockStateHolder;
|
||||
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.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
@ -53,44 +52,48 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
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.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.util.CraftNamespacedKey;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -104,11 +107,24 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
|
||||
|
||||
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
|
||||
// ------------------------------------------------------------------------
|
||||
@ -119,7 +135,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
private Map<String, List<Property<?>>> allBlockProperties = null;
|
||||
|
||||
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
|
||||
this.parent = new PaperweightAdapter();
|
||||
this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -128,6 +144,10 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
return resourceLocation == null ? null : resourceLocation.toString();
|
||||
}
|
||||
|
||||
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
||||
entity.save(compoundTag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
|
||||
return parent;
|
||||
@ -219,7 +239,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
}
|
||||
|
||||
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
|
||||
@ -264,7 +285,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
// Read the NBT data
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -277,54 +298,6 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
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
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World 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);
|
||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag);
|
||||
readEntityIntoTag(mcEntity, minecraftTag);
|
||||
//add Id for AbstractChangeSet to work
|
||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
||||
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) {
|
||||
ServerLevel nmsWorld = getServerLevel(world);
|
||||
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;
|
||||
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
|
||||
*/ Stream.empty();
|
||||
@ -516,11 +490,18 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||
ItemStack stack = new ItemStack(
|
||||
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
|
||||
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
|
||||
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);
|
||||
}
|
||||
|
||||
@ -547,29 +528,19 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
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
|
||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
||||
return weStack;
|
||||
final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart(
|
||||
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||
nmsStack.getComponentsPatch()
|
||||
).getOrThrow();
|
||||
return new BaseItemStack(
|
||||
BukkitAdapter.asItemType(itemStack.getType()),
|
||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)),
|
||||
itemStack.getAmount()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -577,17 +548,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
return parent.toNative(foreign);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryTag toNativeBinary(final net.minecraft.nbt.Tag foreign) {
|
||||
return parent.toNativeBinary(foreign);
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
|
||||
if (foreign instanceof PaperweightLazyCompoundTag) {
|
||||
return ((PaperweightLazyCompoundTag) foreign).get();
|
||||
}
|
||||
return (net.minecraft.nbt.Tag) parent.fromNative(foreign);
|
||||
return parent.fromNative(foreign);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -605,7 +571,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
final Registry<Biome> registry = MinecraftServer
|
||||
.getServer()
|
||||
.registryAccess()
|
||||
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
|
||||
.registryOrThrow(BIOME);
|
||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
|
||||
Biome biome = registry.get(resourceLocation);
|
||||
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())
|
||||
.getServer()
|
||||
.registryAccess()
|
||||
.ownedRegistryOrThrow(
|
||||
Registry.BIOME_REGISTRY);
|
||||
.registryOrThrow(BIOME);
|
||||
List<ResourceLocation> keys = biomeRegistry.stream()
|
||||
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
|
||||
List<NamespacedKey> namespacedKeys = new ArrayList<>();
|
||||
@ -659,4 +624,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -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.math.IntPair;
|
||||
@ -15,14 +15,15 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
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.FullChunkStatus;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
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.. :( )
|
||||
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;
|
||||
if (nextTick || cachedChanges.size() >= 1024) {
|
||||
if (nextTick) {
|
||||
@ -140,7 +141,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
return false;
|
||||
}
|
||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
||||
blockEntity.load((CompoundTag) nativeTag);
|
||||
blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -157,7 +158,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(LevelChunk levelChunk) {
|
||||
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
||||
return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -181,7 +182,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
// Un-nest neighbour updating
|
||||
for (Direction direction : NEIGHBOUR_ORDER) {
|
||||
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()) {
|
@ -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.DelegateSemaphore;
|
||||
@ -22,7 +22,7 @@ import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitEntity;
|
||||
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.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -31,12 +31,9 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.IdMap;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.BitStorage;
|
||||
@ -48,34 +45,16 @@ import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.DataLayer;
|
||||
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.chunk.*;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.AbstractSet;
|
||||
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.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
@ -84,15 +63,17 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
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<BlockEntity, CompoundTag> nmsTile2We =
|
||||
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
||||
private static final Function<BlockEntity, CompoundTag> nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag(
|
||||
Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
|
||||
);
|
||||
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter());
|
||||
@ -133,7 +114,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
this.maxSectionPosition = maxHeight >> 4;
|
||||
this.skyLight = 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();
|
||||
}
|
||||
|
||||
@ -265,7 +246,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (blockEntity == null) {
|
||||
return null;
|
||||
}
|
||||
return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId));
|
||||
return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -294,8 +275,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
|
||||
LightLayer.BLOCK,
|
||||
sectionPos,
|
||||
dataLayer,
|
||||
true
|
||||
dataLayer
|
||||
);
|
||||
}
|
||||
skyLight[alayer] = dataLayer;
|
||||
@ -322,7 +302,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
Arrays.fill(LAYER_COUNT, (byte) 15);
|
||||
dataLayer = new DataLayer(LAYER_COUNT);
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos,
|
||||
dataLayer, true
|
||||
dataLayer
|
||||
);
|
||||
}
|
||||
blockLight[alayer] = dataLayer;
|
||||
@ -339,7 +319,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
|
||||
@Override
|
||||
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) {
|
||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||
@ -458,7 +446,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
synchronized (super.sectionLocks[getSectionIndex]) {
|
||||
LevelChunkSection existingSection = levelChunkSections[getSectionIndex];
|
||||
if (createCopy && existingSection != null) {
|
||||
copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy());
|
||||
copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
|
||||
}
|
||||
|
||||
if (existingSection == null) {
|
||||
@ -491,8 +479,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PalettedContainer<Holder<Biome>> biomeData = existingSection.getBiomes();
|
||||
setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData);
|
||||
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -527,7 +514,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||
copy.storeSection(getSectionIndex, copyArr);
|
||||
if (biomes != null && existingSection != null) {
|
||||
copy.storeBiomes(getSectionIndex, existingSection.getBiomes().copy());
|
||||
copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,8 +526,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
.getBukkitImplAdapter()
|
||||
.getInternalBiomeId(
|
||||
BiomeTypes.PLAINS)),
|
||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
||||
null
|
||||
PalettedContainer.Strategy.SECTION_BIOMES
|
||||
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
|
||||
newSection = PaperweightPlatformAdapter.newChunkSection(
|
||||
layerNo,
|
||||
@ -600,11 +586,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
sectionLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
PalettedContainer<Holder<Biome>> biomeData = existingSection.getBiomes();
|
||||
|
||||
if (biomes != null && biomes[setSectionIndex] != null) {
|
||||
setBiomesToPalettedContainer(biomes[setSectionIndex], biomeData);
|
||||
}
|
||||
PalettedContainer<Holder<Biome>> biomeData = setBiomesToPalettedContainer(
|
||||
biomes,
|
||||
setSectionIndex,
|
||||
existingSection.getBiomes()
|
||||
);
|
||||
|
||||
newSection =
|
||||
PaperweightPlatformAdapter.newChunkSection(
|
||||
@ -689,7 +675,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
|
||||
for (UUID uuid : entityRemoves) {
|
||||
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid);
|
||||
Entity entity = nmsWorld.getEntities().get(uuid);
|
||||
if (entity != null) {
|
||||
removeEntity(entity);
|
||||
}
|
||||
@ -784,7 +770,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
tag.put("x", IntTag.valueOf(x));
|
||||
tag.put("y", IntTag.valueOf(y));
|
||||
tag.put("z", IntTag.valueOf(z));
|
||||
tileEntity.load(tag);
|
||||
tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1060,8 +1046,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
|
||||
lightLayer,
|
||||
sectionPos,
|
||||
dataLayer,
|
||||
true
|
||||
dataLayer
|
||||
);
|
||||
}
|
||||
synchronized (dataLayer) {
|
||||
@ -1079,22 +1064,35 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
}
|
||||
|
||||
private void setBiomesToPalettedContainer(
|
||||
final BiomeType[] biomes,
|
||||
PalettedContainer<Holder<Biome>> data
|
||||
private PalettedContainer<Holder<Biome>> setBiomesToPalettedContainer(
|
||||
final BiomeType[][] biomes,
|
||||
final int sectionIndex,
|
||||
final PalettedContainerRO<Holder<Biome>> data
|
||||
) {
|
||||
int index = 0;
|
||||
if (biomes == null) {
|
||||
return;
|
||||
PalettedContainer<Holder<Biome>> biomeData;
|
||||
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
||||
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 x = 0; x < 4; x++, index++) {
|
||||
BiomeType biomeType = biomes[index];
|
||||
BiomeType biomeType = sectionBiomes[index];
|
||||
if (biomeType == null) {
|
||||
continue;
|
||||
}
|
||||
data.set(
|
||||
biomeData.set(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
@ -1106,6 +1104,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
}
|
||||
}
|
||||
return biomeData;
|
||||
}
|
||||
|
||||
@Override
|
@ -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.queue.IBlocks;
|
||||
@ -8,19 +8,23 @@ import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
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.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
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 java.util.Arrays;
|
||||
@ -33,6 +37,8 @@ import java.util.concurrent.Future;
|
||||
|
||||
public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private final char[][] blocks;
|
||||
@ -61,7 +67,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
blockEntity.getBlockPos().getY(),
|
||||
blockEntity.getBlockPos().getZ()
|
||||
),
|
||||
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
|
||||
new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())))
|
||||
);
|
||||
}
|
||||
|
||||
@ -80,7 +86,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
protected void storeEntity(Entity entity) {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag);
|
||||
entity.save(compoundTag);
|
||||
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||
}
|
||||
|
||||
@ -185,11 +191,19 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
blocks[layer] = data;
|
||||
}
|
||||
|
||||
protected void storeBiomes(int layer, PalettedContainer<Holder<Biome>> biomeData) {
|
||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
||||
if (biomes == null) {
|
||||
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
|
@ -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.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkW
|
||||
|
||||
public PaperweightMapChunkUtil() throws NoSuchFieldException {
|
||||
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
|
||||
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a"));
|
||||
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b"));
|
||||
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "b"));
|
||||
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "c"));
|
||||
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"));
|
||||
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
|
||||
fieldX.setAccessible(true);
|
@ -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.DelegateSemaphore;
|
||||
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.BlockTypesCache;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.world.ChunkEntitySlices;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
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.TicketType;
|
||||
import net.minecraft.util.BitStorage;
|
||||
import net.minecraft.util.ExceptionCollector;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.util.ThreadingDetector;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.util.ZeroBitStorage;
|
||||
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.LevelAccessor;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
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.HashMapPalette;
|
||||
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.PalettedContainer;
|
||||
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.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
|
||||
import sun.misc.Unsafe;
|
||||
import org.bukkit.craftbukkit.CraftChunk;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@ -79,6 +83,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
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 static final Field fieldData;
|
||||
@ -100,14 +107,23 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
private static final MethodHandle methodRemoveGameEventListener;
|
||||
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 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 {
|
||||
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
try {
|
||||
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
|
||||
fieldData.setAccessible(true);
|
||||
@ -121,11 +137,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
|
||||
fieldPalette.setAccessible(true);
|
||||
|
||||
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
|
||||
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "g"));
|
||||
fieldTickingFluidCount.setAccessible(true);
|
||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
|
||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
|
||||
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
|
||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||
@ -133,7 +149,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
"b"
|
||||
), long.class);
|
||||
getVisibleChunkIfPresent.setAccessible(true);
|
||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
||||
|
||||
if (!PaperLib.isPaper()) {
|
||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||
@ -147,31 +163,66 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
}
|
||||
|
||||
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
||||
Refraction.pickName("removeGameEventListener", "d"),
|
||||
BlockEntity.class
|
||||
Refraction.pickName("removeGameEventListener", "a"),
|
||||
BlockEntity.class,
|
||||
ServerLevel.class
|
||||
);
|
||||
removeGameEventListener.setAccessible(true);
|
||||
methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener);
|
||||
methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener);
|
||||
|
||||
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
||||
Refraction.pickName(
|
||||
"removeBlockEntityTicker",
|
||||
"l"
|
||||
"k"
|
||||
), BlockPos.class
|
||||
);
|
||||
removeBlockEntityTicker.setAccessible(true);
|
||||
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
|
||||
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
|
||||
|
||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||
fieldRemove.setAccessible(true);
|
||||
|
||||
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bW"));
|
||||
fieldOffers.setAccessible(true);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable rethrow) {
|
||||
rethrow.printStackTrace();
|
||||
throw new RuntimeException(rethrow);
|
||||
boolean chunkRewrite;
|
||||
try {
|
||||
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;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
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(
|
||||
@ -255,7 +306,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -265,9 +317,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
|
||||
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
|
||||
// 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()
|
||||
.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) {
|
||||
@ -286,20 +338,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
|
||||
// UNLOADED_CHUNK
|
||||
Optional<LevelChunk> optional = ((Either) chunkHolder
|
||||
.getTickingChunkFuture()
|
||||
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
|
||||
LevelChunk levelChunk;
|
||||
if (PaperLib.isPaper()) {
|
||||
// getChunkAtIfLoadedImmediately is paper only
|
||||
optional = optional.or(() -> Optional.ofNullable(nmsWorld
|
||||
levelChunk = nmsWorld
|
||||
.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;
|
||||
}
|
||||
LevelChunk levelChunk = optional.get();
|
||||
TaskManager.taskManager().task(() -> {
|
||||
ClientboundLevelChunkWithLightPacket packet;
|
||||
if (PaperLib.isPaper()) {
|
||||
@ -307,9 +360,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
levelChunk,
|
||||
nmsWorld.getChunkSource().getLightEngine(),
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
false // last false is to not bother with x-ray
|
||||
null
|
||||
// last false is to not bother with x-ray
|
||||
);
|
||||
} else {
|
||||
// deprecated on paper - deprecation suppressed
|
||||
@ -317,8 +369,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
levelChunk,
|
||||
nmsWorld.getChunkSource().getLightEngine(),
|
||||
null,
|
||||
null,
|
||||
true
|
||||
null
|
||||
);
|
||||
}
|
||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||
@ -424,12 +475,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
.getBukkitImplAdapter()
|
||||
.getInternalBiomeId(
|
||||
BiomeTypes.PLAINS)),
|
||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
||||
null
|
||||
PalettedContainer.Strategy.SECTION_BIOMES
|
||||
);
|
||||
}
|
||||
|
||||
return new LevelChunkSection(layer, blockStatePalettedContainer, biomes);
|
||||
return new LevelChunkSection(blockStatePalettedContainer, biomes);
|
||||
} catch (final Throwable e) {
|
||||
throw e;
|
||||
} finally {
|
||||
@ -447,15 +497,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
||||
) {
|
||||
if (biomes == null) {
|
||||
return new LevelChunkSection(layer, biomeRegistry);
|
||||
return new LevelChunkSection(biomeRegistry);
|
||||
}
|
||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
|
||||
Block.BLOCK_STATE_REGISTRY,
|
||||
Blocks.AIR.defaultBlockState(),
|
||||
PalettedContainer.Strategy.SECTION_STATES,
|
||||
null
|
||||
PalettedContainer.Strategy.SECTION_STATES
|
||||
);
|
||||
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<>(
|
||||
biomeRegistry,
|
||||
biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
||||
null
|
||||
PalettedContainer.Strategy.SECTION_BIOMES
|
||||
);
|
||||
|
||||
final Palette<Holder<Biome>> biomePalette;
|
||||
@ -571,7 +619,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
}
|
||||
|
||||
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) {
|
||||
return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN
|
||||
: null;
|
||||
@ -581,13 +629,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
|
||||
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
|
||||
try {
|
||||
// Do the method ourselves to avoid trying to reflect generic method parameters
|
||||
// similar to removeGameEventListener
|
||||
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
|
||||
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
|
||||
if (blockEntity != null) {
|
||||
if (!levelChunk.level.isClientSide) {
|
||||
methodRemoveGameEventListener.invoke(levelChunk, beacon);
|
||||
methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level);
|
||||
}
|
||||
fieldRemove.set(beacon, true);
|
||||
}
|
||||
@ -599,30 +645,32 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
}
|
||||
|
||||
static List<Entity> getEntities(LevelChunk chunk) {
|
||||
return chunk.level.entityManager.getEntities(chunk.getPos());
|
||||
}
|
||||
|
||||
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
||||
boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread();
|
||||
boolean unset = false;
|
||||
if (isVillager) {
|
||||
ExceptionCollector<RuntimeException> collector = new ExceptionCollector<>();
|
||||
if (PaperLib.isPaper()) {
|
||||
if (POST_CHUNK_REWRITE) {
|
||||
try {
|
||||
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);
|
||||
//noinspection unchecked
|
||||
return (List<Entity>) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e);
|
||||
}
|
||||
}
|
||||
entity.save(compoundTag);
|
||||
if (unset) {
|
||||
try {
|
||||
fieldOffers.set(entity, null);
|
||||
EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk);
|
||||
return List.of(entityList.getRawData());
|
||||
} 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> {
|
@ -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.extent.processor.ProcessorScope;
|
@ -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.core.configuration.Settings;
|
||||
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.TicketType;
|
||||
import net.minecraft.util.Unit;
|
||||
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.concurrent.CompletableFuture;
|
||||
@ -18,7 +18,7 @@ import java.util.function.IntConsumer;
|
||||
public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> {
|
||||
|
||||
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) {
|
||||
super(serverLevel, queue);
|
@ -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.RelightMode;
|
||||
@ -7,7 +7,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -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.LazyCompoundTag;
|
@ -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.core.Fawe;
|
||||
import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
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.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -20,14 +18,19 @@ import com.sk89q.worldedit.world.RegenOptions;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
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.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
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.Level;
|
||||
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.chunk.ChunkAccess;
|
||||
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.ProtoChunk;
|
||||
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.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
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.flat.FlatLevelGeneratorSettings;
|
||||
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.PrimaryLevelData;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.generator.CustomChunkGenerator;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
@ -74,6 +80,8 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
|
||||
|
||||
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 delegateField;
|
||||
private static final Field chunkSourceField;
|
||||
private static final Field generatorStructureStateField;
|
||||
private static final Field ringPositionsField;
|
||||
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_REFERENCES,
|
||||
Concurrency.FULL
|
||||
Concurrency.NONE
|
||||
); // 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.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.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.INITIALIZE_LIGHT,
|
||||
Concurrency.FULL
|
||||
); // initialize_light: radius 0
|
||||
chunkStati.put(
|
||||
ChunkStatus.LIGHT,
|
||||
Concurrency.FULL
|
||||
); // light: radius 1, but no writes to other chunks, only current chunk
|
||||
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
|
||||
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
|
||||
chunkStati.put(ChunkStatus.SPAWN, Concurrency.NONE); // spawn: radius 0
|
||||
|
||||
try {
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
@ -134,22 +142,27 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
flatBedrockField = tmpFlatBedrockField;
|
||||
|
||||
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
|
||||
"settings", "h"));
|
||||
"settings", "e"));
|
||||
generatorSettingBaseSupplierField.setAccessible(true);
|
||||
|
||||
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "g"));
|
||||
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d"));
|
||||
generatorSettingFlatField.setAccessible(true);
|
||||
|
||||
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
|
||||
delegateField.setAccessible(true);
|
||||
|
||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "K"));
|
||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
|
||||
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);
|
||||
|
||||
hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "i"));
|
||||
hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(
|
||||
Refraction.pickName("hasGeneratedPositions", "h")
|
||||
);
|
||||
hasGeneratedPositionsField.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -162,9 +175,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
private ServerLevel freshWorld;
|
||||
private ServerChunkCache freshChunkProvider;
|
||||
private LevelStorageSource.LevelStorageAccess session;
|
||||
private StructureManager structureManager;
|
||||
private StructureTemplateManager structureTemplateManager;
|
||||
private ThreadedLevelLightEngine threadedLevelLightEngine;
|
||||
private ChunkGenerator chunkGenerator;
|
||||
private WorldGenContext worldGenContext;
|
||||
|
||||
private Path tempDir;
|
||||
|
||||
@ -207,12 +221,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
|
||||
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
|
||||
|
||||
BiomeProvider biomeProvider = getBiomeProvider();
|
||||
|
||||
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
|
||||
WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
|
||||
WorldGenSettings newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
|
||||
WorldOptions originalOpts = originalWorldData.worldGenOptions();
|
||||
WorldOptions newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(OptionalLong.of(seed))
|
||||
: originalOpts;
|
||||
LevelSettings newWorldSettings = new LevelSettings(
|
||||
"faweregentempworld",
|
||||
@ -221,9 +233,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
originalWorldData.settings.difficulty(),
|
||||
originalWorldData.settings.allowCommands(),
|
||||
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
|
||||
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
|
||||
@ -232,66 +254,70 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
session,
|
||||
newWorldData,
|
||||
originalServerWorld.dimension(),
|
||||
originalServerWorld.dimensionTypeRegistration(),
|
||||
DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow()
|
||||
.getOrThrow(levelStemResourceKey),
|
||||
new RegenNoOpWorldLoadListener(),
|
||||
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
|
||||
newOpts.dimensions().getOrThrow(levelStemResourceKey).generator(),
|
||||
originalServerWorld.isDebug(),
|
||||
seed,
|
||||
ImmutableList.of(),
|
||||
false,
|
||||
originalServerWorld.getRandomSequences(),
|
||||
environment,
|
||||
generator,
|
||||
biomeProvider
|
||||
) {
|
||||
private final Holder<Biome> singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId(
|
||||
|
||||
private final Holder<Biome> singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess()
|
||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
|
||||
) : null;
|
||||
|
||||
@Override
|
||||
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
|
||||
public void tick(@NotNull BooleanSupplier shouldKeepTicking) { //no ticking
|
||||
}
|
||||
|
||||
@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()) {
|
||||
return singleBiome;
|
||||
}
|
||||
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ,
|
||||
PaperweightRegen.this.chunkGenerator.climateSampler()
|
||||
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(
|
||||
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
|
||||
);
|
||||
}
|
||||
|
||||
}).get();
|
||||
freshWorld.noSave = true;
|
||||
removeWorldFromWorldsMap();
|
||||
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
|
||||
if (paperConfigField != null) {
|
||||
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
|
||||
paperConfigField.set(freshWorld, originalServerWorld.paperConfig());
|
||||
}
|
||||
|
||||
//generator
|
||||
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
|
||||
if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
|
||||
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
|
||||
chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat);
|
||||
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
|
||||
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
||||
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier =
|
||||
(Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField
|
||||
.get(originalGenerator);
|
||||
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>)
|
||||
generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator);
|
||||
BiomeSource biomeSource;
|
||||
if (options.hasBiomeType()) {
|
||||
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME
|
||||
.asHolderIdMap()
|
||||
.byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())));
|
||||
biomeSource = new FixedBiomeSource(
|
||||
DedicatedServer.getServer().registryAccess()
|
||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
biomeSource = originalGenerator.getBiomeSource();
|
||||
}
|
||||
chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, noiseBasedChunkGenerator.noises,
|
||||
biomeSource, seed,
|
||||
chunkGenerator = new NoiseBasedChunkGenerator(
|
||||
biomeSource,
|
||||
generatorSettingBaseSupplier
|
||||
);
|
||||
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
|
||||
chunkGenerator = customChunkGenerator.delegate;
|
||||
chunkGenerator = customChunkGenerator.getDelegate();
|
||||
} else {
|
||||
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
|
||||
return false;
|
||||
@ -300,22 +326,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
|
||||
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(
|
||||
freshWorld,
|
||||
session,
|
||||
@ -333,7 +345,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
) {
|
||||
// redirect to LevelChunks created in #createChunks
|
||||
@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);
|
||||
if (chunkAccess == null && create) {
|
||||
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);
|
||||
//let's start then
|
||||
structureManager = server.getStructureManager();
|
||||
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
||||
structureTemplateManager = server.getStructureManager();
|
||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
||||
|
||||
this.worldGenContext = new WorldGenContext(freshWorld, chunkGenerator, structureTemplateManager,
|
||||
threadedLevelLightEngine
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -362,7 +395,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
try {
|
||||
freshChunkProvider.close(false);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
@ -385,7 +418,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
@Override
|
||||
protected ProtoChunk createProtoChunk(int x, int z) {
|
||||
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
|
||||
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
||||
// 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
|
||||
@ -427,14 +464,12 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
//util
|
||||
@SuppressWarnings("unchecked")
|
||||
private void removeWorldFromWorldsMap() {
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
try {
|
||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
||||
map.remove("faweregentempworld");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
|
||||
@ -451,11 +486,15 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
||||
public void updateSpawnPos(@NotNull ChunkPos spawnPos) {
|
||||
}
|
||||
|
||||
@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
|
||||
@ -487,15 +526,14 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
// avoid warning on paper
|
||||
|
||||
// compatibility with spigot
|
||||
|
||||
@SuppressWarnings("unused") // compatibility with spigot
|
||||
public boolean generateFlatBedrock() {
|
||||
return generateFlatBedrock;
|
||||
}
|
||||
|
||||
// no one will ever see the entities!
|
||||
@Override
|
||||
public List<CompoundTag> getEntities() {
|
||||
public @NotNull List<CompoundTag> getEntities() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@ -516,23 +554,41 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return chunkStatus.getName();
|
||||
return chunkStatus.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) {
|
||||
return chunkStatus.generate(
|
||||
Runnable::run, // TODO revisit, we might profit from this somehow?
|
||||
freshWorld,
|
||||
chunkGenerator,
|
||||
structureManager,
|
||||
threadedLevelLightEngine,
|
||||
c -> CompletableFuture.completedFuture(Either.left(c)),
|
||||
accessibleChunks,
|
||||
true
|
||||
worldGenContext,
|
||||
Runnable::run,
|
||||
CompletableFuture::completedFuture,
|
||||
accessibleChunks
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -36,6 +36,7 @@ repositories {
|
||||
name = "Glaremasters"
|
||||
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")) }
|
||||
}
|
||||
|
||||
@ -169,7 +170,7 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
include(dependency("it.unimi.dsi:fastutil"))
|
||||
}
|
||||
relocate("org.incendo.serverlib", "com.fastasyncworldedit.serverlib") {
|
||||
include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.4"))
|
||||
include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.6"))
|
||||
}
|
||||
relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") {
|
||||
include(dependency("com.intellectualsites.paster:Paster"))
|
||||
@ -210,7 +211,7 @@ tasks {
|
||||
versionNumber.set("${project.version}")
|
||||
versionType.set("release")
|
||||
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"))
|
||||
changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" +
|
||||
"FastAsyncWorldEdit/releases/tag/${project.version}")
|
||||
|
@ -31,6 +31,8 @@ import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@ -186,10 +188,12 @@ public interface IBukkitAdapter {
|
||||
}
|
||||
|
||||
default org.bukkit.entity.EntityType adapt(EntityType entityType) {
|
||||
if (!entityType.getId().startsWith("minecraft:")) {
|
||||
throw new IllegalArgumentException("Bukkit only supports vanilla entities");
|
||||
NamespacedKey entityKey = NamespacedKey.fromString(entityType.toString());
|
||||
if (entityKey == null) {
|
||||
throw new IllegalArgumentException("Entity key '" + entityType + "' does not map to Bukkit");
|
||||
}
|
||||
return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10).toLowerCase(Locale.ROOT));
|
||||
|
||||
return Registry.ENTITY_TYPE.get(entityKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,7 +347,7 @@ public interface IBukkitAdapter {
|
||||
* @return WorldEdit EntityType
|
||||
*/
|
||||
default EntityType adapt(org.bukkit.entity.EntityType entityType) {
|
||||
return EntityTypes.get(entityType.getName().toLowerCase(Locale.ROOT));
|
||||
return EntityTypes.get(entityType.getKey().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
|
||||
import com.fastasyncworldedit.core.util.MathMan;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
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.LongArrayList;
|
||||
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.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@ -36,6 +42,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@ -62,7 +69,7 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
|
||||
protected final RegenOptions options;
|
||||
|
||||
//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 Long2ObjectOpenHashMap<Chunk> chunks = new Long2ObjectOpenHashMap<>();
|
||||
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, ...)?
|
||||
//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
|
||||
Int2ObjectOpenHashMap<long[]> chunkCoordsForRadius = new Int2ObjectOpenHashMap<>();
|
||||
chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> {
|
||||
if (radius == -1) { //ignore ChunkStatus.EMPTY
|
||||
return;
|
||||
// to get the chunks we need to generate in the nth chunk status, we need to know how many chunks
|
||||
// we need to generate in the n + 1 th chunk status. Summing up the margin solves that
|
||||
LinkedHashMap<ChunkStatus, long[]> chunkCoordsForChunkStatus = new LinkedHashMap<>();
|
||||
int borderSum = 1;
|
||||
// TODO (j21): use SequencedMap#sequencedKeySet().reversed()
|
||||
final List<ChunkStatus> reversedKeys = Lists.reverse(new ArrayList<>(chunkStatuses.keySet()));
|
||||
for (final ChunkStatus status : reversedKeys) {
|
||||
chunkCoordsForChunkStatus.put(status, getChunkCoordsRegen(region, borderSum));
|
||||
borderSum += status.requiredNeighborChunkRadius();
|
||||
}
|
||||
int border = 10 - radius; //9 = 8 + 1, 8: max border radius used in chunk stages, 1: need 1 extra chunk for chunk
|
||||
// features to generate at the border of the region
|
||||
chunkCoordsForRadius.put(radius, getChunkCoordsRegen(region, border));
|
||||
});
|
||||
|
||||
//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));
|
||||
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
|
||||
Int2ObjectOpenHashMap<Long2ObjectOpenHashMap<List<IChunkAccess>>> worldLimits = new Int2ObjectOpenHashMap<>();
|
||||
chunkStatuses.keySet().stream().mapToInt(ChunkStatusWrapper::requiredNeighborChunkRadius0).distinct().forEach(radius -> {
|
||||
if (radius == -1) { //ignore ChunkStatus.EMPTY
|
||||
return;
|
||||
// a memory-efficient, lightweight "list" that calculates index -> ChunkAccess
|
||||
// as needed when accessed
|
||||
class LazyChunkList extends AbstractList<IChunkAccess> {
|
||||
private final int size;
|
||||
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<>();
|
||||
for (long xz : chunkCoordsForRadius.get(radius)) {
|
||||
int x = MathMan.unpairIntX(xz);
|
||||
int z = MathMan.unpairIntY(xz);
|
||||
List<IChunkAccess> l = new ArrayList<>((radius + 1 + radius) * (radius + 1 + radius));
|
||||
for (int zz = z - radius; zz <= z + radius; zz++) { //order is important, first z then x
|
||||
for (int xx = x - radius; xx <= x + radius; xx++) {
|
||||
l.add(protoChunks.get(MathMan.pairInt(xx, zz)));
|
||||
@Override
|
||||
public IChunkAccess get(final int index) {
|
||||
Objects.checkIndex(index, size);
|
||||
int absX = (index % sizeSqrt) + minX;
|
||||
int absZ = (index / sizeSqrt) + minZ;
|
||||
return protoChunks.get(MathMan.pairInt(absX, absZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
map.put(xz, l);
|
||||
|
||||
}
|
||||
@Label("Regeneration")
|
||||
@Category("FAWE")
|
||||
@Name("fawe.regen")
|
||||
class RegenerationEvent extends Event {
|
||||
private String chunkStatus;
|
||||
private int chunksToProcess;
|
||||
}
|
||||
worldLimits.put(radius, map);
|
||||
});
|
||||
|
||||
//run generation tasks excluding FULL chunk status
|
||||
for (Map.Entry<ChunkStatus, Concurrency> entry : chunkStatuses.entrySet()) {
|
||||
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);
|
||||
Long2ObjectOpenHashMap<List<IChunkAccess>> limitsForRadius = worldLimits.get(radius);
|
||||
long[] coords = chunkCoordsForChunkStatus.get(chunkStatus);
|
||||
event.chunksToProcess = coords.length;
|
||||
if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) {
|
||||
SequentialTasks<ConcurrentTasks<LongList>> tasks = getChunkStatusTaskRows(coords, radius);
|
||||
for (ConcurrentTasks<LongList> para : tasks) {
|
||||
@ -224,7 +250,8 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
|
||||
for (LongList row : para) {
|
||||
scheduled.add(() -> {
|
||||
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
|
||||
List<Runnable> scheduled = new ArrayList<>(coords.length);
|
||||
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);
|
||||
} 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
|
||||
executor.submit(() -> {
|
||||
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
|
||||
}
|
||||
event.commit();
|
||||
}
|
||||
|
||||
//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);
|
||||
chunks.put(xz, createChunk(proto));
|
||||
}
|
||||
|
||||
//final chunkstatus
|
||||
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);
|
||||
FULL.processChunkSave(xz, List.of(chunk));
|
||||
}
|
||||
|
||||
//populate
|
||||
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 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,
|
||||
BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256);
|
||||
source = new SingleThreadQueueExtent(
|
||||
BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0,
|
||||
BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256
|
||||
);
|
||||
source.init(target, initSourceQueueCache(), null);
|
||||
return true;
|
||||
}
|
||||
@ -503,7 +538,7 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
|
||||
int numlists = Math.min(requiredNeighbors * 2 + 1, maxZ - minZ + 1);
|
||||
|
||||
Int2ObjectOpenHashMap<LongList> byZ = new Int2ObjectOpenHashMap<>();
|
||||
int expectedListLength = (coordsCount + 1) / (maxZ - minZ);
|
||||
int expectedListLength = (coordsCount + 1) / (maxZ - minZ + 2);
|
||||
|
||||
//init lists
|
||||
for (int i = minZ; i <= maxZ; i++) {
|
||||
@ -581,13 +616,16 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
|
||||
try {
|
||||
processChunk(accessibleChunks).get();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(
|
||||
"Error while running " + name() + " on chunk " + MathMan.unpairIntX(xz) + "/" + MathMan.unpairIntY(xz),
|
||||
e
|
||||
);
|
||||
LOGGER.error("Error while running {} on chunk {}/{}",
|
||||
name(), MathMan.unpairIntX(xz), MathMan.unpairIntY(xz), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SequentialTasks<T> extends Tasks<T> {
|
||||
|
@ -135,7 +135,7 @@ public abstract class ChunkListener implements Listener {
|
||||
@Deprecated(since = "2.0.0")
|
||||
public void cleanup(Chunk chunk) {
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (entity.getType() == EntityType.DROPPED_ITEM) {
|
||||
if (entity.getType() == EntityType.ITEM) {
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package com.sk89q.bukkit.util;
|
||||
|
||||
import com.sk89q.util.ReflectionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
@ -96,12 +97,11 @@ public class CommandRegistration {
|
||||
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) {
|
||||
Bukkit.getServer().getLogger().severe(plugin.getDescription().getName()
|
||||
+ ": Could not retrieve server CommandMap, using fallback instead!");
|
||||
fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer());
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin);
|
||||
+ ": Could not retrieve server CommandMap");
|
||||
throw new IllegalStateException("Failed to retrieve command map, make sure you are running supported server software");
|
||||
} else {
|
||||
serverCommandMap = commandMap;
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.8.20"
|
||||
kotlin("jvm") version "1.9.23"
|
||||
application
|
||||
}
|
||||
|
||||
applyCommonConfiguration()
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
}
|
||||
|
||||
application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter")
|
||||
tasks.named<JavaExec>("run") {
|
||||
workingDir = rootProject.projectDir
|
||||
|
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.configuration;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.file.YamlConfiguration;
|
||||
import com.fastasyncworldedit.core.util.StringMan;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -14,8 +15,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -27,6 +30,9 @@ public class Config {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private final Map<String, Object> removedKeyVals = new HashMap<>();
|
||||
private List<String> existingMigrateNodes = null;
|
||||
|
||||
public Config() {
|
||||
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
|
||||
}
|
||||
@ -43,7 +49,8 @@ public class Config {
|
||||
try {
|
||||
return (T) field.get(instance);
|
||||
} 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) {
|
||||
return;
|
||||
}
|
||||
Migrate migrate = field.getAnnotation(Migrate.class);
|
||||
if (existingMigrateNodes != null && migrate != null) {
|
||||
existingMigrateNodes.add(migrate.value());
|
||||
}
|
||||
if (field.getType() == String.class && !(value instanceof String)) {
|
||||
value = value + "";
|
||||
}
|
||||
@ -74,17 +85,22 @@ public class Config {
|
||||
field.set(instance, value);
|
||||
return;
|
||||
} 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) {
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
existingMigrateNodes = new ArrayList<>();
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
|
||||
for (String key : yml.getKeys(true)) {
|
||||
Object value = yml.get(key);
|
||||
@ -93,6 +109,10 @@ public class Config {
|
||||
}
|
||||
set(key, value, getClass());
|
||||
}
|
||||
for (String node : existingMigrateNodes) {
|
||||
removedKeyVals.remove(node);
|
||||
}
|
||||
existingMigrateNodes = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -113,7 +133,7 @@ public class Config {
|
||||
save(writer, getClass(), instance, 0);
|
||||
writer.close();
|
||||
} 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 TODO
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface Migrate {
|
||||
|
||||
String value();
|
||||
|
||||
}
|
||||
|
||||
@Ignore // This is not part of the config
|
||||
public static class ConfigBlock<T> {
|
||||
|
||||
@ -222,7 +255,6 @@ public class Config {
|
||||
try {
|
||||
String CTRF = System.lineSeparator();
|
||||
String spacing = StringMan.repeat(" ", indent);
|
||||
HashMap<Class<?>, Object> instances = new HashMap<>();
|
||||
for (Field field : clazz.getFields()) {
|
||||
if (field.getAnnotation(Ignore.class) != null) {
|
||||
continue;
|
||||
@ -239,31 +271,14 @@ public class Config {
|
||||
}
|
||||
if (current == ConfigBlock.class) {
|
||||
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current);
|
||||
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);
|
||||
if (create != null) {
|
||||
@ -281,7 +296,6 @@ public class Config {
|
||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||
if (value == null) {
|
||||
field.set(instance, value = current.getDeclaredConstructor().newInstance());
|
||||
instances.put(current, value);
|
||||
}
|
||||
save(writer, current, value, indent + 2);
|
||||
} else {
|
||||
@ -292,7 +306,42 @@ public class Config {
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
} catch (Throwable ignored) {
|
||||
LOGGER.warn(
|
||||
"Invalid config field: {} for {}",
|
||||
"Invalid config field: {} for {}. It is possible this is because it has been removed.",
|
||||
StringMan.join(split, "."),
|
||||
toNodeName(instance.getClass().getSimpleName())
|
||||
);
|
||||
@ -379,7 +428,7 @@ public class Config {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed retrieving instance for config node: {}", StringUtil.joinString(split, "."), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -79,6 +79,8 @@ public class Settings extends Config {
|
||||
@Create
|
||||
public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS;
|
||||
@Create
|
||||
public GENERAL GENERAL;
|
||||
@Create
|
||||
public ConfigBlock<LIMITS> LIMITS;
|
||||
|
||||
private Settings() {
|
||||
@ -145,6 +147,14 @@ public class Settings extends Config {
|
||||
limit.MAX_HISTORY,
|
||||
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,
|
||||
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",
|
||||
})
|
||||
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")
|
||||
public int MAX_EXPRESSION_MS = 50;
|
||||
@Comment({
|
||||
@ -622,18 +644,6 @@ public class Settings extends Config {
|
||||
})
|
||||
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"})
|
||||
@ -751,4 +761,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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ public class FaweLimit {
|
||||
public int MAX_BLOCKSTATES = 0;
|
||||
public int MAX_ENTITIES = 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 INVENTORY_MODE = 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_ENTITIES = 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.FAST_PLACEMENT = true;
|
||||
MAX.CONFIRM_LARGE = true;
|
||||
@ -237,6 +241,8 @@ public class FaweLimit {
|
||||
&& MAX_BLOCKSTATES == Integer.MAX_VALUE
|
||||
&& MAX_ENTITIES == 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
|
||||
&& SPEED_REDUCTION == 0
|
||||
&& FAST_PLACEMENT
|
||||
@ -256,6 +262,8 @@ public class FaweLimit {
|
||||
MAX_FAILS = limit.MAX_FAILS;
|
||||
MAX_ITERATIONS = limit.MAX_ITERATIONS;
|
||||
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;
|
||||
SPEED_REDUCTION = limit.SPEED_REDUCTION;
|
||||
FAST_PLACEMENT = limit.FAST_PLACEMENT;
|
||||
@ -279,6 +287,8 @@ public class FaweLimit {
|
||||
limit.MAX_FAILS = MAX_FAILS;
|
||||
limit.MAX_ITERATIONS = MAX_ITERATIONS;
|
||||
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.CONFIRM_LARGE = CONFIRM_LARGE;
|
||||
limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS;
|
||||
|
@ -554,8 +554,15 @@ public class MainUtil {
|
||||
}
|
||||
|
||||
public static BufferedImage readImage(URL url) throws IOException {
|
||||
try (final InputStream stream = readImageStream(url.toURI())) {
|
||||
return readImage(stream);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException("failed to parse url to uri reference", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream readImageStream(final URI uri) throws IOException {
|
||||
try {
|
||||
final URI uri = url.toURI();
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET();
|
||||
|
||||
if (uri.getHost().equalsIgnoreCase("i.imgur.com")) {
|
||||
@ -566,16 +573,13 @@ public class MainUtil {
|
||||
requestBuilder.build(),
|
||||
HttpResponse.BodyHandlers.ofInputStream()
|
||||
);
|
||||
try (final InputStream body = response.body()) {
|
||||
final InputStream body = response.body();
|
||||
if (response.statusCode() > 299) {
|
||||
throw new IOException("Expected 2xx as response code, but received " + response.statusCode());
|
||||
}
|
||||
return readImage(body);
|
||||
}
|
||||
return body;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("request was interrupted", e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException("failed to parse url to uri reference", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,8 +176,8 @@ public class ImageUtil {
|
||||
}
|
||||
|
||||
public static BufferedImage load(URI uri) throws InputParseException {
|
||||
try {
|
||||
return MainUtil.readImage(getInputStream(uri));
|
||||
try (final InputStream stream = getInputStream(uri)) {
|
||||
return MainUtil.readImage(stream);
|
||||
} catch (IOException e) {
|
||||
throw new InputParseException(TextComponent.of(e.getMessage()));
|
||||
}
|
||||
@ -190,7 +190,7 @@ public class ImageUtil {
|
||||
File file = new File(uri.getPath());
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
return new URL(uriStr).openStream();
|
||||
return MainUtil.readImageStream(uri);
|
||||
} catch (IOException e) {
|
||||
throw new InputParseException(TextComponent.of(e.getMessage()));
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
@ -73,8 +73,7 @@ public class WorldEditManifest {
|
||||
}
|
||||
|
||||
try {
|
||||
URL url = new URL(classPath);
|
||||
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
|
||||
JarURLConnection jarConnection = (JarURLConnection) URI.create(classPath).toURL().openConnection();
|
||||
Manifest manifest = jarConnection.getManifest();
|
||||
return manifest.getMainAttributes();
|
||||
} catch (IOException e) {
|
||||
|
@ -184,6 +184,9 @@ public class GenerationCommands {
|
||||
|
||||
BlockVector3 pos = session.getPlacementPosition(actor);
|
||||
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)));
|
||||
return affected;
|
||||
}
|
||||
@ -227,6 +230,9 @@ public class GenerationCommands {
|
||||
|
||||
BlockVector3 pos = session.getPlacementPosition(actor);
|
||||
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)));
|
||||
return affected;
|
||||
}
|
||||
@ -293,7 +299,7 @@ public class GenerationCommands {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected)));
|
||||
@ -379,7 +385,7 @@ public class GenerationCommands {
|
||||
worldEdit.checkMaxRadius(size);
|
||||
BlockVector3 pos = session.getPlacementPosition(actor);
|
||||
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();
|
||||
}
|
||||
actor.print(Caption.of("worldedit.pyramid.created", TextComponent.of(affected)));
|
||||
@ -457,7 +463,7 @@ public class GenerationCommands {
|
||||
hollow,
|
||||
session.getTimeout()
|
||||
);
|
||||
if (actor instanceof Player) {
|
||||
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
|
||||
((Player) actor).findFreePosition();
|
||||
}
|
||||
actor.print(Caption.of("worldedit.generate.created", TextComponent.of(affected)));
|
||||
@ -741,7 +747,7 @@ public class GenerationCommands {
|
||||
radius.divide(max),
|
||||
sphericity / 100
|
||||
);
|
||||
if (actor instanceof Player) {
|
||||
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
|
||||
((Player) actor).findFreePosition();
|
||||
}
|
||||
actor.print(Caption.of("worldedit.sphere.created", TextComponent.of(affected)));
|
||||
|
@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
|
||||
import com.fastasyncworldedit.core.FaweAPI;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
import com.fastasyncworldedit.core.util.MaskTraverser;
|
||||
@ -715,6 +716,9 @@ public class RegionCommands {
|
||||
session.setSourceMask(mask);
|
||||
//FAWE end
|
||||
}
|
||||
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
|
||||
((Player) actor).findFreePosition();
|
||||
}
|
||||
if (success) {
|
||||
actor.print(Caption.of("worldedit.regen.regenerated"));
|
||||
} else {
|
||||
@ -788,7 +792,7 @@ public class RegionCommands {
|
||||
String.join(" ", expression),
|
||||
session.getTimeout()
|
||||
);
|
||||
if (actor instanceof Player) {
|
||||
if (actor instanceof Player && Settings.settings().GENERAL.UNSTUCK_ON_GENERATE) {
|
||||
((Player) actor).findFreePosition();
|
||||
}
|
||||
actor.print(Caption.of("worldedit.deform.deformed", TextComponent.of(affected)));
|
||||
|
@ -26,6 +26,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
|
||||
import com.fastasyncworldedit.core.util.MainUtil;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
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.file.FilenameException;
|
||||
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.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
import org.enginehub.piston.exception.CommandException;
|
||||
import org.enginehub.piston.exception.StopExecutionException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -79,9 +84,12 @@ import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -536,6 +544,42 @@ public class SchematicCommands {
|
||||
.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(
|
||||
name = "formats",
|
||||
aliases = {"listformats", "f"},
|
||||
@ -700,10 +744,10 @@ public class SchematicCommands {
|
||||
|
||||
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(
|
||||
" / %dkb",
|
||||
Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT
|
||||
actor.getLimit().SCHEM_FILE_SIZE_LIMIT
|
||||
);
|
||||
}
|
||||
|
||||
@ -804,14 +848,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;
|
||||
private final ClipboardFormat format;
|
||||
private final ClipboardHolder holder;
|
||||
SchematicOutputTask(
|
||||
Actor actor,
|
||||
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 File rootDir;
|
||||
private File file;
|
||||
|
||||
SchematicSaveTask(
|
||||
Actor actor,
|
||||
@ -821,11 +899,9 @@ public class SchematicCommands {
|
||||
ClipboardHolder holder,
|
||||
boolean overwrite
|
||||
) {
|
||||
this.actor = actor;
|
||||
super(actor, format, holder);
|
||||
this.file = file;
|
||||
this.rootDir = rootDir;
|
||||
this.format = format;
|
||||
this.holder = holder;
|
||||
this.overwrite = overwrite;
|
||||
}
|
||||
|
||||
@ -837,7 +913,7 @@ public class SchematicCommands {
|
||||
|
||||
//FAWE start
|
||||
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;
|
||||
String curFilepath = file.getAbsolutePath();
|
||||
@ -867,7 +943,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) {
|
||||
numFiles = 0;
|
||||
@ -880,7 +956,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) {
|
||||
TextComponent noSlotsErr = TextComponent.of( //TODO - to be moved into captions/translatablecomponents
|
||||
@ -931,7 +1007,7 @@ public class SchematicCommands {
|
||||
if (checkFilesize) {
|
||||
|
||||
double curKb = filesizeKb + directorysizeKb;
|
||||
int allocatedKb = Settings.settings().EXPERIMENTAL.PER_PLAYER_FILE_SIZE_LIMIT;
|
||||
int allocatedKb = actor.getLimit().SCHEM_FILE_SIZE_LIMIT;
|
||||
|
||||
if (overwrite) {
|
||||
curKb -= oldKbOverwritten;
|
||||
@ -966,11 +1042,11 @@ public class SchematicCommands {
|
||||
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(
|
||||
//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.",
|
||||
TextColor.GRAY
|
||||
);
|
||||
@ -984,7 +1060,32 @@ public class SchematicCommands {
|
||||
//FAWE end
|
||||
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> {
|
||||
|
@ -56,6 +56,7 @@ public class BaseEntity implements NbtValued {
|
||||
* @param nbtData NBT data
|
||||
* @deprecated Use {@link BaseEntity#BaseEntity(EntityType, LazyReference)}
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
@Deprecated
|
||||
public BaseEntity(EntityType type, CompoundTag nbtData) {
|
||||
this(type);
|
||||
@ -87,6 +88,7 @@ public class BaseEntity implements NbtValued {
|
||||
*
|
||||
* @param other the object to clone
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public BaseEntity(BaseEntity other) {
|
||||
checkNotNull(other);
|
||||
this.type = other.getType();
|
||||
|
@ -62,6 +62,7 @@ public class BlockChangeLimiter extends AbstractDelegateExtent {
|
||||
*
|
||||
* @param limit the limit (>= 0) or -1 for no limit
|
||||
*/
|
||||
@SuppressWarnings("this-escape") // Unlikely anyone is extending this in practice
|
||||
public void setLimit(int limit) {
|
||||
checkArgument(limit >= -1, "limit >= -1 required");
|
||||
this.limit = limit;
|
||||
|
@ -19,11 +19,16 @@
|
||||
|
||||
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.InputStream;
|
||||
|
||||
public class ForwardSeekableInputStream extends InputStream {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
protected InputStream parent;
|
||||
protected long position = 0;
|
||||
|
||||
@ -60,7 +65,7 @@ public class ForwardSeekableInputStream extends InputStream {
|
||||
|
||||
@Override
|
||||
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;
|
||||
return read;
|
||||
}
|
||||
@ -86,6 +91,7 @@ public class ForwardSeekableInputStream extends InputStream {
|
||||
|
||||
public void seek(long n) throws IOException {
|
||||
long diff = n - position;
|
||||
LOGGER.error("Seek to {} from {} using {}", n, position, diff);
|
||||
|
||||
if (diff < 0) {
|
||||
throw new IOException("Can't seek backwards");
|
||||
|
@ -357,7 +357,7 @@ public class HttpRequest implements Closeable {
|
||||
*/
|
||||
public static URL url(String url) {
|
||||
try {
|
||||
return new URL(url);
|
||||
return URI.create(url).toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -371,13 +371,7 @@ public class HttpRequest implements Closeable {
|
||||
*/
|
||||
private static URL reformat(URL existing) {
|
||||
try {
|
||||
URL url = new URL(existing.toString());
|
||||
URI uri = new URI(
|
||||
url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(),
|
||||
url.getPath(), url.getQuery(), url.getRef()
|
||||
);
|
||||
url = uri.toURL();
|
||||
return url;
|
||||
return existing.toURI().toURL();
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
return existing;
|
||||
}
|
||||
|
@ -83,4 +83,26 @@ public final class ActorCallbackPaste {
|
||||
.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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import com.google.gson.reflect.TypeToken;
|
||||
import com.sk89q.worldedit.util.net.HttpRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
@ -33,23 +34,38 @@ public class EngineHubPaste implements Paster {
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
@Override
|
||||
public Callable<URL> paste(String content) {
|
||||
return new PasteTask(content);
|
||||
public Callable<URL> paste(String content, PasteMetadata metadata) {
|
||||
return new PasteTask(content, metadata);
|
||||
}
|
||||
|
||||
private static final class PasteTask implements Callable<URL> {
|
||||
|
||||
private final String content;
|
||||
private final PasteMetadata metadata;
|
||||
|
||||
private PasteTask(String content) {
|
||||
private PasteTask(String content, PasteMetadata metadata) {
|
||||
this.content = content;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL call() throws IOException, InterruptedException {
|
||||
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()
|
||||
.expectResponseCode(200)
|
||||
.returnContent()
|
||||
@ -68,7 +84,7 @@ public class EngineHubPaste implements Paster {
|
||||
.execute()
|
||||
.expectResponseCode(200, 204);
|
||||
|
||||
return new URL(response.viewUrl);
|
||||
return URI.create(response.viewUrl).toURL();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -24,6 +24,10 @@ import java.util.concurrent.Callable;
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
@ -82,21 +82,22 @@ public class FutureForwardingTask<V> extends AbstractTask<V> {
|
||||
return future.get(timeout, unit);
|
||||
}
|
||||
|
||||
// TODO: consider deprecating in favor of Future.State?
|
||||
@Override
|
||||
public State getState() {
|
||||
public Task.State getState() {
|
||||
if (isCancelled()) {
|
||||
return State.CANCELLED;
|
||||
return Task.State.CANCELLED;
|
||||
} else if (isDone()) {
|
||||
try {
|
||||
get();
|
||||
return State.SUCCEEDED;
|
||||
return Task.State.SUCCEEDED;
|
||||
} catch (InterruptedException e) {
|
||||
return State.CANCELLED;
|
||||
return Task.State.CANCELLED;
|
||||
} catch (ExecutionException e) {
|
||||
return State.FAILED;
|
||||
return Task.State.FAILED;
|
||||
}
|
||||
} else {
|
||||
return State.RUNNING;
|
||||
return Task.State.RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,10 @@ public final class BlockCategories {
|
||||
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 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 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 BAMBOO_BLOCKS = get("minecraft:bamboo_blocks");
|
||||
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");
|
||||
@Deprecated
|
||||
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 DRAGON_IMMUNE = get("minecraft:dragon_immune");
|
||||
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 ICE = get("minecraft:ice");
|
||||
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_NETHER = get("minecraft:infiniburn_nether");
|
||||
public static final BlockCategory INFINIBURN_OVERWORLD = get("minecraft:infiniburn_overworld");
|
||||
|
@ -60,6 +60,7 @@ public class BlockType implements Keyed, Pattern {
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private final String id;
|
||||
@SuppressWarnings("this-escape")
|
||||
private final LazyReference<FuzzyBlockState> emptyFuzzy
|
||||
= LazyReference.from(() -> new FuzzyBlockState(this));
|
||||
//FAWE start
|
||||
|
@ -483,6 +483,10 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType COPPER_GRATE = init();
|
||||
@Nullable
|
||||
public static final BlockType COPPER_ORE = init();
|
||||
@Nullable
|
||||
public static final BlockType COPPER_TRAPDOOR = init();
|
||||
@Nullable
|
||||
public static final BlockType CORNFLOWER = init();
|
||||
@Nullable
|
||||
public static final BlockType CRACKED_DEEPSLATE_BRICKS = init();
|
||||
@ -495,6 +499,8 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType CRACKED_STONE_BRICKS = init();
|
||||
@Nullable
|
||||
public static final BlockType CRAFTER = init();
|
||||
@Nullable
|
||||
public static final BlockType CRAFTING_TABLE = init();
|
||||
@Nullable
|
||||
public static final BlockType CREEPER_HEAD = init();
|
||||
@ -685,8 +691,6 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType DEEPSLATE_COPPER_ORE = init();
|
||||
@Nullable
|
||||
public static final BlockType COPPER_TRAPDOOR = init();
|
||||
@Nullable
|
||||
public static final BlockType DEEPSLATE_DIAMOND_ORE = init();
|
||||
@Nullable
|
||||
public static final BlockType DEEPSLATE_EMERALD_ORE = init();
|
||||
@ -747,8 +751,6 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType ENDER_CHEST = init();
|
||||
@Nullable
|
||||
public static final BlockType EXPOSED_CHISELED_COPPER = init();
|
||||
@Nullable
|
||||
public static final BlockType END_GATEWAY = init();
|
||||
@Nullable
|
||||
public static final BlockType END_PORTAL = init();
|
||||
@ -767,6 +769,8 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType END_STONE_BRICK_WALL = init();
|
||||
@Nullable
|
||||
public static final BlockType EXPOSED_CHISELED_COPPER = init();
|
||||
@Nullable
|
||||
public static final BlockType EXPOSED_COPPER = init();
|
||||
@Nullable
|
||||
public static final BlockType EXPOSED_COPPER_BULB = init();
|
||||
@ -836,6 +840,9 @@ public final class BlockTypes {
|
||||
public static final BlockType GRASS = init();
|
||||
@Nullable
|
||||
public static final BlockType GRASS_BLOCK = init();
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public static final BlockType GRASS_PATH = init();
|
||||
@Nullable
|
||||
public static final BlockType GRAVEL = init();
|
||||
@Nullable
|
||||
@ -901,6 +908,8 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType HAY_BLOCK = init();
|
||||
@Nullable
|
||||
public static final BlockType HEAVY_CORE = init();
|
||||
@Nullable
|
||||
public static final BlockType HEAVY_WEIGHTED_PRESSURE_PLATE = init();
|
||||
@Nullable
|
||||
public static final BlockType HONEYCOMB_BLOCK = init();
|
||||
@ -925,8 +934,6 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType INFESTED_CRACKED_STONE_BRICKS = init();
|
||||
@Nullable
|
||||
public static final BlockType CRAFTER = init();
|
||||
@Nullable
|
||||
public static final BlockType INFESTED_DEEPSLATE = init();
|
||||
@Nullable
|
||||
public static final BlockType INFESTED_MOSSY_STONE_BRICKS = init();
|
||||
@ -1954,10 +1961,12 @@ public final class BlockTypes {
|
||||
@Nullable
|
||||
public static final BlockType TWISTING_VINES = init();
|
||||
@Nullable
|
||||
public static final BlockType VERDANT_FROGLIGHT = init();
|
||||
@Nullable
|
||||
public static final BlockType TWISTING_VINES_PLANT = init();
|
||||
@Nullable
|
||||
public static final BlockType VAULT = init();
|
||||
@Nullable
|
||||
public static final BlockType VERDANT_FROGLIGHT = init();
|
||||
@Nullable
|
||||
public static final BlockType VINE = init();
|
||||
@Nullable
|
||||
public static final BlockType VOID_AIR = init();
|
||||
@ -2026,7 +2035,7 @@ public final class BlockTypes {
|
||||
public static final BlockType WAXED_CUT_COPPER_SLAB = init();
|
||||
@Nullable
|
||||
public static final BlockType WAXED_CUT_COPPER_STAIRS = init();
|
||||
@ Nullable
|
||||
@Nullable
|
||||
public static final BlockType WAXED_EXPOSED_CHISELED_COPPER = init();
|
||||
@Nullable
|
||||
public static final BlockType WAXED_EXPOSED_COPPER = init();
|
||||
|
@ -163,7 +163,7 @@ public class AnvilChunk13 implements Chunk {
|
||||
throw new InvalidFormatException("Too short block state table");
|
||||
}
|
||||
currentSerializedValue = blockStatesSerialized[nextSerializedItem++];
|
||||
localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits;
|
||||
localBlockId |= (int) ((currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits);
|
||||
currentSerializedValue >>>= bitsNextLong;
|
||||
remainingBits = 64 - bitsNextLong;
|
||||
} else {
|
||||
|
@ -35,6 +35,8 @@ public final class EntityTypes {
|
||||
@Nullable
|
||||
public static final EntityType AREA_EFFECT_CLOUD = get("minecraft:area_effect_cloud");
|
||||
@Nullable
|
||||
public static final EntityType ARMADILLO = get("minecraft:armadillo");
|
||||
@Nullable
|
||||
public static final EntityType ARMOR_STAND = get("minecraft:armor_stand");
|
||||
@Nullable
|
||||
public static final EntityType ARROW = get("minecraft:arrow");
|
||||
@ -51,8 +53,12 @@ public final class EntityTypes {
|
||||
@Nullable
|
||||
public static final EntityType BOAT = get("minecraft:boat");
|
||||
@Nullable
|
||||
public static final EntityType BOGGED = get("minecraft:bogged");
|
||||
@Nullable
|
||||
public static final EntityType BREEZE = get("minecraft:breeze");
|
||||
@Nullable
|
||||
public static final EntityType BREEZE_WIND_CHARGE = get("minecraft:breeze_wind_charge");
|
||||
@Nullable
|
||||
public static final EntityType CAMEL = get("minecraft:camel");
|
||||
@Nullable
|
||||
public static final EntityType CAT = get("minecraft:cat");
|
||||
@ -171,6 +177,8 @@ public final class EntityTypes {
|
||||
@Nullable
|
||||
public static final EntityType OCELOT = get("minecraft:ocelot");
|
||||
@Nullable
|
||||
public static final EntityType OMINOUS_ITEM_SPAWNER = get("minecraft:ominous_item_spawner");
|
||||
@Nullable
|
||||
public static final EntityType PAINTING = get("minecraft:painting");
|
||||
@Nullable
|
||||
public static final EntityType PANDA = get("minecraft:panda");
|
||||
|
@ -29,28 +29,36 @@ public final class ItemCategories {
|
||||
|
||||
public static final ItemCategory ACACIA_LOGS = get("minecraft:acacia_logs");
|
||||
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 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 BANNERS = get("minecraft:banners");
|
||||
public static final ItemCategory BEACON_PAYMENT_ITEMS = get("minecraft:beacon_payment_items");
|
||||
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 BOATS = get("minecraft:boats");
|
||||
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 BUTTONS = get("minecraft:buttons");
|
||||
public static final ItemCategory CAMEL_FOOD = get("minecraft:camel_food");
|
||||
public static final ItemCategory CANDLES = get("minecraft:candles");
|
||||
@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 CHEST_ARMOR = get("minecraft:chest_armor");
|
||||
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 COAL_ORES = get("minecraft:coal_ores");
|
||||
public static final ItemCategory COALS = get("minecraft:coals");
|
||||
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 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_IGNITERS = get("minecraft:creeper_igniters");
|
||||
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 DIRT = get("minecraft:dirt");
|
||||
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 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 FENCES = get("minecraft:fences");
|
||||
public static final ItemCategory FISHES = get("minecraft:fishes");
|
||||
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 FREEZE_IMMUNE_WEARABLES = get("minecraft:freeze_immune_wearables");
|
||||
public static final ItemCategory FROG_FOOD = get("minecraft:frog_food");
|
||||
@Deprecated
|
||||
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 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 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 IRON_ORES = get("minecraft:iron_ores");
|
||||
public static final ItemCategory JUNGLE_LOGS = get("minecraft:jungle_logs");
|
||||
public static final ItemCategory LAPIS_ORES = get("minecraft:lapis_ores");
|
||||
public static final ItemCategory LEAVES = get("minecraft:leaves");
|
||||
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_THAT_BURN = get("minecraft:logs_that_burn");
|
||||
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 NON_FLAMMABLE_WOOD = get("minecraft:non_flammable_wood");
|
||||
public static final ItemCategory NOTEBLOCK_TOP_INSTRUMENTS = get("minecraft:noteblock_top_instruments");
|
||||
public static final ItemCategory OAK_LOGS = get("minecraft:oak_logs");
|
||||
@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");
|
||||
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 PIG_FOOD = get("minecraft:pig_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_REPELLENTS = get("minecraft:piglin_repellents");
|
||||
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 REDSTONE_ORES = get("minecraft:redstone_ores");
|
||||
public static final ItemCategory SAND = get("minecraft:sand");
|
||||
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 SIGNS = get("minecraft:signs");
|
||||
public static final ItemCategory SKULLS = get("minecraft:skulls");
|
||||
public static final ItemCategory SLABS = get("minecraft:slabs");
|
||||
public static final ItemCategory SMALL_FLOWERS = get("minecraft:small_flowers");
|
||||
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_CRAFTING_MATERIALS = get("minecraft:stone_crafting_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 TALL_FLOWERS = get("minecraft:tall_flowers");
|
||||
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 TRIM_MATERIALS = get("minecraft:trim_materials");
|
||||
public static final ItemCategory TRIM_TEMPLATES = get("minecraft:trim_templates");
|
||||
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 WALLS = get("minecraft:walls");
|
||||
public static final ItemCategory WARPED_STEMS = get("minecraft:warped_stems");
|
||||
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_DOORS = get("minecraft:wooden_doors");
|
||||
public static final ItemCategory WOODEN_FENCES = get("minecraft:wooden_fences");
|
||||
|
@ -42,7 +42,7 @@ public class ItemType implements RegistryItem, Keyed {
|
||||
public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type", true);
|
||||
|
||||
private final String id;
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressWarnings({"deprecation", "this-escape"})
|
||||
private transient final LazyReference<String> name = LazyReference.from(() -> {
|
||||
String name = GuavaUtil.firstNonNull(
|
||||
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
|
||||
@ -51,10 +51,12 @@ public class ItemType implements RegistryItem, Keyed {
|
||||
);
|
||||
return name.isEmpty() ? getId() : name;
|
||||
});
|
||||
@SuppressWarnings("this-escape")
|
||||
private transient final LazyReference<Component> richName = LazyReference.from(() ->
|
||||
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
|
||||
.getRegistries().getItemRegistry().getRichName(this)
|
||||
);
|
||||
@SuppressWarnings("this-escape")
|
||||
private transient final LazyReference<ItemMaterial> itemMaterial = LazyReference.from(() ->
|
||||
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
|
||||
.getRegistries().getItemRegistry().getMaterial(this)
|
||||
|
@ -105,6 +105,10 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType ARMOR_STAND = init();
|
||||
@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();
|
||||
@Nullable
|
||||
public static final ItemType ARROW = init();
|
||||
@ -297,6 +301,10 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType BLUE_WOOL = init();
|
||||
@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();
|
||||
@Nullable
|
||||
public static final ItemType BONE_BLOCK = init();
|
||||
@ -319,6 +327,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType BREAD = init();
|
||||
@Nullable
|
||||
public static final ItemType BREEZE_ROD = init();
|
||||
@Nullable
|
||||
public static final ItemType BREEZE_SPAWN_EGG = init();
|
||||
@Nullable
|
||||
public static final ItemType BREWER_POTTERY_SHERD = init();
|
||||
@ -971,6 +981,12 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType FLINT_AND_STEEL = init();
|
||||
@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();
|
||||
@Nullable
|
||||
public static final ItemType FLOWER_POT = init();
|
||||
@ -1132,6 +1148,10 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType GUNPOWDER = init();
|
||||
@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();
|
||||
@Nullable
|
||||
public static final ItemType HAY_BLOCK = init();
|
||||
@ -1142,6 +1162,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType HEARTBREAK_POTTERY_SHERD = init();
|
||||
@Nullable
|
||||
public static final ItemType HEAVY_CORE = init();
|
||||
@Nullable
|
||||
public static final ItemType HEAVY_WEIGHTED_PRESSURE_PLATE = init();
|
||||
@Nullable
|
||||
public static final ItemType HOGLIN_SPAWN_EGG = init();
|
||||
@ -1404,6 +1426,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType LOOM = init();
|
||||
@Nullable
|
||||
public static final ItemType MACE = init();
|
||||
@Nullable
|
||||
public static final ItemType MAGENTA_BANNER = init();
|
||||
@Nullable
|
||||
public static final ItemType MAGENTA_BED = init();
|
||||
@ -1668,6 +1692,10 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType OCHRE_FROGLIGHT = init();
|
||||
@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();
|
||||
@Nullable
|
||||
public static final ItemType ORANGE_BED = init();
|
||||
@ -2075,6 +2103,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType SCAFFOLDING = init();
|
||||
@Nullable
|
||||
public static final ItemType SCRAPE_POTTERY_SHERD = init();
|
||||
@Nullable
|
||||
public static final ItemType SCULK = init();
|
||||
@Nullable
|
||||
public static final ItemType SCULK_CATALYST = init();
|
||||
@ -2085,6 +2115,7 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType SCULK_VEIN = init();
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static final ItemType SCUTE = init();
|
||||
@Nullable
|
||||
public static final ItemType SEA_LANTERN = init();
|
||||
@ -2424,10 +2455,14 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType TURTLE_HELMET = init();
|
||||
@Nullable
|
||||
public static final ItemType TURTLE_SCUTE = init();
|
||||
@Nullable
|
||||
public static final ItemType TURTLE_SPAWN_EGG = init();
|
||||
@Nullable
|
||||
public static final ItemType TWISTING_VINES = init();
|
||||
@Nullable
|
||||
public static final ItemType VAULT = init();
|
||||
@Nullable
|
||||
public static final ItemType VERDANT_FROGLIGHT = init();
|
||||
@Nullable
|
||||
public static final ItemType VEX_ARMOR_TRIM_SMITHING_TEMPLATE = init();
|
||||
@ -2614,6 +2649,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType WILD_ARMOR_TRIM_SMITHING_TEMPLATE = init();
|
||||
@Nullable
|
||||
public static final ItemType WIND_CHARGE = init();
|
||||
@Nullable
|
||||
public static final ItemType WITCH_SPAWN_EGG = init();
|
||||
@Nullable
|
||||
public static final ItemType WITHER_ROSE = init();
|
||||
@ -2624,6 +2661,8 @@ public final class ItemTypes {
|
||||
@Nullable
|
||||
public static final ItemType WITHER_SPAWN_EGG = init();
|
||||
@Nullable
|
||||
public static final ItemType WOLF_ARMOR = init();
|
||||
@Nullable
|
||||
public static final ItemType WOLF_SPAWN_EGG = init();
|
||||
@Nullable
|
||||
public static final ItemType WOODEN_AXE = init();
|
||||
|
@ -100,7 +100,7 @@ dependencies {
|
||||
}
|
||||
|
||||
// No need for this at runtime
|
||||
"modCompileOnly"("me.lucko:fabric-permissions-api:0.1-SNAPSHOT")
|
||||
"modCompileOnly"("me.lucko:fabric-permissions-api:0.3.1")
|
||||
|
||||
// Hook these up manually, because Fabric doesn't seem to quite do it properly.
|
||||
"compileOnly"("net.fabricmc:sponge-mixin:${project.versions.mixin}")
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren