mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-01-22 07:00:05 +00:00
This commit is contained in:
commit
c96f750402
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -27,9 +27,10 @@ body:
|
|||||||
description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first.
|
description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first.
|
||||||
multiple: false
|
multiple: false
|
||||||
options:
|
options:
|
||||||
- '1.20.5/6'
|
- '1.21'
|
||||||
- '1.20'
|
- '1.20.6'
|
||||||
- '1.19.4'
|
- '1.20.4'
|
||||||
|
- '1.20.2'
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
2
.github/workflows/build-pr.yml
vendored
2
.github/workflows/build-pr.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
2
.github/workflows/upload-release-assets.yml
vendored
2
.github/workflows/upload-release-assets.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
@ -34,7 +34,7 @@ logger.lifecycle("""
|
|||||||
*******************************************
|
*******************************************
|
||||||
""")
|
""")
|
||||||
|
|
||||||
var rootVersion by extra("2.10.1")
|
var rootVersion by extra("2.11.2")
|
||||||
var snapshot by extra("SNAPSHOT")
|
var snapshot by extra("SNAPSHOT")
|
||||||
var revision: String by extra("")
|
var revision: String by extra("")
|
||||||
var buildNumber by extra("")
|
var buildNumber by extra("")
|
||||||
@ -83,7 +83,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyCommonConfiguration()
|
applyCommonConfiguration()
|
||||||
val supportedVersions = listOf("1.19.4", "1.20", "1.20.4", "1.20.5", "1.20.6")
|
val supportedVersions = listOf("1.19.4", "1.20", "1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1")
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
supportedVersions.forEach {
|
supportedVersions.forEach {
|
||||||
|
@ -28,7 +28,7 @@ dependencies {
|
|||||||
implementation(gradleApi())
|
implementation(gradleApi())
|
||||||
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
|
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
|
||||||
implementation("com.github.johnrengelman:shadow:8.1.1")
|
implementation("com.github.johnrengelman:shadow:8.1.1")
|
||||||
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.1")
|
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.2")
|
||||||
constraints {
|
constraints {
|
||||||
val asmVersion = "[9.7,)"
|
val asmVersion = "[9.7,)"
|
||||||
implementation("org.ow2.asm:asm:$asmVersion") {
|
implementation("org.ow2.asm:asm:$asmVersion") {
|
||||||
|
@ -23,7 +23,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
|||||||
val disabledLint = listOf(
|
val disabledLint = listOf(
|
||||||
"processing", "path", "fallthrough", "serial", "overloads", "this-escape",
|
"processing", "path", "fallthrough", "serial", "overloads", "this-escape",
|
||||||
)
|
)
|
||||||
options.release.set(17)
|
options.release.set(21)
|
||||||
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
|
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
|
||||||
options.isDeprecation = true
|
options.isDeprecation = true
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
@ -61,7 +61,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
|||||||
"https://jd.advntr.dev/api/latest/",
|
"https://jd.advntr.dev/api/latest/",
|
||||||
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
|
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
|
||||||
"https://www.antlr.org/api/Java/",
|
"https://www.antlr.org/api/Java/",
|
||||||
"https://jd.papermc.io/paper/1.20.6/",
|
"https://jd.papermc.io/paper/1.21/",
|
||||||
"https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/"
|
"https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/"
|
||||||
)
|
)
|
||||||
docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}"
|
docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}"
|
||||||
|
@ -40,8 +40,7 @@ fun Project.applyLibrariesConfiguration() {
|
|||||||
|
|
||||||
val relocations = mapOf(
|
val relocations = mapOf(
|
||||||
"net.kyori.text" to "com.sk89q.worldedit.util.formatting.text",
|
"net.kyori.text" to "com.sk89q.worldedit.util.formatting.text",
|
||||||
"net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori",
|
"net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori"
|
||||||
"net.kyori.adventure.nbt" to "com.sk89q.worldedit.util.nbt"
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,9 +52,14 @@ fun Project.applyLibrariesConfiguration() {
|
|||||||
exclude(dependency("com.google.guava:guava"))
|
exclude(dependency("com.google.guava:guava"))
|
||||||
exclude(dependency("com.google.code.gson:gson"))
|
exclude(dependency("com.google.code.gson:gson"))
|
||||||
exclude(dependency("com.google.errorprone:error_prone_annotations"))
|
exclude(dependency("com.google.errorprone:error_prone_annotations"))
|
||||||
|
exclude(dependency("com.google.guava:failureaccess"))
|
||||||
exclude(dependency("org.checkerframework:checker-qual"))
|
exclude(dependency("org.checkerframework:checker-qual"))
|
||||||
|
exclude(dependency("org.jetbrains:annotations"))
|
||||||
exclude(dependency("org.apache.logging.log4j:log4j-api"))
|
exclude(dependency("org.apache.logging.log4j:log4j-api"))
|
||||||
exclude(dependency("com.google.code.findbugs:jsr305"))
|
exclude(dependency("com.google.code.findbugs:jsr305"))
|
||||||
|
exclude {
|
||||||
|
it.moduleGroup == "org.jetbrains.kotlin"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relocations.forEach { (from, to) ->
|
relocations.forEach { (from, to) ->
|
||||||
@ -67,12 +71,20 @@ fun Project.applyLibrariesConfiguration() {
|
|||||||
.filterIsInstance<ModuleDependency>()
|
.filterIsInstance<ModuleDependency>()
|
||||||
.map { it.copy() }
|
.map { it.copy() }
|
||||||
.map { dependency ->
|
.map { dependency ->
|
||||||
|
val category = dependency.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE)?.name
|
||||||
|
if (category == Category.REGULAR_PLATFORM || category == Category.ENFORCED_PLATFORM) {
|
||||||
|
return@map dependency
|
||||||
|
}
|
||||||
|
try {
|
||||||
dependency.artifact {
|
dependency.artifact {
|
||||||
name = dependency.name
|
name = dependency.name
|
||||||
type = artifactType
|
type = artifactType
|
||||||
extension = "jar"
|
extension = "jar"
|
||||||
classifier = artifactType
|
classifier = artifactType
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw RuntimeException("Failed to add artifact to dependency: $dependency", e)
|
||||||
|
}
|
||||||
dependency
|
dependency
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +97,10 @@ fun Project.applyLibrariesConfiguration() {
|
|||||||
from({
|
from({
|
||||||
altConfigFiles("sources")
|
altConfigFiles("sources")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Yeet module-info's
|
||||||
|
exclude("module-info.java")
|
||||||
|
|
||||||
relocations.forEach { (from, to) ->
|
relocations.forEach { (from, to) ->
|
||||||
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
|
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
|
||||||
val textPattern = Regex.fromLiteral(from)
|
val textPattern = Regex.fromLiteral(from)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
# Minecraft expectations
|
# Minecraft expectations
|
||||||
paper = "1.20.6-R0.1-SNAPSHOT"
|
paper = "1.21-R0.1-SNAPSHOT"
|
||||||
fastutil = "8.5.9"
|
fastutil = "8.5.9"
|
||||||
guava = "31.1-jre"
|
guava = "31.1-jre"
|
||||||
log4j = "2.19.0"
|
log4j = "2.19.0"
|
||||||
@ -14,22 +14,22 @@ mapmanager = "1.8.0-SNAPSHOT"
|
|||||||
griefprevention = "17.0.0"
|
griefprevention = "17.0.0"
|
||||||
griefdefender = "2.1.0-SNAPSHOT"
|
griefdefender = "2.1.0-SNAPSHOT"
|
||||||
residence = "4.5._13.1"
|
residence = "4.5._13.1"
|
||||||
towny = "0.100.3.2"
|
towny = "0.100.3.12"
|
||||||
plotsquared = "7.3.8"
|
plotsquared = "7.3.9"
|
||||||
|
|
||||||
# Third party
|
# Third party
|
||||||
bstats = "3.0.2"
|
bstats = "3.0.2"
|
||||||
sparsebitset = "1.3"
|
sparsebitset = "1.3"
|
||||||
parallelgzip = "1.0.5"
|
parallelgzip = "1.0.5"
|
||||||
adventure = "4.17.0"
|
adventure = "4.17.0"
|
||||||
adventure-bukkit = "4.3.3"
|
adventure-bukkit = "4.3.4"
|
||||||
checkerqual = "3.43.0"
|
checkerqual = "3.46.0"
|
||||||
truezip = "6.8.4"
|
truezip = "6.8.4"
|
||||||
auto-value = "1.10.4"
|
auto-value = "1.11.0"
|
||||||
findbugs = "3.0.2"
|
findbugs = "3.0.2"
|
||||||
rhino-runtime = "1.7.15"
|
rhino-runtime = "1.7.15"
|
||||||
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
|
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
|
||||||
antlr4 = "4.13.1"
|
antlr4 = "4.13.2"
|
||||||
json-simple = "1.1.1"
|
json-simple = "1.1.1"
|
||||||
jlibnoise = "1.0.0"
|
jlibnoise = "1.0.0"
|
||||||
jchronic = "0.2.4a"
|
jchronic = "0.2.4a"
|
||||||
@ -40,6 +40,7 @@ paperlib = "1.0.8"
|
|||||||
paster = "1.1.6"
|
paster = "1.1.6"
|
||||||
vault = "1.7.1"
|
vault = "1.7.1"
|
||||||
serverlib = "2.3.6"
|
serverlib = "2.3.6"
|
||||||
|
linbus = "0.1.2"
|
||||||
## Internal
|
## Internal
|
||||||
text-adapter = "3.0.6"
|
text-adapter = "3.0.6"
|
||||||
text = "3.0.4"
|
text = "3.0.4"
|
||||||
@ -78,7 +79,6 @@ bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats
|
|||||||
bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
|
bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
|
||||||
sparsebitset = { group = "com.zaxxer", name = "SparseBitSet", version.ref = "sparsebitset" }
|
sparsebitset = { group = "com.zaxxer", name = "SparseBitSet", version.ref = "sparsebitset" }
|
||||||
parallelgzip = { group = "org.anarres", name = "parallelgzip", version.ref = "parallelgzip" }
|
parallelgzip = { group = "org.anarres", name = "parallelgzip", version.ref = "parallelgzip" }
|
||||||
adventureNbt = { group = "net.kyori", name = "adventure-nbt", version.ref = "adventure" }
|
|
||||||
truezip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" }
|
truezip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" }
|
||||||
autoValueAnnotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" }
|
autoValueAnnotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" }
|
||||||
autoValue = { group = "com.google.auto.value", name = "auto-value", version.ref = "auto-value" }
|
autoValue = { group = "com.google.auto.value", name = "auto-value", version.ref = "auto-value" }
|
||||||
@ -101,6 +101,11 @@ paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref
|
|||||||
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
|
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
|
||||||
serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" }
|
serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" }
|
||||||
checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" }
|
checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" }
|
||||||
|
linBus-bom = { group = "org.enginehub.lin-bus", name = "lin-bus-bom", version.ref = "linbus" }
|
||||||
|
linBus-common = { group = "org.enginehub.lin-bus", name = "lin-bus-common" }
|
||||||
|
linBus-stream = { group = "org.enginehub.lin-bus", name = "lin-bus-stream" }
|
||||||
|
linBus-tree = { group = "org.enginehub.lin-bus", name = "lin-bus-tree" }
|
||||||
|
linBus-format-snbt = { group = "org.enginehub.lin-bus.format", name = "lin-bus-format-snbt" }
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
## Text
|
## Text
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit"
|
|||||||
|
|
||||||
include("worldedit-libs")
|
include("worldedit-libs")
|
||||||
|
|
||||||
listOf("1_19_4", "1_20", "1_20_2", "1_20_4", "1_20_5").forEach {
|
listOf("1_20_2", "1_20_4", "1_20_5", "1_21").forEach {
|
||||||
include("worldedit-bukkit:adapters:adapter-$it")
|
include("worldedit-bukkit:adapters:adapter-$it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.bukkit.adapter.ext.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
|
|
||||||
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.level.block.entity.SignBlockEntity;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
|
||||||
|
|
||||||
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 Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
|
|
||||||
|
|
||||||
PaperweightFakePlayer(ServerLevel world) {
|
|
||||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vec3 position() {
|
|
||||||
return ORIGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void die(DamageSource damagesource) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OptionalInt openMenu(MenuProvider factory) {
|
|
||||||
return OptionalInt.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateOptions(ServerboundClientInformationPacket packet) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void displayClientMessage(Component message, boolean actionBar) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void awardStat(Stat<?> stat, int amount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void awardStat(Stat<?> stat) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInvulnerableTo(DamageSource damageSource) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openTextEdit(SignBlockEntity sign) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.bukkit.adapter.ext.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
|
||||||
import 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.ServerLevel;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.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> {
|
|
||||||
private static final int UPDATE = 1;
|
|
||||||
private static final int NOTIFY = 2;
|
|
||||||
|
|
||||||
private final PaperweightAdapter adapter;
|
|
||||||
private final WeakReference<ServerLevel> world;
|
|
||||||
private SideEffectSet sideEffectSet;
|
|
||||||
|
|
||||||
public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference<ServerLevel> world) {
|
|
||||||
this.adapter = adapter;
|
|
||||||
this.world = world;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServerLevel getWorld() {
|
|
||||||
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
|
||||||
this.sideEffectSet = sideEffectSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LevelChunk getChunk(int x, int z) {
|
|
||||||
return getWorld().getChunk(x, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) {
|
|
||||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
|
||||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
|
||||||
? Block.stateById(stateId)
|
|
||||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) {
|
|
||||||
return chunk.getBlockState(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
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) {
|
|
||||||
return Block.updateFromNeighbourShapes(block, getWorld(), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPos getPosition(int x, int y, int z) {
|
|
||||||
return new BlockPos(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateLightingForBlock(BlockPos position) {
|
|
||||||
getWorld().getChunkSource().getLightEngine().checkBlock(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkTicking(LevelChunk chunk) {
|
|
||||||
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void markBlockChanged(LevelChunk chunk, BlockPos position) {
|
|
||||||
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
|
|
||||||
getWorld().getChunkSource().blockChanged(position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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());
|
|
||||||
} else {
|
|
||||||
// When we don't want events, manually run the physics without them.
|
|
||||||
Block block = oldState.getBlock();
|
|
||||||
fireNeighborChanged(pos, world, block, pos.west());
|
|
||||||
fireNeighborChanged(pos, world, block, pos.east());
|
|
||||||
fireNeighborChanged(pos, world, block, pos.below());
|
|
||||||
fireNeighborChanged(pos, world, block, pos.above());
|
|
||||||
fireNeighborChanged(pos, world, block, pos.north());
|
|
||||||
fireNeighborChanged(pos, world, block, pos.south());
|
|
||||||
}
|
|
||||||
if (newState.hasAnalogOutputSignal()) {
|
|
||||||
world.updateNeighbourForOutputSignal(pos, newState.getBlock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not sure why neighborChanged is deprecated
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
|
||||||
world.getBlockState(neighborPos).neighborChanged(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) {
|
|
||||||
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));
|
|
||||||
world.getCraftServer().getPluginManager().callEvent(event);
|
|
||||||
if (event.isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
|
||||||
newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,189 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
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_19_R3.nbt.PaperweightLazyCompoundTag;
|
|
||||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
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.PushReaction;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.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;
|
|
||||||
private final CompoundTag tile;
|
|
||||||
|
|
||||||
public PaperweightBlockMaterial(Block block) {
|
|
||||||
this(block, block.defaultBlockState());
|
|
||||||
}
|
|
||||||
|
|
||||||
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", "aP"));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock() {
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState getState() {
|
|
||||||
return blockState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CraftBlockData getCraftBlockData() {
|
|
||||||
return craftBlockData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Material getMaterial() {
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAir() {
|
|
||||||
return blockState.isAir();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullCube() {
|
|
||||||
return craftMaterial.isOccluding();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOpaque() {
|
|
||||||
return material.isSolidBlocking();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPowerSource() {
|
|
||||||
return blockState.isSignalSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLiquid() {
|
|
||||||
return material.isLiquid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSolid() {
|
|
||||||
return material.isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getHardness() {
|
|
||||||
return craftBlockData.getState().destroySpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getResistance() {
|
|
||||||
return block.getExplosionResistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getSlipperiness() {
|
|
||||||
return block.getFriction();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLightValue() {
|
|
||||||
return blockState.getLightEmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLightOpacity() {
|
|
||||||
return opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFragileWhenPushed() {
|
|
||||||
return material.getPushReaction() == PushReaction.DESTROY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUnpushable() {
|
|
||||||
return material.getPushReaction() == PushReaction.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTicksRandomly() {
|
|
||||||
return block.isRandomlyTicking(blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMovementBlocker() {
|
|
||||||
return material.isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBurnable() {
|
|
||||||
return material.isFlammable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isToolRequired() {
|
|
||||||
// Removed in 1.16.1, this is not present in higher versions
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReplacedDuringPlacement() {
|
|
||||||
return material.isReplaceable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTranslucent() {
|
|
||||||
return isTranslucent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasContainer() {
|
|
||||||
return block instanceof EntityBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTile() {
|
|
||||||
return block instanceof EntityBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompoundTag getDefaultTile() {
|
|
||||||
return tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMapColor() {
|
|
||||||
// rgb field
|
|
||||||
return material.getColor().col;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,286 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
|
||||||
import com.fastasyncworldedit.core.math.IntPair;
|
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
|
||||||
import com.fastasyncworldedit.core.util.task.RunnableVal;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
|
||||||
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.level.ServerChunkCache;
|
|
||||||
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_19_R3.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
|
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
|
|
||||||
net.minecraft.world.level.block.state.BlockState, BlockPos> {
|
|
||||||
|
|
||||||
private static final int UPDATE = 1;
|
|
||||||
private static final int NOTIFY = 2;
|
|
||||||
private static final Direction[] NEIGHBOUR_ORDER = {
|
|
||||||
Direction.EAST,
|
|
||||||
Direction.WEST,
|
|
||||||
Direction.DOWN,
|
|
||||||
Direction.UP,
|
|
||||||
Direction.NORTH,
|
|
||||||
Direction.SOUTH
|
|
||||||
};
|
|
||||||
private final PaperweightFaweAdapter paperweightFaweAdapter;
|
|
||||||
private final WeakReference<Level> level;
|
|
||||||
private final AtomicInteger lastTick;
|
|
||||||
private final Set<CachedChange> cachedChanges = new HashSet<>();
|
|
||||||
private final Set<IntPair> cachedChunksToSend = new HashSet<>();
|
|
||||||
private SideEffectSet sideEffectSet;
|
|
||||||
|
|
||||||
public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference<Level> level) {
|
|
||||||
this.paperweightFaweAdapter = paperweightFaweAdapter;
|
|
||||||
this.level = level;
|
|
||||||
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
|
|
||||||
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
|
|
||||||
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Level getLevel() {
|
|
||||||
return Objects.requireNonNull(level.get(), "The reference to the world was lost");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
|
|
||||||
this.sideEffectSet = sideEffectSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LevelChunk getChunk(int x, int z) {
|
|
||||||
return getLevel().getChunk(x, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) {
|
|
||||||
int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar());
|
|
||||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
|
||||||
? Block.stateById(stateId)
|
|
||||||
: ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) {
|
|
||||||
return levelChunk.getBlockState(blockPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public synchronized net.minecraft.world.level.block.state.BlockState setBlockState(
|
|
||||||
LevelChunk levelChunk, BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState
|
|
||||||
) {
|
|
||||||
int currentTick = MinecraftServer.currentTick;
|
|
||||||
if (Fawe.isMainThread()) {
|
|
||||||
return levelChunk.setBlockState(blockPos, blockState,
|
|
||||||
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 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.locX, levelChunk.locZ));
|
|
||||||
boolean nextTick = lastTick.get() > currentTick;
|
|
||||||
if (nextTick || cachedChanges.size() >= 1024) {
|
|
||||||
if (nextTick) {
|
|
||||||
lastTick.set(currentTick);
|
|
||||||
}
|
|
||||||
flushAsync(nextTick);
|
|
||||||
}
|
|
||||||
return blockState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState,
|
|
||||||
BlockPos blockPos
|
|
||||||
) {
|
|
||||||
return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPos getPosition(int x, int y, int z) {
|
|
||||||
return new BlockPos(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateLightingForBlock(BlockPos blockPos) {
|
|
||||||
getLevel().getChunkSource().getLightEngine().checkBlock(blockPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
|
|
||||||
// We will assume that the tile entity was created for us,
|
|
||||||
// though we do not do this on the other versions
|
|
||||||
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
|
||||||
if (blockEntity == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
|
||||||
blockEntity.load((CompoundTag) nativeTag);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyBlockUpdate(
|
|
||||||
LevelChunk levelChunk, BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState oldState,
|
|
||||||
net.minecraft.world.level.block.state.BlockState newState
|
|
||||||
) {
|
|
||||||
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
|
|
||||||
getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkTicking(LevelChunk levelChunk) {
|
|
||||||
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) {
|
|
||||||
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
|
|
||||||
((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyNeighbors(
|
|
||||||
BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState oldState,
|
|
||||||
net.minecraft.world.level.block.state.BlockState newState
|
|
||||||
) {
|
|
||||||
Level level = getLevel();
|
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
|
||||||
level.blockUpdated(blockPos, oldState.getBlock());
|
|
||||||
} else {
|
|
||||||
// When we don't want events, manually run the physics without them.
|
|
||||||
// Un-nest neighbour updating
|
|
||||||
for (Direction direction : NEIGHBOUR_ORDER) {
|
|
||||||
BlockPos shifted = blockPos.relative(direction);
|
|
||||||
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newState.hasAnalogOutputSignal()) {
|
|
||||||
level.updateNeighbourForOutputSignal(blockPos, newState.getBlock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateNeighbors(
|
|
||||||
BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState oldState,
|
|
||||||
net.minecraft.world.level.block.state.BlockState newState,
|
|
||||||
int recursionLimit
|
|
||||||
) {
|
|
||||||
Level level = getLevel();
|
|
||||||
// a == updateNeighbors
|
|
||||||
// b == updateDiagonalNeighbors
|
|
||||||
oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
|
||||||
CraftWorld craftWorld = level.getWorld();
|
|
||||||
if (craftWorld != null) {
|
|
||||||
BlockPhysicsEvent event = new BlockPhysicsEvent(
|
|
||||||
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
|
|
||||||
CraftBlockData.fromData(newState)
|
|
||||||
);
|
|
||||||
level.getCraftServer().getPluginManager().callEvent(event);
|
|
||||||
if (event.isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit);
|
|
||||||
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlockStateChange(
|
|
||||||
BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState oldState,
|
|
||||||
net.minecraft.world.level.block.state.BlockState newState
|
|
||||||
) {
|
|
||||||
getLevel().onBlockStateChange(blockPos, oldState, newState);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void flushAsync(final boolean sendChunks) {
|
|
||||||
final Set<CachedChange> changes = Set.copyOf(cachedChanges);
|
|
||||||
cachedChanges.clear();
|
|
||||||
final Set<IntPair> toSend;
|
|
||||||
if (sendChunks) {
|
|
||||||
toSend = Set.copyOf(cachedChunksToSend);
|
|
||||||
cachedChunksToSend.clear();
|
|
||||||
} else {
|
|
||||||
toSend = Collections.emptySet();
|
|
||||||
}
|
|
||||||
RunnableVal<Object> runnableVal = new RunnableVal<>() {
|
|
||||||
@Override
|
|
||||||
public void run(Object value) {
|
|
||||||
changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
|
|
||||||
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
|
|
||||||
));
|
|
||||||
if (!sendChunks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (IntPair chunk : toSend) {
|
|
||||||
PaperweightPlatformAdapter.sendChunk(chunk, getLevel().getWorld().getHandle(), chunk.x(), chunk.z());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void flush() {
|
|
||||||
RunnableVal<Object> runnableVal = new RunnableVal<>() {
|
|
||||||
@Override
|
|
||||||
public void run(Object value) {
|
|
||||||
cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
|
|
||||||
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
|
|
||||||
));
|
|
||||||
for (IntPair chunk : cachedChunksToSend) {
|
|
||||||
PaperweightPlatformAdapter.sendChunk(chunk, getLevel().getWorld().getHandle(), chunk.x(), chunk.z());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (Fawe.isMainThread()) {
|
|
||||||
runnableVal.run();
|
|
||||||
} else {
|
|
||||||
TaskManager.taskManager().sync(runnableVal);
|
|
||||||
}
|
|
||||||
cachedChanges.clear();
|
|
||||||
cachedChunksToSend.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private record CachedChange(
|
|
||||||
LevelChunk levelChunk,
|
|
||||||
BlockPos blockPos,
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,259 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
|
|
||||||
import com.fastasyncworldedit.core.queue.IBlocks;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
|
||||||
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_19_R3.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.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;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
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;
|
|
||||||
private final int minHeight;
|
|
||||||
private final int maxHeight;
|
|
||||||
final ServerLevel serverLevel;
|
|
||||||
final LevelChunk levelChunk;
|
|
||||||
private Holder<Biome>[][] biomes = null;
|
|
||||||
|
|
||||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
|
||||||
this.levelChunk = levelChunk;
|
|
||||||
this.serverLevel = levelChunk.level;
|
|
||||||
this.minHeight = serverLevel.getMinBuildHeight();
|
|
||||||
this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive.
|
|
||||||
this.blocks = new char[getSectionCount()][];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void storeTile(BlockEntity blockEntity) {
|
|
||||||
tiles.put(
|
|
||||||
BlockVector3.at(
|
|
||||||
blockEntity.getBlockPos().getX(),
|
|
||||||
blockEntity.getBlockPos().getY(),
|
|
||||||
blockEntity.getBlockPos().getZ()
|
|
||||||
),
|
|
||||||
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public CompoundTag getTile(int x, int y, int z) {
|
|
||||||
return tiles.get(BlockVector3.at(x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
protected void storeEntity(Entity entity) {
|
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
|
||||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
|
||||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag);
|
|
||||||
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<CompoundTag> getEntities() {
|
|
||||||
return this.entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
|
||||||
for (CompoundTag tag : entities) {
|
|
||||||
if (uuid.equals(tag.getUUID())) {
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCreateCopy() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int setCreateCopy(boolean createCopy) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxY() {
|
|
||||||
return maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMinY() {
|
|
||||||
return minHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxSectionPosition() {
|
|
||||||
return maxHeight >> 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMinSectionPosition() {
|
|
||||||
return minHeight >> 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
|
||||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()][(y & 12) << 2 | (z & 12) | (x & 12) >> 2];
|
|
||||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeSectionLighting(int layer, boolean sky) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean trim(boolean aggressive, int layer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlocks reset() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSectionCount() {
|
|
||||||
return serverLevel.getSectionsCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void storeSection(int layer, char[] data) {
|
|
||||||
blocks[layer] = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
|
|
||||||
if (biomes == null) {
|
|
||||||
biomes = new Holder[getSectionCount()][];
|
|
||||||
}
|
|
||||||
if (biomes[layer] == null) {
|
|
||||||
biomes[layer] = new Holder[64];
|
|
||||||
}
|
|
||||||
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
biomes[layer][i] = palettedContainer.get(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOGGER.error(
|
|
||||||
"Cannot correctly save biomes to history. Expected class type {} but got {}",
|
|
||||||
PalettedContainer.class.getSimpleName(),
|
|
||||||
biomeData.getClass().getSimpleName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseBlock getFullBlock(int x, int y, int z) {
|
|
||||||
BlockState state = BlockTypesCache.states[get(x, y, z)];
|
|
||||||
return state.toBaseBlock(this, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasSection(int layer) {
|
|
||||||
layer -= getMinSectionPosition();
|
|
||||||
return blocks[layer] != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] load(int layer) {
|
|
||||||
layer -= getMinSectionPosition();
|
|
||||||
if (blocks[layer] == null) {
|
|
||||||
blocks[layer] = new char[4096];
|
|
||||||
Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR);
|
|
||||||
}
|
|
||||||
return blocks[layer];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] loadIfPresent(int layer) {
|
|
||||||
layer -= getMinSectionPosition();
|
|
||||||
return blocks[layer];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState getBlock(int x, int y, int z) {
|
|
||||||
return BlockTypesCache.states[get(x, y, z)];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSkyLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getEmittedLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getHeightMap(HeightMapType type) {
|
|
||||||
return new int[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public char get(int x, int y, int z) {
|
|
||||||
final int layer = (y >> 4) - getMinSectionPosition();
|
|
||||||
final int index = (y & 15) << 8 | z << 4 | x;
|
|
||||||
return blocks[layer][index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean trim(boolean aggressive) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,752 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
|
||||||
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
|
|
||||||
import com.fastasyncworldedit.core.util.MathMan;
|
|
||||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
|
||||||
import com.mojang.datafixers.util.Either;
|
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
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;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
|
||||||
import net.minecraft.server.level.ChunkMap;
|
|
||||||
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.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.GlobalPalette;
|
|
||||||
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.SingleValuePalette;
|
|
||||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftChunk;
|
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import static net.minecraft.core.registries.Registries.BIOME;
|
|
||||||
|
|
||||||
public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|
||||||
|
|
||||||
public static final Field fieldData;
|
|
||||||
|
|
||||||
public static final Constructor<?> dataConstructor;
|
|
||||||
|
|
||||||
public static final Field fieldStorage;
|
|
||||||
public static final Field fieldPalette;
|
|
||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
|
||||||
private static final Field fieldTickingBlockCount;
|
|
||||||
private static final Field fieldBiomes;
|
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
|
||||||
|
|
||||||
private static final Field fieldThreadingDetector;
|
|
||||||
private static final Field fieldLock;
|
|
||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
|
||||||
|
|
||||||
private static final Field fieldOffers;
|
|
||||||
private static final MerchantOffers OFFERS = new MerchantOffers();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
Class<?> dataClazz = fieldData.getType();
|
|
||||||
dataConstructor = dataClazz.getDeclaredConstructors()[0];
|
|
||||||
dataConstructor.setAccessible(true);
|
|
||||||
|
|
||||||
fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b"));
|
|
||||||
fieldStorage.setAccessible(true);
|
|
||||||
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
|
|
||||||
fieldPalette.setAccessible(true);
|
|
||||||
|
|
||||||
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
|
|
||||||
fieldTickingFluidCount.setAccessible(true);
|
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
|
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
|
||||||
Field tmpFieldBiomes;
|
|
||||||
try {
|
|
||||||
// It seems to actually be biomes, but is apparently obfuscated to "j"
|
|
||||||
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
|
||||||
} catch (NoSuchFieldException ignored) {
|
|
||||||
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("j");
|
|
||||||
}
|
|
||||||
fieldBiomes = tmpFieldBiomes;
|
|
||||||
fieldBiomes.setAccessible(true);
|
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
|
||||||
"getVisibleChunkIfPresent",
|
|
||||||
"b"
|
|
||||||
), long.class);
|
|
||||||
getVisibleChunkIfPresent.setAccessible(true);
|
|
||||||
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
|
||||||
|
|
||||||
if (!PaperLib.isPaper()) {
|
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
|
||||||
fieldThreadingDetector.setAccessible(true);
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
|
||||||
fieldLock.setAccessible(true);
|
|
||||||
} else {
|
|
||||||
// in paper, the used methods are synchronized properly
|
|
||||||
fieldThreadingDetector = null;
|
|
||||||
fieldLock = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
|
||||||
Refraction.pickName("removeGameEventListener", "a"),
|
|
||||||
BlockEntity.class,
|
|
||||||
ServerLevel.class
|
|
||||||
);
|
|
||||||
removeGameEventListener.setAccessible(true);
|
|
||||||
methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener);
|
|
||||||
|
|
||||||
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
|
||||||
Refraction.pickName(
|
|
||||||
"removeBlockEntityTicker",
|
|
||||||
"l"
|
|
||||||
), BlockPos.class
|
|
||||||
);
|
|
||||||
removeBlockEntityTicker.setAccessible(true);
|
|
||||||
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
|
|
||||||
|
|
||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
|
||||||
fieldRemove.setAccessible(true);
|
|
||||||
|
|
||||||
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", "L"));
|
|
||||||
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
|
|
||||||
} catch (NoSuchFieldException ignored) {
|
|
||||||
}
|
|
||||||
POST_CHUNK_REWRITE = chunkRewrite;
|
|
||||||
|
|
||||||
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bT"));
|
|
||||||
fieldOffers.setAccessible(true);
|
|
||||||
} catch (RuntimeException | Error e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean setSectionAtomic(
|
|
||||||
LevelChunkSection[] sections,
|
|
||||||
LevelChunkSection expected,
|
|
||||||
LevelChunkSection value,
|
|
||||||
int layer
|
|
||||||
) {
|
|
||||||
if (layer >= 0 && layer < sections.length) {
|
|
||||||
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is no point in having a functional semaphore for paper servers.
|
|
||||||
private static final ThreadLocal<DelegateSemaphore> SEMAPHORE_THREAD_LOCAL =
|
|
||||||
ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null));
|
|
||||||
|
|
||||||
static DelegateSemaphore applyLock(LevelChunkSection section) {
|
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
return SEMAPHORE_THREAD_LOCAL.get();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
synchronized (section) {
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
|
||||||
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
|
|
||||||
synchronized (currentThreadingDetector) {
|
|
||||||
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
|
|
||||||
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
|
||||||
return delegateSemaphore;
|
|
||||||
}
|
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
|
||||||
fieldLock.set(currentThreadingDetector, newLock);
|
|
||||||
return newLock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) {
|
|
||||||
if (!PaperLib.isPaper()) {
|
|
||||||
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false);
|
|
||||||
if (nmsChunk != null) {
|
|
||||||
return nmsChunk;
|
|
||||||
}
|
|
||||||
if (Fawe.isMainThread()) {
|
|
||||||
return serverLevel.getChunk(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ);
|
|
||||||
if (nmsChunk != null) {
|
|
||||||
addTicket(serverLevel, chunkX, chunkZ);
|
|
||||||
return nmsChunk;
|
|
||||||
}
|
|
||||||
nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
|
|
||||||
if (nmsChunk != null) {
|
|
||||||
addTicket(serverLevel, chunkX, chunkZ);
|
|
||||||
return nmsChunk;
|
|
||||||
}
|
|
||||||
// Avoid "async" methods from the main thread.
|
|
||||||
if (Fawe.isMainThread()) {
|
|
||||||
return serverLevel.getChunk(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
|
|
||||||
try {
|
|
||||||
CraftChunk chunk;
|
|
||||||
try {
|
|
||||||
chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS);
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
String world = serverLevel.getWorld().getName();
|
|
||||||
// We've already taken 10 seconds we can afford to wait a little here.
|
|
||||||
boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null);
|
|
||||||
if (loaded) {
|
|
||||||
LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world);
|
|
||||||
// Retry chunk load
|
|
||||||
chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get();
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addTicket(serverLevel, chunkX, chunkZ);
|
|
||||||
return (LevelChunk) chunk.getHandle(ChunkStatus.FULL);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
|
|
||||||
// Ensure chunk is definitely loaded before applying a ticket
|
|
||||||
io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
|
|
||||||
.getChunkSource()
|
|
||||||
.addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
|
|
||||||
ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap;
|
|
||||||
try {
|
|
||||||
return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ));
|
|
||||||
} catch (Throwable thr) {
|
|
||||||
throw new RuntimeException(thr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void sendChunk(Object chunk, ServerLevel nmsWorld, int chunkX, int chunkZ) {
|
|
||||||
ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ);
|
|
||||||
if (chunkHolder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
|
|
||||||
LevelChunk levelChunk;
|
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
// getChunkAtIfLoadedImmediately is paper only
|
|
||||||
levelChunk = nmsWorld
|
|
||||||
.getChunkSource()
|
|
||||||
.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 (levelChunk == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MinecraftServer.getServer().execute(() -> {
|
|
||||||
ClientboundLevelChunkWithLightPacket packet;
|
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
synchronized (chunk) {
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
|
||||||
levelChunk,
|
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
false // last false is to not bother with x-ray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (chunk) {
|
|
||||||
// deprecated on paper - deprecation suppressed
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
|
||||||
levelChunk,
|
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
|
|
||||||
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
NMS conversion
|
|
||||||
*/
|
|
||||||
public static LevelChunkSection newChunkSection(
|
|
||||||
final int layer,
|
|
||||||
final char[] blocks,
|
|
||||||
CachedBukkitAdapter adapter,
|
|
||||||
Registry<Biome> biomeRegistry,
|
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
|
||||||
) {
|
|
||||||
return newChunkSection(layer, null, blocks, adapter, biomeRegistry, biomes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LevelChunkSection newChunkSection(
|
|
||||||
final int layer,
|
|
||||||
final Function<Integer, char[]> get,
|
|
||||||
char[] set,
|
|
||||||
CachedBukkitAdapter adapter,
|
|
||||||
Registry<Biome> biomeRegistry,
|
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
|
||||||
) {
|
|
||||||
if (set == null) {
|
|
||||||
return newChunkSection(layer, biomeRegistry, biomes);
|
|
||||||
}
|
|
||||||
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
|
|
||||||
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
|
|
||||||
final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get();
|
|
||||||
final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get();
|
|
||||||
try {
|
|
||||||
int num_palette;
|
|
||||||
if (get == null) {
|
|
||||||
num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, null);
|
|
||||||
} else {
|
|
||||||
num_palette = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, get, set, adapter, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
|
|
||||||
if (bitsPerEntry > 0 && bitsPerEntry < 5) {
|
|
||||||
bitsPerEntry = 4;
|
|
||||||
} else if (bitsPerEntry > 8) {
|
|
||||||
bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
|
|
||||||
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
|
|
||||||
final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong);
|
|
||||||
|
|
||||||
if (num_palette == 1) {
|
|
||||||
for (int i = 0; i < blockBitArrayEnd; i++) {
|
|
||||||
blockStates[i] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntryNonZero, 4096, blockStates);
|
|
||||||
bitArray.fromRaw(blocksCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd);
|
|
||||||
final BitStorage nmsBits;
|
|
||||||
if (bitsPerEntry == 0) {
|
|
||||||
nmsBits = new ZeroBitStorage(4096);
|
|
||||||
} else {
|
|
||||||
nmsBits = new SimpleBitStorage(bitsPerEntry, 4096, bits);
|
|
||||||
}
|
|
||||||
List<net.minecraft.world.level.block.state.BlockState> palette;
|
|
||||||
if (bitsPerEntry < 9) {
|
|
||||||
palette = new ArrayList<>();
|
|
||||||
for (int i = 0; i < num_palette; i++) {
|
|
||||||
int ordinal = paletteToBlock[i];
|
|
||||||
blockToPalette[ordinal] = Integer.MAX_VALUE;
|
|
||||||
final BlockState state = BlockTypesCache.states[ordinal];
|
|
||||||
palette.add(((PaperweightBlockMaterial) state.getMaterial()).getState());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
palette = List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create palette with data
|
|
||||||
@SuppressWarnings("deprecation") // constructor is deprecated on paper, but needed to keep compatibility with spigot
|
|
||||||
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blockStatePalettedContainer =
|
|
||||||
new PalettedContainer<>(
|
|
||||||
Block.BLOCK_STATE_REGISTRY,
|
|
||||||
PalettedContainer.Strategy.SECTION_STATES,
|
|
||||||
PalettedContainer.Strategy.SECTION_STATES.getConfiguration(Block.BLOCK_STATE_REGISTRY, bitsPerEntry),
|
|
||||||
nmsBits,
|
|
||||||
palette
|
|
||||||
);
|
|
||||||
if (biomes == null) {
|
|
||||||
IdMap<Holder<Biome>> biomeHolderIdMap = biomeRegistry.asHolderIdMap();
|
|
||||||
biomes = new PalettedContainer<>(
|
|
||||||
biomeHolderIdMap,
|
|
||||||
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
|
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(
|
|
||||||
BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LevelChunkSection(layer, blockStatePalettedContainer, biomes);
|
|
||||||
} catch (final Throwable e) {
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
|
|
||||||
Arrays.fill(paletteToBlock, Integer.MAX_VALUE);
|
|
||||||
Arrays.fill(blockStates, 0);
|
|
||||||
Arrays.fill(blocksCopy, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") // Only deprecated in paper
|
|
||||||
private static LevelChunkSection newChunkSection(
|
|
||||||
int layer,
|
|
||||||
Registry<Biome> biomeRegistry,
|
|
||||||
@Nullable PalettedContainer<Holder<Biome>> biomes
|
|
||||||
) {
|
|
||||||
if (biomes == null) {
|
|
||||||
return new LevelChunkSection(layer, biomeRegistry);
|
|
||||||
}
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
|
|
||||||
Block.BLOCK_STATE_REGISTRY,
|
|
||||||
Blocks.AIR.defaultBlockState(),
|
|
||||||
PalettedContainer.Strategy.SECTION_STATES,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
return new LevelChunkSection(layer, dataPaletteBlocks, biomes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setBiomesToChunkSection(LevelChunkSection section, PalettedContainer<Holder<Biome>> biomes) {
|
|
||||||
try {
|
|
||||||
fieldBiomes.set(section, biomes);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
LOGGER.error("Could not set biomes to chunk section", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
|
|
||||||
*/
|
|
||||||
public static PalettedContainer<Holder<Biome>> getBiomePalettedContainer(
|
|
||||||
BiomeType[] biomes,
|
|
||||||
IdMap<Holder<Biome>> biomeRegistry
|
|
||||||
) {
|
|
||||||
if (biomes == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
BukkitImplAdapter<?> adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
|
||||||
// Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length
|
|
||||||
Map<BiomeType, Holder<Biome>> palette = new HashMap<>();
|
|
||||||
for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) {
|
|
||||||
Holder<Biome> biome;
|
|
||||||
if (biomeType == null) {
|
|
||||||
biome = biomeRegistry.byId(adapter.getInternalBiomeId(BiomeTypes.PLAINS));
|
|
||||||
} else {
|
|
||||||
biome = biomeRegistry.byId(adapter.getInternalBiomeId(biomeType));
|
|
||||||
}
|
|
||||||
palette.put(biomeType, biome);
|
|
||||||
}
|
|
||||||
int biomeCount = palette.size();
|
|
||||||
int bitsPerEntry = MathMan.log2nlz(biomeCount - 1);
|
|
||||||
Object configuration = PalettedContainer.Strategy.SECTION_STATES.getConfiguration(
|
|
||||||
new FakeIdMapBiome(biomeCount),
|
|
||||||
bitsPerEntry
|
|
||||||
);
|
|
||||||
if (bitsPerEntry > 3) {
|
|
||||||
bitsPerEntry = MathMan.log2nlz(biomeRegistry.size() - 1);
|
|
||||||
}
|
|
||||||
PalettedContainer<Holder<Biome>> biomePalettedContainer = new PalettedContainer<>(
|
|
||||||
biomeRegistry,
|
|
||||||
biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
final Palette<Holder<Biome>> biomePalette;
|
|
||||||
if (bitsPerEntry == 0) {
|
|
||||||
biomePalette = new SingleValuePalette<>(
|
|
||||||
biomePalettedContainer.registry,
|
|
||||||
biomePalettedContainer,
|
|
||||||
new ArrayList<>(palette.values()) // Must be modifiable
|
|
||||||
);
|
|
||||||
} else if (bitsPerEntry == 4) {
|
|
||||||
biomePalette = LinearPalette.create(
|
|
||||||
4,
|
|
||||||
biomePalettedContainer.registry,
|
|
||||||
biomePalettedContainer,
|
|
||||||
new ArrayList<>(palette.values()) // Must be modifiable
|
|
||||||
);
|
|
||||||
} else if (bitsPerEntry < 9) {
|
|
||||||
biomePalette = HashMapPalette.create(
|
|
||||||
bitsPerEntry,
|
|
||||||
biomePalettedContainer.registry,
|
|
||||||
biomePalettedContainer,
|
|
||||||
new ArrayList<>(palette.values()) // Must be modifiable
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
biomePalette = GlobalPalette.create(
|
|
||||||
bitsPerEntry,
|
|
||||||
biomePalettedContainer.registry,
|
|
||||||
biomePalettedContainer,
|
|
||||||
null // unused
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
|
|
||||||
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
|
|
||||||
final int arrayLength = MathMan.ceilZero(64f / blocksPerLong);
|
|
||||||
|
|
||||||
|
|
||||||
BitStorage bitStorage = bitsPerEntry == 0 ? new ZeroBitStorage(64) : new SimpleBitStorage(
|
|
||||||
bitsPerEntry,
|
|
||||||
64,
|
|
||||||
new long[arrayLength]
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Object data = dataConstructor.newInstance(configuration, bitStorage, biomePalette);
|
|
||||||
fieldData.set(biomePalettedContainer, data);
|
|
||||||
int index = 0;
|
|
||||||
for (int y = 0; y < 4; y++) {
|
|
||||||
for (int z = 0; z < 4; z++) {
|
|
||||||
for (int x = 0; x < 4; x++, index++) {
|
|
||||||
BiomeType biomeType = biomes[index];
|
|
||||||
if (biomeType == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Holder<Biome> biome = biomeRegistry.byId(WorldEditPlugin
|
|
||||||
.getInstance()
|
|
||||||
.getBukkitImplAdapter()
|
|
||||||
.getInternalBiomeId(biomeType));
|
|
||||||
if (biome == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
biomePalettedContainer.set(x, y, z, biome);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return biomePalettedContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException {
|
|
||||||
fieldTickingFluidCount.setShort(section, (short) 0);
|
|
||||||
fieldTickingBlockCount.setShort(section, (short) 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BiomeType adapt(Holder<Biome> biome, LevelAccessor levelAccessor) {
|
|
||||||
final Registry<Biome> biomeRegistry = levelAccessor.registryAccess().registryOrThrow(BIOME);
|
|
||||||
if (biomeRegistry.getKey(biome.value()) == null) {
|
|
||||||
return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
|
|
||||||
try {
|
|
||||||
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
|
|
||||||
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
|
|
||||||
if (blockEntity != null) {
|
|
||||||
if (!levelChunk.level.isClientSide) {
|
|
||||||
methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level);
|
|
||||||
}
|
|
||||||
fieldRemove.set(beacon, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos());
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
throwable.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<Entity> getEntities(LevelChunk chunk) {
|
|
||||||
ExceptionCollector<RuntimeException> collector = new ExceptionCollector<>();
|
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
if (POST_CHUNK_REWRITE) {
|
|
||||||
try {
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk);
|
|
||||||
return List.of(entityList.getRawData());
|
|
||||||
} catch (IllegalAccessException 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
|
||||||
boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread();
|
|
||||||
boolean unset = false;
|
|
||||||
if (isVillager) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entity.save(compoundTag);
|
|
||||||
if (unset) {
|
|
||||||
try {
|
|
||||||
fieldOffers.set(entity, null);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException("Failed to set offers field to null again on villager.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId(final net.minecraft.world.level.block.state.BlockState entry) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public net.minecraft.world.level.block.state.BlockState byId(final int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Iterator<net.minecraft.world.level.block.state.BlockState> iterator() {
|
|
||||||
return Collections.emptyIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
record FakeIdMapBiome(int size) implements IdMap<Biome> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId(final Biome entry) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Biome byId(final int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Iterator<Biome> iterator() {
|
|
||||||
return Collections.emptyIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter;
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
|
||||||
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 java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
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 = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
|
|
||||||
|
|
||||||
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) {
|
|
||||||
super(serverLevel, queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ChunkPos createChunkPos(final long chunkKey) {
|
|
||||||
return new ChunkPos(chunkKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long asLong(final int chunkX, final int chunkZ) {
|
|
||||||
return ChunkPos.asLong(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CompletableFuture<?> chunkLoadFuture(final ChunkPos chunkPos) {
|
|
||||||
return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z)
|
|
||||||
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
|
|
||||||
FAWE_TICKET,
|
|
||||||
chunkPos,
|
|
||||||
LIGHT_LEVEL,
|
|
||||||
Unit.INSTANCE
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void invokeRelight(
|
|
||||||
Set<ChunkPos> coords,
|
|
||||||
Consumer<ChunkPos> chunkCallback,
|
|
||||||
IntConsumer processCallback
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("Error occurred on relighting", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allow the server to unload the chunks again.
|
|
||||||
* Also, if chunk packets are sent delayed, we need to do that here
|
|
||||||
*/
|
|
||||||
protected void postProcessChunks(Set<ChunkPos> coords) {
|
|
||||||
boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
|
|
||||||
for (ChunkPos pos : coords) {
|
|
||||||
int x = pos.x;
|
|
||||||
int z = pos.z;
|
|
||||||
if (delay) { // we still need to send the block changes of that chunk
|
|
||||||
PaperweightPlatformAdapter.sendChunk(pos, serverLevel, x, z);
|
|
||||||
}
|
|
||||||
serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,161 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt;
|
|
||||||
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.jnbt.LazyCompoundTag;
|
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.nbt.NumericTag;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|
||||||
|
|
||||||
private final Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier;
|
|
||||||
private CompoundTag compoundTag;
|
|
||||||
|
|
||||||
public PaperweightLazyCompoundTag(Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier) {
|
|
||||||
super(new HashMap<>());
|
|
||||||
this.compoundTagSupplier = compoundTagSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) {
|
|
||||||
this(() -> compoundTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public net.minecraft.nbt.CompoundTag get() {
|
|
||||||
return compoundTagSupplier.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Map<String, Tag> getValue() {
|
|
||||||
if (compoundTag == null) {
|
|
||||||
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
|
||||||
}
|
|
||||||
return compoundTag.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompoundBinaryTag asBinaryTag() {
|
|
||||||
getValue();
|
|
||||||
return compoundTag.asBinaryTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsKey(String key) {
|
|
||||||
return compoundTagSupplier.get().contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getByteArray(String key) {
|
|
||||||
return compoundTagSupplier.get().getByteArray(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getByte(String key) {
|
|
||||||
return compoundTagSupplier.get().getByte(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDouble(String key) {
|
|
||||||
return compoundTagSupplier.get().getDouble(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double asDouble(String key) {
|
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
|
||||||
if (tag instanceof NumericTag numTag) {
|
|
||||||
return numTag.getAsDouble();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getFloat(String key) {
|
|
||||||
return compoundTagSupplier.get().getFloat(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getIntArray(String key) {
|
|
||||||
return compoundTagSupplier.get().getIntArray(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInt(String key) {
|
|
||||||
return compoundTagSupplier.get().getInt(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int asInt(String key) {
|
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
|
||||||
if (tag instanceof NumericTag numTag) {
|
|
||||||
return numTag.getAsInt();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public List<Tag> getList(String key) {
|
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
|
||||||
ArrayList<Tag> list = new ArrayList<>();
|
|
||||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
|
||||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
|
||||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
|
||||||
} else {
|
|
||||||
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public ListTag getListTag(String key) {
|
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag) {
|
|
||||||
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
|
|
||||||
}
|
|
||||||
return new ListTag(StringTag.class, Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
|
|
||||||
ListTag listTag = getListTag(key);
|
|
||||||
if (listTag.getType().equals(listType)) {
|
|
||||||
return (List<T>) listTag.getValue();
|
|
||||||
} else {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long[] getLongArray(String key) {
|
|
||||||
return compoundTagSupplier.get().getLongArray(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLong(String key) {
|
|
||||||
return compoundTagSupplier.get().getLong(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long asLong(String key) {
|
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
|
||||||
if (tag instanceof NumericTag numTag) {
|
|
||||||
return numTag.getAsLong();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getShort(String key) {
|
|
||||||
return compoundTagSupplier.get().getShort(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getString(String key) {
|
|
||||||
return compoundTagSupplier.get().getString(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return compoundTagSupplier.get().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,596 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.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_19_R3.PaperweightGetBlocks;
|
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
||||||
import com.sk89q.worldedit.regions.Region;
|
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
|
||||||
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.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;
|
|
||||||
import net.minecraft.world.level.LevelSettings;
|
|
||||||
import net.minecraft.world.level.biome.Biome;
|
|
||||||
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.ChunkGeneratorStructureState;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
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.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.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.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.Chunk;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.generator.CustomChunkGenerator;
|
|
||||||
import org.bukkit.generator.BiomeProvider;
|
|
||||||
import org.bukkit.generator.BlockPopulator;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.OptionalLong;
|
|
||||||
import java.util.Random;
|
|
||||||
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();
|
|
||||||
|
|
||||||
private static final Field serverWorldsField;
|
|
||||||
private static final Field paperConfigField;
|
|
||||||
private static final Field flatBedrockField;
|
|
||||||
private static final Field generatorSettingFlatField;
|
|
||||||
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;
|
|
||||||
|
|
||||||
//list of chunk stati in correct order without FULL
|
|
||||||
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing
|
|
||||||
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
|
|
||||||
chunkStati.put(
|
|
||||||
ChunkStatus.STRUCTURE_REFERENCES,
|
|
||||||
Concurrency.FULL
|
|
||||||
); // structure refs: radius 8, but only writes to current chunk
|
|
||||||
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // 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.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
|
|
||||||
|
|
||||||
try {
|
|
||||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
|
||||||
serverWorldsField.setAccessible(true);
|
|
||||||
|
|
||||||
Field tmpPaperConfigField;
|
|
||||||
Field tmpFlatBedrockField;
|
|
||||||
try { //only present on paper
|
|
||||||
tmpPaperConfigField = Level.class.getDeclaredField("paperConfig");
|
|
||||||
tmpPaperConfigField.setAccessible(true);
|
|
||||||
|
|
||||||
tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock");
|
|
||||||
tmpFlatBedrockField.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
tmpPaperConfigField = null;
|
|
||||||
tmpFlatBedrockField = null;
|
|
||||||
}
|
|
||||||
paperConfigField = tmpPaperConfigField;
|
|
||||||
flatBedrockField = tmpFlatBedrockField;
|
|
||||||
|
|
||||||
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
|
|
||||||
"settings", "e"));
|
|
||||||
generatorSettingBaseSupplierField.setAccessible(true);
|
|
||||||
|
|
||||||
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", "H"));
|
|
||||||
chunkSourceField.setAccessible(true);
|
|
||||||
|
|
||||||
generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "w"));
|
|
||||||
generatorStructureStateField.setAccessible(true);
|
|
||||||
|
|
||||||
ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g"));
|
|
||||||
ringPositionsField.setAccessible(true);
|
|
||||||
|
|
||||||
hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(
|
|
||||||
Refraction.pickName("hasGeneratedPositions", "h")
|
|
||||||
);
|
|
||||||
hasGeneratedPositionsField.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//runtime
|
|
||||||
private ServerLevel originalServerWorld;
|
|
||||||
private ServerChunkCache originalChunkProvider;
|
|
||||||
private ServerLevel freshWorld;
|
|
||||||
private ServerChunkCache freshChunkProvider;
|
|
||||||
private LevelStorageSource.LevelStorageAccess session;
|
|
||||||
private StructureTemplateManager structureTemplateManager;
|
|
||||||
private ThreadedLevelLightEngine threadedLevelLightEngine;
|
|
||||||
private ChunkGenerator chunkGenerator;
|
|
||||||
|
|
||||||
private Path tempDir;
|
|
||||||
|
|
||||||
private boolean generateFlatBedrock = false;
|
|
||||||
|
|
||||||
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
|
|
||||||
super(originalBukkitWorld, region, target, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean prepare() {
|
|
||||||
this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle();
|
|
||||||
originalChunkProvider = originalServerWorld.getChunkSource();
|
|
||||||
|
|
||||||
//flat bedrock? (only on paper)
|
|
||||||
if (paperConfigField != null) {
|
|
||||||
try {
|
|
||||||
generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seed = options.getSeed().orElse(originalServerWorld.getSeed());
|
|
||||||
chunkStati.forEach((s, c) -> super.chunkStatuses.put(new ChunkStatusWrap(s), c));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected boolean initNewWorld() throws Exception {
|
|
||||||
//world folder
|
|
||||||
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
|
|
||||||
|
|
||||||
//prepare for world init (see upstream implementation for reference)
|
|
||||||
org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment();
|
|
||||||
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
|
|
||||||
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
|
|
||||||
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
|
|
||||||
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
|
|
||||||
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
|
|
||||||
|
|
||||||
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
|
|
||||||
WorldOptions originalOpts = originalWorldData.worldGenOptions();
|
|
||||||
WorldOptions newOpts = options.getSeed().isPresent()
|
|
||||||
? originalOpts.withSeed(OptionalLong.of(seed))
|
|
||||||
: originalOpts;
|
|
||||||
LevelSettings newWorldSettings = new LevelSettings(
|
|
||||||
"faweregentempworld",
|
|
||||||
originalWorldData.settings.gameType(),
|
|
||||||
originalWorldData.settings.hardcore(),
|
|
||||||
originalWorldData.settings.difficulty(),
|
|
||||||
originalWorldData.settings.allowCommands(),
|
|
||||||
originalWorldData.settings.gameRules(),
|
|
||||||
originalWorldData.settings.getDataConfiguration()
|
|
||||||
);
|
|
||||||
|
|
||||||
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(
|
|
||||||
server,
|
|
||||||
server.executor,
|
|
||||||
session,
|
|
||||||
newWorldData,
|
|
||||||
originalServerWorld.dimension(),
|
|
||||||
DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow()
|
|
||||||
.getOrThrow(levelStemResourceKey),
|
|
||||||
new RegenNoOpWorldLoadListener(),
|
|
||||||
originalServerWorld.isDebug(),
|
|
||||||
seed,
|
|
||||||
ImmutableList.of(),
|
|
||||||
false,
|
|
||||||
environment,
|
|
||||||
generator,
|
|
||||||
biomeProvider
|
|
||||||
) {
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
|
|
||||||
if (options.hasBiomeType()) {
|
|
||||||
return singleBiome;
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
|
|
||||||
if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
|
|
||||||
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
|
|
||||||
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
|
|
||||||
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
|
||||||
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField.get(
|
|
||||||
originalGenerator);
|
|
||||||
BiomeSource biomeSource;
|
|
||||||
if (options.hasBiomeType()) {
|
|
||||||
|
|
||||||
biomeSource = new FixedBiomeSource(
|
|
||||||
DedicatedServer.getServer().registryAccess()
|
|
||||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
|
||||||
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
biomeSource = originalGenerator.getBiomeSource();
|
|
||||||
}
|
|
||||||
chunkGenerator = new NoiseBasedChunkGenerator(
|
|
||||||
biomeSource,
|
|
||||||
generatorSettingBaseSupplier
|
|
||||||
);
|
|
||||||
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
|
|
||||||
chunkGenerator = customChunkGenerator.getDelegate();
|
|
||||||
} else {
|
|
||||||
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (generator != null) {
|
|
||||||
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
|
|
||||||
generateConcurrent = generator.isParallelCapable();
|
|
||||||
}
|
|
||||||
// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed
|
|
||||||
|
|
||||||
freshChunkProvider = new ServerChunkCache(
|
|
||||||
freshWorld,
|
|
||||||
session,
|
|
||||||
server.getFixerUpper(),
|
|
||||||
server.getStructureManager(),
|
|
||||||
server.executor,
|
|
||||||
chunkGenerator,
|
|
||||||
freshWorld.spigotConfig.viewDistance,
|
|
||||||
freshWorld.spigotConfig.simulationDistance,
|
|
||||||
server.forceSynchronousWrites(),
|
|
||||||
new RegenNoOpWorldLoadListener(),
|
|
||||||
(chunkCoordIntPair, state) -> {
|
|
||||||
},
|
|
||||||
() -> server.overworld().getDataStorage()
|
|
||||||
) {
|
|
||||||
// redirect to LevelChunks created in #createChunks
|
|
||||||
@Override
|
|
||||||
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) {
|
|
||||||
ChunkAccess chunkAccess = getChunkAt(x, z);
|
|
||||||
if (chunkAccess == null && create) {
|
|
||||||
chunkAccess = createChunk(getProtoChunkAt(x, z));
|
|
||||||
}
|
|
||||||
return chunkAccess;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
structureTemplateManager = server.getStructureManager();
|
|
||||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void cleanup() {
|
|
||||||
try {
|
|
||||||
session.close();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//shutdown chunk provider
|
|
||||||
try {
|
|
||||||
Fawe.instance().getQueueHandler().sync(() -> {
|
|
||||||
try {
|
|
||||||
freshChunkProvider.close(false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove world from server
|
|
||||||
try {
|
|
||||||
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete directory
|
|
||||||
try {
|
|
||||||
SafeFiles.tryHardToDeleteDir(tempDir);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ProtoChunk createProtoChunk(int x, int z) {
|
|
||||||
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
|
|
||||||
this.freshWorld.registryAccess().registryOrThrow(BIOME), null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected LevelChunk createChunk(ProtoChunk protoChunk) {
|
|
||||||
return new LevelChunk(
|
|
||||||
freshWorld,
|
|
||||||
protoChunk,
|
|
||||||
null // we don't want to add entities
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ChunkStatusWrap getFullChunkStatus() {
|
|
||||||
return new ChunkStatusWrap(ChunkStatus.FULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<BlockPopulator> getBlockPopulators() {
|
|
||||||
return originalServerWorld.getWorld().getPopulators();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
|
||||||
// BlockPopulator#populate has to be called synchronously for TileEntity access
|
|
||||||
TaskManager.taskManager().task(() -> {
|
|
||||||
final CraftWorld world = freshWorld.getWorld();
|
|
||||||
final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ);
|
|
||||||
blockPopulator.populate(world, random, chunk);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IChunkCache<IChunkGet> initSourceQueueCache() {
|
|
||||||
return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) {
|
|
||||||
@Override
|
|
||||||
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) {
|
|
||||||
return getChunkAt(x, z);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//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) {
|
|
||||||
return switch (env) {
|
|
||||||
case NETHER -> LevelStem.NETHER;
|
|
||||||
case THE_END -> LevelStem.END;
|
|
||||||
default -> LevelStem.OVERWORLD;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
|
|
||||||
|
|
||||||
private RegenNoOpWorldLoadListener() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Paper only(?) @Override
|
|
||||||
public void setChunkRadius(int radius) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FastProtoChunk extends ProtoChunk {
|
|
||||||
|
|
||||||
public FastProtoChunk(
|
|
||||||
final ChunkPos pos,
|
|
||||||
final UpgradeData upgradeData,
|
|
||||||
final LevelHeightAccessor world,
|
|
||||||
final Registry<Biome> biomeRegistry,
|
|
||||||
@Nullable final BlendingData blendingData
|
|
||||||
) {
|
|
||||||
super(pos, upgradeData, world, biomeRegistry, blendingData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid warning on paper
|
|
||||||
|
|
||||||
// compatibility with spigot
|
|
||||||
|
|
||||||
public boolean generateFlatBedrock() {
|
|
||||||
return generateFlatBedrock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no one will ever see the entities!
|
|
||||||
@Override
|
|
||||||
public List<CompoundTag> getEntities() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class ChunkStatusWrap extends ChunkStatusWrapper<ChunkAccess> {
|
|
||||||
|
|
||||||
private final ChunkStatus chunkStatus;
|
|
||||||
|
|
||||||
public ChunkStatusWrap(ChunkStatus chunkStatus) {
|
|
||||||
this.chunkStatus = chunkStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int requiredNeighborChunkRadius() {
|
|
||||||
return chunkStatus.getRange();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return chunkStatus.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) {
|
|
||||||
return chunkStatus.generate(
|
|
||||||
Runnable::run, // TODO revisit, we might profit from this somehow?
|
|
||||||
freshWorld,
|
|
||||||
chunkGenerator,
|
|
||||||
structureTemplateManager,
|
|
||||||
threadedLevelLightEngine,
|
|
||||||
c -> CompletableFuture.completedFuture(Either.left(c)),
|
|
||||||
accessibleChunks,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A light engine that does nothing. As light is calculated after pasting anyway, we can avoid
|
|
||||||
* work this way.
|
|
||||||
*/
|
|
||||||
static class NoOpLightEngine extends ThreadedLevelLightEngine {
|
|
||||||
|
|
||||||
private static final ProcessorMailbox<Runnable> MAILBOX = ProcessorMailbox.create(task -> {
|
|
||||||
}, "fawe-no-op");
|
|
||||||
private static final ProcessorHandle<Message<Runnable>> HANDLE = ProcessorHandle.of("fawe-no-op", m -> {
|
|
||||||
});
|
|
||||||
|
|
||||||
public NoOpLightEngine(final ServerChunkCache chunkProvider) {
|
|
||||||
super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<ChunkAccess> retainData(final ChunkAccess chunk) {
|
|
||||||
return CompletableFuture.completedFuture(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<ChunkAccess> lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) {
|
|
||||||
return CompletableFuture.completedFuture(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
java
|
|
||||||
}
|
|
||||||
|
|
||||||
applyPaperweightAdapterConfiguration()
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.1-R0.1-SNAPSHOT
|
|
||||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.1-R0.1-20230921.165944-178")
|
|
||||||
compileOnly(libs.paperlib)
|
|
||||||
}
|
|
@ -1,614 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
|
||||||
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
|
||||||
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
|
|
||||||
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.sk89q.jnbt.Tag;
|
|
||||||
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.ext.fawe.v1_20_R1.PaperweightAdapter;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.regen.PaperweightRegen;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldedit.regions.Region;
|
|
||||||
import com.sk89q.worldedit.registry.state.BooleanProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.DirectionalProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.EnumProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.IntegerProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
|
||||||
import com.sk89q.worldedit.util.Direction;
|
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
|
||||||
import com.sk89q.worldedit.world.item.ItemType;
|
|
||||||
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.WritableRegistry;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
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.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 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_20_R1.CraftServer;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.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;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.OptionalInt;
|
|
||||||
import java.util.Set;
|
|
||||||
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;
|
|
||||||
|
|
||||||
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 PaperweightAdapter parent;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Code that may break between versions of Minecraft
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil();
|
|
||||||
private char[] ibdToStateOrdinal = null;
|
|
||||||
private int[] ordinalToIbdID = null;
|
|
||||||
private boolean initialised = false;
|
|
||||||
private Map<String, List<Property<?>>> allBlockProperties = null;
|
|
||||||
|
|
||||||
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
|
|
||||||
this.parent = new PaperweightAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static String getEntityId(Entity entity) {
|
|
||||||
ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType());
|
|
||||||
return resourceLocation == null ? null : resourceLocation.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized boolean init() {
|
|
||||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
|
|
||||||
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
|
|
||||||
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
|
|
||||||
BlockState blockState = BlockTypesCache.states[i];
|
|
||||||
PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial();
|
|
||||||
int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState());
|
|
||||||
char ordinal = blockState.getOrdinalChar();
|
|
||||||
ibdToStateOrdinal[id] = ordinal;
|
|
||||||
ordinalToIbdID[ordinal] = id;
|
|
||||||
}
|
|
||||||
Map<String, List<Property<?>>> properties = new HashMap<>();
|
|
||||||
try {
|
|
||||||
for (Field field : BlockStateProperties.class.getDeclaredFields()) {
|
|
||||||
Object obj = field.get(null);
|
|
||||||
if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property<?> state)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Property<?> property;
|
|
||||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
|
||||||
property = new BooleanProperty(
|
|
||||||
state.getName(),
|
|
||||||
(List<Boolean>) ImmutableList.copyOf(state.getPossibleValues())
|
|
||||||
);
|
|
||||||
} else if (state instanceof DirectionProperty) {
|
|
||||||
property = new DirectionalProperty(
|
|
||||||
state.getName(),
|
|
||||||
state
|
|
||||||
.getPossibleValues()
|
|
||||||
.stream()
|
|
||||||
.map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase()))
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
);
|
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
|
||||||
property = new EnumProperty(
|
|
||||||
state.getName(),
|
|
||||||
state
|
|
||||||
.getPossibleValues()
|
|
||||||
.stream()
|
|
||||||
.map(e -> ((StringRepresentable) e).getSerializedName())
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
);
|
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
|
||||||
property = new IntegerProperty(
|
|
||||||
state.getName(),
|
|
||||||
(List<Integer>) ImmutableList.copyOf(state.getPossibleValues())
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state
|
|
||||||
.getClass()
|
|
||||||
.getSimpleName());
|
|
||||||
}
|
|
||||||
properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> {
|
|
||||||
if (v == null) {
|
|
||||||
v = new ArrayList<>(Collections.singletonList(property));
|
|
||||||
} else {
|
|
||||||
v.add(property);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
allBlockProperties = ImmutableMap.copyOf(properties);
|
|
||||||
}
|
|
||||||
initialised = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockMaterial getMaterial(BlockType blockType) {
|
|
||||||
Block block = getBlock(blockType);
|
|
||||||
return new PaperweightBlockMaterial(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized BlockMaterial getMaterial(BlockState state) {
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
|
|
||||||
return new PaperweightBlockMaterial(blockState.getBlock(), blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(BlockType blockType) {
|
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK)
|
|
||||||
.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public BlockState getBlock(Location location) {
|
|
||||||
Preconditions.checkNotNull(location);
|
|
||||||
|
|
||||||
int x = location.getBlockX();
|
|
||||||
int y = location.getBlockY();
|
|
||||||
int z = location.getBlockZ();
|
|
||||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
|
||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
|
||||||
BlockState state = adapt(blockData);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseBlock getFullBlock(final Location location) {
|
|
||||||
Preconditions.checkNotNull(location);
|
|
||||||
|
|
||||||
int x = location.getBlockX();
|
|
||||||
int y = location.getBlockY();
|
|
||||||
int z = location.getBlockZ();
|
|
||||||
|
|
||||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
|
||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
|
||||||
BlockState state = adapt(blockData);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
if (state.getBlockType().getMaterial().hasContainer()) {
|
|
||||||
|
|
||||||
// Read the NBT data
|
|
||||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
|
||||||
if (blockEntity != null) {
|
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.toBaseBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<SideEffect> getSupportedSideEffects() {
|
|
||||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
|
||||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
|
|
||||||
Preconditions.checkNotNull(entity);
|
|
||||||
|
|
||||||
CraftEntity craftEntity = ((CraftEntity) entity);
|
|
||||||
Entity mcEntity = craftEntity.getHandle();
|
|
||||||
|
|
||||||
String id = getEntityId(mcEntity);
|
|
||||||
|
|
||||||
if (id != null) {
|
|
||||||
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);
|
|
||||||
//add Id for AbstractChangeSet to work
|
|
||||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
|
||||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
|
||||||
tags.put("Id", StringBinaryTag.of(id));
|
|
||||||
return CompoundBinaryTag.from(tags);
|
|
||||||
};
|
|
||||||
return new LazyBaseEntity(type, saveTag);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getRichBlockName(BlockType blockType) {
|
|
||||||
return parent.getRichBlockName(blockType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getRichItemName(ItemType itemType) {
|
|
||||||
return parent.getRichItemName(itemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getRichItemName(BaseItemStack itemStack) {
|
|
||||||
return parent.getRichItemName(itemStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OptionalInt getInternalBlockStateId(BlockState state) {
|
|
||||||
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
|
|
||||||
net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState();
|
|
||||||
return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState adapt(BlockData blockData) {
|
|
||||||
CraftBlockData cbd = ((CraftBlockData) blockData);
|
|
||||||
net.minecraft.world.level.block.state.BlockState ibd = cbd.getState();
|
|
||||||
return adapt(ibd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
|
|
||||||
return BlockTypesCache.states[adaptToChar(blockState)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) {
|
|
||||||
int id = Block.BLOCK_STATE_REGISTRY.getId(blockState);
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
init();
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
} catch (ArrayIndexOutOfBoundsException e1) {
|
|
||||||
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
|
|
||||||
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
|
|
||||||
);
|
|
||||||
return BlockTypesCache.ReservedIDs.AIR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public char ibdIDToOrdinal(int id) {
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
return ibdToStateOrdinal[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] getIbdToStateOrdinal() {
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal;
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return ibdToStateOrdinal;
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
return ibdToStateOrdinal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ordinalToIbdID(char ordinal) {
|
|
||||||
if (initialised) {
|
|
||||||
return ordinalToIbdID[ordinal];
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return ordinalToIbdID[ordinal];
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
return ordinalToIbdID[ordinal];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getOrdinalToIbdID() {
|
|
||||||
if (initialised) {
|
|
||||||
return ordinalToIbdID;
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return ordinalToIbdID;
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
return ordinalToIbdID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
|
|
||||||
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
|
|
||||||
return material.getCraftBlockData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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 && wasAccessibleSinceLastSave(map)) {
|
|
||||||
boolean flag = false;
|
|
||||||
// PlayerChunk.d players = map.players;
|
|
||||||
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
|
|
||||||
*/ Stream.empty();
|
|
||||||
|
|
||||||
ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle();
|
|
||||||
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
|
|
||||||
.forEach(entityPlayer -> {
|
|
||||||
synchronized (chunkPacket) {
|
|
||||||
ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
|
|
||||||
if (nmsPacket == null) {
|
|
||||||
nmsPacket = mapUtil.create(this, chunkPacket);
|
|
||||||
chunkPacket.setNativePacket(nmsPacket);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
|
|
||||||
entityPlayer.connection.send(nmsPacket);
|
|
||||||
} finally {
|
|
||||||
FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
|
||||||
return getParent().getProperties(blockType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
|
|
||||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
|
||||||
return blockState1.hasPostProcess(
|
|
||||||
getServerLevel(world),
|
|
||||||
new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
|
||||||
ItemStack stack = new ItemStack(
|
|
||||||
DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM)
|
|
||||||
.get(ResourceLocation.tryParse(baseItemStack.getType().id())),
|
|
||||||
baseItemStack.getAmount()
|
|
||||||
);
|
|
||||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
|
|
||||||
return CraftItemStack.asCraftMirror(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
|
||||||
serverLevel.captureTreeGeneration = true;
|
|
||||||
serverLevel.captureBlockStates = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
|
||||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
|
||||||
serverLevel.captureBlockStates = false;
|
|
||||||
serverLevel.captureTreeGeneration = false;
|
|
||||||
serverLevel.capturedBlockStates.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ServerLevel getServerLevel(final World world) {
|
|
||||||
return ((CraftWorld) world).getHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Tag toNative(net.minecraft.nbt.Tag foreign) {
|
|
||||||
return parent.toNative(foreign);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
|
|
||||||
if (foreign instanceof PaperweightLazyCompoundTag) {
|
|
||||||
return ((PaperweightLazyCompoundTag) foreign).get();
|
|
||||||
}
|
|
||||||
return parent.fromNative(foreign);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
|
|
||||||
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) {
|
|
||||||
return new PaperweightGetBlocks(world, chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInternalBiomeId(BiomeType biomeType) {
|
|
||||||
final Registry<Biome> registry = MinecraftServer
|
|
||||||
.getServer()
|
|
||||||
.registryAccess()
|
|
||||||
.registryOrThrow(BIOME);
|
|
||||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.id());
|
|
||||||
Biome biome = registry.get(resourceLocation);
|
|
||||||
return registry.getId(biome);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<NamespacedKey> getRegisteredBiomes() {
|
|
||||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
|
|
||||||
.getServer()
|
|
||||||
.registryAccess()
|
|
||||||
.registryOrThrow(BIOME);
|
|
||||||
List<ResourceLocation> keys = biomeRegistry.stream()
|
|
||||||
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
|
|
||||||
List<NamespacedKey> namespacedKeys = new ArrayList<>();
|
|
||||||
for (ResourceLocation key : keys) {
|
|
||||||
try {
|
|
||||||
namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
LOGGER.error("Error converting biome key {}", key.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return namespacedKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RelighterFactory getRelighterFactory() {
|
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
return new PaperweightStarlightRelighterFactory();
|
|
||||||
} else {
|
|
||||||
return new NMSRelighterFactory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<Property<?>>> getAllProperties() {
|
|
||||||
if (initialised) {
|
|
||||||
return allBlockProperties;
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
if (initialised) {
|
|
||||||
return allBlockProperties;
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
return allBlockProperties;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBatchProcessor getTickingPostProcessor() {
|
|
||||||
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,34 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
|
||||||
|
|
||||||
//TODO un-very-break-this
|
|
||||||
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkWithLightPacket> {
|
|
||||||
|
|
||||||
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"));
|
|
||||||
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
|
|
||||||
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c"));
|
|
||||||
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
|
|
||||||
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
|
|
||||||
fieldX.setAccessible(true);
|
|
||||||
fieldZ.setAccessible(true);
|
|
||||||
fieldBitMask.setAccessible(true);
|
|
||||||
fieldHeightMap.setAccessible(true);
|
|
||||||
fieldChunkData.setAccessible(true);
|
|
||||||
fieldBlockEntities.setAccessible(true);
|
|
||||||
fieldFull.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientboundLevelChunkWithLightPacket createPacket() {
|
|
||||||
// TODO ??? return new ClientboundLevelChunkPacket();
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,175 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunk;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
|
||||||
import com.fastasyncworldedit.core.registry.state.PropertyKey;
|
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
|
||||||
import net.minecraft.world.level.material.Fluids;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class PaperweightPostProcessor implements IBatchProcessor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) {
|
|
||||||
boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS;
|
|
||||||
// The PostProcessor shouldn't be added, but just in case
|
|
||||||
if (!tickFluid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet;
|
|
||||||
layer:
|
|
||||||
for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) {
|
|
||||||
char[] set = iChunkSet.loadIfPresent(layer);
|
|
||||||
if (set == null) {
|
|
||||||
// No edit means no need to process
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char[] get = null;
|
|
||||||
for (int i = 0; i < 4096; i++) {
|
|
||||||
char ordinal = set[i];
|
|
||||||
char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
|
|
||||||
boolean fromGet = false; // Used for liquids
|
|
||||||
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
|
||||||
if (get == null) {
|
|
||||||
get = getBlocks.load(layer);
|
|
||||||
}
|
|
||||||
// If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't
|
|
||||||
// actually being set
|
|
||||||
if (get == null) {
|
|
||||||
continue layer;
|
|
||||||
}
|
|
||||||
fromGet = true;
|
|
||||||
ordinal = replacedOrdinal = get[i];
|
|
||||||
}
|
|
||||||
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
|
||||||
continue;
|
|
||||||
} else if (!fromGet) { // if fromGet, don't do the same again
|
|
||||||
if (get == null) {
|
|
||||||
get = getBlocks.load(layer);
|
|
||||||
}
|
|
||||||
replacedOrdinal = get[i];
|
|
||||||
}
|
|
||||||
boolean ticking = BlockTypesCache.ticking[ordinal];
|
|
||||||
boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal];
|
|
||||||
boolean replacedWasLiquid = false;
|
|
||||||
BlockState replacedState = null;
|
|
||||||
if (!ticking) {
|
|
||||||
// If the block being replaced was not ticking, it cannot be a liquid
|
|
||||||
if (!replacedWasTicking) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// If the block being replaced is not fluid, we do not need to worry
|
|
||||||
if (!(replacedWasLiquid =
|
|
||||||
(replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
|
||||||
boolean liquid = state.getMaterial().isLiquid();
|
|
||||||
int x = i & 15;
|
|
||||||
int y = (i >> 8) & 15;
|
|
||||||
int z = (i >> 4) & 15;
|
|
||||||
BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z);
|
|
||||||
if (liquid || replacedWasLiquid) {
|
|
||||||
if (liquid) {
|
|
||||||
addFluid(getBlocks.serverLevel, state, position);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this
|
|
||||||
// may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up
|
|
||||||
// being ticked anyway. We only need it to be "hit" once.
|
|
||||||
if (!wasAdjacentToWater(get, set, i, x, y, z)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
addFluid(getBlocks.serverLevel, replacedState, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Extent construct(final Extent child) {
|
|
||||||
throw new UnsupportedOperationException("Processing only");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProcessorScope getScope() {
|
|
||||||
return ProcessorScope.READING_SET_BLOCKS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) {
|
|
||||||
if (set == null || get == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char ordinal;
|
|
||||||
char reserved = BlockTypesCache.ReservedIDs.__RESERVED__;
|
|
||||||
if (x > 0 && set[i - 1] != reserved) {
|
|
||||||
if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (x < 15 && set[i + 1] != reserved) {
|
|
||||||
if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (z > 0 && set[i - 16] != reserved) {
|
|
||||||
if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (z < 15 && set[i + 16] != reserved) {
|
|
||||||
if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (y > 0 && set[i - 256] != reserved) {
|
|
||||||
if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (y < 15 && set[i + 256] != reserved) {
|
|
||||||
return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private boolean isFluid(char ordinal) {
|
|
||||||
return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) {
|
|
||||||
Fluid type;
|
|
||||||
if (replacedState.getBlockType() == BlockTypes.LAVA) {
|
|
||||||
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA;
|
|
||||||
} else {
|
|
||||||
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
|
|
||||||
}
|
|
||||||
serverLevel.scheduleTick(
|
|
||||||
position,
|
|
||||||
type,
|
|
||||||
type.getTickDelay(serverLevel)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
|
|
||||||
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_20_R1.CraftWorld;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public class PaperweightStarlightRelighterFactory implements RelighterFactory {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nonnull Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<?> queue) {
|
|
||||||
org.bukkit.World w = Bukkit.getWorld(world.getName());
|
|
||||||
if (w == null) {
|
|
||||||
return NullRelighter.INSTANCE;
|
|
||||||
}
|
|
||||||
return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
|||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
@ -54,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.DoubleBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.EndBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.FloatBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ListBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ShortBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeCategory;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -81,6 +69,8 @@ import com.sk89q.worldedit.world.item.ItemType;
|
|||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderSet;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||||
@ -92,6 +82,7 @@ import net.minecraft.server.level.ChunkHolder;
|
|||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.util.thread.BlockableEventLoop;
|
import net.minecraft.util.thread.BlockableEventLoop;
|
||||||
import net.minecraft.world.Clearable;
|
import net.minecraft.world.Clearable;
|
||||||
@ -122,6 +113,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
import org.bukkit.World.Environment;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
|
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
|
||||||
@ -134,9 +126,26 @@ import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.enginehub.linbus.common.LinTagId;
|
||||||
|
import org.enginehub.linbus.tree.LinByteArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinByteTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinDoubleTag;
|
||||||
|
import org.enginehub.linbus.tree.LinEndTag;
|
||||||
|
import org.enginehub.linbus.tree.LinFloatTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntTag;
|
||||||
|
import org.enginehub.linbus.tree.LinListTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongTag;
|
||||||
|
import org.enginehub.linbus.tree.LinShortTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTagType;
|
||||||
import org.spigotmc.SpigotConfig;
|
import org.spigotmc.SpigotConfig;
|
||||||
import org.spigotmc.WatchdogThread;
|
import org.spigotmc.WatchdogThread;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -144,6 +153,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -158,7 +168,6 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
@ -172,6 +181,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private final Field chunkProviderExecutorField;
|
private final Field chunkProviderExecutorField;
|
||||||
private final Watchdog watchdog;
|
private final Watchdog watchdog;
|
||||||
|
|
||||||
|
private static final RandomSource random = RandomSource.create();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that may break between versions of Minecraft
|
// Code that may break between versions of Minecraft
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -280,7 +291,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Block getBlockFromType(BlockType blockType) {
|
private static Block getBlockFromType(BlockType blockType) {
|
||||||
|
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +315,29 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
|
||||||
|
int internalId = Block.getId(blockState);
|
||||||
|
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||||
|
if (state == null) {
|
||||||
|
state = BukkitAdapter.adapt(CraftBlockData.createData(blockState));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiomeType adapt(Biome biome) {
|
||||||
|
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(biome);
|
||||||
|
if (mcBiome == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return BiomeType.REGISTRY.get(mcBiome.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
|
||||||
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
|
return Block.stateById(internalId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(Location location) {
|
public BlockState getBlock(Location location) {
|
||||||
checkNotNull(location);
|
checkNotNull(location);
|
||||||
@ -318,14 +351,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||||
int internalId = Block.getId(blockData);
|
return adapt(blockData);
|
||||||
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -345,7 +371,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.toBaseBlock();
|
return state.toBaseBlock();
|
||||||
@ -355,8 +381,40 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
public BiomeType getBiome(Location location) {
|
||||||
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
checkNotNull(location);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
|
||||||
|
return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBiome(Location location, BiomeType biome) {
|
||||||
|
checkNotNull(location);
|
||||||
|
checkNotNull(biome);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id())))));
|
||||||
|
chunk.setUnsaved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(World world) {
|
||||||
|
return new PaperweightWorldNativeAccess(this,
|
||||||
|
new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static net.minecraft.core.Direction adapt(Direction face) {
|
private static net.minecraft.core.Direction adapt(Direction face) {
|
||||||
@ -427,7 +485,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
readEntityIntoTag(mcEntity, tag);
|
readEntityIntoTag(mcEntity, tag);
|
||||||
return new BaseEntity(
|
return new BaseEntity(
|
||||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,9 +501,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
||||||
|
|
||||||
if (createdEntity != null) {
|
if (createdEntity != null) {
|
||||||
CompoundBinaryTag nativeTag = state.getNbt();
|
LinCompoundTag nativeTag = state.getNbt();
|
||||||
if (nativeTag != null) {
|
if (nativeTag != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeLin(nativeTag);
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
tag.remove(name);
|
tag.remove(name);
|
||||||
}
|
}
|
||||||
@ -493,21 +551,39 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
|
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
|
||||||
|
.newBuilder()
|
||||||
|
.build(new CacheLoader<>() {
|
||||||
@Override
|
@Override
|
||||||
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
|
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) {
|
||||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
||||||
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else if (state instanceof DirectionProperty) {
|
} else if (state instanceof DirectionProperty) {
|
||||||
return new DirectionalProperty(state.getName(),
|
return new DirectionalProperty(
|
||||||
(List<Direction>) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<Direction>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
||||||
|
.getSerializedName()
|
||||||
|
.toUpperCase(Locale.ROOT)))
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
||||||
return new EnumProperty(state.getName(),
|
return new EnumProperty(
|
||||||
(List<String>) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<String>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> ((StringRepresentable) e).getSerializedName())
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
||||||
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
|
throw new IllegalArgumentException("WorldEdit needs an update to support " + state
|
||||||
|
.getClass()
|
||||||
|
.getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -527,13 +603,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) {
|
||||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
||||||
new StructureBlockEntity(
|
new StructureBlockEntity(
|
||||||
new BlockPos(pos.x(), pos.y(), pos.z()),
|
new BlockPos(pos.x(), pos.y(), pos.z()),
|
||||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
||||||
),
|
),
|
||||||
__ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
|
__ -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,7 +634,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
weStack.setNbt((LinCompoundTag) toNativeLin(nmsStack.getTag()));
|
||||||
return weStack;
|
return weStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,14 +677,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) {
|
public boolean canPlaceAt(World world, BlockVector3 position, BlockState blockState) {
|
||||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
||||||
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
public boolean regenerate(World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
||||||
try {
|
try {
|
||||||
doRegen(bukkitWorld, region, extent, options);
|
doRegen(bukkitWorld, region, extent, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -618,7 +694,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
private void doRegen(World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
||||||
Environment env = bukkitWorld.getEnvironment();
|
Environment env = bukkitWorld.getEnvironment();
|
||||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||||
|
|
||||||
@ -646,6 +722,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
levelProperties.settings.getDataConfiguration()
|
levelProperties.settings.getDataConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
||||||
levelProperties.isFlatWorld()
|
levelProperties.isFlatWorld()
|
||||||
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
||||||
@ -682,7 +759,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
Map<String, World> map = (Map<String, World>) serverWorldsField.get(Bukkit.getServer());
|
||||||
map.remove("faweregentempworld");
|
map.remove("faweregentempworld");
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
@ -734,7 +811,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
state = state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
extent.setBlock(vec, state.toBaseBlock());
|
extent.setBlock(vec, state.toBaseBlock());
|
||||||
if (options.shouldRegenBiomes()) {
|
if (options.shouldRegenBiomes()) {
|
||||||
@ -794,7 +871,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) {
|
public boolean clearContainerBlockContents(World world, BlockVector3 pt) {
|
||||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
||||||
@ -805,6 +882,45 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeRegistries() {
|
||||||
|
DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||||
|
// Biomes
|
||||||
|
for (ResourceLocation name : server.registryAccess().registryOrThrow(Registries.BIOME).keySet()) {
|
||||||
|
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
||||||
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BiomeCategories
|
||||||
|
Registry<Biome> biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
biomeRegistry.getTagNames().forEach(tagKey -> {
|
||||||
|
String key = tagKey.location().toString();
|
||||||
|
if (BiomeCategory.REGISTRY.get(key) == null) {
|
||||||
|
BiomeCategory.REGISTRY.register(key, new BiomeCategory(
|
||||||
|
key,
|
||||||
|
() -> biomeRegistry.getTag(tagKey)
|
||||||
|
.stream()
|
||||||
|
.flatMap(HolderSet.Named::stream)
|
||||||
|
.map(Holder::value)
|
||||||
|
.map(this::adapt)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
|
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||||
|
for (BlockVector2 chunk : chunks) {
|
||||||
|
nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false));
|
||||||
|
}
|
||||||
|
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that is less likely to break
|
// Code that is less likely to break
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -817,51 +933,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return native WorldEdit NBT structure
|
* @return native WorldEdit NBT structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
public LinTag<?> toNativeLin(net.minecraft.nbt.Tag foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
||||||
Map<String, BinaryTag> values = new HashMap<>();
|
Map<String, LinTag<?>> values = new HashMap<>();
|
||||||
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
||||||
|
|
||||||
for (String str : foreignKeys) {
|
for (String str : foreignKeys) {
|
||||||
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
||||||
values.put(str, toNativeBinary(base));
|
values.put(str, toNativeLin(base));
|
||||||
}
|
}
|
||||||
return CompoundBinaryTag.from(values);
|
return LinCompoundTag.of(values);
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
||||||
return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
||||||
return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
||||||
return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
||||||
return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
||||||
return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
||||||
return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
||||||
return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
||||||
try {
|
try {
|
||||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
return toNativeLinList((net.minecraft.nbt.ListTag) foreign);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||||
return ListBinaryTag.empty();
|
|
||||||
}
|
}
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||||
return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
||||||
return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
||||||
return StringBinaryTag.of(foreign.getAsString());
|
return LinStringTag.of(foreign.getAsString());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
||||||
return EndBinaryTag.get();
|
return LinEndTag.instance();
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -872,14 +986,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @throws SecurityException on error
|
* @throws SecurityException on error
|
||||||
* @throws IllegalArgumentException on error
|
* @throws IllegalArgumentException on error
|
||||||
*/
|
*/
|
||||||
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
private LinListTag<?> toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
||||||
ListBinaryTag.Builder values = ListBinaryTag.builder();
|
LinListTag.Builder<LinTag<?>> builder = LinListTag.builder(
|
||||||
|
LinTagType.fromId(LinTagId.fromId(foreign.getElementType()))
|
||||||
|
);
|
||||||
|
|
||||||
for (net.minecraft.nbt.Tag tag : foreign) {
|
for (net.minecraft.nbt.Tag tag : foreign) {
|
||||||
values.add(toNativeBinary(tag));
|
builder.add(toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -889,44 +1005,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return non-native structure
|
* @return non-native structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) {
|
public net.minecraft.nbt.Tag fromNativeLin(LinTag<?> foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof CompoundBinaryTag) {
|
if (foreign instanceof LinCompoundTag compoundTag) {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
for (String key : ((CompoundBinaryTag) foreign).keySet()) {
|
for (var entry : compoundTag.value().entrySet()) {
|
||||||
tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key)));
|
tag.put(entry.getKey(), fromNativeLin(entry.getValue()));
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof ByteBinaryTag) {
|
} else if (foreign instanceof LinByteTag byteTag) {
|
||||||
return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value());
|
return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte());
|
||||||
} else if (foreign instanceof ByteArrayBinaryTag) {
|
} else if (foreign instanceof LinByteArrayTag byteArrayTag) {
|
||||||
return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value());
|
||||||
} else if (foreign instanceof DoubleBinaryTag) {
|
} else if (foreign instanceof LinDoubleTag doubleTag) {
|
||||||
return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value());
|
return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble());
|
||||||
} else if (foreign instanceof FloatBinaryTag) {
|
} else if (foreign instanceof LinFloatTag floatTag) {
|
||||||
return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value());
|
return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat());
|
||||||
} else if (foreign instanceof IntBinaryTag) {
|
} else if (foreign instanceof LinIntTag intTag) {
|
||||||
return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value());
|
return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt());
|
||||||
} else if (foreign instanceof IntArrayBinaryTag) {
|
} else if (foreign instanceof LinIntArrayTag intArrayTag) {
|
||||||
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.IntArrayTag(intArrayTag.value());
|
||||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
} else if (foreign instanceof LinLongArrayTag longArrayTag) {
|
||||||
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.LongArrayTag(longArrayTag.value());
|
||||||
} else if (foreign instanceof ListBinaryTag) {
|
} else if (foreign instanceof LinListTag<?> listTag) {
|
||||||
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
||||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
for (var t : listTag.value()) {
|
||||||
for (BinaryTag t : foreignList) {
|
tag.add(fromNativeLin(t));
|
||||||
tag.add(fromNativeBinary(t));
|
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof LongBinaryTag) {
|
} else if (foreign instanceof LinLongTag longTag) {
|
||||||
return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value());
|
return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong());
|
||||||
} else if (foreign instanceof ShortBinaryTag) {
|
} else if (foreign instanceof LinShortTag shortTag) {
|
||||||
return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value());
|
return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort());
|
||||||
} else if (foreign instanceof StringBinaryTag) {
|
} else if (foreign instanceof LinStringTag stringTag) {
|
||||||
return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value());
|
return net.minecraft.nbt.StringTag.valueOf(stringTag.value());
|
||||||
} else if (foreign instanceof EndBinaryTag) {
|
} else if (foreign instanceof LinEndTag) {
|
||||||
return net.minecraft.nbt.EndTag.INSTANCE;
|
return net.minecraft.nbt.EndTag.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
||||||
@ -977,7 +1092,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
Field tickField = MinecraftServer.class.getDeclaredField(
|
Field tickField = MinecraftServer.class.getDeclaredField(
|
||||||
Refraction.pickName("nextTickTime", "ah")
|
Refraction.pickName("nextTickTime", "ag")
|
||||||
);
|
);
|
||||||
if (tickField.getType() != long.class) {
|
if (tickField.getType() != long.class) {
|
||||||
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
||||||
|
@ -35,7 +35,6 @@ import com.mojang.datafixers.DataFixer;
|
|||||||
import com.mojang.datafixers.DataFixerBuilder;
|
import com.mojang.datafixers.DataFixerBuilder;
|
||||||
import com.mojang.datafixers.schemas.Schema;
|
import com.mojang.datafixers.schemas.Schema;
|
||||||
import com.mojang.serialization.Dynamic;
|
import com.mojang.serialization.Dynamic;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.NbtOps;
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@ -48,7 +47,9 @@ import net.minecraft.util.datafix.fixes.References;
|
|||||||
import net.minecraft.world.item.DyeColor;
|
import net.minecraft.world.item.DyeColor;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
@ -62,7 +63,6 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
||||||
@ -78,16 +78,15 @@ import javax.annotation.Nullable;
|
|||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
||||||
|
|
||||||
//FAWE start - BinaryTag
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
||||||
if (type == FixTypes.CHUNK) {
|
if (type == FixTypes.CHUNK) {
|
||||||
return (T) fixChunk((CompoundBinaryTag) original, srcVer);
|
return (T) fixChunk((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_ENTITY) {
|
} else if (type == FixTypes.BLOCK_ENTITY) {
|
||||||
return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixBlockEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.ENTITY) {
|
} else if (type == FixTypes.ENTITY) {
|
||||||
return (T) fixEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_STATE) {
|
} else if (type == FixTypes.BLOCK_STATE) {
|
||||||
return (T) fixBlockState((String) original, srcVer);
|
return (T) fixBlockState((String) original, srcVer);
|
||||||
} else if (type == FixTypes.ITEM_TYPE) {
|
} else if (type == FixTypes.ITEM_TYPE) {
|
||||||
@ -98,24 +97,23 @@ public class PaperweightDataConverters extends DataFixerBuilder implements com.s
|
|||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) {
|
private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) {
|
private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) {
|
private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
private String fixBlockState(String blockState, int srcVer) {
|
private String fixBlockState(String blockState, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
||||||
|
@ -24,20 +24,22 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Objects;
|
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 UPDATE = 1;
|
||||||
@ -101,9 +103,16 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
|
public boolean updateTileEntity(final BlockPos position, final LinCompoundTag tag) {
|
||||||
|
// We will assume that the tile entity was created for us
|
||||||
|
BlockEntity tileEntity = getWorld().getBlockEntity(position);
|
||||||
|
if (tileEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Tag nativeTag = adapter.fromNativeLin(tag);
|
||||||
|
PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
||||||
@ -144,6 +153,12 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
ServerLevel world = getWorld();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Not sure why neighborChanged is deprecated
|
// Not sure why neighborChanged is deprecated
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
||||||
@ -153,8 +168,6 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
@Override
|
@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();
|
ServerLevel world = getWorld();
|
||||||
// a == updateNeighbors
|
|
||||||
// b == updateDiagonalNeighbors
|
|
||||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||||
CraftWorld craftWorld = world.getWorld();
|
CraftWorld craftWorld = world.getWorld();
|
||||||
|
@ -34,9 +34,6 @@ import com.sk89q.worldedit.util.Direction;
|
|||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -82,6 +79,9 @@ import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
|
|||||||
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
|
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -277,7 +277,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,14 +305,14 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
||||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
Supplier<LinCompoundTag> saveTag = () -> {
|
||||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||||
readEntityIntoTag(mcEntity, minecraftTag);
|
readEntityIntoTag(mcEntity, minecraftTag);
|
||||||
//add Id for AbstractChangeSet to work
|
//add Id for AbstractChangeSet to work
|
||||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag);
|
||||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
final Map<String, LinTag<?>> tags = NbtUtils.getLinCompoundTagValues(tag);
|
||||||
tags.put("Id", StringBinaryTag.of(id));
|
tags.put("Id", LinStringTag.of(id));
|
||||||
return CompoundBinaryTag.from(tags);
|
return LinCompoundTag.of(tags);
|
||||||
};
|
};
|
||||||
return new LazyBaseEntity(type, saveTag);
|
return new LazyBaseEntity(type, saveTag);
|
||||||
} else {
|
} else {
|
||||||
@ -517,7 +517,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
weStack.setNbt(((LinCompoundTag) toNativeLin(nmsStack.getTag())));
|
||||||
return weStack;
|
return weStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,15 +9,13 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
@ -25,6 +23,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
|||||||
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -133,14 +132,14 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos blockPos, LinCompoundTag tag) {
|
||||||
// We will assume that the tile entity was created for us,
|
// We will assume that the tile entity was created for us,
|
||||||
// though we do not do this on the other versions
|
// though we do not do this on the other versions
|
||||||
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
||||||
if (blockEntity == null) {
|
if (blockEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeLin(tag);
|
||||||
blockEntity.load((CompoundTag) nativeTag);
|
blockEntity.load((CompoundTag) nativeTag);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -218,6 +217,12 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
Level world = getLevel();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockStateChange(
|
public void onBlockStateChange(
|
||||||
BlockPos blockPos,
|
BlockPos blockPos,
|
||||||
|
@ -738,7 +738,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
final CompoundTag nativeTag = iterator.next();
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag<?, ?>> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
@ -364,7 +364,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
MinecraftServer.getServer().execute(() -> {
|
MinecraftServer.getServer().execute(() -> {
|
||||||
ClientboundLevelChunkWithLightPacket packet;
|
ClientboundLevelChunkWithLightPacket packet;
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
synchronized (chunk) {
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
nmsWorld.getChunkSource().getLightEngine(),
|
||||||
@ -372,9 +371,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null,
|
null,
|
||||||
false // last false is to not bother with x-ray
|
false // last false is to not bother with x-ray
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
synchronized (chunk) {
|
|
||||||
// deprecated on paper - deprecation suppressed
|
// deprecated on paper - deprecation suppressed
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
@ -383,7 +380,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag;
|
|||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.nbt.NumericTag;
|
import net.minecraft.nbt.NumericTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, Tag> getValue() {
|
public Map<String, Tag<?, ?>> getValue() {
|
||||||
if (compoundTag == null) {
|
if (compoundTag == null) {
|
||||||
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
||||||
}
|
}
|
||||||
@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundBinaryTag asBinaryTag() {
|
public LinCompoundTag toLinTag() {
|
||||||
getValue();
|
getValue();
|
||||||
return compoundTag.asBinaryTag();
|
return compoundTag.toLinTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(String key) {
|
public boolean containsKey(String key) {
|
||||||
@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<Tag> getList(String key) {
|
public List<? extends Tag<?, ?>> getList(String key) {
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
||||||
ArrayList<Tag> list = new ArrayList<>();
|
ArrayList<Tag<?, ?>> list = new ArrayList<>();
|
||||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
for (net.minecraft.nbt.Tag elem : nbtList) {
|
||||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
||||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
||||||
@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
|
public <T extends Tag<?, ?>> List<T> getList(String key, Class<T> listType) {
|
||||||
ListTag listTag = getListTag(key);
|
ListTag listTag = getListTag(key);
|
||||||
if (listTag.getType().equals(listType)) {
|
if (listTag.getType().equals(listType)) {
|
||||||
return (List<T>) listTag.getValue();
|
return (List<T>) listTag.getValue();
|
||||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
|||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
@ -54,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.DoubleBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.EndBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.FloatBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ListBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ShortBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeCategory;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -81,6 +69,8 @@ import com.sk89q.worldedit.world.item.ItemType;
|
|||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderSet;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||||
@ -92,6 +82,7 @@ import net.minecraft.server.level.ChunkHolder;
|
|||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.util.thread.BlockableEventLoop;
|
import net.minecraft.util.thread.BlockableEventLoop;
|
||||||
import net.minecraft.world.Clearable;
|
import net.minecraft.world.Clearable;
|
||||||
@ -122,6 +113,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
import org.bukkit.World.Environment;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
|
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
|
||||||
@ -134,9 +126,26 @@ import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.enginehub.linbus.common.LinTagId;
|
||||||
|
import org.enginehub.linbus.tree.LinByteArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinByteTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinDoubleTag;
|
||||||
|
import org.enginehub.linbus.tree.LinEndTag;
|
||||||
|
import org.enginehub.linbus.tree.LinFloatTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntTag;
|
||||||
|
import org.enginehub.linbus.tree.LinListTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongTag;
|
||||||
|
import org.enginehub.linbus.tree.LinShortTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTagType;
|
||||||
import org.spigotmc.SpigotConfig;
|
import org.spigotmc.SpigotConfig;
|
||||||
import org.spigotmc.WatchdogThread;
|
import org.spigotmc.WatchdogThread;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -144,6 +153,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -158,7 +168,6 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
@ -172,6 +181,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private final Field chunkProviderExecutorField;
|
private final Field chunkProviderExecutorField;
|
||||||
private final Watchdog watchdog;
|
private final Watchdog watchdog;
|
||||||
|
|
||||||
|
private static final RandomSource random = RandomSource.create();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that may break between versions of Minecraft
|
// Code that may break between versions of Minecraft
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -280,7 +291,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Block getBlockFromType(BlockType blockType) {
|
private static Block getBlockFromType(BlockType blockType) {
|
||||||
|
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +315,29 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
|
||||||
|
int internalId = Block.getId(blockState);
|
||||||
|
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||||
|
if (state == null) {
|
||||||
|
state = BukkitAdapter.adapt(CraftBlockData.createData(blockState));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiomeType adapt(Biome biome) {
|
||||||
|
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(biome);
|
||||||
|
if (mcBiome == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return BiomeType.REGISTRY.get(mcBiome.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
|
||||||
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
|
return Block.stateById(internalId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(Location location) {
|
public BlockState getBlock(Location location) {
|
||||||
checkNotNull(location);
|
checkNotNull(location);
|
||||||
@ -318,14 +351,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||||
int internalId = Block.getId(blockData);
|
return adapt(blockData);
|
||||||
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -345,7 +371,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.toBaseBlock();
|
return state.toBaseBlock();
|
||||||
@ -355,7 +381,38 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
public BiomeType getBiome(Location location) {
|
||||||
|
checkNotNull(location);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
|
||||||
|
return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBiome(Location location, BiomeType biome) {
|
||||||
|
checkNotNull(location);
|
||||||
|
checkNotNull(biome);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id())))));
|
||||||
|
chunk.setUnsaved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(World world) {
|
||||||
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +484,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
readEntityIntoTag(mcEntity, tag);
|
readEntityIntoTag(mcEntity, tag);
|
||||||
return new BaseEntity(
|
return new BaseEntity(
|
||||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,9 +500,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
||||||
|
|
||||||
if (createdEntity != null) {
|
if (createdEntity != null) {
|
||||||
CompoundBinaryTag nativeTag = state.getNbt();
|
LinCompoundTag nativeTag = state.getNbt();
|
||||||
if (nativeTag != null) {
|
if (nativeTag != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeLin(nativeTag);
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
tag.remove(name);
|
tag.remove(name);
|
||||||
}
|
}
|
||||||
@ -493,21 +550,39 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
|
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
|
||||||
|
.newBuilder()
|
||||||
|
.build(new CacheLoader<>() {
|
||||||
@Override
|
@Override
|
||||||
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
|
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) {
|
||||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
||||||
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else if (state instanceof DirectionProperty) {
|
} else if (state instanceof DirectionProperty) {
|
||||||
return new DirectionalProperty(state.getName(),
|
return new DirectionalProperty(
|
||||||
(List<Direction>) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<Direction>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
||||||
|
.getSerializedName()
|
||||||
|
.toUpperCase(Locale.ROOT)))
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
||||||
return new EnumProperty(state.getName(),
|
return new EnumProperty(
|
||||||
(List<String>) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<String>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> ((StringRepresentable) e).getSerializedName())
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
||||||
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
|
throw new IllegalArgumentException("WorldEdit needs an update to support " + state
|
||||||
|
.getClass()
|
||||||
|
.getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -527,13 +602,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) {
|
||||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
||||||
new StructureBlockEntity(
|
new StructureBlockEntity(
|
||||||
new BlockPos(pos.x(), pos.y(), pos.z()),
|
new BlockPos(pos.x(), pos.y(), pos.z()),
|
||||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
||||||
),
|
),
|
||||||
__ -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
|
__ -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,7 +633,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
weStack.setNbt((LinCompoundTag) toNativeLin(nmsStack.getTag()));
|
||||||
return weStack;
|
return weStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,14 +676,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) {
|
public boolean canPlaceAt(World world, BlockVector3 position, BlockState blockState) {
|
||||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
||||||
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
public boolean regenerate(World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
||||||
try {
|
try {
|
||||||
doRegen(bukkitWorld, region, extent, options);
|
doRegen(bukkitWorld, region, extent, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -618,7 +693,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
private void doRegen(World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
||||||
Environment env = bukkitWorld.getEnvironment();
|
Environment env = bukkitWorld.getEnvironment();
|
||||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||||
|
|
||||||
@ -646,6 +721,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
levelProperties.settings.getDataConfiguration()
|
levelProperties.settings.getDataConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
||||||
levelProperties.isFlatWorld()
|
levelProperties.isFlatWorld()
|
||||||
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
||||||
@ -682,7 +758,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
Map<String, World> map = (Map<String, World>) serverWorldsField.get(Bukkit.getServer());
|
||||||
map.remove("faweregentempworld");
|
map.remove("faweregentempworld");
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
@ -734,7 +810,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
state = state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
extent.setBlock(vec, state.toBaseBlock());
|
extent.setBlock(vec, state.toBaseBlock());
|
||||||
if (options.shouldRegenBiomes()) {
|
if (options.shouldRegenBiomes()) {
|
||||||
@ -794,7 +870,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) {
|
public boolean clearContainerBlockContents(World world, BlockVector3 pt) {
|
||||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
||||||
@ -805,6 +881,45 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeRegistries() {
|
||||||
|
DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||||
|
// Biomes
|
||||||
|
for (ResourceLocation name : server.registryAccess().registryOrThrow(Registries.BIOME).keySet()) {
|
||||||
|
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
||||||
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BiomeCategories
|
||||||
|
Registry<Biome> biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
biomeRegistry.getTagNames().forEach(tagKey -> {
|
||||||
|
String key = tagKey.location().toString();
|
||||||
|
if (BiomeCategory.REGISTRY.get(key) == null) {
|
||||||
|
BiomeCategory.REGISTRY.register(key, new BiomeCategory(
|
||||||
|
key,
|
||||||
|
() -> biomeRegistry.getTag(tagKey)
|
||||||
|
.stream()
|
||||||
|
.flatMap(HolderSet.Named::stream)
|
||||||
|
.map(Holder::value)
|
||||||
|
.map(this::adapt)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
|
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||||
|
for (BlockVector2 chunk : chunks) {
|
||||||
|
nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false));
|
||||||
|
}
|
||||||
|
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that is less likely to break
|
// Code that is less likely to break
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -817,51 +932,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return native WorldEdit NBT structure
|
* @return native WorldEdit NBT structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
public LinTag<?> toNativeLin(net.minecraft.nbt.Tag foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
||||||
Map<String, BinaryTag> values = new HashMap<>();
|
Map<String, LinTag<?>> values = new HashMap<>();
|
||||||
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
||||||
|
|
||||||
for (String str : foreignKeys) {
|
for (String str : foreignKeys) {
|
||||||
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
||||||
values.put(str, toNativeBinary(base));
|
values.put(str, toNativeLin(base));
|
||||||
}
|
}
|
||||||
return CompoundBinaryTag.from(values);
|
return LinCompoundTag.of(values);
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
||||||
return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
||||||
return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
||||||
return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
||||||
return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
||||||
return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
||||||
return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
||||||
return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
||||||
try {
|
try {
|
||||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
return toNativeLinList((net.minecraft.nbt.ListTag) foreign);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||||
return ListBinaryTag.empty();
|
|
||||||
}
|
}
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||||
return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
||||||
return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
||||||
return StringBinaryTag.of(foreign.getAsString());
|
return LinStringTag.of(foreign.getAsString());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
||||||
return EndBinaryTag.get();
|
return LinEndTag.instance();
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -872,14 +985,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @throws SecurityException on error
|
* @throws SecurityException on error
|
||||||
* @throws IllegalArgumentException on error
|
* @throws IllegalArgumentException on error
|
||||||
*/
|
*/
|
||||||
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
private LinListTag<?> toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
||||||
ListBinaryTag.Builder values = ListBinaryTag.builder();
|
LinListTag.Builder<LinTag<?>> builder = LinListTag.builder(
|
||||||
|
LinTagType.fromId(LinTagId.fromId(foreign.getElementType()))
|
||||||
|
);
|
||||||
|
|
||||||
for (net.minecraft.nbt.Tag tag : foreign) {
|
for (net.minecraft.nbt.Tag tag : foreign) {
|
||||||
values.add(toNativeBinary(tag));
|
builder.add(toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -889,44 +1004,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return non-native structure
|
* @return non-native structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) {
|
public net.minecraft.nbt.Tag fromNativeLin(LinTag<?> foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof CompoundBinaryTag) {
|
if (foreign instanceof LinCompoundTag compoundTag) {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
for (String key : ((CompoundBinaryTag) foreign).keySet()) {
|
for (var entry : compoundTag.value().entrySet()) {
|
||||||
tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key)));
|
tag.put(entry.getKey(), fromNativeLin(entry.getValue()));
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof ByteBinaryTag) {
|
} else if (foreign instanceof LinByteTag byteTag) {
|
||||||
return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value());
|
return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte());
|
||||||
} else if (foreign instanceof ByteArrayBinaryTag) {
|
} else if (foreign instanceof LinByteArrayTag byteArrayTag) {
|
||||||
return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value());
|
||||||
} else if (foreign instanceof DoubleBinaryTag) {
|
} else if (foreign instanceof LinDoubleTag doubleTag) {
|
||||||
return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value());
|
return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble());
|
||||||
} else if (foreign instanceof FloatBinaryTag) {
|
} else if (foreign instanceof LinFloatTag floatTag) {
|
||||||
return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value());
|
return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat());
|
||||||
} else if (foreign instanceof IntBinaryTag) {
|
} else if (foreign instanceof LinIntTag intTag) {
|
||||||
return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value());
|
return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt());
|
||||||
} else if (foreign instanceof IntArrayBinaryTag) {
|
} else if (foreign instanceof LinIntArrayTag intArrayTag) {
|
||||||
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.IntArrayTag(intArrayTag.value());
|
||||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
} else if (foreign instanceof LinLongArrayTag longArrayTag) {
|
||||||
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.LongArrayTag(longArrayTag.value());
|
||||||
} else if (foreign instanceof ListBinaryTag) {
|
} else if (foreign instanceof LinListTag<?> listTag) {
|
||||||
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
||||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
for (var t : listTag.value()) {
|
||||||
for (BinaryTag t : foreignList) {
|
tag.add(fromNativeLin(t));
|
||||||
tag.add(fromNativeBinary(t));
|
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof LongBinaryTag) {
|
} else if (foreign instanceof LinLongTag longTag) {
|
||||||
return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value());
|
return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong());
|
||||||
} else if (foreign instanceof ShortBinaryTag) {
|
} else if (foreign instanceof LinShortTag shortTag) {
|
||||||
return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value());
|
return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort());
|
||||||
} else if (foreign instanceof StringBinaryTag) {
|
} else if (foreign instanceof LinStringTag stringTag) {
|
||||||
return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value());
|
return net.minecraft.nbt.StringTag.valueOf(stringTag.value());
|
||||||
} else if (foreign instanceof EndBinaryTag) {
|
} else if (foreign instanceof LinEndTag) {
|
||||||
return net.minecraft.nbt.EndTag.INSTANCE;
|
return net.minecraft.nbt.EndTag.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
||||||
@ -977,7 +1091,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
Field tickField = MinecraftServer.class.getDeclaredField(
|
Field tickField = MinecraftServer.class.getDeclaredField(
|
||||||
Refraction.pickName("nextTickTime", "ah")
|
Refraction.pickName("nextTickTime", "ag")
|
||||||
);
|
);
|
||||||
if (tickField.getType() != long.class) {
|
if (tickField.getType() != long.class) {
|
||||||
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
||||||
|
@ -35,8 +35,6 @@ import com.mojang.datafixers.DataFixer;
|
|||||||
import com.mojang.datafixers.DataFixerBuilder;
|
import com.mojang.datafixers.DataFixerBuilder;
|
||||||
import com.mojang.datafixers.schemas.Schema;
|
import com.mojang.datafixers.schemas.Schema;
|
||||||
import com.mojang.serialization.Dynamic;
|
import com.mojang.serialization.Dynamic;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.NbtOps;
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@ -49,7 +47,9 @@ import net.minecraft.util.datafix.fixes.References;
|
|||||||
import net.minecraft.world.item.DyeColor;
|
import net.minecraft.world.item.DyeColor;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
@ -63,7 +63,6 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
||||||
@ -79,16 +78,15 @@ import javax.annotation.Nullable;
|
|||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
||||||
|
|
||||||
//FAWE start - BinaryTag
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
||||||
if (type == FixTypes.CHUNK) {
|
if (type == FixTypes.CHUNK) {
|
||||||
return (T) fixChunk((CompoundBinaryTag) original, srcVer);
|
return (T) fixChunk((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_ENTITY) {
|
} else if (type == FixTypes.BLOCK_ENTITY) {
|
||||||
return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixBlockEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.ENTITY) {
|
} else if (type == FixTypes.ENTITY) {
|
||||||
return (T) fixEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_STATE) {
|
} else if (type == FixTypes.BLOCK_STATE) {
|
||||||
return (T) fixBlockState((String) original, srcVer);
|
return (T) fixBlockState((String) original, srcVer);
|
||||||
} else if (type == FixTypes.ITEM_TYPE) {
|
} else if (type == FixTypes.ITEM_TYPE) {
|
||||||
@ -99,24 +97,23 @@ public class PaperweightDataConverters extends DataFixerBuilder implements com.s
|
|||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) {
|
private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) {
|
private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) {
|
private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
private String fixBlockState(String blockState, int srcVer) {
|
private String fixBlockState(String blockState, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
||||||
|
@ -19,25 +19,28 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3;
|
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Objects;
|
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 UPDATE = 1;
|
||||||
@ -101,9 +104,16 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) {
|
||||||
|
// We will assume that the tile entity was created for us
|
||||||
|
BlockEntity tileEntity = getWorld().getBlockEntity(position);
|
||||||
|
if (tileEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Tag nativeTag = adapter.fromNativeLin(tag);
|
||||||
|
PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
||||||
@ -144,6 +154,12 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
ServerLevel world = getWorld();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Not sure why neighborChanged is deprecated
|
// Not sure why neighborChanged is deprecated
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
||||||
@ -153,8 +169,6 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
@Override
|
@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();
|
ServerLevel world = getWorld();
|
||||||
// a == updateNeighbors
|
|
||||||
// b == updateDiagonalNeighbors
|
|
||||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||||
CraftWorld craftWorld = world.getWorld();
|
CraftWorld craftWorld = world.getWorld();
|
||||||
@ -177,5 +191,4 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
public void flush() {
|
public void flush() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,6 @@ import com.sk89q.worldedit.util.Direction;
|
|||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -82,6 +79,9 @@ import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
|||||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
|
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -277,7 +277,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,14 +305,14 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
||||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
Supplier<LinCompoundTag> saveTag = () -> {
|
||||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||||
readEntityIntoTag(mcEntity, minecraftTag);
|
readEntityIntoTag(mcEntity, minecraftTag);
|
||||||
//add Id for AbstractChangeSet to work
|
//add Id for AbstractChangeSet to work
|
||||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag);
|
||||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
final Map<String, LinTag<?>> tags = NbtUtils.getLinCompoundTagValues(tag);
|
||||||
tags.put("Id", StringBinaryTag.of(id));
|
tags.put("Id", LinStringTag.of(id));
|
||||||
return CompoundBinaryTag.from(tags);
|
return LinCompoundTag.of(tags);
|
||||||
};
|
};
|
||||||
return new LazyBaseEntity(type, saveTag);
|
return new LazyBaseEntity(type, saveTag);
|
||||||
} else {
|
} else {
|
||||||
@ -517,7 +517,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
weStack.setNbt(((LinCompoundTag) toNativeLin(nmsStack.getTag())));
|
||||||
return weStack;
|
return weStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,14 +9,13 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
@ -24,6 +23,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
|||||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -132,14 +132,14 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos blockPos, LinCompoundTag tag) {
|
||||||
// We will assume that the tile entity was created for us,
|
// We will assume that the tile entity was created for us,
|
||||||
// though we do not do this on the other versions
|
// though we do not do this on the other versions
|
||||||
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
||||||
if (blockEntity == null) {
|
if (blockEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeLin(tag);
|
||||||
blockEntity.load((CompoundTag) nativeTag);
|
blockEntity.load((CompoundTag) nativeTag);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -217,6 +217,12 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
Level world = getLevel();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockStateChange(
|
public void onBlockStateChange(
|
||||||
BlockPos blockPos,
|
BlockPos blockPos,
|
||||||
|
@ -737,7 +737,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
final CompoundTag nativeTag = iterator.next();
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag<?, ?>> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
@ -364,7 +364,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
MinecraftServer.getServer().execute(() -> {
|
MinecraftServer.getServer().execute(() -> {
|
||||||
ClientboundLevelChunkWithLightPacket packet;
|
ClientboundLevelChunkWithLightPacket packet;
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
synchronized (chunk) {
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
nmsWorld.getChunkSource().getLightEngine(),
|
||||||
@ -372,9 +371,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null,
|
null,
|
||||||
false // last false is to not bother with x-ray
|
false // last false is to not bother with x-ray
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
synchronized (chunk) {
|
|
||||||
// deprecated on paper - deprecation suppressed
|
// deprecated on paper - deprecation suppressed
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
@ -383,7 +380,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag;
|
|||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.nbt.NumericTag;
|
import net.minecraft.nbt.NumericTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, Tag> getValue() {
|
public Map<String, Tag<?, ?>> getValue() {
|
||||||
if (compoundTag == null) {
|
if (compoundTag == null) {
|
||||||
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
||||||
}
|
}
|
||||||
@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundBinaryTag asBinaryTag() {
|
public LinCompoundTag toLinTag() {
|
||||||
getValue();
|
getValue();
|
||||||
return compoundTag.asBinaryTag();
|
return compoundTag.toLinTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(String key) {
|
public boolean containsKey(String key) {
|
||||||
@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<Tag> getList(String key) {
|
public List<? extends Tag<?, ?>> getList(String key) {
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
||||||
ArrayList<Tag> list = new ArrayList<>();
|
ArrayList<Tag<?, ?>> list = new ArrayList<>();
|
||||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
for (net.minecraft.nbt.Tag elem : nbtList) {
|
||||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
||||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
||||||
@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
|
public <T extends Tag<?, ?>> List<T> getList(String key, Class<T> listType) {
|
||||||
ListTag listTag = getListTag(key);
|
ListTag listTag = getListTag(key);
|
||||||
if (listTag.getType().equals(listType)) {
|
if (listTag.getType().equals(listType)) {
|
||||||
return (List<T>) listTag.getValue();
|
return (List<T>) listTag.getValue();
|
||||||
|
@ -12,6 +12,6 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
|
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
|
||||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240617.192752-122")
|
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240702.153951-123")
|
||||||
compileOnly(libs.paperlib)
|
compileOnly(libs.paperlib)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import com.google.common.cache.CacheBuilder;
|
|||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
@ -54,22 +55,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.DoubleBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.EndBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.FloatBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ListBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ShortBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeCategory;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -81,12 +69,13 @@ import com.sk89q.worldedit.world.item.ItemType;
|
|||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderSet;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtOps;
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.nbt.Tag;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
@ -97,6 +86,7 @@ import net.minecraft.server.level.ChunkResult;
|
|||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.util.thread.BlockableEventLoop;
|
import net.minecraft.util.thread.BlockableEventLoop;
|
||||||
import net.minecraft.world.Clearable;
|
import net.minecraft.world.Clearable;
|
||||||
@ -127,6 +117,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
import org.bukkit.World.Environment;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.CraftServer;
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
@ -139,9 +130,26 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.enginehub.linbus.common.LinTagId;
|
||||||
|
import org.enginehub.linbus.tree.LinByteArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinByteTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinDoubleTag;
|
||||||
|
import org.enginehub.linbus.tree.LinEndTag;
|
||||||
|
import org.enginehub.linbus.tree.LinFloatTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntTag;
|
||||||
|
import org.enginehub.linbus.tree.LinListTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongTag;
|
||||||
|
import org.enginehub.linbus.tree.LinShortTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTagType;
|
||||||
import org.spigotmc.SpigotConfig;
|
import org.spigotmc.SpigotConfig;
|
||||||
import org.spigotmc.WatchdogThread;
|
import org.spigotmc.WatchdogThread;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -149,6 +157,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -163,7 +172,6 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
@ -181,6 +189,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private final Field chunkProviderExecutorField;
|
private final Field chunkProviderExecutorField;
|
||||||
private final Watchdog watchdog;
|
private final Watchdog watchdog;
|
||||||
|
|
||||||
|
private static final RandomSource random = RandomSource.create();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that may break between versions of Minecraft
|
// Code that may break between versions of Minecraft
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -289,14 +299,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Block getBlockFromType(BlockType blockType) {
|
private static Block getBlockFromType(BlockType blockType) {
|
||||||
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(
|
|
||||||
blockType.id()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Item getItemFromType(ItemType itemType) {
|
private static Item getItemFromType(ItemType itemType) {
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(itemType.id()));
|
||||||
itemType.id()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -327,14 +334,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BiomeType adapt(Biome biome) {
|
public BiomeType adapt(Biome biome) {
|
||||||
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(
|
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(biome);
|
||||||
biome);
|
|
||||||
if (mcBiome == null) {
|
if (mcBiome == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return BiomeType.REGISTRY.get(mcBiome.toString());
|
return BiomeType.REGISTRY.get(mcBiome.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
|
||||||
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
|
return Block.stateById(internalId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(Location location) {
|
public BlockState getBlock(Location location) {
|
||||||
checkNotNull(location);
|
checkNotNull(location);
|
||||||
@ -348,14 +359,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||||
int internalId = Block.getId(blockData);
|
return adapt(blockData);
|
||||||
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -375,7 +379,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess());
|
net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess());
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.toBaseBlock();
|
return state.toBaseBlock();
|
||||||
@ -385,7 +389,38 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
public BiomeType getBiome(Location location) {
|
||||||
|
checkNotNull(location);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
|
||||||
|
return biomeTypeFromNMSCache.computeIfAbsent(chunk.getNoiseBiome(x >> 2, y >> 2, z >> 2), b -> BiomeType.REGISTRY.get(b.unwrapKey().get().location().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBiome(Location location, BiomeType biome) {
|
||||||
|
checkNotNull(location);
|
||||||
|
checkNotNull(biome);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
|
chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.id())))));
|
||||||
|
chunk.setUnsaved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(World world) {
|
||||||
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +492,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
readEntityIntoTag(mcEntity, tag);
|
readEntityIntoTag(mcEntity, tag);
|
||||||
return new BaseEntity(
|
return new BaseEntity(
|
||||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,9 +508,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
||||||
|
|
||||||
if (createdEntity != null) {
|
if (createdEntity != null) {
|
||||||
CompoundBinaryTag nativeTag = state.getNbt();
|
LinCompoundTag nativeTag = state.getNbt();
|
||||||
if (nativeTag != null) {
|
if (nativeTag != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeLin(nativeTag);
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
tag.remove(name);
|
tag.remove(name);
|
||||||
}
|
}
|
||||||
@ -484,7 +519,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
|
|
||||||
createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||||
|
|
||||||
worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM);
|
worldServer.addFreshEntityWithPassengers(createdEntity, SpawnReason.CUSTOM);
|
||||||
return createdEntity.getBukkitEntity();
|
return createdEntity.getBukkitEntity();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -525,30 +560,30 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
|
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
|
.build(new CacheLoader<>() {
|
||||||
@Override
|
@Override
|
||||||
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
|
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) {
|
||||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
||||||
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else if (state instanceof DirectionProperty) {
|
} else if (state instanceof DirectionProperty) {
|
||||||
return new DirectionalProperty(
|
return new DirectionalProperty(
|
||||||
state.getName(),
|
state.getName(),
|
||||||
(List<Direction>) state
|
new ArrayList<>((List<Direction>) state
|
||||||
.getPossibleValues()
|
.getPossibleValues()
|
||||||
.stream()
|
.stream()
|
||||||
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
||||||
.getSerializedName()
|
.getSerializedName()
|
||||||
.toUpperCase(Locale.ROOT)))
|
.toUpperCase(Locale.ROOT)))
|
||||||
.collect(Collectors.toList())
|
.toList())
|
||||||
);
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
||||||
return new EnumProperty(
|
return new EnumProperty(
|
||||||
state.getName(),
|
state.getName(),
|
||||||
(List<String>) state
|
new ArrayList<>((List<String>) state
|
||||||
.getPossibleValues()
|
.getPossibleValues()
|
||||||
.stream()
|
.stream()
|
||||||
.map(e -> ((StringRepresentable) e).getSerializedName())
|
.map(e -> ((StringRepresentable) e).getSerializedName())
|
||||||
.collect(Collectors.toList())
|
.toList())
|
||||||
);
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
||||||
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
@ -560,7 +595,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes"})
|
@SuppressWarnings({ "rawtypes" })
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
||||||
Map<String, Property<?>> properties = new TreeMap<>();
|
Map<String, Property<?>> properties = new TreeMap<>();
|
||||||
@ -575,7 +610,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) {
|
||||||
var structureBlock = new StructureBlockEntity(
|
var structureBlock = new StructureBlockEntity(
|
||||||
new BlockPos(pos.x(), pos.y(), pos.z()),
|
new BlockPos(pos.x(), pos.y(), pos.z()),
|
||||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
||||||
@ -583,7 +618,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
structureBlock.setLevel(((CraftPlayer) player).getHandle().level());
|
structureBlock.setLevel(((CraftPlayer) player).getHandle().level());
|
||||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
||||||
structureBlock,
|
structureBlock,
|
||||||
(blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeBinary(nbtData)
|
(blockEntity, registryAccess) -> (net.minecraft.nbt.CompoundTag) fromNativeLin(nbtData)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,13 +630,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
|
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
||||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
ItemStack stack = new ItemStack(
|
ItemStack stack = new ItemStack(
|
||||||
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().id())),
|
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())),
|
||||||
item.getAmount()
|
baseItemStack.getAmount()
|
||||||
);
|
);
|
||||||
final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData());
|
final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData());
|
||||||
final DataComponentPatch patch = COMPONENTS_CODEC
|
final DataComponentPatch patch = COMPONENTS_CODEC
|
||||||
.parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt)
|
.parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
@ -611,15 +646,15 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
var registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final Tag tag = COMPONENTS_CODEC.encodeStart(
|
CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart(
|
||||||
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||||
nmsStack.getComponentsPatch()
|
nmsStack.getComponentsPatch()
|
||||||
).getOrThrow();
|
).getOrThrow();
|
||||||
return new BaseItemStack(
|
return new BaseItemStack(
|
||||||
BukkitAdapter.asItemType(itemStack.getType()),
|
BukkitAdapter.asItemType(itemStack.getType()),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)),
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)),
|
||||||
itemStack.getAmount()
|
itemStack.getAmount()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -628,7 +663,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
|
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) {
|
public boolean simulateItemUse(World world, BlockVector3 position, BaseItem item, Direction face) {
|
||||||
CraftWorld craftWorld = (CraftWorld) world;
|
CraftWorld craftWorld = (CraftWorld) world;
|
||||||
ServerLevel worldServer = craftWorld.getHandle();
|
ServerLevel worldServer = craftWorld.getHandle();
|
||||||
ItemStack stack = CraftItemStack.asNMSCopy(adapt(
|
ItemStack stack = CraftItemStack.asNMSCopy(adapt(
|
||||||
@ -645,8 +680,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack);
|
fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack);
|
||||||
fakePlayer.absMoveTo(position.x(), position.y(), position.z(),
|
fakePlayer.absMoveTo(position.x(), position.y(), position.z(),
|
||||||
(float) face.toVector().toYaw(), (float) face.toVector().toPitch()
|
(float) face.toVector().toYaw(), (float) face.toVector().toPitch());
|
||||||
);
|
|
||||||
|
|
||||||
final BlockPos blockPos = new BlockPos(position.x(), position.y(), position.z());
|
final BlockPos blockPos = new BlockPos(position.x(), position.y(), position.z());
|
||||||
final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos);
|
final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos);
|
||||||
@ -655,10 +689,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
|
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
|
||||||
InteractionResult result = stack.useOn(context);
|
InteractionResult result = stack.useOn(context);
|
||||||
if (result != InteractionResult.SUCCESS) {
|
if (result != InteractionResult.SUCCESS) {
|
||||||
if (worldServer
|
if (worldServer.getBlockState(blockPos).useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) {
|
||||||
.getBlockState(blockPos)
|
|
||||||
.useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace)
|
|
||||||
.consumesAction()) {
|
|
||||||
result = InteractionResult.SUCCESS;
|
result = InteractionResult.SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult();
|
result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult();
|
||||||
@ -669,17 +700,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) {
|
public boolean canPlaceAt(World world, BlockVector3 position, BlockState blockState) {
|
||||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
||||||
return blockData.canSurvive(
|
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
||||||
((CraftWorld) world).getHandle(),
|
|
||||||
new BlockPos(position.x(), position.y(), position.z())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
public boolean regenerate(World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
||||||
try {
|
try {
|
||||||
doRegen(bukkitWorld, region, extent, options);
|
doRegen(bukkitWorld, region, extent, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -689,7 +717,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
private void doRegen(World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
||||||
Environment env = bukkitWorld.getEnvironment();
|
Environment env = bukkitWorld.getEnvironment();
|
||||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||||
|
|
||||||
@ -717,6 +745,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
levelProperties.settings.getDataConfiguration()
|
levelProperties.settings.getDataConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
||||||
levelProperties.isFlatWorld()
|
levelProperties.isFlatWorld()
|
||||||
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
||||||
@ -724,12 +753,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
? PrimaryLevelData.SpecialWorldProperty.DEBUG
|
? PrimaryLevelData.SpecialWorldProperty.DEBUG
|
||||||
: PrimaryLevelData.SpecialWorldProperty.NONE;
|
: PrimaryLevelData.SpecialWorldProperty.NONE;
|
||||||
|
|
||||||
PrimaryLevelData newWorldData = new PrimaryLevelData(
|
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable());
|
||||||
newWorldSettings,
|
|
||||||
newOpts,
|
|
||||||
specialWorldProperty,
|
|
||||||
Lifecycle.stable()
|
|
||||||
);
|
|
||||||
|
|
||||||
ServerLevel freshWorld = new ServerLevel(
|
ServerLevel freshWorld = new ServerLevel(
|
||||||
originalWorld.getServer(),
|
originalWorld.getServer(),
|
||||||
@ -758,7 +782,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
Map<String, World> map = (Map<String, World>) serverWorldsField.get(Bukkit.getServer());
|
||||||
map.remove("faweregentempworld");
|
map.remove("faweregentempworld");
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
@ -775,8 +799,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws
|
private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws WorldEditException {
|
||||||
WorldEditException {
|
|
||||||
List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld);
|
List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld);
|
||||||
BlockableEventLoop<Runnable> executor;
|
BlockableEventLoop<Runnable> executor;
|
||||||
try {
|
try {
|
||||||
@ -811,7 +834,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess());
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess());
|
||||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
state = state.toBaseBlock(((LinCompoundTag) toNativeLin(tag)));
|
||||||
}
|
}
|
||||||
extent.setBlock(vec, state.toBaseBlock());
|
extent.setBlock(vec, state.toBaseBlock());
|
||||||
if (options.shouldRegenBiomes()) {
|
if (options.shouldRegenBiomes()) {
|
||||||
@ -871,7 +894,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) {
|
public boolean clearContainerBlockContents(World world, BlockVector3 pt) {
|
||||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
||||||
@ -882,6 +905,45 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeRegistries() {
|
||||||
|
DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||||
|
// Biomes
|
||||||
|
for (ResourceLocation name : server.registryAccess().registryOrThrow(Registries.BIOME).keySet()) {
|
||||||
|
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
||||||
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BiomeCategories
|
||||||
|
Registry<Biome> biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
biomeRegistry.getTagNames().forEach(tagKey -> {
|
||||||
|
String key = tagKey.location().toString();
|
||||||
|
if (BiomeCategory.REGISTRY.get(key) == null) {
|
||||||
|
BiomeCategory.REGISTRY.register(key, new BiomeCategory(
|
||||||
|
key,
|
||||||
|
() -> biomeRegistry.getTag(tagKey)
|
||||||
|
.stream()
|
||||||
|
.flatMap(HolderSet.Named::stream)
|
||||||
|
.map(Holder::value)
|
||||||
|
.map(this::adapt)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
|
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||||
|
for (BlockVector2 chunk : chunks) {
|
||||||
|
nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false));
|
||||||
|
}
|
||||||
|
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that is less likely to break
|
// Code that is less likely to break
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -894,51 +956,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return native WorldEdit NBT structure
|
* @return native WorldEdit NBT structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
public LinTag<?> toNativeLin(net.minecraft.nbt.Tag foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
||||||
Map<String, BinaryTag> values = new HashMap<>();
|
Map<String, LinTag<?>> values = new HashMap<>();
|
||||||
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
||||||
|
|
||||||
for (String str : foreignKeys) {
|
for (String str : foreignKeys) {
|
||||||
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
||||||
values.put(str, toNativeBinary(base));
|
values.put(str, toNativeLin(base));
|
||||||
}
|
}
|
||||||
return CompoundBinaryTag.from(values);
|
return LinCompoundTag.of(values);
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
||||||
return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
||||||
return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
||||||
return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
||||||
return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
||||||
return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
||||||
return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
||||||
return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
||||||
try {
|
try {
|
||||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
return toNativeLinList((net.minecraft.nbt.ListTag) foreign);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||||
return ListBinaryTag.empty();
|
|
||||||
}
|
}
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||||
return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
||||||
return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
||||||
return StringBinaryTag.of(foreign.getAsString());
|
return LinStringTag.of(foreign.getAsString());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
||||||
return EndBinaryTag.get();
|
return LinEndTag.instance();
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -949,14 +1009,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @throws SecurityException on error
|
* @throws SecurityException on error
|
||||||
* @throws IllegalArgumentException on error
|
* @throws IllegalArgumentException on error
|
||||||
*/
|
*/
|
||||||
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
private LinListTag<?> toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
||||||
ListBinaryTag.Builder values = ListBinaryTag.builder();
|
LinListTag.Builder<LinTag<?>> builder = LinListTag.builder(
|
||||||
|
LinTagType.fromId(LinTagId.fromId(foreign.getElementType()))
|
||||||
|
);
|
||||||
|
|
||||||
for (net.minecraft.nbt.Tag tag : foreign) {
|
for (net.minecraft.nbt.Tag tag : foreign) {
|
||||||
values.add(toNativeBinary(tag));
|
builder.add(toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -966,44 +1028,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return non-native structure
|
* @return non-native structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) {
|
public net.minecraft.nbt.Tag fromNativeLin(LinTag<?> foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof CompoundBinaryTag) {
|
if (foreign instanceof LinCompoundTag compoundTag) {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
for (String key : ((CompoundBinaryTag) foreign).keySet()) {
|
for (var entry : compoundTag.value().entrySet()) {
|
||||||
tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key)));
|
tag.put(entry.getKey(), fromNativeLin(entry.getValue()));
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof ByteBinaryTag) {
|
} else if (foreign instanceof LinByteTag byteTag) {
|
||||||
return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value());
|
return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte());
|
||||||
} else if (foreign instanceof ByteArrayBinaryTag) {
|
} else if (foreign instanceof LinByteArrayTag byteArrayTag) {
|
||||||
return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value());
|
||||||
} else if (foreign instanceof DoubleBinaryTag) {
|
} else if (foreign instanceof LinDoubleTag doubleTag) {
|
||||||
return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value());
|
return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble());
|
||||||
} else if (foreign instanceof FloatBinaryTag) {
|
} else if (foreign instanceof LinFloatTag floatTag) {
|
||||||
return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value());
|
return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat());
|
||||||
} else if (foreign instanceof IntBinaryTag) {
|
} else if (foreign instanceof LinIntTag intTag) {
|
||||||
return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value());
|
return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt());
|
||||||
} else if (foreign instanceof IntArrayBinaryTag) {
|
} else if (foreign instanceof LinIntArrayTag intArrayTag) {
|
||||||
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.IntArrayTag(intArrayTag.value());
|
||||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
} else if (foreign instanceof LinLongArrayTag longArrayTag) {
|
||||||
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.LongArrayTag(longArrayTag.value());
|
||||||
} else if (foreign instanceof ListBinaryTag) {
|
} else if (foreign instanceof LinListTag<?> listTag) {
|
||||||
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
||||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
for (var t : listTag.value()) {
|
||||||
for (BinaryTag t : foreignList) {
|
tag.add(fromNativeLin(t));
|
||||||
tag.add(fromNativeBinary(t));
|
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof LongBinaryTag) {
|
} else if (foreign instanceof LinLongTag longTag) {
|
||||||
return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value());
|
return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong());
|
||||||
} else if (foreign instanceof ShortBinaryTag) {
|
} else if (foreign instanceof LinShortTag shortTag) {
|
||||||
return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value());
|
return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort());
|
||||||
} else if (foreign instanceof StringBinaryTag) {
|
} else if (foreign instanceof LinStringTag stringTag) {
|
||||||
return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value());
|
return net.minecraft.nbt.StringTag.valueOf(stringTag.value());
|
||||||
} else if (foreign instanceof EndBinaryTag) {
|
} else if (foreign instanceof LinEndTag) {
|
||||||
return net.minecraft.nbt.EndTag.INSTANCE;
|
return net.minecraft.nbt.EndTag.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
||||||
@ -1021,7 +1082,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SpigotWatchdog implements Watchdog {
|
private class SpigotWatchdog implements Watchdog {
|
||||||
|
|
||||||
private final Field instanceField;
|
private final Field instanceField;
|
||||||
private final Field lastTickField;
|
private final Field lastTickField;
|
||||||
|
|
||||||
@ -1046,18 +1106,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
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 static class MojangWatchdog implements Watchdog {
|
||||||
|
|
||||||
private final DedicatedServer server;
|
private final DedicatedServer server;
|
||||||
private final Field tickField;
|
private final Field tickField;
|
||||||
|
|
||||||
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
Field tickField = MinecraftServer.class.getDeclaredField(
|
Field tickField = MinecraftServer.class.getDeclaredField(
|
||||||
Refraction.pickName("nextTickTime", "ah")
|
Refraction.pickName("nextTickTime", "ag")
|
||||||
);
|
);
|
||||||
if (tickField.getType() != long.class) {
|
if (tickField.getType() != long.class) {
|
||||||
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
||||||
@ -1073,21 +1131,15 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NoOpWorldLoadListener implements ChunkProgressListener {
|
private static class NoOpWorldLoadListener implements ChunkProgressListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
public void updateSpawnPos(ChunkPos spawnPos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChange(
|
public void onStatusChange(ChunkPos pos, @org.jetbrains.annotations.Nullable ChunkStatus status) {
|
||||||
final ChunkPos pos,
|
|
||||||
@org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1099,5 +1151,4 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,6 @@ import com.mojang.datafixers.DataFixer;
|
|||||||
import com.mojang.datafixers.DataFixerBuilder;
|
import com.mojang.datafixers.DataFixerBuilder;
|
||||||
import com.mojang.datafixers.schemas.Schema;
|
import com.mojang.datafixers.schemas.Schema;
|
||||||
import com.mojang.serialization.Dynamic;
|
import com.mojang.serialization.Dynamic;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R4.PaperweightAdapter;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.NbtOps;
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.nbt.StringTag;
|
import net.minecraft.nbt.StringTag;
|
||||||
@ -51,7 +49,9 @@ import net.minecraft.util.datafix.fixes.References;
|
|||||||
import net.minecraft.world.item.DyeColor;
|
import net.minecraft.world.item.DyeColor;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
@ -65,7 +65,6 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
* Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2)
|
||||||
@ -81,16 +80,15 @@ import javax.annotation.Nullable;
|
|||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
||||||
|
|
||||||
//FAWE start - BinaryTag
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
public <T> T fixUp(FixType<T> type, T original, int srcVer) {
|
||||||
if (type == FixTypes.CHUNK) {
|
if (type == FixTypes.CHUNK) {
|
||||||
return (T) fixChunk((CompoundBinaryTag) original, srcVer);
|
return (T) fixChunk((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_ENTITY) {
|
} else if (type == FixTypes.BLOCK_ENTITY) {
|
||||||
return (T) fixBlockEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixBlockEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.ENTITY) {
|
} else if (type == FixTypes.ENTITY) {
|
||||||
return (T) fixEntity((CompoundBinaryTag) original, srcVer);
|
return (T) fixEntity((LinCompoundTag) original, srcVer);
|
||||||
} else if (type == FixTypes.BLOCK_STATE) {
|
} else if (type == FixTypes.BLOCK_STATE) {
|
||||||
return (T) fixBlockState((String) original, srcVer);
|
return (T) fixBlockState((String) original, srcVer);
|
||||||
} else if (type == FixTypes.ITEM_TYPE) {
|
} else if (type == FixTypes.ITEM_TYPE) {
|
||||||
@ -101,24 +99,23 @@ public class PaperweightDataConverters extends DataFixerBuilder implements com.s
|
|||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixChunk(CompoundBinaryTag originalChunk, int srcVer) {
|
private LinCompoundTag fixChunk(LinCompoundTag originalChunk, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(originalChunk);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(originalChunk);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.CHUNK, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixBlockEntity(CompoundBinaryTag origTileEnt, int srcVer) {
|
private LinCompoundTag fixBlockEntity(LinCompoundTag origTileEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origTileEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origTileEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.BLOCK_ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundBinaryTag fixEntity(CompoundBinaryTag origEnt, int srcVer) {
|
private LinCompoundTag fixEntity(LinCompoundTag origEnt, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeBinary(origEnt);
|
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(origEnt);
|
||||||
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
net.minecraft.nbt.CompoundTag fixed = convert(LegacyType.ENTITY, tag, srcVer);
|
||||||
return (CompoundBinaryTag) adapter.toNativeBinary(fixed);
|
return (LinCompoundTag) adapter.toNativeLin(fixed);
|
||||||
}
|
}
|
||||||
//FAWE end
|
|
||||||
|
|
||||||
private String fixBlockState(String blockState, int srcVer) {
|
private String fixBlockState(String blockState, int srcVer) {
|
||||||
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
||||||
|
@ -24,20 +24,22 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Objects;
|
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 UPDATE = 1;
|
||||||
@ -101,9 +103,16 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
|
public boolean updateTileEntity(final BlockPos position, final LinCompoundTag tag) {
|
||||||
|
// We will assume that the tile entity was created for us
|
||||||
|
BlockEntity tileEntity = getWorld().getBlockEntity(position);
|
||||||
|
if (tileEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Tag nativeTag = adapter.fromNativeLin(tag);
|
||||||
|
PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
||||||
@ -144,7 +153,12 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure why neighborChanged is deprecated
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
ServerLevel world = getWorld();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
||||||
world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false);
|
world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false);
|
||||||
}
|
}
|
||||||
@ -152,8 +166,6 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
@Override
|
@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();
|
ServerLevel world = getWorld();
|
||||||
// a == updateNeighbors
|
|
||||||
// b == updateDiagonalNeighbors
|
|
||||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||||
CraftWorld craftWorld = world.getWorld();
|
CraftWorld craftWorld = world.getWorld();
|
||||||
@ -176,5 +188,4 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
public void flush() {
|
public void flush() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,6 @@ import com.sk89q.worldedit.util.SideEffect;
|
|||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.concurrency.LazyReference;
|
import com.sk89q.worldedit.util.concurrency.LazyReference;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -88,6 +85,9 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
|||||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -286,7 +286,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess());
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess());
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,14 +314,14 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
||||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
Supplier<LinCompoundTag> saveTag = () -> {
|
||||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||||
readEntityIntoTag(mcEntity, minecraftTag);
|
readEntityIntoTag(mcEntity, minecraftTag);
|
||||||
//add Id for AbstractChangeSet to work
|
//add Id for AbstractChangeSet to work
|
||||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag);
|
||||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
final Map<String, LinTag<?>> tags = NbtUtils.getLinCompoundTagValues(tag);
|
||||||
tags.put("Id", StringBinaryTag.of(id));
|
tags.put("Id", LinStringTag.of(id));
|
||||||
return CompoundBinaryTag.from(tags);
|
return LinCompoundTag.of(tags);
|
||||||
};
|
};
|
||||||
return new LazyBaseEntity(type, saveTag);
|
return new LazyBaseEntity(type, saveTag);
|
||||||
} else {
|
} else {
|
||||||
@ -538,7 +538,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
).getOrThrow();
|
).getOrThrow();
|
||||||
return new BaseItemStack(
|
return new BaseItemStack(
|
||||||
BukkitAdapter.asItemType(itemStack.getType()),
|
BukkitAdapter.asItemType(itemStack.getType()),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)),
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)),
|
||||||
itemStack.getAmount()
|
itemStack.getAmount()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,14 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
@ -25,6 +24,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
|||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -133,14 +133,14 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos blockPos, LinCompoundTag tag) {
|
||||||
// We will assume that the tile entity was created for us,
|
// We will assume that the tile entity was created for us,
|
||||||
// though we do not do this on the other versions
|
// though we do not do this on the other versions
|
||||||
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
||||||
if (blockEntity == null) {
|
if (blockEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeLin(tag);
|
||||||
blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess());
|
blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -218,6 +218,12 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
Level world = getLevel();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockStateChange(
|
public void onBlockStateChange(
|
||||||
BlockPos blockPos,
|
BlockPos blockPos,
|
||||||
|
@ -738,7 +738,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
final CompoundTag nativeTag = iterator.next();
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag<?, ?>> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
@ -140,7 +140,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingFluidCount.setAccessible(true);
|
fieldTickingFluidCount.setAccessible(true);
|
||||||
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
|
||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
fieldBiomes = LevelChunkSection.class.getDeclaredField(Refraction.pickName("biomes", "i"));
|
Field tmpFieldBiomes;
|
||||||
|
try {
|
||||||
|
// Seems it's sometimes biomes and sometimes "i". Idk this is just easier than having to try to deal with it
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes"); // apparently unobf
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i"); // apparently obf
|
||||||
|
}
|
||||||
|
fieldBiomes = tmpFieldBiomes;
|
||||||
fieldBiomes.setAccessible(true);
|
fieldBiomes.setAccessible(true);
|
||||||
|
|
||||||
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
|
||||||
@ -353,7 +360,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
MinecraftServer.getServer().execute(() -> {
|
MinecraftServer.getServer().execute(() -> {
|
||||||
ClientboundLevelChunkWithLightPacket packet;
|
ClientboundLevelChunkWithLightPacket packet;
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
synchronized (chunk) {
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
nmsWorld.getChunkSource().getLightEngine(),
|
||||||
@ -361,9 +367,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null,
|
null,
|
||||||
false // last false is to not bother with x-ray
|
false // last false is to not bother with x-ray
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
synchronized (chunk) {
|
|
||||||
// deprecated on paper - deprecation suppressed
|
// deprecated on paper - deprecation suppressed
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
@ -372,7 +376,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag;
|
|||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.nbt.NumericTag;
|
import net.minecraft.nbt.NumericTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, Tag> getValue() {
|
public Map<String, Tag<?, ?>> getValue() {
|
||||||
if (compoundTag == null) {
|
if (compoundTag == null) {
|
||||||
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
||||||
}
|
}
|
||||||
@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundBinaryTag asBinaryTag() {
|
public LinCompoundTag toLinTag() {
|
||||||
getValue();
|
getValue();
|
||||||
return compoundTag.asBinaryTag();
|
return compoundTag.toLinTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(String key) {
|
public boolean containsKey(String key) {
|
||||||
@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<Tag> getList(String key) {
|
public List<? extends Tag<?, ?>> getList(String key) {
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
||||||
ArrayList<Tag> list = new ArrayList<>();
|
ArrayList<Tag<?, ?>> list = new ArrayList<>();
|
||||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
for (net.minecraft.nbt.Tag elem : nbtList) {
|
||||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
||||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
||||||
@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
|
public <T extends Tag<?, ?>> List<T> getList(String key, Class<T> listType) {
|
||||||
ListTag listTag = getListTag(key);
|
ListTag listTag = getListTag(key);
|
||||||
if (listTag.getType().equals(listType)) {
|
if (listTag.getType().equals(listType)) {
|
||||||
return (List<T>) listTag.getValue();
|
return (List<T>) listTag.getValue();
|
||||||
|
@ -11,7 +11,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.19.4-R0.1-SNAPSHOT
|
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/
|
||||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.19.4-R0.1-20230608.201059-104")
|
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.21.1-R0.1-20240811.223934-9")
|
||||||
compileOnly(libs.paperlib)
|
compileOnly(libs.paperlib)
|
||||||
}
|
}
|
@ -17,24 +17,22 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.Lifecycle;
|
import com.mojang.serialization.Lifecycle;
|
||||||
import com.sk89q.jnbt.NBTConstants;
|
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.blocks.BaseItem;
|
import com.sk89q.worldedit.blocks.BaseItem;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.PaperweightPlatformAdapter;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.extension.platform.Watchdog;
|
import com.sk89q.worldedit.extension.platform.Watchdog;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
@ -55,22 +53,9 @@ import com.sk89q.worldedit.util.concurrency.LazyReference;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ByteBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.DoubleBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.EndBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.FloatBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.IntBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ListBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.LongBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.ShortBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeCategory;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -78,21 +63,28 @@ import com.sk89q.worldedit.world.block.BlockState;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||||
import com.sk89q.worldedit.world.item.ItemType;
|
import com.sk89q.worldedit.world.item.ItemType;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderSet;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
import net.minecraft.server.level.ChunkResult;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.util.thread.BlockableEventLoop;
|
import net.minecraft.util.thread.BlockableEventLoop;
|
||||||
import net.minecraft.world.Clearable;
|
import net.minecraft.world.Clearable;
|
||||||
@ -113,8 +105,8 @@ import net.minecraft.world.level.block.entity.StructureBlockEntity;
|
|||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
import net.minecraft.world.level.dimension.LevelStem;
|
import net.minecraft.world.level.dimension.LevelStem;
|
||||||
import net.minecraft.world.level.levelgen.WorldOptions;
|
import net.minecraft.world.level.levelgen.WorldOptions;
|
||||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||||
@ -123,18 +115,35 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
import org.bukkit.World.Environment;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity;
|
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers;
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.enginehub.linbus.common.LinTagId;
|
||||||
|
import org.enginehub.linbus.tree.LinByteArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinByteTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinDoubleTag;
|
||||||
|
import org.enginehub.linbus.tree.LinEndTag;
|
||||||
|
import org.enginehub.linbus.tree.LinFloatTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinIntTag;
|
||||||
|
import org.enginehub.linbus.tree.LinListTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongArrayTag;
|
||||||
|
import org.enginehub.linbus.tree.LinLongTag;
|
||||||
|
import org.enginehub.linbus.tree.LinShortTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTagType;
|
||||||
import org.spigotmc.SpigotConfig;
|
import org.spigotmc.SpigotConfig;
|
||||||
import org.spigotmc.WatchdogThread;
|
import org.spigotmc.WatchdogThread;
|
||||||
|
|
||||||
@ -146,6 +155,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -166,13 +176,16 @@ import static com.google.common.base.Preconditions.checkState;
|
|||||||
|
|
||||||
public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> {
|
public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> {
|
||||||
|
|
||||||
private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName());
|
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
|
||||||
|
|
||||||
private final Field serverWorldsField;
|
private final Field serverWorldsField;
|
||||||
private final Method getChunkFutureMethod;
|
private final Method getChunkFutureMethod;
|
||||||
private final Field chunkProviderExecutorField;
|
private final Field chunkProviderExecutorField;
|
||||||
|
private final PaperweightDataConverters dataFixer;
|
||||||
private final Watchdog watchdog;
|
private final Watchdog watchdog;
|
||||||
|
|
||||||
|
private static final RandomSource random = RandomSource.create();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that may break between versions of Minecraft
|
// Code that may break between versions of Minecraft
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -182,25 +195,25 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
CraftServer.class.cast(Bukkit.getServer());
|
CraftServer.class.cast(Bukkit.getServer());
|
||||||
|
|
||||||
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
|
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
|
||||||
if (dataVersion != 3463 && dataVersion != 3465) {
|
if (dataVersion != 3953 && dataVersion != 3955) {
|
||||||
throw new UnsupportedClassVersionError("Not 1.20(.1)!");
|
throw new UnsupportedClassVersionError("Not 1.21(.1)!");
|
||||||
}
|
}
|
||||||
|
|
||||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||||
serverWorldsField.setAccessible(true);
|
serverWorldsField.setAccessible(true);
|
||||||
|
|
||||||
getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod(
|
getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod(
|
||||||
Refraction.pickName("getChunkFutureMainThread", "c"),
|
StaticRefraction.GET_CHUNK_FUTURE_MAIN_THREAD,
|
||||||
int.class, int.class, ChunkStatus.class, boolean.class
|
int.class, int.class, ChunkStatus.class, boolean.class
|
||||||
);
|
);
|
||||||
getChunkFutureMethod.setAccessible(true);
|
getChunkFutureMethod.setAccessible(true);
|
||||||
|
|
||||||
chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField(
|
chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField(
|
||||||
Refraction.pickName("mainThreadProcessor", "g")
|
StaticRefraction.MAIN_THREAD_PROCESSOR
|
||||||
);
|
);
|
||||||
chunkProviderExecutorField.setAccessible(true);
|
chunkProviderExecutorField.setAccessible(true);
|
||||||
|
|
||||||
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized();
|
this.dataFixer = new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this);
|
||||||
|
|
||||||
Watchdog watchdog;
|
Watchdog watchdog;
|
||||||
try {
|
try {
|
||||||
@ -217,14 +230,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Class.forName("org.spigotmc.SpigotConfig");
|
Class.forName("org.spigotmc.SpigotConfig");
|
||||||
SpigotConfig.config.set("world-settings.faweregentempworld.verbose", false);
|
SpigotConfig.config.set("world-settings.worldeditregentempworld.verbose", false);
|
||||||
} catch (ClassNotFoundException ignored) {
|
} catch (ClassNotFoundException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataFixer getDataFixer() {
|
public DataFixer getDataFixer() {
|
||||||
return PaperweightDataConverters.INSTANCE;
|
return this.dataFixer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,7 +247,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @param tag the tag
|
* @param tag the tag
|
||||||
*/
|
*/
|
||||||
static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) {
|
static void readTagIntoTileEntity(net.minecraft.nbt.CompoundTag tag, BlockEntity tileEntity) {
|
||||||
tileEntity.load(tag);
|
tileEntity.loadWithComponents(tag, MinecraftServer.getServer().registryAccess());
|
||||||
tileEntity.setChanged();
|
tileEntity.setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,13 +290,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @param tag the tag
|
* @param tag the tag
|
||||||
*/
|
*/
|
||||||
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) {
|
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) {
|
||||||
//FAWE start - avoid villager async catcher
|
entity.save(tag);
|
||||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, tag);
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Block getBlockFromType(BlockType blockType) {
|
private static Block getBlockFromType(BlockType blockType) {
|
||||||
|
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +318,29 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
|
||||||
|
int internalId = Block.getId(blockState);
|
||||||
|
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||||
|
if (state == null) {
|
||||||
|
state = BukkitAdapter.adapt(CraftBlockData.createData(blockState));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiomeType adapt(Biome biome) {
|
||||||
|
var mcBiome = ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getKey(biome);
|
||||||
|
if (mcBiome == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return BiomeType.REGISTRY.get(mcBiome.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
|
||||||
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
|
return Block.stateById(internalId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(Location location) {
|
public BlockState getBlock(Location location) {
|
||||||
checkNotNull(location);
|
checkNotNull(location);
|
||||||
@ -321,14 +354,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||||
int internalId = Block.getId(blockData);
|
return adapt(blockData);
|
||||||
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
|
||||||
if (state == null) {
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -347,22 +373,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
// Read the NBT data
|
// Read the NBT data
|
||||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = te.saveWithId(MinecraftServer.getServer().registryAccess());
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.toBaseBlock();
|
return state.toBaseBlock();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
@Override
|
|
||||||
public boolean hasCustomBiomeSupport() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
|
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
|
||||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||||
|
|
||||||
/* @Override
|
@Override
|
||||||
public BiomeType getBiome(Location location) {
|
public BiomeType getBiome(Location location) {
|
||||||
checkNotNull(location);
|
checkNotNull(location);
|
||||||
|
|
||||||
@ -389,14 +410,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
|
|
||||||
final ServerLevel handle = craftWorld.getHandle();
|
final ServerLevel handle = craftWorld.getHandle();
|
||||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||||
chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, new ResourceLocation(b.getId())))));
|
chunk.setBiome(x >> 2, y >> 2, z >> 2, biomeTypeToNMSCache.computeIfAbsent(biome, b -> ((CraftServer) Bukkit.getServer()).getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(ResourceKey.create(Registries.BIOME, ResourceLocation.parse(b.id())))));
|
||||||
chunk.setUnsaved(true);
|
chunk.setUnsaved(true);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(World world) {
|
||||||
return new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1.PaperweightWorldNativeAccess(this,
|
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||||
new WeakReference<>(((CraftWorld) world).getHandle()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static net.minecraft.core.Direction adapt(Direction face) {
|
private static net.minecraft.core.Direction adapt(Direction face) {
|
||||||
@ -466,8 +486,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
readEntityIntoTag(mcEntity, tag);
|
readEntityIntoTag(mcEntity, tag);
|
||||||
return new BaseEntity(
|
return new BaseEntity(
|
||||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
EntityTypes.get(id),
|
||||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,21 +500,26 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||||
ServerLevel worldServer = craftWorld.getHandle();
|
ServerLevel worldServer = craftWorld.getHandle();
|
||||||
|
|
||||||
Entity createdEntity = createEntityFromId(state.getType().id(), craftWorld.getHandle());
|
String entityId = state.getType().id();
|
||||||
|
|
||||||
|
LinCompoundTag nativeTag = state.getNbt();
|
||||||
|
net.minecraft.nbt.CompoundTag tag;
|
||||||
|
if (nativeTag != null) {
|
||||||
|
tag = (net.minecraft.nbt.CompoundTag) fromNativeLin(nativeTag);
|
||||||
|
removeUnwantedEntityTagsRecursively(tag);
|
||||||
|
} else {
|
||||||
|
tag = new net.minecraft.nbt.CompoundTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.putString("id", entityId);
|
||||||
|
|
||||||
|
Entity createdEntity = EntityType.loadEntityRecursive(tag, craftWorld.getHandle(), (loadedEntity) -> {
|
||||||
|
loadedEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||||
|
return loadedEntity;
|
||||||
|
});
|
||||||
|
|
||||||
if (createdEntity != null) {
|
if (createdEntity != null) {
|
||||||
CompoundBinaryTag nativeTag = state.getNbt();
|
worldServer.addFreshEntityWithPassengers(createdEntity, SpawnReason.CUSTOM);
|
||||||
if (nativeTag != null) {
|
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(nativeTag);
|
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
|
||||||
tag.remove(name);
|
|
||||||
}
|
|
||||||
readTagIntoEntity(tag, createdEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
createdEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
||||||
|
|
||||||
worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM);
|
|
||||||
return createdEntity.getBukkitEntity();
|
return createdEntity.getBukkitEntity();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -508,8 +533,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive
|
// Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive
|
||||||
if (tag.contains("Passengers", NBTConstants.TYPE_LIST)) {
|
if (tag.contains("Passengers", LinTagId.LIST.id())) {
|
||||||
net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", NBTConstants.TYPE_COMPOUND);
|
net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", LinTagId.COMPOUND.id());
|
||||||
|
|
||||||
for (int i = 0; i < nbttaglist.size(); ++i) {
|
for (int i = 0; i < nbttaglist.size(); ++i) {
|
||||||
removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i));
|
removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i));
|
||||||
@ -532,22 +557,40 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return TranslatableComponent.of(CraftItemStack.asNMSCopy(BukkitAdapter.adapt(itemStack)).getDescriptionId());
|
return TranslatableComponent.of(CraftItemStack.asNMSCopy(BukkitAdapter.adapt(itemStack)).getDescriptionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
|
private static final LoadingCache<net.minecraft.world.level.block.state.properties.Property, Property<?>> PROPERTY_CACHE = CacheBuilder
|
||||||
|
.newBuilder()
|
||||||
|
.build(new CacheLoader<>() {
|
||||||
@Override
|
@Override
|
||||||
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) throws Exception {
|
public Property<?> load(net.minecraft.world.level.block.state.properties.Property state) {
|
||||||
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
|
||||||
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new BooleanProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else if (state instanceof DirectionProperty) {
|
} else if (state instanceof DirectionProperty) {
|
||||||
return new DirectionalProperty(state.getName(),
|
return new DirectionalProperty(
|
||||||
(List<Direction>) state.getPossibleValues().stream().map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase(Locale.ROOT))).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<Direction>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> Direction.valueOf(((StringRepresentable) e)
|
||||||
|
.getSerializedName()
|
||||||
|
.toUpperCase(Locale.ROOT)))
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
|
||||||
return new EnumProperty(state.getName(),
|
return new EnumProperty(
|
||||||
(List<String>) state.getPossibleValues().stream().map(e -> ((StringRepresentable) e).getSerializedName()).collect(Collectors.toList()));
|
state.getName(),
|
||||||
|
new ArrayList<>((List<String>) state
|
||||||
|
.getPossibleValues()
|
||||||
|
.stream()
|
||||||
|
.map(e -> ((StringRepresentable) e).getSerializedName())
|
||||||
|
.toList())
|
||||||
|
);
|
||||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
||||||
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
|
throw new IllegalArgumentException("WorldEdit needs an update to support " + state
|
||||||
|
.getClass()
|
||||||
|
.getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -567,27 +610,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
public void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) {
|
||||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
var structureBlock = new StructureBlockEntity(
|
||||||
new StructureBlockEntity(
|
|
||||||
new BlockPos(pos.x(), pos.y(), pos.z()),
|
new BlockPos(pos.x(), pos.y(), pos.z()),
|
||||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
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) fromNativeLin(nbtData)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundTag nbtData) {
|
|
||||||
((CraftPlayer) player).getHandle().connection.send(ClientboundBlockEntityDataPacket.create(
|
|
||||||
new StructureBlockEntity(
|
|
||||||
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()),
|
|
||||||
Blocks.STRUCTURE_BLOCK.defaultBlockState()
|
|
||||||
),
|
|
||||||
__ -> (net.minecraft.nbt.CompoundTag) fromNative(nbtData)
|
|
||||||
));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendFakeOP(Player player) {
|
public void sendFakeOP(Player player) {
|
||||||
((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
|
((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
|
||||||
@ -595,34 +629,54 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For serializing and deserializing components.
|
||||||
|
*/
|
||||||
|
private static final Codec<DataComponentPatch> COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf(
|
||||||
|
"components", DataComponentPatch.EMPTY
|
||||||
|
).codec();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
|
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
||||||
|
var registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
ItemStack stack = new ItemStack(
|
ItemStack stack = new ItemStack(
|
||||||
DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().id())),
|
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())),
|
||||||
item.getAmount()
|
baseItemStack.getAmount()
|
||||||
);
|
);
|
||||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())));
|
LinCompoundTag nbt = baseItemStack.getNbt();
|
||||||
|
if (nbt != null) {
|
||||||
|
DataComponentPatch componentPatch = COMPONENTS_CODEC.parse(
|
||||||
|
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||||
|
fromNativeLin(nbt)
|
||||||
|
).getOrThrow();
|
||||||
|
stack.applyComponents(componentPatch);
|
||||||
|
}
|
||||||
return CraftItemStack.asCraftMirror(stack);
|
return CraftItemStack.asCraftMirror(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
|
var registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
CompoundTag tag = (CompoundTag) COMPONENTS_CODEC.encodeStart(
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||||
return weStack;
|
nmsStack.getComponentsPatch()
|
||||||
|
).getOrThrow();
|
||||||
|
return new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)), itemStack.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LoadingCache<ServerLevel, PaperweightFakePlayer> fakePlayers
|
private final LoadingCache<ServerLevel, PaperweightFakePlayer> fakePlayers
|
||||||
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
|
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(PaperweightFakePlayer::new));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean simulateItemUse(org.bukkit.World world, BlockVector3 position, BaseItem item, Direction face) {
|
public boolean simulateItemUse(World world, BlockVector3 position, BaseItem item, Direction face) {
|
||||||
CraftWorld craftWorld = (CraftWorld) world;
|
CraftWorld craftWorld = (CraftWorld) world;
|
||||||
ServerLevel worldServer = craftWorld.getHandle();
|
ServerLevel worldServer = craftWorld.getHandle();
|
||||||
ItemStack stack = CraftItemStack.asNMSCopy(BukkitAdapter.adapt(item instanceof BaseItemStack
|
ItemStack stack = CraftItemStack.asNMSCopy(adapt(
|
||||||
? ((BaseItemStack) item) : new BaseItemStack(item.getType(), item.getNbtData(), 1)));
|
item instanceof BaseItemStack
|
||||||
stack.setTag((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()));
|
? ((BaseItemStack) item)
|
||||||
|
: new BaseItemStack(item.getType(), item.getNbtReference(), 1)
|
||||||
|
));
|
||||||
|
|
||||||
PaperweightFakePlayer fakePlayer;
|
PaperweightFakePlayer fakePlayer;
|
||||||
try {
|
try {
|
||||||
@ -641,7 +695,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
|
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
|
||||||
InteractionResult result = stack.useOn(context);
|
InteractionResult result = stack.useOn(context);
|
||||||
if (result != InteractionResult.SUCCESS) {
|
if (result != InteractionResult.SUCCESS) {
|
||||||
if (worldServer.getBlockState(blockPos).use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) {
|
if (worldServer.getBlockState(blockPos).useItemOn(stack, worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) {
|
||||||
result = InteractionResult.SUCCESS;
|
result = InteractionResult.SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult();
|
result = stack.getItem().use(worldServer, fakePlayer, InteractionHand.MAIN_HAND).getResult();
|
||||||
@ -652,14 +706,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) {
|
public boolean canPlaceAt(World world, BlockVector3 position, BlockState blockState) {
|
||||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||||
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
||||||
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.x(), position.y(), position.z()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
public boolean regenerate(World bukkitWorld, Region region, Extent extent, RegenOptions options) {
|
||||||
try {
|
try {
|
||||||
doRegen(bukkitWorld, region, extent, options);
|
doRegen(bukkitWorld, region, extent, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -669,14 +723,14 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doRegen(org.bukkit.World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
private void doRegen(World bukkitWorld, Region region, Extent extent, RegenOptions options) throws Exception {
|
||||||
Environment env = bukkitWorld.getEnvironment();
|
Environment env = bukkitWorld.getEnvironment();
|
||||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||||
|
|
||||||
Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
|
Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
|
||||||
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
|
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
|
||||||
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
|
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
|
||||||
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) {
|
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("worldeditregentempworld", worldDimKey)) {
|
||||||
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
|
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
|
||||||
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
|
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
|
||||||
.getWorldData().overworldData();
|
.getWorldData().overworldData();
|
||||||
@ -688,7 +742,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
: originalOpts;
|
: originalOpts;
|
||||||
|
|
||||||
LevelSettings newWorldSettings = new LevelSettings(
|
LevelSettings newWorldSettings = new LevelSettings(
|
||||||
"faweregentempworld",
|
"worldeditregentempworld",
|
||||||
levelProperties.settings.gameType(),
|
levelProperties.settings.gameType(),
|
||||||
levelProperties.settings.hardcore(),
|
levelProperties.settings.hardcore(),
|
||||||
levelProperties.settings.difficulty(),
|
levelProperties.settings.difficulty(),
|
||||||
@ -697,6 +751,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
levelProperties.settings.getDataConfiguration()
|
levelProperties.settings.getDataConfiguration()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
||||||
levelProperties.isFlatWorld()
|
levelProperties.isFlatWorld()
|
||||||
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
||||||
@ -733,8 +788,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
Map<String, World> map = (Map<String, World>) serverWorldsField.get(Bukkit.getServer());
|
||||||
map.remove("faweregentempworld");
|
map.remove("worldeditregentempworld");
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
SafeFiles.tryHardToDeleteDir(tempDir);
|
SafeFiles.tryHardToDeleteDir(tempDir);
|
||||||
@ -784,8 +839,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
Objects.requireNonNull(state);
|
Objects.requireNonNull(state);
|
||||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverWorld.registryAccess());
|
||||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
state = state.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)));
|
||||||
}
|
}
|
||||||
extent.setBlock(vec, state.toBaseBlock());
|
extent.setBlock(vec, state.toBaseBlock());
|
||||||
if (options.shouldRegenBiomes()) {
|
if (options.shouldRegenBiomes()) {
|
||||||
@ -807,9 +862,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
try {
|
try {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
chunkLoadings.add(
|
chunkLoadings.add(
|
||||||
((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>)
|
((CompletableFuture<ChunkResult<ChunkAccess>>)
|
||||||
getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true))
|
getChunkFutureMethod.invoke(chunkManager, chunk.x(), chunk.z(), ChunkStatus.FEATURES, true))
|
||||||
.thenApply(either -> either.left().orElse(null))
|
.thenApply(either -> either.orElse(null))
|
||||||
);
|
);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new IllegalStateException("Couldn't load chunk for regen.", e);
|
throw new IllegalStateException("Couldn't load chunk for regen.", e);
|
||||||
@ -845,7 +900,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearContainerBlockContents(org.bukkit.World world, BlockVector3 pt) {
|
public boolean clearContainerBlockContents(World world, BlockVector3 pt) {
|
||||||
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
BlockEntity entity = originalWorld.getBlockEntity(new BlockPos(pt.x(), pt.y(), pt.z()));
|
||||||
@ -856,7 +911,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
@Override
|
||||||
public void initializeRegistries() {
|
public void initializeRegistries() {
|
||||||
DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
DedicatedServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||||
// Biomes
|
// Biomes
|
||||||
@ -865,7 +920,35 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*
|
|
||||||
|
// BiomeCategories
|
||||||
|
Registry<Biome> biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
biomeRegistry.getTagNames().forEach(tagKey -> {
|
||||||
|
String key = tagKey.location().toString();
|
||||||
|
if (BiomeCategory.REGISTRY.get(key) == null) {
|
||||||
|
BiomeCategory.REGISTRY.register(key, new BiomeCategory(
|
||||||
|
key,
|
||||||
|
() -> biomeRegistry.getTag(tagKey)
|
||||||
|
.stream()
|
||||||
|
.flatMap(HolderSet.Named::stream)
|
||||||
|
.map(Holder::value)
|
||||||
|
.map(this::adapt)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
|
List<ChunkAccess> nativeChunks = chunks instanceof Collection<BlockVector2> chunkCollection ? Lists.newArrayListWithCapacity(chunkCollection.size()) : Lists.newArrayList();
|
||||||
|
for (BlockVector2 chunk : chunks) {
|
||||||
|
nativeChunks.add(originalWorld.getChunk(chunk.x(), chunk.z(), ChunkStatus.BIOMES, false));
|
||||||
|
}
|
||||||
|
originalWorld.getChunkSource().chunkMap.resendBiomesForChunks(nativeChunks);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that is less likely to break
|
// Code that is less likely to break
|
||||||
@ -879,51 +962,49 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return native WorldEdit NBT structure
|
* @return native WorldEdit NBT structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
public LinTag<?> toNativeLin(net.minecraft.nbt.Tag foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
if (foreign instanceof net.minecraft.nbt.CompoundTag) {
|
||||||
Map<String, BinaryTag> values = new HashMap<>();
|
Map<String, LinTag<?>> values = new HashMap<>();
|
||||||
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
Set<String> foreignKeys = ((net.minecraft.nbt.CompoundTag) foreign).getAllKeys();
|
||||||
|
|
||||||
for (String str : foreignKeys) {
|
for (String str : foreignKeys) {
|
||||||
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
net.minecraft.nbt.Tag base = ((net.minecraft.nbt.CompoundTag) foreign).get(str);
|
||||||
values.put(str, toNativeBinary(base));
|
values.put(str, toNativeLin(base));
|
||||||
}
|
}
|
||||||
return CompoundBinaryTag.from(values);
|
return LinCompoundTag.of(values);
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteTag) {
|
||||||
return ByteBinaryTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
return LinByteTag.of(((net.minecraft.nbt.ByteTag) foreign).getAsByte());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ByteArrayTag) {
|
||||||
return ByteArrayBinaryTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
return LinByteArrayTag.of(((net.minecraft.nbt.ByteArrayTag) foreign).getAsByteArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
} else if (foreign instanceof net.minecraft.nbt.DoubleTag) {
|
||||||
return DoubleBinaryTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
return LinDoubleTag.of(((net.minecraft.nbt.DoubleTag) foreign).getAsDouble());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
} else if (foreign instanceof net.minecraft.nbt.FloatTag) {
|
||||||
return FloatBinaryTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
return LinFloatTag.of(((net.minecraft.nbt.FloatTag) foreign).getAsFloat());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntTag) {
|
||||||
return IntBinaryTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
return LinIntTag.of(((net.minecraft.nbt.IntTag) foreign).getAsInt());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.IntArrayTag) {
|
||||||
return IntArrayBinaryTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
return LinIntArrayTag.of(((net.minecraft.nbt.IntArrayTag) foreign).getAsIntArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongArrayTag) {
|
||||||
return LongArrayBinaryTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
return LinLongArrayTag.of(((net.minecraft.nbt.LongArrayTag) foreign).getAsLongArray());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ListTag) {
|
||||||
try {
|
try {
|
||||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
return toNativeLinList((net.minecraft.nbt.ListTag) foreign);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||||
return ListBinaryTag.empty();
|
|
||||||
}
|
}
|
||||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||||
return LongBinaryTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
return LinLongTag.of(((net.minecraft.nbt.LongTag) foreign).getAsLong());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
} else if (foreign instanceof net.minecraft.nbt.ShortTag) {
|
||||||
return ShortBinaryTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
return LinShortTag.of(((net.minecraft.nbt.ShortTag) foreign).getAsShort());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
} else if (foreign instanceof net.minecraft.nbt.StringTag) {
|
||||||
return StringBinaryTag.of(foreign.getAsString());
|
return LinStringTag.of(foreign.getAsString());
|
||||||
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
} else if (foreign instanceof net.minecraft.nbt.EndTag) {
|
||||||
return EndBinaryTag.get();
|
return LinEndTag.instance();
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -934,14 +1015,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @throws SecurityException on error
|
* @throws SecurityException on error
|
||||||
* @throws IllegalArgumentException on error
|
* @throws IllegalArgumentException on error
|
||||||
*/
|
*/
|
||||||
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
private LinListTag<?> toNativeLinList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
||||||
ListBinaryTag.Builder values = ListBinaryTag.builder();
|
LinListTag.Builder<LinTag<?>> builder = LinListTag.builder(
|
||||||
|
LinTagType.fromId(LinTagId.fromId(foreign.getElementType()))
|
||||||
|
);
|
||||||
|
|
||||||
for (net.minecraft.nbt.Tag tag : foreign) {
|
for (net.minecraft.nbt.Tag tag : foreign) {
|
||||||
values.add(toNativeBinary(tag));
|
builder.add(toNativeLin(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -951,44 +1034,43 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
* @return non-native structure
|
* @return non-native structure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.nbt.Tag fromNativeBinary(BinaryTag foreign) {
|
public net.minecraft.nbt.Tag fromNativeLin(LinTag<?> foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (foreign instanceof CompoundBinaryTag) {
|
if (foreign instanceof LinCompoundTag compoundTag) {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
for (String key : ((CompoundBinaryTag) foreign).keySet()) {
|
for (var entry : compoundTag.value().entrySet()) {
|
||||||
tag.put(key, fromNativeBinary(((CompoundBinaryTag) foreign).get(key)));
|
tag.put(entry.getKey(), fromNativeLin(entry.getValue()));
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof ByteBinaryTag) {
|
} else if (foreign instanceof LinByteTag byteTag) {
|
||||||
return net.minecraft.nbt.ByteTag.valueOf(((ByteBinaryTag) foreign).value());
|
return net.minecraft.nbt.ByteTag.valueOf(byteTag.valueAsByte());
|
||||||
} else if (foreign instanceof ByteArrayBinaryTag) {
|
} else if (foreign instanceof LinByteArrayTag byteArrayTag) {
|
||||||
return new net.minecraft.nbt.ByteArrayTag(((ByteArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.ByteArrayTag(byteArrayTag.value());
|
||||||
} else if (foreign instanceof DoubleBinaryTag) {
|
} else if (foreign instanceof LinDoubleTag doubleTag) {
|
||||||
return net.minecraft.nbt.DoubleTag.valueOf(((DoubleBinaryTag) foreign).value());
|
return net.minecraft.nbt.DoubleTag.valueOf(doubleTag.valueAsDouble());
|
||||||
} else if (foreign instanceof FloatBinaryTag) {
|
} else if (foreign instanceof LinFloatTag floatTag) {
|
||||||
return net.minecraft.nbt.FloatTag.valueOf(((FloatBinaryTag) foreign).value());
|
return net.minecraft.nbt.FloatTag.valueOf(floatTag.valueAsFloat());
|
||||||
} else if (foreign instanceof IntBinaryTag) {
|
} else if (foreign instanceof LinIntTag intTag) {
|
||||||
return net.minecraft.nbt.IntTag.valueOf(((IntBinaryTag) foreign).value());
|
return net.minecraft.nbt.IntTag.valueOf(intTag.valueAsInt());
|
||||||
} else if (foreign instanceof IntArrayBinaryTag) {
|
} else if (foreign instanceof LinIntArrayTag intArrayTag) {
|
||||||
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.IntArrayTag(intArrayTag.value());
|
||||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
} else if (foreign instanceof LinLongArrayTag longArrayTag) {
|
||||||
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
|
return new net.minecraft.nbt.LongArrayTag(longArrayTag.value());
|
||||||
} else if (foreign instanceof ListBinaryTag) {
|
} else if (foreign instanceof LinListTag<?> listTag) {
|
||||||
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
||||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
for (var t : listTag.value()) {
|
||||||
for (BinaryTag t : foreignList) {
|
tag.add(fromNativeLin(t));
|
||||||
tag.add(fromNativeBinary(t));
|
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (foreign instanceof LongBinaryTag) {
|
} else if (foreign instanceof LinLongTag longTag) {
|
||||||
return net.minecraft.nbt.LongTag.valueOf(((LongBinaryTag) foreign).value());
|
return net.minecraft.nbt.LongTag.valueOf(longTag.valueAsLong());
|
||||||
} else if (foreign instanceof ShortBinaryTag) {
|
} else if (foreign instanceof LinShortTag shortTag) {
|
||||||
return net.minecraft.nbt.ShortTag.valueOf(((ShortBinaryTag) foreign).value());
|
return net.minecraft.nbt.ShortTag.valueOf(shortTag.valueAsShort());
|
||||||
} else if (foreign instanceof StringBinaryTag) {
|
} else if (foreign instanceof LinStringTag stringTag) {
|
||||||
return net.minecraft.nbt.StringTag.valueOf(((StringBinaryTag) foreign).value());
|
return net.minecraft.nbt.StringTag.valueOf(stringTag.value());
|
||||||
} else if (foreign instanceof EndBinaryTag) {
|
} else if (foreign instanceof LinEndTag) {
|
||||||
return net.minecraft.nbt.EndTag.INSTANCE;
|
return net.minecraft.nbt.EndTag.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
||||||
@ -1027,7 +1109,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
WatchdogThread.tick();
|
WatchdogThread.tick();
|
||||||
}
|
}
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
LOGGER.log(Level.WARNING, "Failed to tick watchdog", e);
|
logger.log(Level.WARNING, "Failed to tick watchdog", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1038,9 +1120,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
|
|
||||||
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
Field tickField = MinecraftServer.class.getDeclaredField(
|
Field tickField = MinecraftServer.class.getDeclaredField(StaticRefraction.NEXT_TICK_TIME);
|
||||||
Refraction.pickName("nextTickTime", "ah")
|
|
||||||
);
|
|
||||||
if (tickField.getType() != long.class) {
|
if (tickField.getType() != long.class) {
|
||||||
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
|
||||||
}
|
}
|
||||||
@ -1074,8 +1154,5 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChunkRadius(int radius) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -17,20 +17,20 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
|
import net.minecraft.server.level.ClientInformation;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.stats.Stat;
|
import net.minecraft.stats.Stat;
|
||||||
import net.minecraft.world.MenuProvider;
|
import net.minecraft.world.MenuProvider;
|
||||||
import net.minecraft.world.damagesource.DamageSource;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.HumanoidArm;
|
||||||
|
import net.minecraft.world.entity.player.ChatVisiblity;
|
||||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
|
||||||
|
|
||||||
import java.util.OptionalInt;
|
import java.util.OptionalInt;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -38,9 +38,12 @@ import java.util.UUID;
|
|||||||
class PaperweightFakePlayer extends ServerPlayer {
|
class PaperweightFakePlayer extends ServerPlayer {
|
||||||
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]");
|
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]");
|
||||||
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
|
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
|
||||||
|
private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation(
|
||||||
|
"en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false
|
||||||
|
);
|
||||||
|
|
||||||
PaperweightFakePlayer(ServerLevel world) {
|
PaperweightFakePlayer(ServerLevel world) {
|
||||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
|
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,18 +59,13 @@ class PaperweightFakePlayer extends ServerPlayer {
|
|||||||
public void die(DamageSource damagesource) {
|
public void die(DamageSource damagesource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OptionalInt openMenu(MenuProvider factory) {
|
public OptionalInt openMenu(MenuProvider factory) {
|
||||||
return OptionalInt.empty();
|
return OptionalInt.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateOptions(ServerboundClientInformationPacket packet) {
|
public void updateOptions(ClientInformation clientOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -17,9 +17,8 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
@ -27,17 +26,20 @@ import com.sk89q.worldedit.util.SideEffect;
|
|||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Objects;
|
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 UPDATE = 1;
|
||||||
@ -101,9 +103,16 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(BlockPos position, CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos position, LinCompoundTag tag) {
|
||||||
|
// We will assume that the tile entity was created for us
|
||||||
|
BlockEntity tileEntity = getWorld().getBlockEntity(position);
|
||||||
|
if (tileEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Tag nativeTag = adapter.fromNativeLin(tag);
|
||||||
|
PaperweightAdapter.readTagIntoTileEntity((net.minecraft.nbt.CompoundTag) nativeTag, tileEntity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
||||||
@ -144,17 +153,19 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure why neighborChanged is deprecated
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
ServerLevel world = getWorld();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
||||||
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
|
world.getBlockState(neighborPos).handleNeighborChanged(world, neighborPos, block, pos, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateNeighbors(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();
|
ServerLevel world = getWorld();
|
||||||
// a == updateNeighbors
|
|
||||||
// b == updateDiagonalNeighbors
|
|
||||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||||
CraftWorld craftWorld = world.getWorld();
|
CraftWorld craftWorld = world.getWorld();
|
||||||
@ -177,5 +188,4 @@ public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChun
|
|||||||
public void flush() {
|
public void flush() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.bukkit.adapter.ext.fawe.v1_21_R1;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class to map all names that we use.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Overloads are split into multiple fields, as they <em>CAN</em> have different obfuscated names.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public final class StaticRefraction {
|
||||||
|
public static final String GET_CHUNK_FUTURE_MAIN_THREAD = Refraction.pickName(
|
||||||
|
"getChunkFutureMainThread", "c"
|
||||||
|
);
|
||||||
|
public static final String MAIN_THREAD_PROCESSOR = Refraction.pickName(
|
||||||
|
"mainThreadProcessor", "g"
|
||||||
|
);
|
||||||
|
public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e");
|
||||||
|
public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_");
|
||||||
|
/**
|
||||||
|
* {@code addFreshEntityWithPassengers(Entity entity)}.
|
||||||
|
*/
|
||||||
|
public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY = Refraction.pickName(
|
||||||
|
"addFreshEntityWithPassengers", "a_"
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* {@code addFreshEntityWithPassengers(Entity entity, CreatureSpawnEvent.SpawnReason reason)}.
|
||||||
|
*/
|
||||||
|
public static final String ADD_FRESH_ENTITY_WITH_PASSENGERS_ENTITY_SPAWN_REASON =
|
||||||
|
Refraction.pickName("addFreshEntityWithPassengers", "a_");
|
||||||
|
/**
|
||||||
|
* {@code addFreshEntity(Entity entity)}.
|
||||||
|
*/
|
||||||
|
public static final String ADD_FRESH_ENTITY = Refraction.pickName("addFreshEntity", "b");
|
||||||
|
/**
|
||||||
|
* {@code addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason)}.
|
||||||
|
*/
|
||||||
|
public static final String ADD_FRESH_ENTITY_SPAWN_REASON = Refraction.pickName(
|
||||||
|
"addFreshEntity", "b"
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* {@code getBlockEntity(BlockPos blockPos)}.
|
||||||
|
*/
|
||||||
|
public static final String GET_BLOCK_ENTITY = Refraction.pickName("getBlockEntity", "c_");
|
||||||
|
/**
|
||||||
|
* {@code setBlock(BlockPos blockPos, BlockState blockState, int flags)}.
|
||||||
|
*/
|
||||||
|
public static final String SET_BLOCK = Refraction.pickName("setBlock", "a");
|
||||||
|
/**
|
||||||
|
* {@code setBlock(BlockPos blockPos, BlockState blockState, int flags, int maxUpdateDepth)}.
|
||||||
|
*/
|
||||||
|
public static final String SET_BLOCK_MAX_UPDATE = Refraction.pickName("setBlock", "a");
|
||||||
|
public static final String REMOVE_BLOCK = Refraction.pickName("removeBlock", "a");
|
||||||
|
/**
|
||||||
|
* {@code destroyBlock(BlockPos blockPos, boolean drop)}.
|
||||||
|
*/
|
||||||
|
public static final String DESTROY_BLOCK = Refraction.pickName("destroyBlock", "b");
|
||||||
|
/**
|
||||||
|
* {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity)}.
|
||||||
|
*/
|
||||||
|
public static final String DESTROY_BLOCK_BREAKING_ENTITY = Refraction.pickName(
|
||||||
|
"destroyBlock", "a"
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* {@code destroyBlock(BlockPos blockPos, boolean drop, Entity breakingEntity, int maxUpdateDepth)}.
|
||||||
|
*/
|
||||||
|
public static final String DESTROY_BLOCK_BREAKING_ENTITY_MAX_UPDATE = Refraction.pickName(
|
||||||
|
"destroyBlock", "a"
|
||||||
|
);
|
||||||
|
}
|
@ -1,27 +1,24 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.util.ReflectionUtil;
|
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag;
|
|
||||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.world.level.EmptyBlockGetter;
|
import net.minecraft.world.level.EmptyBlockGetter;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.EntityBlock;
|
import net.minecraft.world.level.block.EntityBlock;
|
||||||
import net.minecraft.world.level.block.LiquidBlock;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.Fluids;
|
||||||
import net.minecraft.world.level.material.PushReaction;
|
import net.minecraft.world.level.material.PushReaction;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
|
|
||||||
public class PaperweightBlockMaterial implements BlockMaterial {
|
public class PaperweightBlockMaterial implements BlockMaterial {
|
||||||
|
|
||||||
private final Block block;
|
private final Block block;
|
||||||
private final BlockState blockState;
|
private final BlockState blockState;
|
||||||
private final boolean isTranslucent;
|
|
||||||
private final CraftBlockData craftBlockData;
|
private final CraftBlockData craftBlockData;
|
||||||
private final org.bukkit.Material craftMaterial;
|
private final org.bukkit.Material craftMaterial;
|
||||||
private final int opacity;
|
private final int opacity;
|
||||||
@ -36,19 +33,14 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
|||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
this.craftBlockData = CraftBlockData.fromData(blockState);
|
this.craftBlockData = CraftBlockData.fromData(blockState);
|
||||||
this.craftMaterial = craftBlockData.getMaterial();
|
this.craftMaterial = craftBlockData.getMaterial();
|
||||||
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block,
|
|
||||||
Refraction.pickName("properties", "aN"));
|
|
||||||
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
|
|
||||||
Refraction.pickName("canOcclude", "m")
|
|
||||||
);
|
|
||||||
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||||
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
|
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
|
||||||
BlockPos.ZERO,
|
BlockPos.ZERO,
|
||||||
blockState
|
blockState
|
||||||
);
|
);
|
||||||
tile = tileEntity == null
|
tile = tileEntity == null ? null : new PaperweightLazyCompoundTag(
|
||||||
? null
|
Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
|
||||||
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block getBlock() {
|
public Block getBlock() {
|
||||||
@ -75,7 +67,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpaque() {
|
public boolean isOpaque() {
|
||||||
return blockState.isOpaque();
|
return blockState.canOcclude();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,14 +77,13 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLiquid() {
|
public boolean isLiquid() {
|
||||||
// TODO: Better check ?
|
return !blockState.getFluidState().is(Fluids.EMPTY);
|
||||||
return block instanceof LiquidBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSolid() {
|
public boolean isSolid() {
|
||||||
// TODO: Replace
|
// No access to world -> EmptyBlockGetter
|
||||||
return blockState.isSolid();
|
return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -132,7 +123,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTicksRandomly() {
|
public boolean isTicksRandomly() {
|
||||||
return block.isRandomlyTicking(blockState);
|
return blockState.isRandomlyTicking();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -158,7 +149,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTranslucent() {
|
public boolean isTranslucent() {
|
||||||
return isTranslucent;
|
return !blockState.canOcclude();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||||
@ -12,13 +12,12 @@ import com.fastasyncworldedit.core.util.NbtUtils;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R3.PaperweightAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt.PaperweightLazyCompoundTag;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.regen.PaperweightRegen;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||||
@ -34,10 +33,8 @@ import com.sk89q.worldedit.registry.state.Property;
|
|||||||
import com.sk89q.worldedit.util.Direction;
|
import com.sk89q.worldedit.util.Direction;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
|
import com.sk89q.worldedit.util.concurrency.LazyReference;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -51,8 +48,12 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.core.WritableRegistry;
|
import net.minecraft.core.WritableRegistry;
|
||||||
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
@ -75,14 +76,17 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity;
|
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftNamespacedKey;
|
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinStringTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -108,6 +112,9 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
||||||
|
private static final Codec<DataComponentPatch> COMPONENTS_CODEC = DataComponentPatch.CODEC.optionalFieldOf(
|
||||||
|
"components", DataComponentPatch.EMPTY
|
||||||
|
).codec();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
@ -116,7 +123,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PaperweightAdapter parent;
|
private final com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1.PaperweightAdapter parent;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Code that may break between versions of Minecraft
|
// Code that may break between versions of Minecraft
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -127,7 +134,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
private Map<String, List<Property<?>>> allBlockProperties = null;
|
private Map<String, List<Property<?>>> allBlockProperties = null;
|
||||||
|
|
||||||
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
|
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
|
||||||
this.parent = new PaperweightAdapter();
|
this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_21_R1.PaperweightAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -136,6 +143,10 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
return resourceLocation == null ? null : resourceLocation.toString();
|
return resourceLocation == null ? null : resourceLocation.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
||||||
|
entity.save(compoundTag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
|
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
@ -228,7 +239,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
public Block getBlock(BlockType blockType) {
|
public Block getBlock(BlockType blockType) {
|
||||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK)
|
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK)
|
||||||
.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
|
.get(ResourceLocation.fromNamespaceAndPath(blockType.getNamespace(), blockType.getResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -273,8 +284,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
// Read the NBT data
|
// Read the NBT data
|
||||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(DedicatedServer.getServer().registryAccess());
|
||||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
return state.toBaseBlock((LinCompoundTag) toNativeLin(tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,14 +313,14 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
||||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
Supplier<LinCompoundTag> saveTag = () -> {
|
||||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||||
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag);
|
readEntityIntoTag(mcEntity, minecraftTag);
|
||||||
//add Id for AbstractChangeSet to work
|
//add Id for AbstractChangeSet to work
|
||||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
final LinCompoundTag tag = (LinCompoundTag) toNativeLin(minecraftTag);
|
||||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
final Map<String, LinTag<?>> tags = NbtUtils.getLinCompoundTagValues(tag);
|
||||||
tags.put("Id", StringBinaryTag.of(id));
|
tags.put("Id", LinStringTag.of(id));
|
||||||
return CompoundBinaryTag.from(tags);
|
return LinCompoundTag.of(tags);
|
||||||
};
|
};
|
||||||
return new LazyBaseEntity(type, saveTag);
|
return new LazyBaseEntity(type, saveTag);
|
||||||
} else {
|
} else {
|
||||||
@ -478,12 +489,18 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
||||||
|
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
ItemStack stack = new ItemStack(
|
ItemStack stack = new ItemStack(
|
||||||
DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM)
|
registryAccess.registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(baseItemStack.getType().id())),
|
||||||
.get(ResourceLocation.tryParse(baseItemStack.getType().id())),
|
|
||||||
baseItemStack.getAmount()
|
baseItemStack.getAmount()
|
||||||
);
|
);
|
||||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
|
final CompoundTag nbt = (net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData());
|
||||||
|
if (nbt != null) {
|
||||||
|
final DataComponentPatch patch = COMPONENTS_CODEC
|
||||||
|
.parse(registryAccess.createSerializationContext(NbtOps.INSTANCE), nbt)
|
||||||
|
.getOrThrow();
|
||||||
|
stack.applyComponents(patch);
|
||||||
|
}
|
||||||
return CraftItemStack.asCraftMirror(stack);
|
return CraftItemStack.asCraftMirror(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,10 +529,17 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
|
final RegistryAccess.Frozen registryAccess = DedicatedServer.getServer().registryAccess();
|
||||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
final net.minecraft.nbt.Tag tag = COMPONENTS_CODEC.encodeStart(
|
||||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
registryAccess.createSerializationContext(NbtOps.INSTANCE),
|
||||||
return weStack;
|
nmsStack.getComponentsPatch()
|
||||||
|
).getOrThrow();
|
||||||
|
return new BaseItemStack(
|
||||||
|
BukkitAdapter.asItemType(itemStack.getType()),
|
||||||
|
LazyReference.from(() -> (LinCompoundTag) toNativeLin(tag)),
|
||||||
|
itemStack.getAmount()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -533,7 +557,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
|
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
|
||||||
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
|
throw new UnsupportedOperationException("Regen support for 1.21 not yet implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -600,15 +624,14 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
|
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
|
||||||
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
|
if (PaperLib.isPaper()) { // Papers new chunk system has no related replacement - therefor we assume true.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
|
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
|
||||||
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
||||||
// fall-through
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.math.IntPair;
|
import com.fastasyncworldedit.core.math.IntPair;
|
||||||
@ -9,22 +9,22 @@ import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
|||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.SideEffectSet;
|
import com.sk89q.worldedit.util.SideEffectSet;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@ -133,15 +133,15 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
|
public boolean updateTileEntity(BlockPos blockPos, LinCompoundTag tag) {
|
||||||
// We will assume that the tile entity was created for us,
|
// We will assume that the tile entity was created for us,
|
||||||
// though we do not do this on the other versions
|
// though we do not do this on the other versions
|
||||||
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
|
||||||
if (blockEntity == null) {
|
if (blockEntity == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
|
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeLin(tag);
|
||||||
blockEntity.load((CompoundTag) nativeTag);
|
blockEntity.loadWithComponents((CompoundTag) nativeTag, DedicatedServer.getServer().registryAccess());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
// Un-nest neighbour updating
|
// Un-nest neighbour updating
|
||||||
for (Direction direction : NEIGHBOUR_ORDER) {
|
for (Direction direction : NEIGHBOUR_ORDER) {
|
||||||
BlockPos shifted = blockPos.relative(direction);
|
BlockPos shifted = blockPos.relative(direction);
|
||||||
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
|
level.getBlockState(shifted).handleNeighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newState.hasAnalogOutputSignal()) {
|
if (newState.hasAnalogOutputSignal()) {
|
||||||
@ -218,6 +218,12 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBlock(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||||
|
Level world = getLevel();
|
||||||
|
newState.onPlace(world, pos, oldState, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockStateChange(
|
public void onBlockStateChange(
|
||||||
BlockPos blockPos,
|
BlockPos blockPos,
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
import com.fastasyncworldedit.bukkit.adapter.BukkitGetBlocks;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
||||||
@ -20,7 +20,7 @@ import com.sk89q.jnbt.StringTag;
|
|||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag;
|
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag;
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
@ -35,6 +35,7 @@ import net.minecraft.core.IdMap;
|
|||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.SectionPos;
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.nbt.IntTag;
|
import net.minecraft.nbt.IntTag;
|
||||||
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.util.BitStorage;
|
import net.minecraft.util.BitStorage;
|
||||||
@ -58,8 +59,8 @@ import net.minecraft.world.level.levelgen.Heightmap;
|
|||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock;
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -91,8 +92,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ());
|
private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ());
|
||||||
private static final Function<BlockEntity, CompoundTag> nmsTile2We =
|
private static final Function<BlockEntity, CompoundTag> nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag(
|
||||||
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess()))
|
||||||
|
);
|
||||||
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.getBukkitImplAdapter());
|
.getBukkitImplAdapter());
|
||||||
@ -263,7 +265,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (blockEntity == null) {
|
if (blockEntity == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId));
|
return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -336,7 +338,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
Entity entity = serverLevel.getEntity(uuid);
|
ensureLoaded(serverLevel, chunkX, chunkZ);
|
||||||
|
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||||
|
Entity entity = null;
|
||||||
|
for (Entity e : entities) {
|
||||||
|
if (e.getUUID().equals(uuid)) {
|
||||||
|
entity = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||||
@ -388,7 +398,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
public Iterator<CompoundTag> iterator() {
|
public Iterator<CompoundTag> iterator() {
|
||||||
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
PaperweightPlatformAdapter.readEntityIntoTag(input, tag);
|
input.save(tag);
|
||||||
return (CompoundTag) adapter.toNative(tag);
|
return (CompoundTag) adapter.toNative(tag);
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return result.iterator();
|
return result.iterator();
|
||||||
@ -541,9 +551,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
// Don't attempt to tick section whilst we're editing
|
// Don't attempt to tick section whilst we're editing
|
||||||
if (existingSection != null) {
|
if (existingSection != null) {
|
||||||
PaperweightPlatformAdapter.clearCounts(existingSection);
|
PaperweightPlatformAdapter.clearCounts(existingSection);
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
existingSection.tickingList.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
@ -590,9 +597,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
|
|
||||||
//ensure that the server doesn't try to tick the chunksection while we're editing it. (Again)
|
//ensure that the server doesn't try to tick the chunksection while we're editing it. (Again)
|
||||||
PaperweightPlatformAdapter.clearCounts(existingSection);
|
PaperweightPlatformAdapter.clearCounts(existingSection);
|
||||||
if (PaperLib.isPaper()) {
|
|
||||||
existingSection.tickingList.clear();
|
|
||||||
}
|
|
||||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(existingSection);
|
||||||
|
|
||||||
// Synchronize to prevent further acquisitions
|
// Synchronize to prevent further acquisitions
|
||||||
@ -634,9 +638,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
biomeRegistry,
|
biomeRegistry,
|
||||||
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
|
||||||
);
|
);
|
||||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
if (!PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, existingSection,
|
||||||
levelChunkSections,
|
|
||||||
existingSection,
|
|
||||||
newSection,
|
newSection,
|
||||||
getSectionIndex
|
getSectionIndex
|
||||||
)) {
|
)) {
|
||||||
@ -730,7 +732,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
final CompoundTag nativeTag = iterator.next();
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag<?, ?>> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
@ -803,7 +805,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
tag.put("x", IntTag.valueOf(x));
|
tag.put("x", IntTag.valueOf(x));
|
||||||
tag.put("y", IntTag.valueOf(y));
|
tag.put("y", IntTag.valueOf(y));
|
||||||
tag.put("z", IntTag.valueOf(z));
|
tag.put("z", IntTag.valueOf(z));
|
||||||
tileEntity.load(tag);
|
tileEntity.loadWithComponents(tag, DedicatedServer.getServer().registryAccess());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
|
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
|
||||||
import com.fastasyncworldedit.core.queue.IBlocks;
|
import com.fastasyncworldedit.core.queue.IBlocks;
|
||||||
@ -8,7 +8,7 @@ import com.google.common.base.Suppliers;
|
|||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt.PaperweightLazyCompoundTag;
|
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
@ -16,6 +16,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
@ -62,7 +63,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
blockEntity.getBlockPos().getY(),
|
blockEntity.getBlockPos().getY(),
|
||||||
blockEntity.getBlockPos().getZ()
|
blockEntity.getBlockPos().getZ()
|
||||||
),
|
),
|
||||||
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
|
new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
protected void storeEntity(Entity entity) {
|
protected void storeEntity(Entity entity) {
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag);
|
entity.save(compoundTag);
|
||||||
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
|
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||||
@ -10,10 +10,10 @@ public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkW
|
|||||||
|
|
||||||
public PaperweightMapChunkUtil() throws NoSuchFieldException {
|
public PaperweightMapChunkUtil() throws NoSuchFieldException {
|
||||||
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
|
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
|
||||||
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a"));
|
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "b"));
|
||||||
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b"));
|
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "c"));
|
||||||
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
|
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
|
||||||
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c"));
|
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "d"));
|
||||||
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
|
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
|
||||||
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
|
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
|
||||||
fieldX.setAccessible(true);
|
fieldX.setAccessible(true);
|
@ -1,6 +1,7 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.destroystokyo.paper.util.maplist.EntityList;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
||||||
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
|
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
|
||||||
@ -10,7 +11,6 @@ import com.fastasyncworldedit.core.math.BitArrayUnstretched;
|
|||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.mojang.datafixers.util.Either;
|
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||||
@ -20,7 +20,6 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import io.papermc.paper.world.ChunkEntitySlices;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.IdMap;
|
import net.minecraft.core.IdMap;
|
||||||
@ -31,7 +30,6 @@ import net.minecraft.server.level.ChunkHolder;
|
|||||||
import net.minecraft.server.level.ChunkMap;
|
import net.minecraft.server.level.ChunkMap;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.level.TicketType;
|
|
||||||
import net.minecraft.util.BitStorage;
|
import net.minecraft.util.BitStorage;
|
||||||
import net.minecraft.util.ExceptionCollector;
|
import net.minecraft.util.ExceptionCollector;
|
||||||
import net.minecraft.util.SimpleBitStorage;
|
import net.minecraft.util.SimpleBitStorage;
|
||||||
@ -39,17 +37,14 @@ import net.minecraft.util.ThreadingDetector;
|
|||||||
import net.minecraft.util.Unit;
|
import net.minecraft.util.Unit;
|
||||||
import net.minecraft.util.ZeroBitStorage;
|
import net.minecraft.util.ZeroBitStorage;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.npc.AbstractVillager;
|
|
||||||
import net.minecraft.world.entity.npc.Villager;
|
|
||||||
import net.minecraft.world.item.trading.MerchantOffers;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.GlobalPalette;
|
import net.minecraft.world.level.chunk.GlobalPalette;
|
||||||
import net.minecraft.world.level.chunk.HashMapPalette;
|
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
@ -58,10 +53,11 @@ import net.minecraft.world.level.chunk.LinearPalette;
|
|||||||
import net.minecraft.world.level.chunk.Palette;
|
import net.minecraft.world.level.chunk.Palette;
|
||||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
import net.minecraft.world.level.chunk.SingleValuePalette;
|
import net.minecraft.world.level.chunk.SingleValuePalette;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftChunk;
|
import org.bukkit.craftbukkit.CraftChunk;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -80,7 +76,6 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -101,6 +96,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Field fieldTickingFluidCount;
|
private static final Field fieldTickingFluidCount;
|
||||||
private static final Field fieldTickingBlockCount;
|
private static final Field fieldTickingBlockCount;
|
||||||
|
private static final Field fieldBiomes;
|
||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
@ -109,10 +105,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
private static final Field fieldBiomes;
|
|
||||||
|
|
||||||
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
|
* 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
|
||||||
@ -124,9 +116,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
static final boolean POST_CHUNK_REWRITE;
|
|
||||||
private static Method PAPER_CHUNK_GEN_ALL_ENTITIES;
|
private static Method PAPER_CHUNK_GEN_ALL_ENTITIES;
|
||||||
private static Field LEVEL_CHUNK_ENTITIES;
|
|
||||||
private static Field SERVER_LEVEL_ENTITY_MANAGER;
|
private static Field SERVER_LEVEL_ENTITY_MANAGER;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -150,10 +140,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldTickingBlockCount.setAccessible(true);
|
fieldTickingBlockCount.setAccessible(true);
|
||||||
Field tmpFieldBiomes;
|
Field tmpFieldBiomes;
|
||||||
try {
|
try {
|
||||||
// It seems to actually be biomes, but is apparently obfuscated to "i"
|
// Seems it's sometimes biomes and sometimes "i". Idk this is just easier than having to try to deal with it
|
||||||
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes");
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("biomes"); // apparently unobf
|
||||||
} catch (NoSuchFieldException ignored) {
|
} catch (NoSuchFieldException ignored) {
|
||||||
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i");
|
tmpFieldBiomes = LevelChunkSection.class.getDeclaredField("i"); // apparently obf
|
||||||
}
|
}
|
||||||
fieldBiomes = tmpFieldBiomes;
|
fieldBiomes = tmpFieldBiomes;
|
||||||
fieldBiomes.setAccessible(true);
|
fieldBiomes.setAccessible(true);
|
||||||
@ -187,40 +177,24 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
||||||
Refraction.pickName(
|
Refraction.pickName(
|
||||||
"removeBlockEntityTicker",
|
"removeBlockEntityTicker",
|
||||||
"l"
|
"k"
|
||||||
), BlockPos.class
|
), BlockPos.class
|
||||||
);
|
);
|
||||||
removeBlockEntityTicker.setAccessible(true);
|
removeBlockEntityTicker.setAccessible(true);
|
||||||
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
|
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
|
||||||
|
|
||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
|
|
||||||
boolean chunkRewrite;
|
|
||||||
try {
|
try {
|
||||||
ServerLevel.class.getDeclaredMethod("getEntityLookup");
|
Level.class.getDeclaredMethod("moonrise$getEntityLookup");
|
||||||
chunkRewrite = true;
|
|
||||||
PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities");
|
PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities");
|
||||||
PAPER_CHUNK_GEN_ALL_ENTITIES.setAccessible(true);
|
PAPER_CHUNK_GEN_ALL_ENTITIES.setAccessible(true);
|
||||||
} catch (NoSuchMethodException ignored) {
|
} 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
|
// Non-Paper
|
||||||
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M"));
|
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "N"));
|
||||||
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
|
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
|
||||||
} catch (NoSuchFieldException ignored) {
|
|
||||||
}
|
}
|
||||||
POST_CHUNK_REWRITE = chunkRewrite;
|
|
||||||
|
|
||||||
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bU"));
|
|
||||||
fieldOffers.setAccessible(true);
|
|
||||||
} catch (RuntimeException | Error e) {
|
} catch (RuntimeException | Error e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -336,7 +310,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
// Ensure chunk is definitely loaded before applying a ticket
|
// Ensure chunk is definitely loaded before applying a ticket
|
||||||
io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
|
io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
|
||||||
.getChunkSource()
|
.getChunkSource()
|
||||||
.addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
|
.addRegionTicket(ChunkHolderManager.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
|
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
|
||||||
@ -362,10 +336,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
.getChunkSource()
|
.getChunkSource()
|
||||||
.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
|
.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
|
||||||
} else {
|
} else {
|
||||||
levelChunk = ((Optional<LevelChunk>) ((Either) chunkHolder
|
levelChunk = chunkHolder.getTickingChunkFuture()
|
||||||
.getTickingChunkFuture() // method is not present with new paper chunk system
|
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null);
|
||||||
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left())
|
|
||||||
.orElse(null);
|
|
||||||
}
|
}
|
||||||
if (levelChunk == null) {
|
if (levelChunk == null) {
|
||||||
return;
|
return;
|
||||||
@ -373,7 +345,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
MinecraftServer.getServer().execute(() -> {
|
MinecraftServer.getServer().execute(() -> {
|
||||||
ClientboundLevelChunkWithLightPacket packet;
|
ClientboundLevelChunkWithLightPacket packet;
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
synchronized (chunk) {
|
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
nmsWorld.getChunkSource().getLightEngine(),
|
nmsWorld.getChunkSource().getLightEngine(),
|
||||||
@ -381,9 +352,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null,
|
null,
|
||||||
false // last false is to not bother with x-ray
|
false // last false is to not bother with x-ray
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
synchronized (chunk) {
|
|
||||||
// deprecated on paper - deprecation suppressed
|
// deprecated on paper - deprecation suppressed
|
||||||
packet = new ClientboundLevelChunkWithLightPacket(
|
packet = new ClientboundLevelChunkWithLightPacket(
|
||||||
levelChunk,
|
levelChunk,
|
||||||
@ -392,7 +361,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -673,49 +641,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static List<Entity> getEntities(LevelChunk chunk) {
|
static List<Entity> getEntities(LevelChunk chunk) {
|
||||||
ExceptionCollector<RuntimeException> collector = new ExceptionCollector<>();
|
|
||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
if (POST_CHUNK_REWRITE) {
|
|
||||||
try {
|
try {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (List<Entity>) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ));
|
return (List<Entity>) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level
|
||||||
|
.moonrise$getEntityLookup()
|
||||||
|
.getChunk(chunk.locX, chunk.locZ));
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e);
|
throw new RuntimeException("Failed to lookup entities [PAPER=true]", e);
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk);
|
|
||||||
return List.of(entityList.getRawData());
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e));
|
|
||||||
// fall through
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return ((PersistentEntitySectionManager<Entity>) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos());
|
return ((PersistentEntitySectionManager<Entity>) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos());
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e));
|
throw new RuntimeException("Failed to lookup entities [PAPER=false]", e);
|
||||||
}
|
|
||||||
collector.throwIfPresent();
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
|
||||||
boolean unset = false;
|
|
||||||
if (entity instanceof Villager villager && !Fawe.isMainThread()) {
|
|
||||||
try {
|
|
||||||
if (fieldOffers.get(entity) == null) {
|
|
||||||
villager.setOffers(OFFERS);
|
|
||||||
unset = true;
|
|
||||||
}
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException("Failed to set offers field to villager to avoid async catcher.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entity.save(compoundTag);
|
|
||||||
if (unset) {
|
|
||||||
((Villager) entity).setOffers(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter;
|
import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
@ -8,7 +8,8 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.server.level.TicketType;
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.util.Unit;
|
import net.minecraft.util.Unit;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkPyramid;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -18,7 +19,9 @@ import java.util.function.IntConsumer;
|
|||||||
public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> {
|
public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> {
|
||||||
|
|
||||||
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
|
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
|
||||||
private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
|
private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkPyramid.LOADING_PYRAMID
|
||||||
|
.getStepTo(ChunkStatus.FULL)
|
||||||
|
.getAccumulatedRadiusOf(ChunkStatus.LIGHT);
|
||||||
|
|
||||||
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) {
|
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) {
|
||||||
super(serverLevel, queue);
|
super(serverLevel, queue);
|
||||||
@ -51,7 +54,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLeve
|
|||||||
IntConsumer processCallback
|
IntConsumer processCallback
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
|
serverLevel.getChunkSource().getLightEngine().starlight$serverRelightChunks(coords, chunkCallback, processCallback);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error("Error occurred on relighting", e);
|
LOGGER.error("Error occurred on relighting", e);
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
|
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
||||||
@ -7,7 +7,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
|||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.nbt;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt;
|
||||||
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.LazyCompoundTag;
|
import com.sk89q.jnbt.LazyCompoundTag;
|
||||||
@ -6,8 +6,8 @@ import com.sk89q.jnbt.ListTag;
|
|||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import net.minecraft.nbt.NumericTag;
|
import net.minecraft.nbt.NumericTag;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -36,7 +36,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, Tag> getValue() {
|
public Map<String, Tag<?, ?>> getValue() {
|
||||||
if (compoundTag == null) {
|
if (compoundTag == null) {
|
||||||
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
|
||||||
}
|
}
|
||||||
@ -44,9 +44,9 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundBinaryTag asBinaryTag() {
|
public LinCompoundTag toLinTag() {
|
||||||
getValue();
|
getValue();
|
||||||
return compoundTag.asBinaryTag();
|
return compoundTag.toLinTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(String key) {
|
public boolean containsKey(String key) {
|
||||||
@ -94,10 +94,10 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<Tag> getList(String key) {
|
public List<? extends Tag<?, ?>> getList(String key) {
|
||||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
||||||
ArrayList<Tag> list = new ArrayList<>();
|
ArrayList<Tag<?, ?>> list = new ArrayList<>();
|
||||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
for (net.minecraft.nbt.Tag elem : nbtList) {
|
||||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
||||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
||||||
@ -120,7 +120,7 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
|
public <T extends Tag<?, ?>> List<T> getList(String key, Class<T> listType) {
|
||||||
ListTag listTag = getListTag(key);
|
ListTag listTag = getListTag(key);
|
||||||
if (listTag.getType().equals(listType)) {
|
if (listTag.getType().equals(listType)) {
|
||||||
return (List<T>) listTag.getValue();
|
return (List<T>) listTag.getValue();
|
@ -1,22 +1,22 @@
|
|||||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.regen;
|
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.regen;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
||||||
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
|
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.queue.IChunkCache;
|
import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.datafixers.util.Either;
|
|
||||||
import com.mojang.serialization.Lifecycle;
|
import com.mojang.serialization.Lifecycle;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.PaperweightGetBlocks;
|
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.PaperweightGetBlocks;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
@ -25,12 +25,15 @@ import net.minecraft.nbt.CompoundTag;
|
|||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.ChunkMap;
|
import net.minecraft.server.level.ChunkMap;
|
||||||
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
|
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
|
||||||
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.StaticCache2D;
|
||||||
import net.minecraft.util.thread.ProcessorHandle;
|
import net.minecraft.util.thread.ProcessorHandle;
|
||||||
import net.minecraft.util.thread.ProcessorMailbox;
|
import net.minecraft.util.thread.ProcessorMailbox;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
@ -43,10 +46,12 @@ import net.minecraft.world.level.biome.FixedBiomeSource;
|
|||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.chunk.UpgradeData;
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkPyramid;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||||
import net.minecraft.world.level.dimension.LevelStem;
|
import net.minecraft.world.level.dimension.LevelStem;
|
||||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||||
@ -61,11 +66,12 @@ import net.minecraft.world.level.storage.PrimaryLevelData;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.generator.CustomChunkGenerator;
|
import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
|
||||||
import org.bukkit.generator.BiomeProvider;
|
import org.bukkit.generator.BiomeProvider;
|
||||||
import org.bukkit.generator.BlockPopulator;
|
import org.bukkit.generator.BlockPopulator;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -105,23 +111,22 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
|
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
|
||||||
chunkStati.put(
|
chunkStati.put(
|
||||||
ChunkStatus.STRUCTURE_REFERENCES,
|
ChunkStatus.STRUCTURE_REFERENCES,
|
||||||
Concurrency.FULL
|
Concurrency.NONE
|
||||||
); // structure refs: radius 8, but only writes to current chunk
|
); // structure refs: radius 8, but only writes to current chunk
|
||||||
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0
|
chunkStati.put(ChunkStatus.BIOMES, Concurrency.NONE); // biomes: radius 0
|
||||||
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
|
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
|
||||||
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
|
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
|
||||||
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
|
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
|
||||||
/*chunkStati.put(
|
|
||||||
ChunkStatus.LIQUID_CARVERS,
|
|
||||||
Concurrency.NONE
|
|
||||||
); // liquid carvers: radius 0, but RADIUS and FULL change results*/
|
|
||||||
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
|
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
|
||||||
|
chunkStati.put(
|
||||||
|
ChunkStatus.INITIALIZE_LIGHT,
|
||||||
|
Concurrency.FULL
|
||||||
|
); // initialize_light: radius 0
|
||||||
chunkStati.put(
|
chunkStati.put(
|
||||||
ChunkStatus.LIGHT,
|
ChunkStatus.LIGHT,
|
||||||
Concurrency.FULL
|
Concurrency.FULL
|
||||||
); // light: radius 1, but no writes to other chunks, only current chunk
|
); // light: radius 1, but no writes to other chunks, only current chunk
|
||||||
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
|
chunkStati.put(ChunkStatus.SPAWN, Concurrency.NONE); // spawn: radius 0
|
||||||
// chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||||
@ -155,7 +160,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
|
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
|
||||||
chunkSourceField.setAccessible(true);
|
chunkSourceField.setAccessible(true);
|
||||||
|
|
||||||
generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v"));
|
generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "w"));
|
||||||
generatorStructureStateField.setAccessible(true);
|
generatorStructureStateField.setAccessible(true);
|
||||||
|
|
||||||
ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g"));
|
ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g"));
|
||||||
@ -179,6 +184,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
private StructureTemplateManager structureTemplateManager;
|
private StructureTemplateManager structureTemplateManager;
|
||||||
private ThreadedLevelLightEngine threadedLevelLightEngine;
|
private ThreadedLevelLightEngine threadedLevelLightEngine;
|
||||||
private ChunkGenerator chunkGenerator;
|
private ChunkGenerator chunkGenerator;
|
||||||
|
private WorldGenContext worldGenContext;
|
||||||
|
|
||||||
private Path tempDir;
|
private Path tempDir;
|
||||||
|
|
||||||
@ -186,6 +192,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
|
|
||||||
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
|
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
|
||||||
super(originalBukkitWorld, region, target, options);
|
super(originalBukkitWorld, region, target, options);
|
||||||
|
if (PaperLib.isPaper()) {
|
||||||
|
throw new UnsupportedOperationException("Regeneration currently not support on Paper due to the new generation system");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -273,11 +282,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
|
public void tick(@NotNull BooleanSupplier shouldKeepTicking) { //no ticking
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
|
public @NotNull Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
|
||||||
if (options.hasBiomeType()) {
|
if (options.hasBiomeType()) {
|
||||||
return singleBiome;
|
return singleBiome;
|
||||||
}
|
}
|
||||||
@ -285,6 +294,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
|
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}).get();
|
}).get();
|
||||||
freshWorld.noSave = true;
|
freshWorld.noSave = true;
|
||||||
removeWorldFromWorldsMap();
|
removeWorldFromWorldsMap();
|
||||||
@ -298,11 +308,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
|
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
|
||||||
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
|
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
|
||||||
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
||||||
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField.get(
|
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>)
|
||||||
originalGenerator);
|
generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator);
|
||||||
BiomeSource biomeSource;
|
BiomeSource biomeSource;
|
||||||
if (options.hasBiomeType()) {
|
if (options.hasBiomeType()) {
|
||||||
|
|
||||||
biomeSource = new FixedBiomeSource(
|
biomeSource = new FixedBiomeSource(
|
||||||
DedicatedServer.getServer().registryAccess()
|
DedicatedServer.getServer().registryAccess()
|
||||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
||||||
@ -345,7 +354,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
) {
|
) {
|
||||||
// redirect to LevelChunks created in #createChunks
|
// redirect to LevelChunks created in #createChunks
|
||||||
@Override
|
@Override
|
||||||
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) {
|
public ChunkAccess getChunk(int x, int z, @NotNull ChunkStatus chunkstatus, boolean create) {
|
||||||
ChunkAccess chunkAccess = getChunkAt(x, z);
|
ChunkAccess chunkAccess = getChunkAt(x, z);
|
||||||
if (chunkAccess == null && create) {
|
if (chunkAccess == null && create) {
|
||||||
chunkAccess = createChunk(getProtoChunkAt(x, z));
|
chunkAccess = createChunk(getProtoChunkAt(x, z));
|
||||||
@ -356,14 +365,16 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
|
|
||||||
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
|
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
|
||||||
// Optimisation for needless ring position calculation when the seed and biome is the same.
|
// Optimisation for needless ring position calculation when the seed and biome is the same.
|
||||||
ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap);
|
ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(
|
||||||
|
originalChunkProvider.chunkMap);
|
||||||
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state);
|
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state);
|
||||||
if (hasGeneratedPositions) {
|
if (hasGeneratedPositions) {
|
||||||
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> origPositions =
|
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> origPositions =
|
||||||
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(state);
|
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(state);
|
||||||
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(
|
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(
|
||||||
origPositions);
|
origPositions);
|
||||||
ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap);
|
ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(
|
||||||
|
freshChunkProvider.chunkMap);
|
||||||
ringPositionsField.set(newState, copy);
|
ringPositionsField.set(newState, copy);
|
||||||
hasGeneratedPositionsField.setBoolean(newState, true);
|
hasGeneratedPositionsField.setBoolean(newState, true);
|
||||||
}
|
}
|
||||||
@ -375,6 +386,13 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
structureTemplateManager = server.getStructureManager();
|
structureTemplateManager = server.getStructureManager();
|
||||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
||||||
|
|
||||||
|
this.worldGenContext = new WorldGenContext(
|
||||||
|
freshWorld,
|
||||||
|
chunkGenerator,
|
||||||
|
structureTemplateManager,
|
||||||
|
threadedLevelLightEngine,
|
||||||
|
originalChunkProvider.chunkMap.worldGenContext.mainThreadMailBox()
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,14 +477,12 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
//util
|
//util
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void removeWorldFromWorldsMap() {
|
private void removeWorldFromWorldsMap() {
|
||||||
Fawe.instance().getQueueHandler().sync(() -> {
|
|
||||||
try {
|
try {
|
||||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
||||||
map.remove("faweregentempworld");
|
map.remove("faweregentempworld");
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
|
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
|
||||||
@ -483,11 +499,15 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
public void updateSpawnPos(@NotNull ChunkPos spawnPos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
|
public void onStatusChange(
|
||||||
|
final @NotNull ChunkPos pos,
|
||||||
|
@org.jetbrains.annotations.Nullable final net.minecraft.world.level.chunk.status.ChunkStatus status
|
||||||
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -519,15 +539,14 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
|
|
||||||
// avoid warning on paper
|
// avoid warning on paper
|
||||||
|
|
||||||
// compatibility with spigot
|
@SuppressWarnings("unused") // compatibility with spigot
|
||||||
|
|
||||||
public boolean generateFlatBedrock() {
|
public boolean generateFlatBedrock() {
|
||||||
return generateFlatBedrock;
|
return generateFlatBedrock;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no one will ever see the entities!
|
// no one will ever see the entities!
|
||||||
@Override
|
@Override
|
||||||
public List<CompoundTag> getEntities() {
|
public @NotNull List<CompoundTag> getEntities() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +562,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int requiredNeighborChunkRadius() {
|
public int requiredNeighborChunkRadius() {
|
||||||
return chunkStatus.getRange();
|
return ChunkPyramid.GENERATION_PYRAMID.getStepTo(ChunkStatus.FULL).getAccumulatedRadiusOf(chunkStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -553,14 +572,27 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) {
|
public CompletableFuture<?> processChunk(List<ChunkAccess> accessibleChunks) {
|
||||||
return chunkStatus.generate(
|
ChunkAccess chunkAccess = accessibleChunks.get(accessibleChunks.size() / 2);
|
||||||
Runnable::run, // TODO revisit, we might profit from this somehow?
|
int chunkX = chunkAccess.getPos().x;
|
||||||
|
int chunkZ = chunkAccess.getPos().z;
|
||||||
|
getProtoChunkAt(chunkX, chunkZ);
|
||||||
|
StaticCache2D<GenerationChunkHolder> neighbours = StaticCache2D
|
||||||
|
.create(
|
||||||
|
chunkX,
|
||||||
|
chunkZ,
|
||||||
|
requiredNeighborChunkRadius(),
|
||||||
|
(final int nx, final int nz) -> new ChunkHolder(new ChunkPos(nx, nz),
|
||||||
|
ChunkHolderManager.MAX_TICKET_LEVEL,
|
||||||
freshWorld,
|
freshWorld,
|
||||||
chunkGenerator,
|
|
||||||
structureTemplateManager,
|
|
||||||
threadedLevelLightEngine,
|
threadedLevelLightEngine,
|
||||||
c -> CompletableFuture.completedFuture(Either.left(c)),
|
null,
|
||||||
accessibleChunks
|
freshChunkProvider.chunkMap
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return ChunkPyramid.GENERATION_PYRAMID.getStepTo(chunkStatus).apply(
|
||||||
|
worldGenContext,
|
||||||
|
neighbours,
|
||||||
|
chunkAccess
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +614,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<ChunkAccess> lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) {
|
public @NotNull CompletableFuture<ChunkAccess> lightChunk(final @NotNull ChunkAccess chunk, final boolean excludeBlocks) {
|
||||||
return CompletableFuture.completedFuture(chunk);
|
return CompletableFuture.completedFuture(chunk);
|
||||||
}
|
}
|
||||||
|
|
@ -182,9 +182,6 @@ tasks.named<ShadowJar>("shadowJar") {
|
|||||||
relocate("org.lz4", "com.fastasyncworldedit.core.lz4") {
|
relocate("org.lz4", "com.fastasyncworldedit.core.lz4") {
|
||||||
include(dependency("org.lz4:lz4-java:1.8.0"))
|
include(dependency("org.lz4:lz4-java:1.8.0"))
|
||||||
}
|
}
|
||||||
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
|
|
||||||
include(dependency("net.kyori:adventure-nbt:4.17.0"))
|
|
||||||
}
|
|
||||||
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
|
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
|
||||||
include(dependency("com.zaxxer:SparseBitSet:1.3"))
|
include(dependency("com.zaxxer:SparseBitSet:1.3"))
|
||||||
}
|
}
|
||||||
@ -215,7 +212,7 @@ tasks {
|
|||||||
versionNumber.set("${project.version}")
|
versionNumber.set("${project.version}")
|
||||||
versionType.set("release")
|
versionType.set("release")
|
||||||
uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar"))
|
uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar"))
|
||||||
gameVersions.addAll(listOf("1.20.6", "1.20.5", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4"))
|
gameVersions.addAll(listOf("1.21", "1.20.6", "1.20.5", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4"))
|
||||||
loaders.addAll(listOf("paper", "spigot"))
|
loaders.addAll(listOf("paper", "spigot"))
|
||||||
changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" +
|
changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" +
|
||||||
"FastAsyncWorldEdit/releases/tag/${project.version}")
|
"FastAsyncWorldEdit/releases/tag/${project.version}")
|
||||||
|
@ -8,15 +8,13 @@ import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
|||||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
import com.sk89q.worldedit.util.Direction;
|
import com.sk89q.worldedit.util.Direction;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
@ -33,6 +31,8 @@ import org.bukkit.entity.Entity;
|
|||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -81,7 +81,7 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData) {
|
default void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData) {
|
||||||
getParent().sendFakeNBT(player, pos, nbtData);
|
getParent().sendFakeNBT(player, pos, nbtData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +115,26 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
|||||||
return getParent().getInternalBlockStateId(state);
|
return getParent().getInternalBlockStateId(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean clearContainerBlockContents(World world, BlockVector3 pt) {
|
||||||
|
return getParent().clearContainerBlockContents(world, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void setBiome(Location location, BiomeType biome) {
|
||||||
|
getParent().setBiome(location, biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default BiomeType getBiome(Location location) {
|
||||||
|
return getParent().getBiome(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
getParent().sendBiomeUpdates(world, chunks);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default BlockMaterial getMaterial(BlockType blockType) {
|
default BlockMaterial getMaterial(BlockType blockType) {
|
||||||
return getParent().getMaterial(blockType);
|
return getParent().getMaterial(blockType);
|
||||||
@ -131,8 +151,8 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default BinaryTag toNativeBinary(T foreign) {
|
default LinTag<?> toNativeLin(T foreign) {
|
||||||
return getParent().toNativeBinary(foreign);
|
return getParent().toNativeLin(foreign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -141,8 +161,8 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default T fromNativeBinary(BinaryTag foreign) {
|
default T fromNativeLin(LinTag foreign) {
|
||||||
return getParent().fromNativeBinary(foreign);
|
return getParent().fromNativeLin(foreign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,8 +3,8 @@ package com.fastasyncworldedit.bukkit.regions.plotsquared;
|
|||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.FaweAPI;
|
import com.fastasyncworldedit.core.FaweAPI;
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReader;
|
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter;
|
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriterV2;
|
||||||
import com.fastasyncworldedit.core.jnbt.CompressedCompoundTag;
|
import com.fastasyncworldedit.core.jnbt.CompressedCompoundTag;
|
||||||
import com.fastasyncworldedit.core.jnbt.CompressedSchematicTag;
|
import com.fastasyncworldedit.core.jnbt.CompressedSchematicTag;
|
||||||
import com.fastasyncworldedit.core.util.IOUtil;
|
import com.fastasyncworldedit.core.util.IOUtil;
|
||||||
@ -29,17 +29,19 @@ import com.sk89q.worldedit.WorldEdit;
|
|||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader;
|
import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader;
|
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
import org.anarres.parallelgzip.ParallelGZIPOutputStream;
|
import org.anarres.parallelgzip.ParallelGZIPOutputStream;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.enginehub.linbus.stream.LinBinaryIO;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -182,7 +184,7 @@ public class FaweDelegateSchematicHandler {
|
|||||||
try (OutputStream stream = new FileOutputStream(tmp);
|
try (OutputStream stream = new FileOutputStream(tmp);
|
||||||
NBTOutputStream output = new NBTOutputStream(
|
NBTOutputStream output = new NBTOutputStream(
|
||||||
new BufferedOutputStream(new ParallelGZIPOutputStream(stream)))) {
|
new BufferedOutputStream(new ParallelGZIPOutputStream(stream)))) {
|
||||||
new FastSchematicWriter(output).write(clipboard);
|
new FastSchematicWriterV2(output).write(clipboard);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try (OutputStream stream = new FileOutputStream(tmp);
|
try (OutputStream stream = new FileOutputStream(tmp);
|
||||||
@ -194,7 +196,7 @@ public class FaweDelegateSchematicHandler {
|
|||||||
} else {
|
} else {
|
||||||
try (OutputStream stream = new FileOutputStream(tmp);
|
try (OutputStream stream = new FileOutputStream(tmp);
|
||||||
NBTOutputStream output = new NBTOutputStream(new ParallelGZIPOutputStream(stream))) {
|
NBTOutputStream output = new NBTOutputStream(new ParallelGZIPOutputStream(stream))) {
|
||||||
Map<String, Tag> map = tag.getValue();
|
Map<String, Tag<?, ?>> map = tag.getValue();
|
||||||
output.writeNamedTag("Schematic", map.getOrDefault("Schematic", tag));
|
output.writeNamedTag("Schematic", map.getOrDefault("Schematic", tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +228,7 @@ public class FaweDelegateSchematicHandler {
|
|||||||
try {
|
try {
|
||||||
try (ParallelGZIPOutputStream gzip = new ParallelGZIPOutputStream(output)) {
|
try (ParallelGZIPOutputStream gzip = new ParallelGZIPOutputStream(output)) {
|
||||||
try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
|
try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
|
||||||
Map<String, Tag> map = weTag.getValue();
|
Map<String, Tag<?, ?>> map = weTag.getValue();
|
||||||
nos.writeNamedTag("Schematic", map.getOrDefault("Schematic", weTag));
|
nos.writeNamedTag("Schematic", map.getOrDefault("Schematic", weTag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +241,7 @@ public class FaweDelegateSchematicHandler {
|
|||||||
|
|
||||||
public Schematic getSchematic(@Nonnull InputStream is) {
|
public Schematic getSchematic(@Nonnull InputStream is) {
|
||||||
try {
|
try {
|
||||||
FastSchematicReader schematicReader = new FastSchematicReader(
|
FastSchematicReaderV2 schematicReader = new FastSchematicReaderV2(
|
||||||
new NBTInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(is)))));
|
new NBTInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(is)))));
|
||||||
Clipboard clip = schematicReader.read();
|
Clipboard clip = schematicReader.read();
|
||||||
return new Schematic(clip);
|
return new Schematic(clip);
|
||||||
@ -249,8 +251,8 @@ public class FaweDelegateSchematicHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SpongeSchematicReader schematicReader =
|
SpongeSchematicV3Reader schematicReader =
|
||||||
new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
|
new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(new GZIPInputStream(is))));
|
||||||
Clipboard clip = schematicReader.read();
|
Clipboard clip = schematicReader.read();
|
||||||
return new Schematic(clip);
|
return new Schematic(clip);
|
||||||
} catch (IOException e2) {
|
} catch (IOException e2) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.fastasyncworldedit.bukkit.util;
|
package com.fastasyncworldedit.bukkit.util;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.io.FastBufferedInputStream;
|
||||||
|
import it.unimi.dsi.fastutil.io.FastBufferedOutputStream;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||||
@ -19,5 +21,7 @@ final class DoNotMiniseThese {
|
|||||||
private final LongSet d = null;
|
private final LongSet d = null;
|
||||||
private final Int2ObjectMap<?> e = null;
|
private final Int2ObjectMap<?> e = null;
|
||||||
private final Object2ObjectArrayMap<?, ?> f = null;
|
private final Object2ObjectArrayMap<?, ?> f = null;
|
||||||
|
private final FastBufferedInputStream g = null;
|
||||||
|
private final FastBufferedOutputStream h = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
||||||
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
@ -61,6 +60,7 @@ import org.bukkit.event.player.PlayerDropItemEvent;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
import org.bukkit.permissions.PermissionAttachment;
|
import org.bukkit.permissions.PermissionAttachment;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -430,7 +430,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
|||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK && block instanceof BaseBlock) {
|
if (block.getBlockType() == BlockTypes.STRUCTURE_BLOCK && block instanceof BaseBlock) {
|
||||||
CompoundBinaryTag nbt = ((BaseBlock) block).getNbt();
|
LinCompoundTag nbt = ((BaseBlock) block).getNbt();
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
adapter.sendFakeNBT(player, pos, nbt);
|
adapter.sendFakeNBT(player, pos, nbt);
|
||||||
adapter.sendFakeOP(player);
|
adapter.sendFakeOP(player);
|
||||||
|
@ -27,7 +27,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
|||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
|
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
|
||||||
import com.sk89q.jnbt.AdventureNBTConverter;
|
import com.sk89q.jnbt.LinBusConverter;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.blocks.BaseItem;
|
import com.sk89q.worldedit.blocks.BaseItem;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||||
@ -35,14 +35,13 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
import com.sk89q.worldedit.util.Direction;
|
import com.sk89q.worldedit.util.Direction;
|
||||||
import com.sk89q.worldedit.util.SideEffect;
|
import com.sk89q.worldedit.util.SideEffect;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.nbt.BinaryTag;
|
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.RegenOptions;
|
import com.sk89q.worldedit.world.RegenOptions;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
@ -61,6 +60,8 @@ import org.bukkit.block.data.BlockData;
|
|||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -110,7 +111,7 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
|||||||
BlockState getBlock(Location location);
|
BlockState getBlock(Location location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the block at the given location.
|
* Get the block with NBT data at the given location.
|
||||||
*
|
*
|
||||||
* @param location the location
|
* @param location the location
|
||||||
* @return the block
|
* @return the block
|
||||||
@ -183,7 +184,7 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
|||||||
* @param pos The position
|
* @param pos The position
|
||||||
* @param nbtData The NBT Data
|
* @param nbtData The NBT Data
|
||||||
*/
|
*/
|
||||||
void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag nbtData);
|
void sendFakeNBT(Player player, BlockVector3 pos, LinCompoundTag nbtData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the client think it has operator status.
|
* Make the client think it has operator status.
|
||||||
@ -280,6 +281,46 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
|||||||
throw new UnsupportedOperationException("This adapter does not support clearing block contents.");
|
throw new UnsupportedOperationException("This adapter does not support clearing block contents.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the biome at a location.
|
||||||
|
*
|
||||||
|
* @param location the location
|
||||||
|
* @param biome the new biome
|
||||||
|
*/
|
||||||
|
default void setBiome(Location location, BiomeType biome) {
|
||||||
|
throw new UnsupportedOperationException("This adapter does not support custom biomes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current biome at a location.
|
||||||
|
*
|
||||||
|
* @param location the location
|
||||||
|
* @return the biome
|
||||||
|
*/
|
||||||
|
default BiomeType getBiome(Location location) {
|
||||||
|
throw new UnsupportedOperationException("This adapter does not support custom biomes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize registries that require NMS access.
|
||||||
|
*/
|
||||||
|
default void initializeRegistries() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends biome updates for the given chunks.
|
||||||
|
*
|
||||||
|
* <p>This doesn't modify biomes at all, it just sends the current state of the biomes
|
||||||
|
* in the world to all of the nearby players, updating the visual representation of the
|
||||||
|
* biomes on their clients.</p>
|
||||||
|
*
|
||||||
|
* @param world the world
|
||||||
|
* @param chunks a list of chunk coordinates to send biome updates for
|
||||||
|
*/
|
||||||
|
default void sendBiomeUpdates(World world, Iterable<BlockVector2> chunks) {
|
||||||
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
default BlockMaterial getMaterial(BlockType blockType) {
|
default BlockMaterial getMaterial(BlockType blockType) {
|
||||||
return getMaterial(blockType.getDefaultState());
|
return getMaterial(blockType.getDefaultState());
|
||||||
@ -291,11 +332,11 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
|||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
default Tag toNative(T foreign) {
|
default Tag toNative(T foreign) {
|
||||||
return AdventureNBTConverter.fromAdventure(toNativeBinary(foreign));
|
return LinBusConverter.toJnbtTag(toNativeLin(foreign));
|
||||||
}
|
}
|
||||||
|
|
||||||
default BinaryTag toNativeBinary(T foreign) {
|
default LinTag<?> toNativeLin(T foreign) {
|
||||||
return toNative(foreign).asBinaryTag();
|
return toNative(foreign).toLinTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -303,14 +344,14 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
|||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return fromNativeBinary(foreign.asBinaryTag());
|
return fromNativeLin(foreign.toLinTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
default T fromNativeBinary(BinaryTag foreign) {
|
default T fromNativeLin(LinTag<?> foreign) {
|
||||||
if (foreign == null) {
|
if (foreign == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return fromNative(AdventureNBTConverter.fromAdventure(foreign));
|
return fromNative(LinBusConverter.toJnbtTag(foreign));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -135,6 +135,7 @@ permissions:
|
|||||||
worldedit.brush.options.transform: true
|
worldedit.brush.options.transform: true
|
||||||
worldedit.brush.options.scroll: true
|
worldedit.brush.options.scroll: true
|
||||||
worldedit.brush.options.visualize: true
|
worldedit.brush.options.visualize: true
|
||||||
|
worldedit.tool.none: true
|
||||||
worldedit.tool.deltree: true
|
worldedit.tool.deltree: true
|
||||||
worldedit.tool.farwand: true
|
worldedit.tool.farwand: true
|
||||||
worldedit.tool.lrbuild: true
|
worldedit.tool.lrbuild: true
|
||||||
|
@ -46,7 +46,6 @@ dependencies {
|
|||||||
implementation(libs.findbugs)
|
implementation(libs.findbugs)
|
||||||
implementation(libs.rhino)
|
implementation(libs.rhino)
|
||||||
compileOnly(libs.adventureApi)
|
compileOnly(libs.adventureApi)
|
||||||
compileOnlyApi(libs.adventureNbt)
|
|
||||||
compileOnlyApi(libs.adventureMiniMessage)
|
compileOnlyApi(libs.adventureMiniMessage)
|
||||||
implementation(libs.zstd) { isTransitive = false }
|
implementation(libs.zstd) { isTransitive = false }
|
||||||
compileOnly(libs.paster)
|
compileOnly(libs.paster)
|
||||||
@ -56,10 +55,10 @@ dependencies {
|
|||||||
antlr(libs.antlr4)
|
antlr(libs.antlr4)
|
||||||
implementation(libs.antlr4Runtime)
|
implementation(libs.antlr4Runtime)
|
||||||
implementation(libs.jsonSimple) { isTransitive = false }
|
implementation(libs.jsonSimple) { isTransitive = false }
|
||||||
|
implementation(platform(libs.linBus.bom))
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
testRuntimeOnly(libs.log4jCore)
|
testRuntimeOnly(libs.log4jCore)
|
||||||
testImplementation(libs.adventureNbt)
|
|
||||||
testImplementation(libs.parallelgzip)
|
testImplementation(libs.parallelgzip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public class MobSpawnerBlock extends BaseBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getNbtData() {
|
public CompoundTag getNbtData() {
|
||||||
Map<String, Tag> values = new HashMap<>();
|
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||||
values.put("Delay", new ShortTag(delay));
|
values.put("Delay", new ShortTag(delay));
|
||||||
values.put("SpawnCount", new ShortTag(spawnCount));
|
values.put("SpawnCount", new ShortTag(spawnCount));
|
||||||
values.put("SpawnRange", new ShortTag(spawnRange));
|
values.put("SpawnRange", new ShortTag(spawnRange));
|
||||||
@ -170,7 +170,7 @@ public class MobSpawnerBlock extends BaseBlock {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Tag> values = rootTag.getValue();
|
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||||
|
|
||||||
Tag t = values.get("id");
|
Tag t = values.get("id");
|
||||||
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) {
|
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) {
|
||||||
|
@ -104,7 +104,7 @@ public class SignBlock extends BaseBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getNbtData() {
|
public CompoundTag getNbtData() {
|
||||||
Map<String, Tag> values = new HashMap<>();
|
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||||
if (isLegacy()) {
|
if (isLegacy()) {
|
||||||
values.put("Text1", new StringTag(text[0]));
|
values.put("Text1", new StringTag(text[0]));
|
||||||
values.put("Text2", new StringTag(text[1]));
|
values.put("Text2", new StringTag(text[1]));
|
||||||
@ -112,7 +112,7 @@ public class SignBlock extends BaseBlock {
|
|||||||
values.put("Text4", new StringTag(text[3]));
|
values.put("Text4", new StringTag(text[3]));
|
||||||
} else {
|
} else {
|
||||||
ListTag messages = new ListTag(StringTag.class, Arrays.stream(text).map(StringTag::new).collect(Collectors.toList()));
|
ListTag messages = new ListTag(StringTag.class, Arrays.stream(text).map(StringTag::new).collect(Collectors.toList()));
|
||||||
Map<String, Tag> frontTextTag = new HashMap<>();
|
Map<String, Tag<?, ?>> frontTextTag = new HashMap<>();
|
||||||
frontTextTag.put("messages", messages);
|
frontTextTag.put("messages", messages);
|
||||||
values.put("front_text", new CompoundTag(frontTextTag));
|
values.put("front_text", new CompoundTag(frontTextTag));
|
||||||
}
|
}
|
||||||
@ -125,9 +125,9 @@ public class SignBlock extends BaseBlock {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Tag> values = rootTag.getValue();
|
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||||
|
|
||||||
Tag t;
|
Tag<?, ?> t;
|
||||||
|
|
||||||
text = new String[]{EMPTY, EMPTY, EMPTY, EMPTY};
|
text = new String[]{EMPTY, EMPTY, EMPTY, EMPTY};
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ public class SkullBlock extends BaseBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getNbtData() {
|
public CompoundTag getNbtData() {
|
||||||
Map<String, Tag> values = new HashMap<>();
|
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||||
Map<String, Tag> inner = new HashMap<>();
|
Map<String, Tag<?, ?>> inner = new HashMap<>();
|
||||||
inner.put("Name", new StringTag(owner));
|
inner.put("Name", new StringTag(owner));
|
||||||
values.put(DeprecationUtil.getHeadOwnerKey(), new CompoundTag(inner));
|
values.put(DeprecationUtil.getHeadOwnerKey(), new CompoundTag(inner));
|
||||||
return new CompoundTag(values);
|
return new CompoundTag(values);
|
||||||
@ -113,7 +113,7 @@ public class SkullBlock extends BaseBlock {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Tag> values = rootTag.getValue();
|
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||||
|
|
||||||
Tag t;
|
Tag t;
|
||||||
|
|
||||||
|
@ -116,7 +116,10 @@ public class FaweAPI {
|
|||||||
* @param file the file to load
|
* @param file the file to load
|
||||||
* @return a clipboard containing the schematic
|
* @return a clipboard containing the schematic
|
||||||
* @see ClipboardFormat
|
* @see ClipboardFormat
|
||||||
|
* @deprecated Opens streams that are not then closed. Use {@link ClipboardFormats#findByFile(File)} and its relevant
|
||||||
|
* methods to allow closing created streams/closing the reader (which will close the stream(s))
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "2.11.1")
|
||||||
public static Clipboard load(File file) throws IOException {
|
public static Clipboard load(File file) throws IOException {
|
||||||
return ClipboardFormats.findByFile(file).load(file);
|
return ClipboardFormats.findByFile(file).load(file);
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ public enum FaweCache implements Trimable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CompoundTag asTag(Map<String, Object> value) {
|
public CompoundTag asTag(Map<String, Object> value) {
|
||||||
HashMap<String, Tag> map = new HashMap<>();
|
HashMap<String, Tag<?, ?>> map = new HashMap<>();
|
||||||
for (Map.Entry<String, Object> entry : value.entrySet()) {
|
for (Map.Entry<String, Object> entry : value.entrySet()) {
|
||||||
Object child = entry.getValue();
|
Object child = entry.getValue();
|
||||||
Tag tag = asTag(child);
|
Tag tag = asTag(child);
|
||||||
|
@ -91,7 +91,7 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
|||||||
newClipboard.setOrigin(position);
|
newClipboard.setOrigin(position);
|
||||||
ClipboardHolder holder = new ClipboardHolder(newClipboard);
|
ClipboardHolder holder = new ClipboardHolder(newClipboard);
|
||||||
session.setClipboard(holder);
|
session.setClipboard(holder);
|
||||||
int blocks = builder.size();
|
long blocks = builder.longSize();
|
||||||
player.print(Caption.of("fawe.worldedit.copy.command.copy", blocks));
|
player.print(Caption.of("fawe.worldedit.copy.command.copy", blocks));
|
||||||
} else {
|
} else {
|
||||||
AffineTransform transform = null;
|
AffineTransform transform = null;
|
||||||
|
@ -24,7 +24,8 @@ public record PopulateSchem(Mask mask, List<ClipboardHolder> clipboards, int rar
|
|||||||
CuboidRegion cuboid = new CuboidRegion(
|
CuboidRegion cuboid = new CuboidRegion(
|
||||||
editSession.getWorld(),
|
editSession.getWorld(),
|
||||||
position.subtract(size1, size1, size1),
|
position.subtract(size1, size1, size1),
|
||||||
position.add(size1, size1, size1)
|
position.add(size1, size1, size1),
|
||||||
|
true
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
editSession.addSchems(cuboid, mask, clipboards, rarity, randomRotate);
|
editSession.addSchems(cuboid, mask, clipboards, rarity, randomRotate);
|
||||||
|
@ -51,6 +51,7 @@ public abstract class Scroll implements ScrollTool {
|
|||||||
parserContext.setActor(player);
|
parserContext.setActor(player);
|
||||||
parserContext.setWorld(player.getWorld());
|
parserContext.setWorld(player.getWorld());
|
||||||
parserContext.setSession(session);
|
parserContext.setSession(session);
|
||||||
|
parserContext.setTryLegacy(player.getLimit().ALLOW_LEGACY);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CLIPBOARD:
|
case CLIPBOARD:
|
||||||
if (arguments.size() != 2) {
|
if (arguments.size() != 2) {
|
||||||
|
@ -6,6 +6,7 @@ import com.sk89q.util.StringUtil;
|
|||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@ -18,6 +19,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -31,10 +33,15 @@ public class Config {
|
|||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
private final Map<String, Object> removedKeyVals = new HashMap<>();
|
private final Map<String, Object> removedKeyVals = new HashMap<>();
|
||||||
|
@Nullable
|
||||||
|
private Map<String, Map.Entry<String, Object>> copyTo = new HashMap<>();
|
||||||
|
private boolean performCopyTo = false;
|
||||||
private List<String> existingMigrateNodes = null;
|
private List<String> existingMigrateNodes = null;
|
||||||
|
|
||||||
public Config() {
|
public Config() {
|
||||||
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
|
// This is now definitely required as the save -> load -> save order means the @CopiedFrom annotated fields work
|
||||||
|
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0, null);
|
||||||
|
performCopyTo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,11 +67,12 @@ public class Config {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value of a specific node. Probably throws some error if you supply non existing keys or invalid values.
|
* Set the value of a specific node. Probably throws some error if you supply non existing keys or invalid values.
|
||||||
|
* This should only be called during loading of a config file
|
||||||
*
|
*
|
||||||
* @param key config node
|
* @param key config node
|
||||||
* @param value value
|
* @param value value
|
||||||
*/
|
*/
|
||||||
private void set(String key, Object value, Class<?> root) {
|
private void setLoadedNode(String key, Object value, Class<?> root) {
|
||||||
String[] split = key.split("\\.");
|
String[] split = key.split("\\.");
|
||||||
Object instance = getInstance(split, root);
|
Object instance = getInstance(split, root);
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
@ -74,8 +82,18 @@ public class Config {
|
|||||||
if (field.getAnnotation(Final.class) != null) {
|
if (field.getAnnotation(Final.class) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (copyTo != null) {
|
||||||
|
copyTo.remove(key); // Remove if the config field is already written
|
||||||
|
final Object finalValue = value;
|
||||||
|
copyTo.replaceAll((copyToNode, entry) -> {
|
||||||
|
if (!key.equals(entry.getKey())) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
return new AbstractMap.SimpleEntry<>(key, finalValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
Migrate migrate = field.getAnnotation(Migrate.class);
|
Migrate migrate = field.getAnnotation(Migrate.class);
|
||||||
if (existingMigrateNodes != null && migrate != null) {
|
if (migrate != null) {
|
||||||
existingMigrateNodes.add(migrate.value());
|
existingMigrateNodes.add(migrate.value());
|
||||||
}
|
}
|
||||||
if (field.getType() == String.class && !(value instanceof String)) {
|
if (field.getType() == String.class && !(value instanceof String)) {
|
||||||
@ -90,8 +108,9 @@ public class Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
removedKeyVals.put(key, value);
|
removedKeyVals.put(key, value);
|
||||||
LOGGER.error(
|
LOGGER.warn(
|
||||||
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed.",
|
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed or was set with an " +
|
||||||
|
"invalid value.",
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
instance,
|
instance,
|
||||||
@ -110,7 +129,7 @@ public class Config {
|
|||||||
if (value instanceof MemorySection) {
|
if (value instanceof MemorySection) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
set(key, value, getClass());
|
setLoadedNode(key, value, getClass());
|
||||||
}
|
}
|
||||||
for (String node : existingMigrateNodes) {
|
for (String node : existingMigrateNodes) {
|
||||||
removedKeyVals.remove(node);
|
removedKeyVals.remove(node);
|
||||||
@ -133,7 +152,7 @@ public class Config {
|
|||||||
}
|
}
|
||||||
PrintWriter writer = new PrintWriter(file);
|
PrintWriter writer = new PrintWriter(file);
|
||||||
Object instance = this;
|
Object instance = this;
|
||||||
save(writer, getClass(), instance, 0);
|
save(writer, getClass(), instance, 0, null);
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.error("Failed to save config file: {}", file, e);
|
LOGGER.error("Failed to save config file: {}", file, e);
|
||||||
@ -190,7 +209,7 @@ public class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that a field should be instantiated / created.
|
* Indicates that a field should be migrated from a node that is deleted
|
||||||
*
|
*
|
||||||
* @since 2.10.0
|
* @since 2.10.0
|
||||||
*/
|
*/
|
||||||
@ -202,6 +221,19 @@ public class Config {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a field's default value should match another input if the config is otherwise already generated
|
||||||
|
*
|
||||||
|
* @since 2.11.0
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
public @interface CopiedFrom {
|
||||||
|
|
||||||
|
String value();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Ignore // This is not part of the config
|
@Ignore // This is not part of the config
|
||||||
public static class ConfigBlock<T> {
|
public static class ConfigBlock<T> {
|
||||||
|
|
||||||
@ -254,7 +286,7 @@ public class Config {
|
|||||||
return value != null ? value.toString() : "null";
|
return value != null ? value.toString() : "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent) {
|
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent, String parentNode) {
|
||||||
try {
|
try {
|
||||||
String CTRF = System.lineSeparator();
|
String CTRF = System.lineSeparator();
|
||||||
String spacing = StringMan.repeat(" ", indent);
|
String spacing = StringMan.repeat(" ", indent);
|
||||||
@ -274,7 +306,7 @@ public class Config {
|
|||||||
}
|
}
|
||||||
if (current == ConfigBlock.class) {
|
if (current == ConfigBlock.class) {
|
||||||
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
|
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
|
||||||
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current);
|
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current, parentNode);
|
||||||
continue;
|
continue;
|
||||||
} else if (!removedKeyVals.isEmpty()) {
|
} else if (!removedKeyVals.isEmpty()) {
|
||||||
Migrate migrate = field.getAnnotation(Migrate.class);
|
Migrate migrate = field.getAnnotation(Migrate.class);
|
||||||
@ -283,6 +315,18 @@ public class Config {
|
|||||||
field.set(instance, value);
|
field.set(instance, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CopiedFrom copiedFrom;
|
||||||
|
if (copyTo != null && (copiedFrom = field.getAnnotation(CopiedFrom.class)) != null) {
|
||||||
|
String node = toNodeName(field.getName());
|
||||||
|
node = parentNode == null ? node : parentNode + "." + node;
|
||||||
|
Map.Entry<String, Object> entry = copyTo.remove(node);
|
||||||
|
Object copiedVal;
|
||||||
|
if (entry == null) {
|
||||||
|
copyTo.put(node, new AbstractMap.SimpleEntry<>(copiedFrom.value(), null));
|
||||||
|
} else if ((copiedVal = entry.getValue()) != null) {
|
||||||
|
field.set(instance, copiedVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
Create create = field.getAnnotation(Create.class);
|
Create create = field.getAnnotation(Create.class);
|
||||||
if (create != null) {
|
if (create != null) {
|
||||||
Object value = field.get(instance);
|
Object value = field.get(instance);
|
||||||
@ -296,11 +340,12 @@ public class Config {
|
|||||||
writer.write(spacing + "# " + commentLine + CTRF);
|
writer.write(spacing + "# " + commentLine + CTRF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
String node = toNodeName(current.getSimpleName());
|
||||||
|
writer.write(spacing + node + ":" + CTRF);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
field.set(instance, value = current.getDeclaredConstructor().newInstance());
|
field.set(instance, value = current.getDeclaredConstructor().newInstance());
|
||||||
}
|
}
|
||||||
save(writer, current, value, indent + 2);
|
save(writer, current, value, indent + 2, parentNode == null ? node : parentNode + "." + node);
|
||||||
} else {
|
} else {
|
||||||
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
|
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
|
||||||
field.get(instance),
|
field.get(instance),
|
||||||
@ -311,6 +356,10 @@ public class Config {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.error("Failed to save config file", e);
|
LOGGER.error("Failed to save config file", e);
|
||||||
}
|
}
|
||||||
|
if (parentNode == null && performCopyTo) {
|
||||||
|
performCopyTo = false;
|
||||||
|
copyTo = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void handleConfigBlockSave(
|
private <T> void handleConfigBlockSave(
|
||||||
@ -320,7 +369,8 @@ public class Config {
|
|||||||
Field field,
|
Field field,
|
||||||
String spacing,
|
String spacing,
|
||||||
String CTRF,
|
String CTRF,
|
||||||
Class<T> current
|
Class<T> current,
|
||||||
|
String parentNode
|
||||||
) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
|
) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
|
||||||
Comment comment = current.getAnnotation(Comment.class);
|
Comment comment = current.getAnnotation(Comment.class);
|
||||||
if (comment != null) {
|
if (comment != null) {
|
||||||
@ -330,6 +380,7 @@ public class Config {
|
|||||||
}
|
}
|
||||||
BlockName blockNames = current.getAnnotation(BlockName.class);
|
BlockName blockNames = current.getAnnotation(BlockName.class);
|
||||||
if (blockNames != null) {
|
if (blockNames != null) {
|
||||||
|
String node = toNodeName(current.getSimpleName());
|
||||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||||
ConfigBlock<T> configBlock = (ConfigBlock<T>) field.get(instance);
|
ConfigBlock<T> configBlock = (ConfigBlock<T>) field.get(instance);
|
||||||
if (configBlock == null || configBlock.getInstances().isEmpty()) {
|
if (configBlock == null || configBlock.getInstances().isEmpty()) {
|
||||||
@ -343,7 +394,7 @@ public class Config {
|
|||||||
for (Map.Entry<String, T> entry : configBlock.getRaw().entrySet()) {
|
for (Map.Entry<String, T> entry : configBlock.getRaw().entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
|
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
|
||||||
save(writer, current, entry.getValue(), indent + 4);
|
save(writer, current, entry.getValue(), indent + 4, parentNode == null ? node : parentNode + "." + node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,7 @@ public class Settings extends Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
limit.UNIVERSAL_DISALLOWED_BLOCKS &= newLimit.UNIVERSAL_DISALLOWED_BLOCKS;
|
limit.UNIVERSAL_DISALLOWED_BLOCKS &= newLimit.UNIVERSAL_DISALLOWED_BLOCKS;
|
||||||
|
limit.ALLOW_LEGACY &= newLimit.ALLOW_LEGACY;
|
||||||
|
|
||||||
if (limit.DISALLOWED_BLOCKS == null) {
|
if (limit.DISALLOWED_BLOCKS == null) {
|
||||||
limit.DISALLOWED_BLOCKS = newLimit.DISALLOWED_BLOCKS.isEmpty() ? Collections.emptySet() : new HashSet<>(
|
limit.DISALLOWED_BLOCKS = newLimit.DISALLOWED_BLOCKS.isEmpty() ? Collections.emptySet() : new HashSet<>(
|
||||||
@ -439,6 +440,10 @@ public class Settings extends Config {
|
|||||||
" - If fast-placement is disabled, this may cause edits to be slower."
|
" - If fast-placement is disabled, this may cause edits to be slower."
|
||||||
})
|
})
|
||||||
public boolean UNIVERSAL_DISALLOWED_BLOCKS = true;
|
public boolean UNIVERSAL_DISALLOWED_BLOCKS = true;
|
||||||
|
@Comment({
|
||||||
|
"If legacy, mumerical, blocks IDs should be able to be used (i.e. 12:2),"
|
||||||
|
})
|
||||||
|
public boolean ALLOW_LEGACY = true;
|
||||||
@Comment({
|
@Comment({
|
||||||
"List of blocks to deny use of. Can be either an entire block type or a block with a specific property value.",
|
"List of blocks to deny use of. Can be either an entire block type or a block with a specific property value.",
|
||||||
"Where block properties are specified, any blockstate with the property will be disallowed (e.g. all directions",
|
"Where block properties are specified, any blockstate with the property will be disallowed (e.g. all directions",
|
||||||
@ -518,6 +523,9 @@ public class Settings extends Config {
|
|||||||
public int DELETE_AFTER_DAYS = 7;
|
public int DELETE_AFTER_DAYS = 7;
|
||||||
@Comment("Delete history in memory on logout (does not effect disk)")
|
@Comment("Delete history in memory on logout (does not effect disk)")
|
||||||
public boolean DELETE_ON_LOGOUT = true;
|
public boolean DELETE_ON_LOGOUT = true;
|
||||||
|
@Comment("Delete history on disk on logout")
|
||||||
|
@CopiedFrom("history.delete-on-logout")
|
||||||
|
public boolean DELETE_DISK_ON_LOGOUT = false;
|
||||||
@Comment({
|
@Comment({
|
||||||
"If history should be enabled by default for plugins using WorldEdit:",
|
"If history should be enabled by default for plugins using WorldEdit:",
|
||||||
" - It is faster to have disabled",
|
" - It is faster to have disabled",
|
||||||
|
@ -64,26 +64,47 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
public Future<Boolean> init() {
|
public Future<Boolean> init() {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("CREATE TABLE IF NOT EXISTS`" + this.prefix +
|
try (PreparedStatement stmt = connection.prepareStatement("CREATE TABLE IF NOT EXISTS`" + this.prefix +
|
||||||
"edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1`" +
|
"_edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1` " +
|
||||||
"INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1`" +
|
"INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1` " +
|
||||||
"INT NOT NULL, `y2` INT NOT NULL, `size` INT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) {
|
"INT NOT NULL, `y2` INT NOT NULL, `size` BIGINT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) {
|
||||||
stmt.executeUpdate();
|
stmt.executeUpdate();
|
||||||
}
|
}
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD COLUMN `command` VARCHAR")) {
|
String alterTablePrefix = "ALTER TABLE`" + this.prefix + "edits` ";
|
||||||
|
try (PreparedStatement stmt =
|
||||||
|
connection.prepareStatement(alterTablePrefix + "ADD COLUMN `command` VARCHAR")) {
|
||||||
stmt.executeUpdate();
|
stmt.executeUpdate();
|
||||||
} catch (SQLException ignored) {
|
} catch (SQLException ignored) {
|
||||||
} // Already updated
|
} // Already updated
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD SIZE INT DEFAULT 0 NOT NULL")) {
|
try (PreparedStatement stmt =
|
||||||
|
connection.prepareStatement(alterTablePrefix + "ADD COLUMN `size` BIGINT DEFAULT 0 NOT NULL")) {
|
||||||
stmt.executeUpdate();
|
stmt.executeUpdate();
|
||||||
} catch (SQLException ignored) {
|
} catch (SQLException ignored) {
|
||||||
} // Already updated
|
} // Already updated
|
||||||
|
|
||||||
|
boolean migrated = false;
|
||||||
|
try (PreparedStatement stmt =
|
||||||
|
connection.prepareStatement("INSERT INTO `" + this.prefix + "_edits` " +
|
||||||
|
"(player, id, time, x1, x2, z1, z2, y1, y2, size, command) " +
|
||||||
|
"SELECT player, id, time, x1, x2, z1, z2, y1, y2, size, command " +
|
||||||
|
"FROM `" + this.prefix + "edits`")) {
|
||||||
|
|
||||||
|
stmt.executeUpdate();
|
||||||
|
migrated = true;
|
||||||
|
} catch (SQLException ignored) {
|
||||||
|
} // Already updated
|
||||||
|
if (migrated) {
|
||||||
|
try (PreparedStatement stmt = connection.prepareStatement("DROP TABLE `" + this.prefix + "edits`")) {
|
||||||
|
stmt.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Future<Integer> delete(UUID uuid, int id) {
|
public Future<Integer> delete(UUID uuid, int id) {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `player`=? AND `id`=?")) {
|
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "_edits` WHERE `player`=? " +
|
||||||
|
"AND `id`=?")) {
|
||||||
stmt.setBytes(1, toBytes(uuid));
|
stmt.setBytes(1, toBytes(uuid));
|
||||||
stmt.setInt(2, id);
|
stmt.setInt(2, id);
|
||||||
return stmt.executeUpdate();
|
return stmt.executeUpdate();
|
||||||
@ -94,7 +115,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
public Future<RollbackOptimizedHistory> getEdit(@Nonnull UUID uuid, int id) {
|
public Future<RollbackOptimizedHistory> getEdit(@Nonnull UUID uuid, int id) {
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM`" + this.prefix +
|
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM`" + this.prefix +
|
||||||
"edits` WHERE `player`=? AND `id`=?")) {
|
"_edits` WHERE `player`=? AND `id`=?")) {
|
||||||
stmt.setBytes(1, toBytes(uuid));
|
stmt.setBytes(1, toBytes(uuid));
|
||||||
stmt.setInt(2, id);
|
stmt.setInt(2, id);
|
||||||
ResultSet result = stmt.executeQuery();
|
ResultSet result = stmt.executeQuery();
|
||||||
@ -119,7 +140,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
CuboidRegion region = new CuboidRegion(BlockVector3.at(x1, y1, z1), BlockVector3.at(x2, y2, z2));
|
CuboidRegion region = new CuboidRegion(BlockVector3.at(x1, y1, z1), BlockVector3.at(x2, y2, z2));
|
||||||
|
|
||||||
long time = result.getInt("time") * 1000L;
|
long time = result.getInt("time") * 1000L;
|
||||||
long size = result.getInt("size");
|
long size = result.getLong("size");
|
||||||
|
|
||||||
String command = result.getString("command");
|
String command = result.getString("command");
|
||||||
|
|
||||||
@ -135,7 +156,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
long now = System.currentTimeMillis() / 1000;
|
long now = System.currentTimeMillis() / 1000;
|
||||||
final int then = (int) (now - diff);
|
final int then = (int) (now - diff);
|
||||||
return call(() -> {
|
return call(() -> {
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `time`<?")) {
|
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "_edits` WHERE `time`<?")) {
|
||||||
stmt.setInt(1, then);
|
stmt.setInt(1, then);
|
||||||
return stmt.executeUpdate();
|
return stmt.executeUpdate();
|
||||||
}
|
}
|
||||||
@ -160,7 +181,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
try {
|
try {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
String stmtStr = """
|
String stmtStr = """
|
||||||
SELECT * FROM `%sedits`
|
SELECT * FROM `%s_edits`
|
||||||
WHERE `time` > ?
|
WHERE `time` > ?
|
||||||
AND `x2` >= ?
|
AND `x2` >= ?
|
||||||
AND `x1` <= ?
|
AND `x1` <= ?
|
||||||
@ -202,7 +223,8 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
}
|
}
|
||||||
if (delete && uuid != null) {
|
if (delete && uuid != null) {
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix +
|
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix +
|
||||||
"edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=?")) {
|
"_edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? " +
|
||||||
|
"AND `z1`<=?")) {
|
||||||
byte[] uuidBytes = ByteBuffer
|
byte[] uuidBytes = ByteBuffer
|
||||||
.allocate(16)
|
.allocate(16)
|
||||||
.putLong(uuid.getMostSignificantBits())
|
.putLong(uuid.getMostSignificantBits())
|
||||||
@ -249,7 +271,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
RollbackOptimizedHistory[] copy = IntStream.range(0, size)
|
RollbackOptimizedHistory[] copy = IntStream.range(0, size)
|
||||||
.mapToObj(i -> historyChanges.poll()).toArray(RollbackOptimizedHistory[]::new);
|
.mapToObj(i -> historyChanges.poll()).toArray(RollbackOptimizedHistory[]::new);
|
||||||
|
|
||||||
try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "edits`" +
|
try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "_edits`" +
|
||||||
" (`player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)")) {
|
" (`player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)")) {
|
||||||
// `player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)"
|
// `player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)"
|
||||||
for (RollbackOptimizedHistory change : copy) {
|
for (RollbackOptimizedHistory change : copy) {
|
||||||
@ -270,7 +292,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
stmt.setInt(8, pos1.y() - 128);
|
stmt.setInt(8, pos1.y() - 128);
|
||||||
stmt.setInt(9, pos2.y() - 128);
|
stmt.setInt(9, pos2.y() - 128);
|
||||||
stmt.setString(10, change.getCommand());
|
stmt.setString(10, change.getCommand());
|
||||||
stmt.setInt(11, change.size());
|
stmt.setLong(11, change.longSize());
|
||||||
stmt.executeUpdate();
|
stmt.executeUpdate();
|
||||||
stmt.clearParameters();
|
stmt.clearParameters();
|
||||||
}
|
}
|
||||||
|
@ -3,25 +3,25 @@ package com.fastasyncworldedit.core.entity;
|
|||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
import com.sk89q.worldedit.world.entity.EntityType;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class LazyBaseEntity extends BaseEntity {
|
public class LazyBaseEntity extends BaseEntity {
|
||||||
|
|
||||||
private Supplier<CompoundBinaryTag> saveTag;
|
private Supplier<LinCompoundTag> saveTag;
|
||||||
|
|
||||||
public LazyBaseEntity(EntityType type, Supplier<CompoundBinaryTag> saveTag) {
|
public LazyBaseEntity(EntityType type, Supplier<LinCompoundTag> saveTag) {
|
||||||
super(type);
|
super(type);
|
||||||
this.saveTag = saveTag;
|
this.saveTag = saveTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public CompoundBinaryTag getNbt() {
|
public LinCompoundTag getNbt() {
|
||||||
Supplier<CompoundBinaryTag> tmp = saveTag;
|
Supplier<LinCompoundTag> tmp = saveTag;
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
saveTag = null;
|
saveTag = null;
|
||||||
if (Fawe.isMainThread()) {
|
if (Fawe.isMainThread()) {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.fastasyncworldedit.core.exception;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
|
||||||
|
public class OutsideWorldBoundsException extends WorldEditException {
|
||||||
|
|
||||||
|
private final int y;
|
||||||
|
|
||||||
|
public OutsideWorldBoundsException(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int y() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -143,7 +143,7 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
int end = command.lastIndexOf(']');
|
int end = command.lastIndexOf(']');
|
||||||
mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
|
mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
|
||||||
} else {
|
} else {
|
||||||
BlockMaskBuilder builder = new BlockMaskBuilder();
|
BlockMaskBuilder builder = new BlockMaskBuilder(context);
|
||||||
try {
|
try {
|
||||||
builder.addRegex(full);
|
builder.addRegex(full);
|
||||||
} catch (InputParseException ignored) {
|
} catch (InputParseException ignored) {
|
||||||
|
@ -200,6 +200,7 @@ public class ConsumeBindings extends Bindings {
|
|||||||
public BaseBlock baseBlock(Actor actor, String argument) {
|
public BaseBlock baseBlock(Actor actor, String argument) {
|
||||||
ParserContext parserContext = new ParserContext();
|
ParserContext parserContext = new ParserContext();
|
||||||
parserContext.setActor(actor);
|
parserContext.setActor(actor);
|
||||||
|
parserContext.setTryLegacy(actor.getLimit().ALLOW_LEGACY);
|
||||||
if (actor instanceof Entity) {
|
if (actor instanceof Entity) {
|
||||||
Extent extent = ((Entity) actor).getExtent();
|
Extent extent = ((Entity) actor).getExtent();
|
||||||
if (extent instanceof World) {
|
if (extent instanceof World) {
|
||||||
|
@ -101,7 +101,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
if (!contains(x, z)) {
|
if (!contains(x, y, z)) {
|
||||||
if (!limit.MAX_FAILS()) {
|
if (!limit.MAX_FAILS()) {
|
||||||
WEManager.weManager().cancelEditSafe(this, FaweCache.OUTSIDE_REGION);
|
WEManager.weManager().cancelEditSafe(this, FaweCache.OUTSIDE_REGION);
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,6 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -81,7 +79,7 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
CompoundTag nbt = localBlock.getNbtData();
|
CompoundTag nbt = localBlock.getNbtData();
|
||||||
Map<String, Tag> value = new HashMap<>(nbt.getValue());
|
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
|
||||||
for (String key : strip) {
|
for (String key : strip) {
|
||||||
value.remove(key);
|
value.remove(key);
|
||||||
}
|
}
|
||||||
@ -93,7 +91,7 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
CompoundTag nbt = entity.getNbtData();
|
CompoundTag nbt = entity.getNbtData();
|
||||||
Map<String, Tag> value = new HashMap<>(nbt.getValue());
|
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
|
||||||
for (String key : strip) {
|
for (String key : strip) {
|
||||||
value.remove(key);
|
value.remove(key);
|
||||||
}
|
}
|
||||||
@ -110,7 +108,7 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
}
|
}
|
||||||
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
|
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
|
||||||
for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
|
for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
|
||||||
ImmutableMap.Builder<String, Tag> map = ImmutableMap.builder();
|
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
|
||||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
||||||
entry.getValue().getValue().forEach((k, v) -> {
|
entry.getValue().getValue().forEach((k, v) -> {
|
||||||
if (strip.contains(k.toLowerCase())) {
|
if (strip.contains(k.toLowerCase())) {
|
||||||
@ -132,7 +130,7 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
CompoundTag entity = iterator.next();
|
CompoundTag entity = iterator.next();
|
||||||
ImmutableMap.Builder<String, Tag> map = ImmutableMap.builder();
|
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
|
||||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
||||||
entity.getValue().forEach((k, v) -> {
|
entity.getValue().forEach((k, v) -> {
|
||||||
if (strip.contains(k.toUpperCase(Locale.ROOT))) {
|
if (strip.contains(k.toUpperCase(Locale.ROOT))) {
|
||||||
|
@ -93,7 +93,7 @@ public class TransformExtent extends BlockTransformExtent {
|
|||||||
@Override
|
@Override
|
||||||
public BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
BlockVector3 p = getPos(x, y, z);
|
BlockVector3 p = getPos(x, y, z);
|
||||||
return super.getBiomeType(p.x(), y, p.z());
|
return super.getBiomeType(p.x(), p.y(), p.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,7 +152,7 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
|||||||
public Collection<CompoundTag> getTileEntities() {
|
public Collection<CompoundTag> getTileEntities() {
|
||||||
convertTilesToIndex();
|
convertTilesToIndex();
|
||||||
nbtMapIndex.replaceAll((index, tag) -> {
|
nbtMapIndex.replaceAll((index, tag) -> {
|
||||||
Map<String, Tag> values = new HashMap<>(tag.getValue());
|
Map<String, Tag<?, ?>> values = new HashMap<>(tag.getValue());
|
||||||
if (!values.containsKey("x")) {
|
if (!values.containsKey("x")) {
|
||||||
int y = index / getArea();
|
int y = index / getArea();
|
||||||
index -= y * getArea();
|
index -= y * getArea();
|
||||||
@ -176,7 +176,7 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean setTile(int index, CompoundTag tag) {
|
private boolean setTile(int index, CompoundTag tag) {
|
||||||
final Map<String, Tag> values = new HashMap<>(tag.getValue());
|
final Map<String, Tag<?, ?>> values = new HashMap<>(tag.getValue());
|
||||||
values.remove("x");
|
values.remove("x");
|
||||||
values.remove("y");
|
values.remove("y");
|
||||||
values.remove("z");
|
values.remove("z");
|
||||||
|
@ -586,7 +586,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
for (BlockArrayClipboard.ClipboardEntity entity : entities) {
|
for (BlockArrayClipboard.ClipboardEntity entity : entities) {
|
||||||
if (entity.getState() != null && entity.getState().getNbtData() != null) {
|
if (entity.getState() != null && entity.getState().getNbtData() != null) {
|
||||||
CompoundTag data = entity.getState().getNbtData();
|
CompoundTag data = entity.getState().getNbtData();
|
||||||
HashMap<String, Tag> value = new HashMap<>(data.getValue());
|
HashMap<String, Tag<?, ?>> value = new HashMap<>(data.getValue());
|
||||||
List<DoubleTag> pos = new ArrayList<>(3);
|
List<DoubleTag> pos = new ArrayList<>(3);
|
||||||
pos.add(new DoubleTag(entity.getLocation().x()));
|
pos.add(new DoubleTag(entity.getLocation().x()));
|
||||||
pos.add(new DoubleTag(entity.getLocation().x()));
|
pos.add(new DoubleTag(entity.getLocation().x()));
|
||||||
@ -710,7 +710,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setTile(int x, int y, int z, CompoundTag tag) {
|
public boolean setTile(int x, int y, int z, CompoundTag tag) {
|
||||||
final Map<String, Tag> values = new HashMap<>(tag.getValue());
|
final Map<String, Tag<?, ?>> values = new HashMap<>(tag.getValue());
|
||||||
values.put("x", new IntTag(x));
|
values.put("x", new IntTag(x));
|
||||||
values.put("y", new IntTag(y));
|
values.put("y", new IntTag(y));
|
||||||
values.put("z", new IntTag(z));
|
values.put("z", new IntTag(z));
|
||||||
|
@ -106,7 +106,7 @@ public abstract class LinearClipboard extends SimpleClipboard {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
Map<String, Tag> map = new HashMap<>(entity.getNbtData().getValue());
|
Map<String, Tag<?, ?>> map = new HashMap<>(entity.getNbtData().getValue());
|
||||||
NBTUtils.addUUIDToMap(map, uuid);
|
NBTUtils.addUUIDToMap(map, uuid);
|
||||||
entity.setNbtData(new CompoundTag(map));
|
entity.setNbtData(new CompoundTag(map));
|
||||||
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user