3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-10-04 20:51:05 +02:00

Merge branch 'v3' into feature/anvil

Dieser Commit ist enthalten in:
dordsor21 2024-03-27 17:01:38 +00:00
Commit b735405b54
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 1E53E88969FFCF0B
171 geänderte Dateien mit 3341 neuen und 2606 gelöschten Zeilen

Datei anzeigen

@ -342,7 +342,7 @@ ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true ij_editorconfig_spaces_around_assignment_operators = true
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.pom, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul}] [{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
ij_xml_align_attributes = true ij_xml_align_attributes = true
ij_xml_align_text = false ij_xml_align_text = false
ij_xml_attribute_wrap = normal ij_xml_attribute_wrap = normal
@ -360,7 +360,7 @@ ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal ij_xml_text_wrap = normal
[{*.ats, *.ts}] [{*.ats,*.ts}]
ij_continuation_indent_size = 4 ij_continuation_indent_size = 4
ij_typescript_align_imports = false ij_typescript_align_imports = false
ij_typescript_align_multiline_array_initializer_expression = false ij_typescript_align_multiline_array_initializer_expression = false
@ -528,7 +528,7 @@ ij_typescript_while_brace_force = never
ij_typescript_while_on_new_line = false ij_typescript_while_on_new_line = false
ij_typescript_wrap_comments = false ij_typescript_wrap_comments = false
[{*.bash, *.sh, *.zsh}] [{*.bash,*.sh,*.zsh}]
indent_size = 2 indent_size = 2
tab_width = 2 tab_width = 2
ij_shell_binary_ops_start_line = false ij_shell_binary_ops_start_line = false
@ -537,7 +537,7 @@ ij_shell_minify_program = false
ij_shell_redirect_followed_by_space = false ij_shell_redirect_followed_by_space = false
ij_shell_switch_cases_indented = false ij_shell_switch_cases_indented = false
[{*.cjs, *.js}] [{*.cjs,*.js}]
ij_continuation_indent_size = 4 ij_continuation_indent_size = 4
ij_javascript_align_imports = false ij_javascript_align_imports = false
ij_javascript_align_multiline_array_initializer_expression = false ij_javascript_align_multiline_array_initializer_expression = false
@ -702,10 +702,10 @@ ij_javascript_while_brace_force = never
ij_javascript_while_on_new_line = false ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false ij_javascript_wrap_comments = false
[{*.ft, *.vm, *.vsl}] [{*.ft,*.vm,*.vsl}]
ij_vtl_keep_indents_on_empty_lines = false ij_vtl_keep_indents_on_empty_lines = false
[{*.gant, *.gradle, *.groovy, *.gy}] [{*.gant,*.gradle,*.groovy,*.gy}]
ij_groovy_align_group_field_declarations = false ij_groovy_align_group_field_declarations = false
ij_groovy_align_multiline_array_initializer_expression = false ij_groovy_align_multiline_array_initializer_expression = false
ij_groovy_align_multiline_assignment = false ij_groovy_align_multiline_assignment = false
@ -884,7 +884,7 @@ ij_groovy_while_brace_force = never
ij_groovy_while_on_new_line = false ij_groovy_while_on_new_line = false
ij_groovy_wrap_long_lines = false ij_groovy_wrap_long_lines = false
[{*.gradle.kts, *.kt, *.kts, *.main.kts}] [{*.gradle.kts,*.kt,*.kts,*.main.kts}]
ij_kotlin_align_in_columns_case_branch = false ij_kotlin_align_in_columns_case_branch = false
ij_kotlin_align_multiline_binary_operation = false ij_kotlin_align_multiline_binary_operation = false
ij_kotlin_align_multiline_extends_list = false ij_kotlin_align_multiline_extends_list = false
@ -963,7 +963,7 @@ ij_kotlin_wrap_elvis_expressions = 1
ij_kotlin_wrap_expression_body_functions = 0 ij_kotlin_wrap_expression_body_functions = 0
ij_kotlin_wrap_first_method_in_call_chain = false ij_kotlin_wrap_first_method_in_call_chain = false
[{*.har, *.jsb2, *.jsb3, *.json, .babelrc, .eslintrc, .stylelintrc, bowerrc, jest.config, mcmod.info}] [{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config,mcmod.info}]
indent_size = 2 indent_size = 2
ij_json_keep_blank_lines_in_code = 0 ij_json_keep_blank_lines_in_code = 0
ij_json_keep_indents_on_empty_lines = false ij_json_keep_indents_on_empty_lines = false
@ -976,7 +976,7 @@ ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false ij_json_wrap_long_lines = false
[{*.htm, *.html, *.sht, *.shtm, *.shtml}] [{*.htm,*.html,*.sht,*.shtm,*.shtml}]
ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
ij_html_align_attributes = true ij_html_align_attributes = true
ij_html_align_text = false ij_html_align_text = false
@ -1004,7 +1004,7 @@ ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal ij_html_text_wrap = normal
ij_html_uniform_ident = false ij_html_uniform_ident = false
[{*.yaml, *.yml}] [{*.yaml,*.yml}]
indent_size = 2 indent_size = 2
ij_yaml_keep_indents_on_empty_lines = false ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true ij_yaml_keep_line_breaks = true

Datei anzeigen

@ -27,11 +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.2' - '1.20.4'
- '1.20' - '1.20'
- '1.19.4' - '1.19.4'
- '1.18.2' - '1.18.2'
- '1.17.1'
validations: validations:
required: true required: true

47
.github/renovate.json vendored
Datei anzeigen

@ -1,18 +1,18 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema" : "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends" : [
"config:base", "config:recommended",
":semanticCommitsDisabled" ":semanticCommitsDisabled"
], ],
"automerge": true, "automerge" : true,
"ignoreDeps": [ "ignoreDeps" : [
"guava", "guava",
"com.google.guava:guava", "com.google.guava:guava",
"rhino-runtime", "rhino-runtime",
"org.antlr", "org.antlr",
"antlr4-runtime", "antlr4-runtime",
"fastutil", "fastutil",
"it.unimi.dsi:fastutil", "it.unimi.dsi:fastutil",
"auto-value-annotations", "auto-value-annotations",
"auto-value", "auto-value",
"com.google.code.gson:gson", "com.google.code.gson:gson",
@ -29,7 +29,34 @@
"org.spongepowered:spongeapi", "org.spongepowered:spongeapi",
"org.yaml:snakeyaml" "org.yaml:snakeyaml"
], ],
"labels": ["Renovate"], "labels" : [
"rebaseWhen": "conflicted", "Renovate"
"schedule": ["on the first day of the month"] ],
"rebaseWhen" : "conflicted",
"customManagers" : [
{
"customType" : "regex",
"datasourceTemplate" : "custom.paperweight-userdev",
"fileMatch" : "^worldedit-bukkit\\/adapters\\/adapter-\\d+_\\d+(_\\d+)?\\/build\\.gradle\\.kts$",
"matchStrings" : [
"url=(?<registryUrl>.*)\\s",
"paperDevBundle\\(\"(?<currentValue>.*?)\"\\)\\s"
],
"matchStringsStrategy": "combination",
"depNameTemplate" : "paperweight-userdev",
"extractVersionTemplate" : "(?<version>\\d+\\.\\d+\\.?\\d*-R0\\.1-\\d+\\.\\d+-\\d+)"
}
],
"customDatasources" : {
"paperweight-userdev": {
"defaultRegistryUrlTemplate": "",
"format": "html"
}
},
"packageRules" : [
{
"matchDatasources" : ["custom.paperweight-userdev"],
"versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)?-R0\\.1-\\d+\\d+\\.\\d+-(?<build>\\d+)$"
}
]
} }

Datei anzeigen

@ -11,9 +11,9 @@ 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/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle

Datei anzeigen

@ -11,9 +11,9 @@ 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/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle

Datei anzeigen

@ -21,16 +21,16 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
java-version: 17 java-version: 17
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3

Datei anzeigen

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

Datei anzeigen

@ -12,6 +12,6 @@ jobs:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: release-drafter/release-drafter@v5 - uses: release-drafter/release-drafter@v6
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Datei anzeigen

@ -9,9 +9,9 @@ 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/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: temurin distribution: temurin
cache: gradle cache: gradle
@ -19,7 +19,7 @@ jobs:
- name: Clean Build - name: Clean Build
run: ./gradlew clean build --no-daemon run: ./gradlew clean build --no-daemon
- name: Upload Release Assets - name: Upload Release Assets
uses: AButler/upload-release-assets@v2.0 uses: AButler/upload-release-assets@v3.0
with: with:
files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar' files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

Datei anzeigen

@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer
plugins { plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.3.0" id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
id("xyz.jpenilla.run-paper") version "2.2.0" id("xyz.jpenilla.run-paper") version "2.2.3"
} }
if (!File("$rootDir/.git").exists()) { if (!File("$rootDir/.git").exists()) {
@ -34,7 +34,7 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("2.8.3") var rootVersion by extra("2.9.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.17.1", "1.18.2", "1.19.4", "1.20", "1.20.2") val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4")
tasks { tasks {
supportedVersions.forEach { supportedVersions.forEach {
@ -97,7 +97,7 @@ tasks {
} }
} }
runServer { runServer {
minecraftVersion("1.20.2") minecraftVersion("1.20.4")
pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
.toTypedArray()) .toTypedArray())

Datei anzeigen

@ -22,9 +22,9 @@ val properties = Properties().also { props ->
dependencies { dependencies {
implementation(gradleApi()) implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.1") implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
implementation("com.github.johnrengelman:shadow:8.1.1") implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.5") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.11")
} }
kotlin { kotlin {

Datei anzeigen

@ -1,6 +1,6 @@
[versions] [versions]
# Minecraft expectations # Minecraft expectations
paper = "1.20.2-R0.1-SNAPSHOT" paper = "1.20.4-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"
@ -11,19 +11,19 @@ snakeyaml = "2.0"
dummypermscompat = "1.10" dummypermscompat = "1.10"
worldguard-bukkit = "7.0.9" worldguard-bukkit = "7.0.9"
mapmanager = "1.8.0-SNAPSHOT" mapmanager = "1.8.0-SNAPSHOT"
griefprevention = "16.18.1" 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.0.1" towny = "0.100.1.23"
plotsquared = "7.1.0" plotsquared = "7.3.6"
# 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.14.0" adventure = "4.16.0"
adventure-bukkit = "4.3.1" adventure-bukkit = "4.3.2"
checkerqual = "3.40.0" checkerqual = "3.42.0"
truezip = "6.8.4" truezip = "6.8.4"
auto-value = "1.10.4" auto-value = "1.10.4"
findbugs = "3.0.2" findbugs = "3.0.2"
@ -43,14 +43,14 @@ serverlib = "2.3.4"
## Internal ## Internal
text-adapter = "3.0.6" text-adapter = "3.0.6"
text = "3.0.4" text = "3.0.4"
piston = "0.5.7" piston = "0.5.8"
# Tests # Tests
mockito = "5.6.0" mockito = "5.11.0"
# Gradle plugins # Gradle plugins
pluginyml = "0.6.0" pluginyml = "0.6.0"
minotaur = "2.8.4" minotaur = "2.8.7"
[libraries] [libraries]
# Minecraft expectations # Minecraft expectations

Binäre Datei nicht angezeigt.

Datei anzeigen

@ -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.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

20
gradlew.bat vendored
Datei anzeigen

@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail

Datei anzeigen

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

Datei anzeigen

@ -1,32 +0,0 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkPacket> {
public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("x", "b"));
fieldBitMask = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("z", "c"));
fieldHeightMap = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("availableSections", "d"));
fieldChunkData = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("biomes", "f"));
fieldBlockEntities = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("buffer", "g"));
fieldFull = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("blockEntitiesTags", "h"));
fieldX.setAccessible(true);
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
}
@Override
public ClientboundLevelChunkPacket createPacket() {
// TODO ??? return new ClientboundLevelChunkPacket();
throw new UnsupportedOperationException();
}
}

Datei anzeigen

@ -1,526 +0,0 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
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.configuration.Settings;
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.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 it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
import net.minecraft.resources.ResourceLocation;
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.Unit;
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.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
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.gameevent.GameEventDispatcher;
import net.minecraft.world.level.gameevent.GameEventListener;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
import sun.misc.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
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 java.util.stream.Stream;
public final class PaperweightPlatformAdapter extends NMSAdapter {
public static final Field fieldStorage;
public static final Field fieldPalette;
public static final Field fieldBits;
public static final Field fieldBitsPerEntry;
private static final Field fieldTickingFluidContent;
private static final Field fieldTickingBlockCount;
private static final Field fieldNonEmptyBlockCount;
private static final Field fieldBiomes;
private static final MethodHandle methodGetVisibleChunk;
private static final Field fieldLock;
private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveBlockEntityTicker;
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 {
try {
fieldBits = PalettedContainer.class.getDeclaredField(Refraction.pickName("bits", "l"));
fieldBits.setAccessible(true);
fieldStorage = PalettedContainer.class.getDeclaredField(Refraction.pickName("storage", "c"));
fieldStorage.setAccessible(true);
fieldPalette = PalettedContainer.class.getDeclaredField(Refraction.pickName("palette", "k"));
fieldPalette.setAccessible(true);
fieldBitsPerEntry = BitStorage.class.getDeclaredField(Refraction.pickName("bits", "c"));
fieldBitsPerEntry.setAccessible(true);
fieldTickingFluidContent = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
fieldTickingFluidContent.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
fieldNonEmptyBlockCount.setAccessible(true);
fieldBiomes = ChunkBiomeContainer.class.getDeclaredField(Refraction.pickName("biomes", "f"));
fieldBiomes.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
"getVisibleChunkIfPresent",
"getVisibleChunk"
), long.class);
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
if (!PaperLib.isPaper()) {
fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
fieldLock.setAccessible(true);
} else {
// in paper, the used methods are synchronized properly
fieldLock = null;
}
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
"gameEventDispatcherSections", "x"));
fieldGameEventDispatcherSections.setAccessible(true);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName(
"removeBlockEntityTicker",
"l"
), BlockPos.class
);
removeBlockEntityTicker.setAccessible(true);
methodremoveBlockEntityTicker = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bU"));
fieldOffers.setAccessible(true);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
rethrow.printStackTrace();
throw new RuntimeException(rethrow);
}
}
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();
Semaphore currentLock = (Semaphore) fieldLock.get(blocks);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
fieldLock.set(blocks, 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 + "!");
}
}
return chunk.getHandle();
} 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
net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
.getChunkSource()
.addRegionTicket(TicketType.PLUGIN, 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("unchecked")
public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) {
ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ);
if (chunkHolder == null) {
return;
}
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
// UNLOADED_CHUNK
Optional<LevelChunk> optional = ((Either) chunkHolder
.getTickingChunkFuture()
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only
optional = optional.or(() -> Optional.ofNullable(nmsWorld
.getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ)));
}
if (optional.isEmpty()) {
return;
}
LevelChunk levelChunk = optional.get();
TaskManager.taskManager().task(() -> {
ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk);
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket));
if (lighting) {
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
boolean trustEdges = true;
ClientboundLightUpdatePacket packet =
new ClientboundLightUpdatePacket(coordIntPair, nmsWorld.getChunkSource().getLightEngine(), null, null,
trustEdges
);
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
}
});
}
private static Stream<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,
boolean fastMode,
CachedBukkitAdapter adapter
) {
return newChunkSection(layer, null, blocks, fastMode, adapter);
}
public static LevelChunkSection newChunkSection(
final int layer,
final Function<Integer, char[]> get,
char[] set,
boolean fastMode,
CachedBukkitAdapter adapter
) {
if (set == null) {
return newChunkSection(layer);
}
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;
final short[] nonEmptyBlockCount = fastMode ? new short[1] : null;
if (get == null) {
num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, nonEmptyBlockCount);
} else {
num_palette = createPalette(
layer,
blockToPalette,
paletteToBlock,
blocksCopy,
get,
set,
adapter,
nonEmptyBlockCount
);
}
// BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
}
if (bitsPerEntry > 8) {
bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1);
}
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntry);
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(bitsPerEntry, 4096, blockStates);
bitArray.fromRaw(blocksCopy);
}
LevelChunkSection levelChunkSection = newChunkSection(layer);
// set palette & data bits
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks =
levelChunkSection.getStates();
// private DataPalette<T> h;
// protected DataBits a;
final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd);
final BitStorage nmsBits = new BitStorage(bitsPerEntry, 4096, bits);
final Palette<net.minecraft.world.level.block.state.BlockState> blockStatePalettedContainer;
if (bitsPerEntry <= 4) {
blockStatePalettedContainer = new LinearPalette<>(Block.BLOCK_STATE_REGISTRY, bitsPerEntry, dataPaletteBlocks,
NbtUtils::readBlockState
);
} else if (bitsPerEntry < 9) {
blockStatePalettedContainer = new HashMapPalette<>(
Block.BLOCK_STATE_REGISTRY,
bitsPerEntry,
dataPaletteBlocks,
NbtUtils::readBlockState,
NbtUtils::writeBlockState
);
} else {
blockStatePalettedContainer = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE;
}
// set palette if required
if (bitsPerEntry < 9) {
for (int i = 0; i < num_palette; i++) {
final int ordinal = paletteToBlock[i];
blockToPalette[ordinal] = Integer.MAX_VALUE;
final BlockState state = BlockTypesCache.states[ordinal];
final net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
blockStatePalettedContainer.idFor(blockState);
}
}
try {
fieldStorage.set(dataPaletteBlocks, nmsBits);
fieldPalette.set(dataPaletteBlocks, blockStatePalettedContainer);
fieldBits.set(dataPaletteBlocks, bitsPerEntry);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
if (!fastMode) {
levelChunkSection.recalcBlockCounts();
} else {
try {
fieldNonEmptyBlockCount.set(levelChunkSection, nonEmptyBlockCount[0]);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return levelChunkSection;
} 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);
}
}
private static LevelChunkSection newChunkSection(int layer) {
return new LevelChunkSection(layer);
}
public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException {
fieldTickingFluidContent.setShort(section, (short) 0);
fieldTickingBlockCount.setShort(section, (short) 0);
}
public static Biome[] getBiomeArray(ChunkBiomeContainer chunkBiomeContainer) {
try {
return (Biome[]) fieldBiomes.get(chunkBiomeContainer);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static BiomeType adapt(Biome biome, LevelAccessor levelAccessor) {
ResourceLocation resourceLocation = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getKey(
biome);
if (resourceLocation == null) {
return levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getId(biome) == -1
? BiomeTypes.OCEAN
: null;
}
return BiomeTypes.get(resourceLocation.toString().toLowerCase(Locale.ROOT));
}
@SuppressWarnings("unchecked")
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try {
// Do the method ourselves to avoid trying to reflect generic method parameters
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) {
if (!levelChunk.level.isClientSide) {
Block block = beacon.getBlockState().getBlock();
if (block instanceof EntityBlock) {
GameEventListener gameEventListener = ((EntityBlock) block).getListener(levelChunk.level, beacon);
if (gameEventListener != null) {
int i = SectionPos.blockToSectionCoord(beacon.getBlockPos().getY());
GameEventDispatcher gameEventDispatcher = levelChunk.getEventDispatcher(i);
gameEventDispatcher.unregister(gameEventListener);
if (gameEventDispatcher.isEmpty()) {
try {
((Int2ObjectMap<GameEventDispatcher>) fieldGameEventDispatcherSections.get(levelChunk))
.remove(i);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
fieldRemove.set(beacon, true);
}
}
methodremoveBlockEntityTicker.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(chunk.getPos());
}
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread();
boolean unset = false;
if (isVillager) {
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);
}
}
}
}

Datei anzeigen

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

Datei anzeigen

@ -1,7 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.entity.LazyBaseEntity;
@ -10,16 +9,13 @@ 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.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
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.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter; import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
@ -39,7 +35,6 @@ 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.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -80,14 +75,12 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk; import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
@ -111,8 +104,7 @@ import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
@ -235,11 +227,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -255,12 +246,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseBlock getFullBlock(final Location location) { public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -337,10 +327,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess( return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
@Override @Override
@ -485,7 +472,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) { if (map != null && map.wasAccessibleSinceLastSave()) {
// PlayerChunk.d players = map.players; // PlayerChunk.d players = map.players;
@ -522,7 +509,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int internalId = BlockStateIdAccess.getBlockStateId(blockState); int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess( return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(), getServerLevel(world),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
); );
} }
@ -538,54 +525,33 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
} }
@Override @Override
public boolean generateTree( protected void preCaptureStates(final ServerLevel serverLevel) {
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, serverLevel.captureTreeGeneration = true;
org.bukkit.World bukkitWorld serverLevel.captureBlockStates = true;
) { }
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) { @Override
blockVector3 = blockVector3.add( protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
0, return new ArrayList<>(serverLevel.capturedBlockStates.values());
1, }
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back @Override
} protected void postCaptureBlockStates(final ServerLevel serverLevel) {
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); serverLevel.captureBlockStates = false;
final BlockVector3 finalBlockVector = blockVector3; serverLevel.captureTreeGeneration = false;
// Sync to main thread to ensure no clashes occur serverLevel.capturedBlockStates.clear();
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> { }
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true; @Override
try { protected ServerLevel getServerLevel(final World world) {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { return ((CraftWorld) world).getHandle();
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
} }
@Override @Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) { public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
// Quickly add each entity to a list copy. // Quickly add each entity to a list copy.
List<Entity> mcEntities = new ArrayList<>(); List<Entity> mcEntities = new ArrayList<>();
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add); getServerLevel(world).entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>(); List<org.bukkit.entity.Entity> list = new ArrayList<>();
mcEntities.forEach((mcEnt) -> { mcEntities.forEach((mcEnt) -> {

Datei anzeigen

@ -153,6 +153,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
} }
this.createCopy = createCopy; this.createCopy = createCopy;
// Increment regardless of whether copy will be created or not to return null from getCopy()
return ++this.copyKey; return ++this.copyKey;
} }

Datei anzeigen

@ -11,6 +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
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.19.4-R0.1-20230608.201059-104") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.19.4-R0.1-20230608.201059-104")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -1,7 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.entity.LazyBaseEntity;
@ -10,15 +9,12 @@ 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.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
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.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
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.BukkitWorld;
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.ext.fawe.v1_19_R3.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.nbt.PaperweightLazyCompoundTag;
@ -38,7 +34,6 @@ 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.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -77,13 +72,11 @@ import net.minecraft.world.level.chunk.LevelChunk;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; 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.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
@ -111,8 +104,7 @@ import java.util.stream.Stream;
import static net.minecraft.core.registries.Registries.BIOME; import static net.minecraft.core.registries.Registries.BIOME;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
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;
@ -244,11 +236,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -264,12 +255,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseBlock getFullBlock(final Location location) { public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -298,10 +288,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess( return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
@Override @Override
@ -446,7 +433,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && wasAccessibleSinceLastSave(map)) { if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false; boolean flag = false;
@ -484,7 +471,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int internalId = BlockStateIdAccess.getBlockStateId(blockState); int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess( return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(), getServerLevel(world),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
); );
} }
@ -501,47 +488,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
} }
@Override @Override
public boolean generateTree( protected void preCaptureStates(final ServerLevel serverLevel) {
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, serverLevel.captureTreeGeneration = true;
org.bukkit.World bukkitWorld serverLevel.captureBlockStates = true;
) { }
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) { @Override
blockVector3 = blockVector3.add( protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
0, return new ArrayList<>(serverLevel.capturedBlockStates.values());
1, }
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back @Override
} protected void postCaptureBlockStates(final ServerLevel serverLevel) {
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); serverLevel.captureBlockStates = false;
final BlockVector3 finalBlockVector = blockVector3; serverLevel.captureTreeGeneration = false;
// Sync to main thread to ensure no clashes occur serverLevel.capturedBlockStates.clear();
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> { }
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true; @Override
try { protected ServerLevel getServerLevel(final World world) {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { return ((CraftWorld) world).getHandle();
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
} }
@Override @Override

Datei anzeigen

@ -156,6 +156,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
} }
this.createCopy = createCopy; this.createCopy = createCopy;
// Increment regardless of whether copy will be created or not to return null from getCopy()
return ++this.copyKey; return ++this.copyKey;
} }

Datei anzeigen

@ -11,7 +11,7 @@ repositories {
} }
dependencies { dependencies {
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ // 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-20230916.212543-167") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.1-R0.1-20230921.165944-178")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -1,7 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.entity.LazyBaseEntity;
@ -10,15 +9,12 @@ 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.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
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.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
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.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; 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.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.nbt.PaperweightLazyCompoundTag;
@ -38,7 +34,6 @@ 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.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -77,13 +72,11 @@ import net.minecraft.world.level.chunk.LevelChunk;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R1.CraftServer; import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; 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.CraftEntity;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
@ -111,8 +104,7 @@ import java.util.stream.Stream;
import static net.minecraft.core.registries.Registries.BIOME; import static net.minecraft.core.registries.Registries.BIOME;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
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;
@ -244,11 +236,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -264,12 +255,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseBlock getFullBlock(final Location location) { public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -298,10 +288,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess( return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
@Override @Override
@ -446,7 +433,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && wasAccessibleSinceLastSave(map)) { if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false; boolean flag = false;
@ -484,7 +471,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int internalId = BlockStateIdAccess.getBlockStateId(blockState); int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess( return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(), getServerLevel(world),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
); );
} }
@ -501,47 +488,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
} }
@Override @Override
public boolean generateTree( protected void preCaptureStates(final ServerLevel serverLevel) {
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, serverLevel.captureTreeGeneration = true;
org.bukkit.World bukkitWorld serverLevel.captureBlockStates = true;
) { }
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) { @Override
blockVector3 = blockVector3.add( protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
0, return new ArrayList<>(serverLevel.capturedBlockStates.values());
1, }
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back @Override
} protected void postCaptureBlockStates(final ServerLevel serverLevel) {
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); serverLevel.captureBlockStates = false;
final BlockVector3 finalBlockVector = blockVector3; serverLevel.captureTreeGeneration = false;
// Sync to main thread to ensure no clashes occur serverLevel.capturedBlockStates.clear();
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> { }
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true; @Override
try { protected ServerLevel getServerLevel(final World world) {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { return ((CraftWorld) world).getHandle();
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
} }
@Override @Override

Datei anzeigen

@ -156,6 +156,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
} }
this.createCopy = createCopy; this.createCopy = createCopy;
// Increment regardless of whether copy will be created or not to return null from getCopy()
return ++this.copyKey; return ++this.copyKey;
} }

Datei anzeigen

@ -11,7 +11,7 @@ repositories {
} }
dependencies { dependencies {
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.2-R0.1-SNAPSHOT
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.2-R0.1-20231029.153906-63") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.2-R0.1-20231203.034718-121")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -1,7 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.entity.LazyBaseEntity;
@ -10,15 +9,12 @@ 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.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
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.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
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.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.regen.PaperweightRegen; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.regen.PaperweightRegen;
@ -37,7 +33,6 @@ 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.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -76,13 +71,11 @@ import net.minecraft.world.level.chunk.LevelChunk;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; import org.bukkit.World;
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;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
@ -110,8 +103,7 @@ import java.util.stream.Stream;
import static net.minecraft.core.registries.Registries.BIOME; import static net.minecraft.core.registries.Registries.BIOME;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
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;
@ -247,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -267,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseBlock getFullBlock(final Location location) { public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -301,10 +291,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess( return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
@Override @Override
@ -449,7 +436,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && wasAccessibleSinceLastSave(map)) { if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false; boolean flag = false;
@ -487,7 +474,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int internalId = BlockStateIdAccess.getBlockStateId(blockState); int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess( return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(), getServerLevel(world),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
); );
} }
@ -504,47 +491,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
} }
@Override @Override
public boolean generateTree( protected void preCaptureStates(final ServerLevel serverLevel) {
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, serverLevel.captureTreeGeneration = true;
org.bukkit.World bukkitWorld serverLevel.captureBlockStates = true;
) { }
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) { @Override
blockVector3 = blockVector3.add( protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
0, return new ArrayList<>(serverLevel.capturedBlockStates.values());
1, }
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back @Override
} protected void postCaptureBlockStates(final ServerLevel serverLevel) {
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); serverLevel.captureBlockStates = false;
final BlockVector3 finalBlockVector = blockVector3; serverLevel.captureTreeGeneration = false;
// Sync to main thread to ensure no clashes occur serverLevel.capturedBlockStates.clear();
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> { }
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true; @Override
try { protected ServerLevel getServerLevel(final World world) {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) { return ((CraftWorld) world).getHandle();
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
} }
@Override @Override

Datei anzeigen

@ -135,6 +135,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
} }
this.createCopy = createCopy; this.createCopy = createCopy;
// Increment regardless of whether copy will be created or not to return null from getCopy()
return ++this.copyKey; return ++this.copyKey;
} }

Datei anzeigen

@ -1,26 +1,17 @@
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
applyPaperweightAdapterConfiguration()
plugins { plugins {
java java
} }
applyPaperweightAdapterConfiguration()
repositories { repositories {
mavenCentral()
gradlePluginPortal() gradlePluginPortal()
} }
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
dependencies { dependencies {
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.17.1-R0.1-20220414.034903-210") // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240325.123556-143")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -17,28 +17,23 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit.adapter.ext.fawe; package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import com.sk89q.jnbt.CompoundTag; 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.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;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.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;
@ -85,7 +80,9 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
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;
@ -111,14 +108,14 @@ 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.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.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.ChunkStatus; 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.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@ -127,20 +124,19 @@ import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer; import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers; 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.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;
@ -159,21 +155,21 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
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;
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 worldsField; private final Field serverWorldsField;
private final Method getChunkFutureMainThreadMethod; private final Method getChunkFutureMethod;
private final Field mainThreadProcessorField; private final Field chunkProviderExecutorField;
private final Watchdog watchdog; private final Watchdog watchdog;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -185,24 +181,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 != 2730) { if (dataVersion != 3698 && dataVersion != 3700) {
throw new UnsupportedClassVersionError("Not 1.17.1!"); throw new UnsupportedClassVersionError("Not 1.20.(3/4)!");
} }
worldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField = CraftServer.class.getDeclaredField("worlds");
worldsField.setAccessible(true); serverWorldsField.setAccessible(true);
getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread", getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod(
Refraction.pickName("getChunkFutureMainThread", "c"),
int.class, int.class, ChunkStatus.class, boolean.class int.class, int.class, ChunkStatus.class, boolean.class
); );
getChunkFutureMainThreadMethod.setAccessible(true); getChunkFutureMethod.setAccessible(true);
mainThreadProcessorField = ServerChunkCache.class.getDeclaredField( chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField(
Refraction.pickName("mainThreadProcessor", "h") Refraction.pickName("mainThreadProcessor", "g")
); );
mainThreadProcessorField.setAccessible(true); chunkProviderExecutorField.setAccessible(true);
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).buildUnoptimized();
Watchdog watchdog; Watchdog watchdog;
try { try {
@ -233,23 +230,13 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* Read the given NBT data into the given tile entity. * Read the given NBT data into the given tile entity.
* *
* @param tileEntity the tile entity * @param tileEntity the tile entity
* @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.load(tag);
tileEntity.setChanged(); tileEntity.setChanged();
} }
/**
* Write the tile entity's NBT data to the given tag.
*
* @param tileEntity the tile entity
* @param tag the tag
*/
private static void readTileEntityIntoTag(BlockEntity tileEntity, net.minecraft.nbt.CompoundTag tag) {
tileEntity.save(tag);
}
/** /**
* Get the ID string of the given entity. * Get the ID string of the given entity.
* *
@ -263,7 +250,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
/** /**
* Create an entity using the given entity ID. * Create an entity using the given entity ID.
* *
* @param id the entity ID * @param id the entity ID
* @param world the world * @param world the world
* @return an entity or null * @return an entity or null
*/ */
@ -276,7 +263,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* Write the given NBT data into the given entity. * Write the given NBT data into the given entity.
* *
* @param entity the entity * @param entity the entity
* @param tag the tag * @param tag the tag
*/ */
private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) { private static void readTagIntoEntity(net.minecraft.nbt.CompoundTag tag, Entity entity) {
entity.load(tag); entity.load(tag);
@ -286,20 +273,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* Write the entity's NBT data to the given tag. * Write the entity's NBT data to the given tag.
* *
* @param entity the entity * @param entity the entity
* @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 Registry.BLOCK.get(ResourceLocation.tryParse(blockType.getId()));
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.getId()));
} }
private static Item getItemFromType(ItemType itemType) { private static Item getItemFromType(ItemType itemType) {
return Registry.ITEM.get(ResourceLocation.tryParse(itemType.getId())); return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(itemType.getId()));
} }
@Override @Override
@ -319,20 +305,21 @@ 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);
} }
@Deprecated
@Override @Override
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld()); CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
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);
final BlockPos blockPos = new BlockPos(x, y, z); final BlockPos blockPos = new BlockPos(x, y, z);
final CraftBlockData blockData = chunk.getBlockState(blockPos).createCraftBlockData(); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = BukkitAdapter.adapt(blockData); int internalId = Block.getId(blockData);
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
if (state == null) { if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock(); org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
@ -357,21 +344,19 @@ 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.save(new net.minecraft.nbt.CompoundTag()); net.minecraft.nbt.CompoundTag tag = te.saveWithId();
//FAWE start - BinaryTag
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
//FAWE end
} }
return state.toBaseBlock(); return state.toBaseBlock();
} }
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightWorldNativeAccess( return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
private static net.minecraft.core.Direction adapt(Direction face) { private static net.minecraft.core.Direction adapt(Direction face) {
@ -431,16 +416,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
CraftEntity craftEntity = ((CraftEntity) entity); CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle(); Entity mcEntity = craftEntity.getHandle();
// Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity
if (mcEntity.isPassenger()) {
return null;
}
String id = getEntityId(mcEntity); String id = getEntityId(mcEntity);
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, tag);
//FAWE start - BinaryTag
return new BaseEntity( return new BaseEntity(
com.sk89q.worldedit.world.entity.EntityTypes.get(id), com.sk89q.worldedit.world.entity.EntityTypes.get(id),
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag)) LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
); );
//FAWE end
} }
@Nullable @Nullable
@ -455,9 +443,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle()); Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle());
if (createdEntity != null) { if (createdEntity != null) {
CompoundTag nativeTag = state.getNbtData(); CompoundBinaryTag nativeTag = state.getNbt();
if (nativeTag != null) { if (nativeTag != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNative(nativeTag); net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(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);
} }
@ -466,13 +454,29 @@ 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.addEntity(createdEntity, SpawnReason.CUSTOM); worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM);
return createdEntity.getBukkitEntity(); return createdEntity.getBukkitEntity();
} else { } else {
return null; return null;
} }
} }
// This removes all unwanted tags from the main entity and all its passengers
private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) {
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
// Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive
if (tag.contains("Passengers", NBTConstants.TYPE_LIST)) {
net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", NBTConstants.TYPE_COMPOUND);
for (int i = 0; i < nbttaglist.size(); ++i) {
removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i));
}
}
}
@Override @Override
public Component getRichBlockName(BlockType blockType) { public Component getRichBlockName(BlockType blockType) {
return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId()); return TranslatableComponent.of(getBlockFromType(blockType).getDescriptionId());
@ -488,7 +492,7 @@ 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<net.minecraft.world.level.block.state.properties.Property, Property<?>>() {
@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) throws Exception {
@ -503,7 +507,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} 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("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName()); throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
} }
} }
}); });
@ -523,20 +527,29 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
@Override @Override
public void sendFakeNBT(final Player player, final BlockVector3 pos, final CompoundBinaryTag nbtData) { public void sendFakeNBT(Player player, BlockVector3 pos, CompoundBinaryTag 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) fromNativeBinary(nbtData)
));
} }
@Override @Override
public void sendFakeOP(Player player) { public void sendFakeOP(Player player) {
((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket( ((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
((CraftPlayer) player).getHandle(), (byte) 28 ((CraftPlayer) player).getHandle(), (byte) 28
)); ));
} }
@Override @Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) { public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount()); ItemStack stack = new ItemStack(
DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(item.getType().getId())),
item.getAmount()
);
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData()))); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(item.getNbtData())));
return CraftItemStack.asCraftMirror(stack); return CraftItemStack.asCraftMirror(stack);
} }
@ -555,7 +568,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.setNbtData(((CompoundTag) toNative(nmsStack.getTag()))); weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack; return weStack;
} }
@ -578,20 +591,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack); fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack);
fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(), fakePlayer.absMoveTo(position.getBlockX(), position.getBlockY(), position.getBlockZ(),
(float) face.toVector().toYaw(), (float) face.toVector().toPitch() (float) face.toVector().toYaw(), (float) face.toVector().toPitch());
);
final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); final BlockPos blockPos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ());
final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos); final Vec3 blockVec = Vec3.atLowerCornerOf(blockPos);
final net.minecraft.core.Direction enumFacing = adapt(face); final net.minecraft.core.Direction enumFacing = adapt(face);
BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false); BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false);
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace); UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
InteractionResult result = stack.placeItem(context, InteractionHand.MAIN_HAND); InteractionResult result = stack.useOn(context);
if (result != InteractionResult.SUCCESS) { if (result != InteractionResult.SUCCESS) {
if (worldServer if (worldServer.getBlockState(blockPos).use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) {
.getBlockState(blockPos)
.use(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();
@ -605,10 +614,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 position, BlockState blockState) { public boolean canPlaceAt(org.bukkit.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.getX(), position.getY(), position.getZ()));
((CraftWorld) world).getHandle(),
new BlockPos(position.getX(), position.getY(), position.getZ())
);
} }
@Override @Override
@ -626,18 +632,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
Environment env = bukkitWorld.getEnvironment(); Environment env = bukkitWorld.getEnvironment();
ChunkGenerator gen = bukkitWorld.getGenerator(); ChunkGenerator gen = bukkitWorld.getGenerator();
Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen"); Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir); LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env); ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) { try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) {
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle(); ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer() PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
.getWorldData().overworldData(); .getWorldData().overworldData();
WorldGenSettings originalOpts = levelProperties.worldGenSettings(); WorldOptions originalOpts = levelProperties.worldGenOptions();
long seed = options.getSeed().orElse(originalWorld.getSeed()); long seed = options.getSeed().orElse(originalWorld.getSeed());
WorldGenSettings newOpts = options.getSeed().isPresent() WorldOptions newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
@ -647,23 +653,35 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
levelProperties.settings.difficulty(), levelProperties.settings.difficulty(),
levelProperties.settings.allowCommands(), levelProperties.settings.allowCommands(),
levelProperties.settings.gameRules(), levelProperties.settings.gameRules(),
levelProperties.settings.getDataPackConfig() levelProperties.settings.getDataConfiguration()
); );
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
levelProperties.isFlatWorld()
? PrimaryLevelData.SpecialWorldProperty.FLAT
: levelProperties.isDebugWorld()
? PrimaryLevelData.SpecialWorldProperty.DEBUG
: PrimaryLevelData.SpecialWorldProperty.NONE;
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable());
ServerLevel freshWorld = new ServerLevel( ServerLevel freshWorld = new ServerLevel(
originalWorld.getServer(), originalWorld.getServer(),
originalWorld.getServer().executor, originalWorld.getServer().executor,
session, newWorldData, session, newWorldData,
originalWorld.dimension(), originalWorld.dimension(),
originalWorld.dimensionType(), new LevelStem(
originalWorld.dimensionTypeRegistration(),
originalWorld.getChunkSource().getGenerator()
),
new NoOpWorldLoadListener(), new NoOpWorldLoadListener(),
newOpts.dimensions().get(worldDimKey).generator(),
originalWorld.isDebug(), originalWorld.isDebug(),
seed, seed,
ImmutableList.of(), ImmutableList.of(),
false, false,
env, gen, originalWorld.getRandomSequences(),
env,
gen,
bukkitWorld.getBiomeProvider() bukkitWorld.getBiomeProvider()
); );
try { try {
@ -674,7 +692,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>) worldsField.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 ignored) { } catch (IllegalAccessException ignored) {
} }
@ -683,7 +701,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} }
private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) { private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) {
ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome); ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registries.BIOME).getKey(origBiome);
if (key == null) { if (key == null) {
return null; return null;
} }
@ -691,12 +709,11 @@ 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 {
executor = (BlockableEventLoop<Runnable>) mainThreadProcessorField.get(serverWorld.getChunkSource()); executor = (BlockableEventLoop<Runnable>) chunkProviderExecutorField.get(serverWorld.getChunkSource());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new IllegalStateException("Couldn't get executor for chunk loading.", e); throw new IllegalStateException("Couldn't get executor for chunk loading.", e);
} }
@ -721,27 +738,20 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ());
ChunkAccess chunk = chunks.get(new ChunkPos(pos)); ChunkAccess chunk = chunks.get(new ChunkPos(pos));
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos);
BlockStateHolder<?> state = ((PaperweightFaweAdapter) WorldEditPlugin int internalId = Block.getId(blockData);
.getInstance() BlockStateHolder<?> state = BlockStateIdAccess.getBlockStateById(internalId);
.getBukkitImplAdapter()).adapt(blockData);
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 = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
blockEntity.save(tag);
//FAWE start - BinaryTag
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag))); state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
//FAWE end
} }
extent.setBlock(vec, state.toBaseBlock()); extent.setBlock(vec, state.toBaseBlock());
if (options.shouldRegenBiomes()) { if (options.shouldRegenBiomes()) {
ChunkBiomeContainer biomeIndex = chunk.getBiomes(); Biome origBiome = chunk.getNoiseBiome(vec.getX(), vec.getY(), vec.getZ()).value();
if (biomeIndex != null) { BiomeType adaptedBiome = adapt(serverWorld, origBiome);
Biome origBiome = biomeIndex.getNoiseBiome(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); if (adaptedBiome != null) {
BiomeType adaptedBiome = adapt(serverWorld, origBiome); extent.setBiome(vec, adaptedBiome);
if (adaptedBiome != null) {
extent.setBiome(vec, adaptedBiome);
}
} }
} }
} }
@ -754,9 +764,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
// Pre-gen all the chunks // Pre-gen all the chunks
for (BlockVector2 chunk : region.getChunks()) { for (BlockVector2 chunk : region.getChunks()) {
try { try {
//noinspection unchecked
chunkLoadings.add( chunkLoadings.add(
((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>) ((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>)
getChunkFutureMainThreadMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true))
.thenApply(either -> either.left().orElse(null)) .thenApply(either -> either.left().orElse(null))
); );
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
@ -815,7 +826,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @param foreign non-native NMS NBT structure * @param foreign non-native NMS NBT structure
* @return native WorldEdit NBT structure * @return native WorldEdit NBT structure
*/ */
//FAWE start - BinaryTag
@Override @Override
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) { public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
if (foreign == null) { if (foreign == null) {
@ -848,7 +858,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
try { try {
return toNativeList((net.minecraft.nbt.ListTag) foreign); return toNativeList((net.minecraft.nbt.ListTag) foreign);
} catch (Throwable e) { } catch (Throwable e) {
LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
return ListBinaryTag.empty(); return ListBinaryTag.empty();
} }
} else if (foreign instanceof net.minecraft.nbt.LongTag) { } else if (foreign instanceof net.minecraft.nbt.LongTag) {
@ -869,11 +879,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* *
* @param foreign the foreign tag * @param foreign the foreign tag
* @return the converted tag * @return the converted tag
* @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 ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
ListBinaryTag.Builder<BinaryTag> values = ListBinaryTag.builder(); ListBinaryTag.Builder values = ListBinaryTag.builder();
for (net.minecraft.nbt.Tag tag : foreign) { for (net.minecraft.nbt.Tag tag : foreign) {
values.add(toNativeBinary(tag)); values.add(toNativeBinary(tag));
@ -913,8 +923,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value()); return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
} else if (foreign instanceof LongArrayBinaryTag) { } else if (foreign instanceof LongArrayBinaryTag) {
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value()); return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
} else if (foreign instanceof ListBinaryTag foreignList) { } else if (foreign instanceof ListBinaryTag) {
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag(); net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
ListBinaryTag foreignList = (ListBinaryTag) foreign;
for (BinaryTag t : foreignList) { for (BinaryTag t : foreignList) {
tag.add(fromNativeBinary(t)); tag.add(fromNativeBinary(t));
} }
@ -931,7 +942,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
} }
} }
//FAWE end
@Override @Override
public boolean supportsWatchdog() { public boolean supportsWatchdog() {
@ -944,7 +954,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;
@ -966,22 +975,23 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
WatchdogThread.tick(); WatchdogThread.tick();
} }
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
LOGGER.log(Level.WARNING, "Failed to tick watchdog", e); logger.log(Level.WARNING, "Failed to tick watchdog", e);
} }
} }
} }
private static class MojangWatchdog implements Watchdog { private 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", "ao") Refraction.pickName("nextTickTime", "ah")
); );
if (tickField.getType() != long.class) {
throw new IllegalStateException("nextTickTime is not a long field, mapping is likely incorrect");
}
tickField.setAccessible(true); tickField.setAccessible(true);
this.tickField = tickField; this.tickField = tickField;
} }
@ -993,17 +1003,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(ChunkPos pos, @Nullable ChunkStatus status) { public void onStatusChange(ChunkPos pos, @org.jetbrains.annotations.Nullable ChunkStatus status) {
} }
@Override @Override
@ -1017,7 +1025,5 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
@Override @Override
public void setChunkRadius(int radius) { public void setChunkRadius(int radius) {
} }
} }
} }

Datei anzeigen

@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit.adapter.ext.fawe; package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -29,17 +29,18 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DSL.TypeReference; import com.mojang.datafixers.DSL.TypeReference;
import com.mojang.datafixers.DataFixer; 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 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;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper; import net.minecraft.util.GsonHelper;
import net.minecraft.util.StringUtil; import net.minecraft.util.StringUtil;
@ -49,7 +50,6 @@ 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 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,20 +63,21 @@ 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)
* <p> *
* We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy * We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy
* which is safer, faster and cleaner code. * which is safer, faster and cleaner code.
* <p> *
* The pre DFU code did not fail when the Source version was unknown. * The pre DFU code did not fail when the Source version was unknown.
* <p> *
* This class also provides util methods for converting compounds to wrap the update call to * This class also provides util methods for converting compounds to wrap the update call to
* receive the source version in the compound * receive the source version in the compound
*/ */
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({ "rawtypes", "unchecked" })
class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer { public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
//FAWE start - BinaryTag //FAWE start - BinaryTag
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -120,12 +121,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
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);
Dynamic<net.minecraft.nbt.Tag> dynamic = new Dynamic<>(OPS_NBT, stateNBT); Dynamic<net.minecraft.nbt.Tag> dynamic = new Dynamic<>(OPS_NBT, stateNBT);
net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update( net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue();
References.BLOCK_STATE,
dynamic,
srcVer,
DATA_VERSION
).getValue();
return nbtToState(fixed); return nbtToState(fixed);
} }
@ -135,11 +131,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
if (tagCompound.contains("Properties", 10)) { if (tagCompound.contains("Properties", 10)) {
sb.append('['); sb.append('[');
net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties"); net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties");
sb.append(props sb.append(props.getAllKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(",")));
.getAllKeys()
.stream()
.map(k -> k + "=" + props.getString(k).replace("\"", ""))
.collect(Collectors.joining(",")));
sb.append(']'); sb.append(']');
} }
return sb.toString(); return sb.toString();
@ -182,7 +174,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
private static final NbtOps OPS_NBT = NbtOps.INSTANCE; private static final NbtOps OPS_NBT = NbtOps.INSTANCE;
private static final int LEGACY_VERSION = 1343; private static final int LEGACY_VERSION = 1343;
private static int DATA_VERSION; private static int DATA_VERSION;
static PaperweightDataConverters INSTANCE; public static PaperweightDataConverters INSTANCE;
private final Map<LegacyType, List<DataConverter>> converters = new EnumMap<>(LegacyType.class); private final Map<LegacyType, List<DataConverter>> converters = new EnumMap<>(LegacyType.class);
private final Map<LegacyType, List<DataInspector>> inspectors = new EnumMap<>(LegacyType.class); private final Map<LegacyType, List<DataInspector>> inspectors = new EnumMap<>(LegacyType.class);
@ -213,7 +205,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
} }
} }
PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) { public PaperweightDataConverters(int dataVersion, PaperweightAdapter adapter) {
super(dataVersion); super(dataVersion);
DATA_VERSION = dataVersion; DATA_VERSION = dataVersion;
INSTANCE = this; INSTANCE = this;
@ -225,13 +217,17 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
// Called after fixers are built and ready for FIXING // Called after fixers are built and ready for FIXING
@Override @Override
public DataFixer build(final Executor executor) { public DataFixer buildUnoptimized() {
return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer()); return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer());
} }
@Override
public DataFixer buildOptimized(final Set<DSL.TypeReference> requiredTypes, Executor executor) {
return buildUnoptimized();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private class WrappedDataFixer implements DataFixer { private class WrappedDataFixer implements DataFixer {
private final DataFixer realFixer; private final DataFixer realFixer;
WrappedDataFixer(DataFixer realFixer) { WrappedDataFixer(DataFixer realFixer) {
@ -252,12 +248,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return realFixer.update(type, dynamic, sourceVer, targetVer); return realFixer.update(type, dynamic, sourceVer, targetVer);
} }
private net.minecraft.nbt.CompoundTag convert( private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int desiredVersion) {
LegacyType type,
net.minecraft.nbt.CompoundTag cmp,
int sourceVer,
int desiredVersion
) {
List<DataConverter> converters = PaperweightDataConverters.this.converters.get(type); List<DataConverter> converters = PaperweightDataConverters.this.converters.get(type);
if (converters != null && !converters.isEmpty()) { if (converters != null && !converters.isEmpty()) {
for (DataConverter converter : converters) { for (DataConverter converter : converters) {
@ -282,7 +273,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
public Schema getSchema(int i) { public Schema getSchema(int i) {
return realFixer.getSchema(i); return realFixer.getSchema(i);
} }
} }
public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) { public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp) {
@ -293,12 +283,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return convert(type.getDFUType(), cmp, sourceVer); return convert(type.getDFUType(), cmp, sourceVer);
} }
public static net.minecraft.nbt.CompoundTag convert( public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
LegacyType type,
net.minecraft.nbt.CompoundTag cmp,
int sourceVer,
int targetVer
) {
return convert(type.getDFUType(), cmp, sourceVer, targetVer); return convert(type.getDFUType(), cmp, sourceVer, targetVer);
} }
@ -311,25 +296,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return convert(type, cmp, sourceVer, DATA_VERSION); return convert(type, cmp, sourceVer, DATA_VERSION);
} }
public static net.minecraft.nbt.CompoundTag convert( public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
TypeReference type,
net.minecraft.nbt.CompoundTag cmp,
int sourceVer,
int targetVer
) {
if (sourceVer >= targetVer) { if (sourceVer >= targetVer) {
return cmp; return cmp;
} }
return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue();
.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer)
.getValue();
} }
public interface DataInspector { public interface DataInspector {
net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer); net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer);
} }
public interface DataConverter { public interface DataConverter {
@ -337,7 +313,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
int getDataVersion(); int getDataVersion();
net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp); net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp);
} }
@ -615,13 +590,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return key; return key;
} }
private static void convertCompound( private static void convertCompound(LegacyType type, net.minecraft.nbt.CompoundTag cmp, String key, int sourceVer, int targetVer) {
LegacyType type,
net.minecraft.nbt.CompoundTag cmp,
String key,
int sourceVer,
int targetVer
) {
cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer)); cmp.put(key, convert(type, cmp.getCompound(key), sourceVer, targetVer));
} }
@ -697,7 +666,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorBlockEntity implements DataInspector { private static class DataInspectorBlockEntity implements DataInspector {
@ -844,8 +812,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
private static class DataInspectorEntity implements DataInspector { private static class DataInspectorEntity implements DataInspector {
private static final Logger a = LogManager.getLogger(PaperweightDataConverters.class);
DataInspectorEntity() { DataInspectorEntity() {
} }
@ -880,7 +846,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
@ -900,12 +865,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
abstract net.minecraft.nbt.CompoundTag inspectChecked( abstract net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer);
net.minecraft.nbt.CompoundTag nbttagcompound,
int sourceVer,
int targetVer
);
} }
private static class DataInspectorItemList extends DataInspectorTagged { private static class DataInspectorItemList extends DataInspectorTagged {
@ -924,7 +884,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return nbttagcompound; return nbttagcompound;
} }
} }
private static class DataInspectorItem extends DataInspectorTagged { private static class DataInspectorItem extends DataInspectorTagged {
@ -943,7 +902,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return nbttagcompound; return nbttagcompound;
} }
} }
private static class DataConverterMaterialId implements DataConverter { private static class DataConverterMaterialId implements DataConverter {
@ -1344,7 +1302,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterBanner implements DataConverter { private static class DataConverterBanner implements DataConverter {
@ -1391,7 +1348,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterPotionId implements DataConverter { private static class DataConverterPotionId implements DataConverter {
@ -1669,15 +1625,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
private static class DataConverterMinecart implements DataConverter { private static class DataConverterMinecart implements DataConverter {
private static final List<String> a = Lists.newArrayList( private static final List<String> a = Lists.newArrayList("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock");
"MinecartRideable",
"MinecartChest",
"MinecartFurnace",
"MinecartTNT",
"MinecartSpawner",
"MinecartHopper",
"MinecartCommandBlock"
);
DataConverterMinecart() { DataConverterMinecart() {
} }
@ -1701,7 +1649,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterMobSpawner implements DataConverter { private static class DataConverterMobSpawner implements DataConverter {
@ -1746,7 +1693,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
} }
private static class DataConverterUUID implements DataConverter { private static class DataConverterUUID implements DataConverter {
@ -1765,47 +1711,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterHealth implements DataConverter { private static class DataConverterHealth implements DataConverter {
private static final Set<String> a = Sets.newHashSet( private static final Set<String> a = Sets.newHashSet("ArmorStand", "Bat", "Blaze", "CaveSpider", "Chicken", "Cow", "Creeper", "EnderDragon", "Enderman", "Endermite", "EntityHorse", "Ghast", "Giant", "Guardian", "LavaSlime", "MushroomCow", "Ozelot", "Pig", "PigZombie", "Rabbit", "Sheep", "Shulker", "Silverfish", "Skeleton", "Slime", "SnowMan", "Spider", "Squid", "Villager", "VillagerGolem", "Witch", "WitherBoss", "Wolf", "Zombie");
"ArmorStand",
"Bat",
"Blaze",
"CaveSpider",
"Chicken",
"Cow",
"Creeper",
"EnderDragon",
"Enderman",
"Endermite",
"EntityHorse",
"Ghast",
"Giant",
"Guardian",
"LavaSlime",
"MushroomCow",
"Ozelot",
"Pig",
"PigZombie",
"Rabbit",
"Sheep",
"Shulker",
"Silverfish",
"Skeleton",
"Slime",
"SnowMan",
"Spider",
"Squid",
"Villager",
"VillagerGolem",
"Witch",
"WitherBoss",
"Wolf",
"Zombie"
);
DataConverterHealth() { DataConverterHealth() {
} }
@ -1834,7 +1744,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterSaddle implements DataConverter { private static class DataConverterSaddle implements DataConverter {
@ -1859,7 +1768,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterHanging implements DataConverter { private static class DataConverterHanging implements DataConverter {
@ -1898,7 +1806,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterDropChances implements DataConverter { private static class DataConverterDropChances implements DataConverter {
@ -1922,15 +1829,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
if (cmp.contains("ArmorDropChances", 9)) { if (cmp.contains("ArmorDropChances", 9)) {
nbttaglist = cmp.getList("ArmorDropChances", 5); nbttaglist = cmp.getList("ArmorDropChances", 5);
if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat( if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) {
2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) {
cmp.remove("ArmorDropChances"); cmp.remove("ArmorDropChances");
} }
} }
return cmp; return cmp;
} }
} }
private static class DataConverterRiding implements DataConverter { private static class DataConverterRiding implements DataConverter {
@ -1966,7 +1871,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
nbttagcompound.remove("Riding"); nbttagcompound.remove("Riding");
return nbttagcompound1; return nbttagcompound1;
} }
} }
private static class DataConverterBook implements DataConverter { private static class DataConverterBook implements DataConverter {
@ -1991,12 +1895,12 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
if (!"null".equals(s) && !StringUtil.isNullOrEmpty(s)) { if (!"null".equals(s) && !StringUtil.isNullOrEmpty(s)) {
if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) { if ((s.charAt(0) != 34 || s.charAt(s.length() - 1) != 34) && (s.charAt(0) != 123 || s.charAt(s.length() - 1) != 125)) {
object = new TextComponent(s); object = Component.literal(s);
} else { } else {
try { try {
object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true); object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true);
if (object == null) { if (object == null) {
object = new TextComponent(""); object = Component.literal("");
} }
} catch (JsonParseException jsonparseexception) { } catch (JsonParseException jsonparseexception) {
; ;
@ -2019,11 +1923,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
} }
if (object == null) { if (object == null) {
object = new TextComponent(s); object = Component.literal(s);
} }
} }
} else { } else {
object = new TextComponent(""); object = Component.literal("");
} }
nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object))); nbttaglist.set(i, net.minecraft.nbt.StringTag.valueOf(Component.Serializer.toJson(object)));
@ -2035,7 +1939,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterCookedFish implements DataConverter { private static class DataConverterCookedFish implements DataConverter {
@ -2056,7 +1959,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterZombie implements DataConverter { private static class DataConverterZombie implements DataConverter {
@ -2099,7 +2001,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
private int convert(int i) { private int convert(int i) {
return i >= 0 && i < 6 ? i : -1; return i >= 0 && i < 6 ? i : -1;
} }
} }
private static class DataConverterVBO implements DataConverter { private static class DataConverterVBO implements DataConverter {
@ -2115,7 +2016,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
cmp.putString("useVbo", "true"); cmp.putString("useVbo", "true");
return cmp; return cmp;
} }
} }
private static class DataConverterGuardian implements DataConverter { private static class DataConverterGuardian implements DataConverter {
@ -2138,7 +2038,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterSkeleton implements DataConverter { private static class DataConverterSkeleton implements DataConverter {
@ -2167,7 +2066,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterZombieType implements DataConverter { private static class DataConverterZombieType implements DataConverter {
@ -2206,7 +2104,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterHorse implements DataConverter { private static class DataConverterHorse implements DataConverter {
@ -2249,7 +2146,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterTileEntity implements DataConverter { private static class DataConverterTileEntity implements DataConverter {
@ -2412,8 +2308,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) { public net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp) {
String s = cmp.getString("id"); String s = cmp.getString("id");
if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals( if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(s)) {
s)) {
net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag"); net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag");
if (!nbttagcompound1.contains("Potion", 8)) { if (!nbttagcompound1.contains("Potion", 8)) {
@ -2427,7 +2322,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterShulker implements DataConverter { private static class DataConverterShulker implements DataConverter {
@ -2446,12 +2340,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterShulkerBoxItem implements DataConverter { private static class DataConverterShulkerBoxItem implements DataConverter {
public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"}; public static final String[] a = new String[] { "minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box" };
DataConverterShulkerBoxItem() { DataConverterShulkerBoxItem() {
} }
@ -2488,7 +2381,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterShulkerBoxBlock implements DataConverter { private static class DataConverterShulkerBoxBlock implements DataConverter {
@ -2507,7 +2399,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterLang implements DataConverter { private static class DataConverterLang implements DataConverter {
@ -2526,7 +2417,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterTotem implements DataConverter { private static class DataConverterTotem implements DataConverter {
@ -2545,7 +2435,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterBedBlock implements DataConverter { private static class DataConverterBedBlock implements DataConverter {
@ -2593,7 +2482,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterBedItem implements DataConverter { private static class DataConverterBedItem implements DataConverter {
@ -2612,16 +2500,14 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataConverterSignText implements DataConverter { private static class DataConverterSignText implements DataConverter {
public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() { public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() {
MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException {
JsonParseException {
if (jsonelement.isJsonPrimitive()) { if (jsonelement.isJsonPrimitive()) {
return new TextComponent(jsonelement.getAsString()); return Component.literal(jsonelement.getAsString());
} else if (jsonelement.isJsonArray()) { } else if (jsonelement.isJsonArray()) {
JsonArray jsonarray = jsonelement.getAsJsonArray(); JsonArray jsonarray = jsonelement.getAsJsonArray();
MutableComponent ichatbasecomponent = null; MutableComponent ichatbasecomponent = null;
@ -2629,11 +2515,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
while (iterator.hasNext()) { while (iterator.hasNext()) {
JsonElement jsonelement1 = (JsonElement) iterator.next(); JsonElement jsonelement1 = (JsonElement) iterator.next();
MutableComponent ichatbasecomponent1 = this.a( MutableComponent ichatbasecomponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext);
jsonelement1,
jsonelement1.getClass(),
jsondeserializationcontext
);
if (ichatbasecomponent == null) { if (ichatbasecomponent == null) {
ichatbasecomponent = ichatbasecomponent1; ichatbasecomponent = ichatbasecomponent1;
@ -2648,11 +2530,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
} }
} }
public Object deserialize( public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException {
JsonElement jsonelement,
Type type,
JsonDeserializationContext jsondeserializationcontext
) throws JsonParseException {
return this.a(jsonelement, type, jsondeserializationcontext); return this.a(jsonelement, type, jsondeserializationcontext);
} }
}).create(); }).create();
@ -2681,12 +2559,12 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
if (!"null".equals(s1) && !StringUtil.isNullOrEmpty(s1)) { if (!"null".equals(s1) && !StringUtil.isNullOrEmpty(s1)) {
if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) { if ((s1.charAt(0) != 34 || s1.charAt(s1.length() - 1) != 34) && (s1.charAt(0) != 123 || s1.charAt(s1.length() - 1) != 125)) {
object = new TextComponent(s1); object = Component.literal(s1);
} else { } else {
try { try {
object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true); object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true);
if (object == null) { if (object == null) {
object = new TextComponent(""); object = Component.literal("");
} }
} catch (JsonParseException jsonparseexception) { } catch (JsonParseException jsonparseexception) {
; ;
@ -2709,20 +2587,18 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
} }
if (object == null) { if (object == null) {
object = new TextComponent(s1); object = Component.literal(s1);
} }
} }
} else { } else {
object = new TextComponent(""); object = Component.literal("");
} }
nbttagcompound.putString(s, Component.Serializer.toJson(object)); nbttagcompound.putString(s, Component.Serializer.toJson(object));
} }
} }
private static class DataInspectorPlayerVehicle implements DataInspector { private static class DataInspectorPlayerVehicle implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
if (cmp.contains("RootVehicle", 10)) { if (cmp.contains("RootVehicle", 10)) {
@ -2735,11 +2611,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorLevelPlayer implements DataInspector { private static class DataInspectorLevelPlayer implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
if (cmp.contains("Player", 10)) { if (cmp.contains("Player", 10)) {
@ -2748,11 +2622,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorStructure implements DataInspector { private static class DataInspectorStructure implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
net.minecraft.nbt.ListTag nbttaglist; net.minecraft.nbt.ListTag nbttaglist;
@ -2783,11 +2655,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorChunks implements DataInspector { private static class DataInspectorChunks implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
if (cmp.contains("Level", 10)) { if (cmp.contains("Level", 10)) {
@ -2799,15 +2669,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
nbttaglist = nbttagcompound1.getList("Entities", 10); nbttaglist = nbttagcompound1.getList("Entities", 10);
for (j = 0; j < nbttaglist.size(); ++j) { for (j = 0; j < nbttaglist.size(); ++j) {
nbttaglist.set( nbttaglist.set(j, convert(LegacyType.ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer));
j,
convert(
LegacyType.ENTITY,
(net.minecraft.nbt.CompoundTag) nbttaglist.get(j),
sourceVer,
targetVer
)
);
} }
} }
@ -2815,26 +2677,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
nbttaglist = nbttagcompound1.getList("TileEntities", 10); nbttaglist = nbttagcompound1.getList("TileEntities", 10);
for (j = 0; j < nbttaglist.size(); ++j) { for (j = 0; j < nbttaglist.size(); ++j) {
nbttaglist.set( nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer));
j,
convert(
LegacyType.BLOCK_ENTITY,
(net.minecraft.nbt.CompoundTag) nbttaglist.get(j),
sourceVer,
targetVer
)
);
} }
} }
} }
return cmp; return cmp;
} }
} }
private static class DataInspectorEntityPassengers implements DataInspector { private static class DataInspectorEntityPassengers implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
if (cmp.contains("Passengers", 9)) { if (cmp.contains("Passengers", 9)) {
@ -2847,11 +2699,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorPlayer implements DataInspector { private static class DataInspectorPlayer implements DataInspector {
@Override @Override
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) { public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
convertItems(cmp, "Inventory", sourceVer, targetVer); convertItems(cmp, "Inventory", sourceVer, targetVer);
@ -2866,11 +2716,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorVillagers implements DataInspector { private static class DataInspectorVillagers implements DataInspector {
ResourceLocation entityVillager = getKey("EntityVillager"); ResourceLocation entityVillager = getKey("EntityVillager");
@Override @Override
@ -2894,11 +2742,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorMobSpawnerMinecart implements DataInspector { private static class DataInspectorMobSpawnerMinecart implements DataInspector {
ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner"); ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner");
ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner");
@ -2913,11 +2759,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorMobSpawnerMobs implements DataInspector { private static class DataInspectorMobSpawnerMobs implements DataInspector {
ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner"); ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner");
@Override @Override
@ -2938,11 +2782,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
private static class DataInspectorCommandBlock implements DataInspector { private static class DataInspectorCommandBlock implements DataInspector {
ResourceLocation tileEntityCommand = getKey("TileEntityCommand"); ResourceLocation tileEntityCommand = getKey("TileEntityCommand");
@Override @Override
@ -2955,7 +2797,5 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
return cmp; return cmp;
} }
} }
} }

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -1,28 +1,23 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.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.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial { public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block; private final Block block;
private final BlockState blockState; private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData; private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial; private final org.bukkit.Material craftMaterial;
private final int opacity; private final int opacity;
@ -35,14 +30,8 @@ public class PaperweightBlockMaterial implements BlockMaterial {
public PaperweightBlockMaterial(Block block, BlockState blockState) { public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block; this.block = block;
this.blockState = blockState; this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState); this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial(); this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aP"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity( BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO, BlockPos.ZERO,
@ -50,7 +39,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
); );
tile = tileEntity == null tile = tileEntity == null
? null ? null
: new PaperweightLazyCompoundTag(Suppliers.memoize(() -> tileEntity.save(new net.minecraft.nbt.CompoundTag()))); : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
} }
public Block getBlock() { public Block getBlock() {
@ -65,10 +54,6 @@ public class PaperweightBlockMaterial implements BlockMaterial {
return craftBlockData; return craftBlockData;
} }
public Material getMaterial() {
return material;
}
@Override @Override
public boolean isAir() { public boolean isAir() {
return blockState.isAir(); return blockState.isAir();
@ -81,7 +66,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isOpaque() { public boolean isOpaque() {
return material.isSolidBlocking(); return blockState.canOcclude();
} }
@Override @Override
@ -91,12 +76,13 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isLiquid() { public boolean isLiquid() {
return material.isLiquid(); return !blockState.getFluidState().is(Fluids.EMPTY);
} }
@Override @Override
public boolean isSolid() { public boolean isSolid() {
return material.isSolid(); // No access to world -> EmptyBlockGetter
return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
} }
@Override @Override
@ -126,12 +112,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isFragileWhenPushed() { public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY; return blockState.getPistonPushReaction() == PushReaction.DESTROY;
} }
@Override @Override
public boolean isUnpushable() { public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK; return blockState.getPistonPushReaction() == PushReaction.BLOCK;
} }
@Override @Override
@ -141,12 +127,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isMovementBlocker() { public boolean isMovementBlocker() {
return material.isSolid(); return craftMaterial.isSolid();
} }
@Override @Override
public boolean isBurnable() { public boolean isBurnable() {
return material.isFlammable(); return craftMaterial.isBurnable();
} }
@Override @Override
@ -157,12 +143,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public boolean isReplacedDuringPlacement() { public boolean isReplacedDuringPlacement() {
return material.isReplaceable(); return blockState.canBeReplaced();
} }
@Override @Override
public boolean isTranslucent() { public boolean isTranslucent() {
return isTranslucent; return !blockState.canOcclude();
} }
@Override @Override
@ -183,7 +169,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
@Override @Override
public int getMapColor() { public int getMapColor() {
// rgb field // rgb field
return material.getColor().col; return block.defaultMapColor().col;
} }
} }

Datei anzeigen

@ -1,7 +1,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.entity.LazyBaseEntity;
@ -10,20 +9,15 @@ 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.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
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.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.PaperweightAdapter; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.regen.PaperweightRegen;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.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;
@ -39,7 +33,6 @@ 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.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag; import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
@ -50,53 +43,51 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.BlockMaterial;
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.WritableRegistry; import net.minecraft.core.WritableRegistry;
import net.minecraft.nbt.IntTag; import net.minecraft.core.registries.Registries;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable; import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk; import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlockState; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -110,12 +101,21 @@ import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements import static net.minecraft.core.registries.Registries.BIOME;
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
private final PaperweightAdapter parent; static {
try {
CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave");
} catch (NoSuchMethodException ignored) { // may not be present in newer paper versions
}
}
private final com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter parent;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // Code that may break between versions of Minecraft
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -126,7 +126,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
private Map<String, List<Property<?>>> allBlockProperties = null; private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException { public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter(); this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter();
} }
@Nullable @Nullable
@ -135,12 +135,15 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
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;
} }
@SuppressWarnings("unchecked")
private synchronized boolean init() { private synchronized boolean init() {
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) { if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false; return false;
@ -227,7 +230,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
} }
public Block getBlock(BlockType blockType) { public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK)
.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
} }
@Deprecated @Deprecated
@ -235,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BlockState getBlock(Location location) { public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -255,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseBlock getFullBlock(final Location location) { public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = getServerLevel(location.getWorld());
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);
@ -274,7 +276,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
// 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.save(new net.minecraft.nbt.CompoundTag()); net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
} }
} }
@ -287,67 +289,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
return SideEffectSet.defaults().getSideEffectsToApply(); return SideEffectSet.defaults().getSideEffectsToApply();
} }
@SuppressWarnings("rawtypes")
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
if (section == null) {
if (blockState.isAir()) {
return true;
}
levelChunkSections[y4] = section = new LevelChunkSection(y4 << 4);
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override @Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) { public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess( return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
} }
@Override @Override
@ -363,7 +307,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> { Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag); final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag); final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
@ -492,9 +436,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ServerLevel nmsWorld = getServerLevel(world);
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) { if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false; boolean flag = false;
// PlayerChunk.d players = map.players; // PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
@ -504,7 +448,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer) stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
.forEach(entityPlayer -> { .forEach(entityPlayer -> {
synchronized (chunkPacket) { synchronized (chunkPacket) {
ClientboundLevelChunkPacket nmsPacket = (ClientboundLevelChunkPacket) chunkPacket.getNativePacket(); ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
if (nmsPacket == null) { if (nmsPacket == null) {
nmsPacket = mapUtil.create(this, chunkPacket); nmsPacket = mapUtil.create(this, chunkPacket);
chunkPacket.setNativePacket(nmsPacket); chunkPacket.setNativePacket(nmsPacket);
@ -530,7 +474,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int internalId = BlockStateIdAccess.getBlockStateId(blockState); int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId); net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess( return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(), getServerLevel(world),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()) new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
); );
} }
@ -538,72 +482,35 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) { public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
ItemStack stack = new ItemStack( ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM)
.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount() baseItemStack.getAmount()
); );
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt()))); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
return CraftItemStack.asCraftMirror(stack); return CraftItemStack.asCraftMirror(stack);
} }
@Override @Override
public boolean generateTree( protected void preCaptureStates(final ServerLevel serverLevel) {
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3, serverLevel.captureTreeGeneration = true;
org.bukkit.World bukkitWorld serverLevel.captureBlockStates = true;
) {
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) {
blockVector3 = blockVector3.add(
0,
1,
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back
}
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle();
final BlockVector3 finalBlockVector = blockVector3;
// Sync to main thread to ensure no clashes occur
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> {
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true;
try {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
} }
@Override @Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) { protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
// Quickly add each entity to a list copy. return new ArrayList<>(serverLevel.capturedBlockStates.values());
List<Entity> mcEntities = new ArrayList<>(); }
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>(); @Override
mcEntities.forEach((mcEnt) -> { protected void postCaptureBlockStates(final ServerLevel serverLevel) {
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); serverLevel.captureBlockStates = false;
if (bukkitEntity.isValid()) { serverLevel.captureTreeGeneration = false;
list.add(bukkitEntity); serverLevel.capturedBlockStates.clear();
} }
}); @Override
return list; protected ServerLevel getServerLevel(final World world) {
return ((CraftWorld) world).getHandle();
} }
@Override @Override
@ -642,7 +549,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
final Registry<Biome> registry = MinecraftServer final Registry<Biome> registry = MinecraftServer
.getServer() .getServer()
.registryAccess() .registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY); .registryOrThrow(BIOME);
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId()); ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
Biome biome = registry.get(resourceLocation); Biome biome = registry.get(resourceLocation);
return registry.getId(biome); return registry.getId(biome);
@ -650,11 +557,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public Iterable<NamespacedKey> getRegisteredBiomes() { public Iterable<NamespacedKey> getRegisteredBiomes() {
WritableRegistry<Biome> biomeRegistry = ((CraftServer) Bukkit.getServer()) WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
.getServer() .getServer()
.registryAccess() .registryAccess()
.ownedRegistryOrThrow( .registryOrThrow(BIOME);
Registry.BIOME_REGISTRY);
List<ResourceLocation> keys = biomeRegistry.stream() List<ResourceLocation> keys = biomeRegistry.stream()
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList(); .map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
List<NamespacedKey> namespacedKeys = new ArrayList<>(); List<NamespacedKey> namespacedKeys = new ArrayList<>();
@ -670,17 +576,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
@Override @Override
public RelighterFactory getRelighterFactory() { public RelighterFactory getRelighterFactory() {
try { if (PaperLib.isPaper()) {
Class.forName("ca.spottedleaf.starlight.light.StarLightEngine"); return new PaperweightStarlightRelighterFactory();
if (PaperweightStarlightRelighter.isUsable()) { } else {
return new PaperweightStarlightRelighterFactory(); return new NMSRelighterFactory();
}
} catch (ThreadDeath td) {
throw td;
} catch (Throwable ignored) {
} }
return new NMSRelighterFactory();
} }
@Override @Override
@ -702,4 +602,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
return new PaperweightPostProcessor(); return new PaperweightPostProcessor();
} }
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
try {
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException ignored) {
// fall-through
}
}
// Papers new chunk system has no related replacement - therefor we assume true.
return true;
}
} }

Datei anzeigen

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
@ -15,14 +15,14 @@ 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.ServerChunkCache;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.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 javax.annotation.Nullable; import javax.annotation.Nullable;
@ -102,7 +102,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
} }
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ())); cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ));
boolean nextTick = lastTick.get() > currentTick; boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) { if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) { if (nextTick) {
@ -157,7 +157,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
@Override @Override
public boolean isChunkTicking(LevelChunk levelChunk) { public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
} }
@Override @Override

Datei anzeigen

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
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,22 +20,21 @@ 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_17_R1_2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.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;
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.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import io.papermc.paper.event.block.BeaconDeactivatedEvent; import io.papermc.paper.event.block.BeaconDeactivatedEvent;
import net.minecraft.core.BlockPos; import net.minecraft.core.*;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.IntTag; import net.minecraft.nbt.IntTag;
import net.minecraft.resources.ResourceLocation;
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;
import net.minecraft.util.ZeroBitStorage;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
@ -43,34 +42,17 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BeaconBlockEntity; import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkBiomeContainer; import net.minecraft.world.level.chunk.*;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.lighting.LevelLightEngine; import net.minecraft.world.level.lighting.LevelLightEngine;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock; import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.AbstractSet; import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -81,14 +63,15 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.minecraft.core.registries.Registries.BIOME;
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ());
private static final Function<BlockEntity, CompoundTag> nmsTile2We = private static final Function<BlockEntity, CompoundTag> nmsTile2We =
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize( tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
() -> tileEntity.save(new net.minecraft.nbt.CompoundTag())));
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance() .getInstance()
.getBukkitImplAdapter()); .getBukkitImplAdapter());
@ -101,6 +84,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
private final int maxHeight; private final int maxHeight;
private final int minSectionPosition; private final int minSectionPosition;
private final int maxSectionPosition; private final int maxSectionPosition;
private final Registry<Biome> biomeRegistry;
private final IdMap<Holder<Biome>> biomeHolderIdMap;
private final ConcurrentHashMap<Integer, PaperweightGetBlocks_Copy> copies = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Integer, PaperweightGetBlocks_Copy> copies = new ConcurrentHashMap<>();
private final Object sendLock = new Object(); private final Object sendLock = new Object();
private LevelChunkSection[] sections; private LevelChunkSection[] sections;
@ -127,6 +112,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
this.maxSectionPosition = maxHeight >> 4; this.maxSectionPosition = maxHeight >> 4;
this.skyLight = new DataLayer[getSectionCount()]; this.skyLight = new DataLayer[getSectionCount()];
this.blockLight = new DataLayer[getSectionCount()]; this.blockLight = new DataLayer[getSectionCount()];
this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME);
this.biomeHolderIdMap = biomeRegistry.asHolderIdMap();
} }
public int getChunkX() { public int getChunkX() {
@ -148,6 +135,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked.");
} }
this.createCopy = createCopy; this.createCopy = createCopy;
// Increment regardless of whether copy will be created or not to return null from getCopy()
return ++this.copyKey; return ++this.copyKey;
} }
@ -212,19 +200,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
public BiomeType getBiomeType(int x, int y, int z) { public BiomeType getBiomeType(int x, int y, int z) {
ChunkBiomeContainer index = getChunk().getBiomes(); LevelChunkSection section = getSections(false)[(y >> 4) - getMinSectionPosition()];
Biome biomes = null; Holder<Biome> biomes = section.getNoiseBiome(x >> 2, (y & 15) >> 2, z >> 2);
if (y == -1) { return PaperweightPlatformAdapter.adapt(biomes, serverLevel);
for (y = serverLevel.getMinBuildHeight(); y < serverLevel.getMaxBuildHeight(); y += 4) {
biomes = index.getNoiseBiome(x >> 2, y >> 2, z >> 2);
if (biomes != null) {
break;
}
}
} else {
biomes = index.getNoiseBiome(x >> 2, y >> 2, z >> 2);
}
return biomes != null ? PaperweightPlatformAdapter.adapt(biomes, serverLevel) : null;
} }
@Override @Override
@ -235,10 +213,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (dataLayer != null) { if (dataLayer != null) {
lightUpdate = true; lightUpdate = true;
synchronized (dataLayer) { synchronized (dataLayer) {
byte[] bytes = PaperLib.isPaper() ? dataLayer.getIfSet() : dataLayer.getData(); byte[] bytes = dataLayer.getData();
if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0);
Arrays.fill(bytes, (byte) 0);
}
} }
} }
if (sky) { if (sky) {
@ -251,10 +227,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (dataLayer1 != null) { if (dataLayer1 != null) {
lightUpdate = true; lightUpdate = true;
synchronized (dataLayer1) { synchronized (dataLayer1) {
byte[] bytes = PaperLib.isPaper() ? dataLayer1.getIfSet() : dataLayer1.getData(); byte[] bytes = dataLayer1.getData();
if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0);
Arrays.fill(bytes, (byte) 0);
}
} }
} }
} }
@ -268,7 +242,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (blockEntity == null) { if (blockEntity == null) {
return null; return null;
} }
return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag()))); return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId));
} }
@Override @Override
@ -297,8 +271,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
LightLayer.BLOCK, LightLayer.BLOCK,
sectionPos, sectionPos,
dataLayer, dataLayer
true
); );
} }
skyLight[alayer] = dataLayer; skyLight[alayer] = dataLayer;
@ -325,7 +298,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
Arrays.fill(LAYER_COUNT, (byte) 15); Arrays.fill(LAYER_COUNT, (byte) 15);
dataLayer = new DataLayer(LAYER_COUNT); dataLayer = new DataLayer(LAYER_COUNT);
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos, ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos,
dataLayer, true dataLayer
); );
} }
blockLight[alayer] = dataLayer; blockLight[alayer] = dataLayer;
@ -342,7 +315,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();
@ -357,6 +338,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
public Set<CompoundTag> getEntities() { public Set<CompoundTag> getEntities() {
ensureLoaded(serverLevel, chunkX, chunkZ);
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk()); List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
if (entities.isEmpty()) { if (entities.isEmpty()) {
return Collections.emptySet(); return Collections.emptySet();
@ -393,7 +375,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();
@ -426,7 +408,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
try { try {
ServerLevel nmsWorld = serverLevel; ServerLevel nmsWorld = serverLevel;
LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
boolean fastmode = set.isFastMode() && Settings.settings().QUEUE.NO_TICK_FASTMODE;
// Remove existing tiles. Create a copy so that we can remove blocks // Remove existing tiles. Create a copy so that we can remove blocks
Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities());
@ -460,18 +441,70 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
} }
final BiomeType[][] biomes = set.getBiomes();
int bitMask = 0; int bitMask = 0;
synchronized (nmsChunk) { synchronized (nmsChunk) {
LevelChunkSection[] levelChunkSections = nmsChunk.getSections(); LevelChunkSection[] levelChunkSections = nmsChunk.getSections();
for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) { for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) {
int getSectionIndex = layerNo - getMinSectionPosition();
int setSectionIndex = layerNo - set.getMinSectionPosition();
if (!set.hasSection(layerNo)) { if (!set.hasSection(layerNo)) {
// No blocks, but might be biomes present. Handle this lazily.
if (biomes == null) {
continue;
}
if (layerNo < set.getMinSectionPosition() || layerNo > set.getMaxSectionPosition()) {
continue;
}
if (biomes[setSectionIndex] != null) {
synchronized (super.sectionLocks[getSectionIndex]) {
LevelChunkSection existingSection = levelChunkSections[getSectionIndex];
if (createCopy && existingSection != null) {
copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
}
if (existingSection == null) {
PalettedContainer<Holder<Biome>> biomeData = PaperweightPlatformAdapter.getBiomePalettedContainer(
biomes[setSectionIndex],
biomeHolderIdMap
);
LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection(
layerNo,
new char[4096],
adapter,
biomeRegistry,
biomeData
);
if (PaperweightPlatformAdapter.setSectionAtomic(
levelChunkSections,
null,
newSection,
getSectionIndex
)) {
updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex);
continue;
} else {
existingSection = levelChunkSections[getSectionIndex];
if (existingSection == null) {
LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ,
getSectionIndex
);
continue;
}
}
} else {
setBiomesToPalettedContainer(biomes, setSectionIndex, existingSection.getBiomes());
}
}
}
continue; continue;
} }
int layer = layerNo - getMinSectionPosition();
bitMask |= 1 << layer; bitMask |= 1 << getSectionIndex;
// setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to
// this chunk GET when #updateGet is called. Future dords, please listen this time. // this chunk GET when #updateGet is called. Future dords, please listen this time.
@ -481,16 +514,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
// synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was
// submitted to keep loaded internal chunks to queue target size. // submitted to keep loaded internal chunks to queue target size.
synchronized (super.sectionLocks[layer]) { synchronized (super.sectionLocks[getSectionIndex]) {
if (createCopy) {
char[] tmpLoad = loadPrivately(layerNo);
char[] copyArr = new char[4096];
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
copy.storeSection(layer, copyArr);
}
LevelChunkSection newSection; LevelChunkSection newSection;
LevelChunkSection existingSection = levelChunkSections[layer]; LevelChunkSection existingSection = levelChunkSections[getSectionIndex];
// 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);
@ -499,23 +526,53 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
if (createCopy) {
char[] tmpLoad = loadPrivately(layerNo);
char[] copyArr = new char[4096];
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
copy.storeSection(getSectionIndex, copyArr);
if (biomes != null && existingSection != null) {
copy.storeBiomes(getSectionIndex, existingSection.getBiomes());
}
}
if (existingSection == null) { if (existingSection == null) {
newSection = PaperweightPlatformAdapter.newChunkSection(layerNo, setArr, fastmode, adapter); PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
if (PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, null, newSection, layer)) { biomeHolderIdMap,
updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer); biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(
BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES
) : PaperweightPlatformAdapter.getBiomePalettedContainer(biomes[setSectionIndex], biomeHolderIdMap);
newSection = PaperweightPlatformAdapter.newChunkSection(
layerNo,
setArr,
adapter,
biomeRegistry,
biomeData
);
if (PaperweightPlatformAdapter.setSectionAtomic(
levelChunkSections,
null,
newSection,
getSectionIndex
)) {
updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex);
continue; continue;
} else { } else {
existingSection = levelChunkSections[layer]; existingSection = levelChunkSections[getSectionIndex];
if (existingSection == null) { if (existingSection == null) {
LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ,
+layer getSectionIndex
); );
continue; continue;
} }
} }
} }
//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()) { if (PaperLib.isPaper()) {
existingSection.tickingList.clear(); existingSection.tickingList.clear();
@ -532,10 +589,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
this.levelChunk = nmsChunk; this.levelChunk = nmsChunk;
this.sections = null; this.sections = null;
this.reset(); this.reset();
} else if (existingSection != getSections(false)[layer]) { } else if (existingSection != getSections(false)[getSectionIndex]) {
this.sections[layer] = existingSection; this.sections[getSectionIndex] = existingSection;
this.reset(); this.reset();
} else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layerNo))) { } else if (!Arrays.equals(
update(getSectionIndex, new char[4096], true),
loadPrivately(layerNo)
)) {
this.reset(layerNo); this.reset(layerNo);
/*} else if (lock.isModified()) { /*} else if (lock.isModified()) {
this.reset(layerNo);*/ this.reset(layerNo);*/
@ -543,56 +603,33 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} finally { } finally {
sectionLock.writeLock().unlock(); sectionLock.writeLock().unlock();
} }
PalettedContainer<Holder<Biome>> biomeData = setBiomesToPalettedContainer(
biomes,
setSectionIndex,
existingSection.getBiomes()
);
newSection = newSection =
PaperweightPlatformAdapter.newChunkSection( PaperweightPlatformAdapter.newChunkSection(
layerNo, layerNo,
this::loadPrivately, this::loadPrivately,
setArr, setArr,
fastmode, adapter,
adapter biomeRegistry,
biomeData
); );
if (!PaperweightPlatformAdapter.setSectionAtomic( if (!PaperweightPlatformAdapter.setSectionAtomic(
levelChunkSections, levelChunkSections,
existingSection, existingSection,
newSection, newSection,
layer getSectionIndex
)) { )) {
LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ, LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ,
+layer getSectionIndex
); );
} else { } else {
updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer); updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex);
}
}
}
}
// Biomes
BiomeType[][] biomes = set.getBiomes();
if (biomes != null) {
// set biomes
ChunkBiomeContainer currentBiomes = nmsChunk.getBiomes();
if (createCopy) {
copy.storeBiomes(currentBiomes);
}
for (int layer = 0; layer < 16; layer++) {
if (biomes[layer] == null) {
continue;
}
for (int y = 0, i = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, i++) {
final BiomeType biome = biomes[layer][i];
if (biome != null) {
Biome nmsBiome =
nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get(
ResourceLocation.tryParse(biome.getId()));
if (nmsBiome == null) {
throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId());
}
currentBiomes.setBiome(x, (layer << 2) + y, z, nmsBiome);
}
}
} }
} }
} }
@ -656,7 +693,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
for (UUID uuid : entityRemoves) { for (UUID uuid : entityRemoves) {
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid); Entity entity = nmsWorld.getEntities().get(uuid);
if (entity != null) { if (entity != null) {
removeEntity(entity); removeEntity(entity);
} }
@ -705,7 +742,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
entity.load(tag); entity.load(tag);
entity.absMoveTo(x, y, z, yaw, pitch); entity.absMoveTo(x, y, z, yaw, pitch);
entity.setUUID(nativeTag.getUUID()); entity.setUUID(nativeTag.getUUID());
if (!nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
LOGGER.warn( LOGGER.warn(
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`", "Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
id, id,
@ -768,7 +805,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
// Set Modified // Set Modified
nmsChunk.setLightCorrect(true); // Set Modified nmsChunk.setLightCorrect(true); // Set Modified
nmsChunk.mustNotSave = false; nmsChunk.mustNotSave = false;
nmsChunk.markUnsaved(); nmsChunk.setUnsaved(true);
// send to player // send to player
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) { if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
this.send(finalMask, finalLightUpdate); this.send(finalMask, finalLightUpdate);
@ -907,11 +944,18 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
try { try {
lock.acquire(); lock.acquire();
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates(); final PalettedContainer<BlockState> blocks = section.getStates();
final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(blocks); final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocks);
final Palette<BlockState> palette = (Palette<BlockState>) PaperweightPlatformAdapter.fieldPalette.get(blocks); final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject);
final int bitsPerEntry = (int) PaperweightPlatformAdapter.fieldBitsPerEntry.get(bits); if (bits instanceof ZeroBitStorage) {
Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper
return data;
}
final Palette<BlockState> palette = (Palette<BlockState>) PaperweightPlatformAdapter.fieldPalette.get(dataObject);
final int bitsPerEntry = bits.getBits();
final long[] blockStates = bits.getRaw(); final long[] blockStates = bits.getRaw();
new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data); new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data);
@ -964,7 +1008,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
private char ordinal(net.minecraft.world.level.block.state.BlockState ibd, PaperweightFaweAdapter adapter) { private char ordinal(BlockState ibd, PaperweightFaweAdapter adapter) {
if (ibd == null) { if (ibd == null) {
return BlockTypesCache.ReservedIDs.AIR; return BlockTypesCache.ReservedIDs.AIR;
} else { } else {
@ -1020,8 +1064,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData( ((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
lightLayer, lightLayer,
sectionPos, sectionPos,
dataLayer, dataLayer
true
); );
} }
synchronized (dataLayer) { synchronized (dataLayer) {
@ -1039,6 +1082,49 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
} }
private PalettedContainer<Holder<Biome>> setBiomesToPalettedContainer(
final BiomeType[][] biomes,
final int sectionIndex,
final PalettedContainerRO<Holder<Biome>> data
) {
PalettedContainer<Holder<Biome>> biomeData;
if (data instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
biomeData = palettedContainer;
} else {
LOGGER.warn(
"Cannot correctly set biomes to world, existing biomes may be lost. Expected class " +
"type {} but got {}",
PalettedContainer.class.getSimpleName(),
data.getClass().getSimpleName()
);
biomeData = data.recreate();
}
BiomeType[] sectionBiomes;
if (biomes == null || (sectionBiomes = biomes[sectionIndex]) == null) {
return biomeData;
}
for (int y = 0, index = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, index++) {
BiomeType biomeType = sectionBiomes[index];
if (biomeType == null) {
continue;
}
biomeData.set(
x,
y,
z,
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(biomeType))
);
}
}
}
return biomeData;
}
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
layer -= getMinSectionPosition(); layer -= getMinSectionPosition();
@ -1067,10 +1153,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
LevelChunkSection existing = getSections(true)[layer]; LevelChunkSection existing = getSections(true)[layer];
try { try {
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocksExisting = existing.getStates(); final PalettedContainer<BlockState> blocksExisting = existing.getStates();
final Object dataObject = PaperweightPlatformAdapter.fieldData.get(blocksExisting);
final Palette<BlockState> palette = (Palette<BlockState>) PaperweightPlatformAdapter.fieldPalette.get( final Palette<BlockState> palette = (Palette<BlockState>) PaperweightPlatformAdapter.fieldPalette.get(
blocksExisting); dataObject);
int paletteSize; int paletteSize;
if (palette instanceof LinearPalette || palette instanceof HashMapPalette) { if (palette instanceof LinearPalette || palette instanceof HashMapPalette) {

Datei anzeigen

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
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,18 +8,22 @@ 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_17_R1_2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.PalettedContainerRO;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
@ -32,6 +36,8 @@ import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet { public class PaperweightGetBlocks_Copy implements IChunkGet {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>(); private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks; private final char[][] blocks;
@ -39,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
private final int maxHeight; private final int maxHeight;
final ServerLevel serverLevel; final ServerLevel serverLevel;
final LevelChunk levelChunk; final LevelChunk levelChunk;
private ChunkBiomeContainer chunkBiomeContainer; private PalettedContainer<Holder<Biome>>[] biomes = null;
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
this.levelChunk = levelChunk; this.levelChunk = levelChunk;
@ -56,7 +62,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ() blockEntity.getBlockPos().getZ()
), ),
new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag()))) new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
); );
} }
@ -75,7 +81,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));
} }
@ -136,28 +142,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
return minHeight >> 4; return minHeight >> 4;
} }
protected void storeBiomes(ChunkBiomeContainer chunkBiomeContainer) {
// The to do one line below is pre-paperweight and needs to be revised
// TODO revisit last parameter, BiomeStorage[] *would* be more efficient
this.chunkBiomeContainer = new ChunkBiomeContainer(chunkBiomeContainer.biomeRegistry, serverLevel,
chunkBiomeContainer.writeBiomes()
);
}
@Override @Override
public BiomeType getBiomeType(int x, int y, int z) { public BiomeType getBiomeType(int x, int y, int z) {
Biome biome = null; Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
if (y == -1) { return PaperweightPlatformAdapter.adapt(biome, serverLevel);
for (y = serverLevel.getMinBuildHeight(); y <= serverLevel.getMaxBuildHeight(); y += 4) {
biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2);
if (biome != null) {
break;
}
}
} else {
biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2);
}
return biome != null ? PaperweightPlatformAdapter.adapt(biome, serverLevel) : null;
} }
@Override @Override
@ -183,6 +171,21 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
blocks[layer] = data; blocks[layer] = data;
} }
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
if (biomes == null) {
biomes = new PalettedContainer[getSectionCount()];
}
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
biomes[layer] = palettedContainer.copy();
} else {
LOGGER.error(
"Cannot correctly save biomes to history. Expected class type {} but got {}",
PalettedContainer.class.getSimpleName(),
biomeData.getClass().getSimpleName()
);
}
}
@Override @Override
public BaseBlock getFullBlock(int x, int y, int z) { public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)]; BlockState state = BlockTypesCache.states[get(x, y, z)];

Datei anzeigen

@ -0,0 +1,34 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
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();
}
}

Datei anzeigen

@ -0,0 +1,719 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_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.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.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.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_20_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.invoke.MethodType;
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 java.lang.invoke.MethodType.methodType;
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 fieldNonEmptyBlockCount;
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;
/*
* This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java
* and is only needed to support 1.19.4 versions before *and* after this change.
*/
private static final MethodHandle CRAFT_CHUNK_GET_HANDLE;
private static final Field fieldRemove;
private static final Logger LOGGER = LogManagerCompat.getLogger();
static final boolean POST_CHUNK_REWRITE;
private static Method PAPER_CHUNK_GEN_ALL_ENTITIES;
private static Field LEVEL_CHUNK_ENTITIES;
private static Field SERVER_LEVEL_ENTITY_MANAGER;
static {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
fieldData.setAccessible(true);
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", "g"));
fieldTickingFluidCount.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "e"));
fieldNonEmptyBlockCount.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", "M"));
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) {
}
POST_CHUNK_REWRITE = chunkRewrite;
} catch (RuntimeException | Error e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
MethodHandle craftChunkGetHandle;
final MethodType type = methodType(LevelChunk.class);
try {
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", type);
} catch (NoSuchMethodException | IllegalAccessException e) {
try {
final MethodType newType = methodType(ChunkAccess.class, ChunkStatus.class);
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", newType);
craftChunkGetHandle = MethodHandles.insertArguments(craftChunkGetHandle, 1, ChunkStatus.FULL);
} catch (NoSuchMethodException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
CRAFT_CHUNK_GET_HANDLE = craftChunkGetHandle;
}
static boolean setSectionAtomic(
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) CRAFT_CHUNK_GET_HANDLE.invoke(chunk);
} 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(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) {
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;
}
TaskManager.taskManager().task(() -> {
ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) {
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null
// last false is to not bother with x-ray
);
} else {
// deprecated on paper - deprecation suppressed
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null
);
}
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
);
}
return new LevelChunkSection(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(biomeRegistry);
}
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
Blocks.AIR.defaultBlockState(),
PalettedContainer.Strategy.SECTION_STATES
);
return new LevelChunkSection(dataPaletteBlocks, biomes);
}
/**
* 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
);
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();
}
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();
}
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
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;
@ -165,7 +165,7 @@ public class PaperweightPostProcessor implements IBatchProcessor {
} else { } else {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER; type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
} }
serverLevel.getLiquidTicks().scheduleTick( serverLevel.scheduleTick(
position, position,
type, type,
type.getTickDelay(serverLevel) type.getTickDelay(serverLevel)

Datei anzeigen

@ -1,19 +1,15 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.IQueueExtent;
import net.minecraft.server.MCUtil; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
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.ChunkStatus;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -21,31 +17,8 @@ import java.util.function.IntConsumer;
public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> { public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLevel, ChunkPos> {
private static final MethodHandle RELIGHT;
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
static {
MethodHandle tmp = null;
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
tmp = lookup.findVirtual(
ThreadedLevelLightEngine.class,
"relight",
MethodType.methodType(
int.class, // return type
// params
Set.class,
Consumer.class,
IntConsumer.class
)
);
tmp = MethodHandles.dropReturn(tmp);
} catch (NoSuchMethodException | IllegalAccessException e) {
LOGGER.error("Failed to locate 'relight' method in ThreadedLevelLightEngine. Is everything up to date?", e);
}
RELIGHT = tmp;
}
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) { public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> queue) {
super(serverLevel, queue); super(serverLevel, queue);
@ -72,25 +45,15 @@ public class PaperweightStarlightRelighter extends StarlightRelighter<ServerLeve
)); ));
} }
public static boolean isUsable() {
return RELIGHT != null;
}
@Override
protected void invokeRelight( protected void invokeRelight(
Set<ChunkPos> coords, Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback, Consumer<ChunkPos> chunkCallback,
IntConsumer processCallback IntConsumer processCallback
) { ) {
try { try {
RELIGHT.invokeExact( serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
serverLevel.getChunkSource().getLightEngine(), } catch (Exception e) {
coords, LOGGER.error("Error occurred on relighting", e);
chunkCallback, // callback per chunk
processCallback // callback for all chunks
);
} catch (Throwable throwable) {
LOGGER.error("Error occurred on relighting", throwable);
} }
} }

Datei anzeigen

@ -1,4 +1,4 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
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_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -23,4 +23,3 @@ public class PaperweightStarlightRelighterFactory implements RelighterFactory {
} }
} }

Datei anzeigen

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

Datei anzeigen

@ -1,36 +1,37 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen; package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
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_17_R1_2.PaperweightGetBlocks; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.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 net.minecraft.core.MappedRegistry; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.biome.Biomes;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.LinearCongruentialGenerator; import net.minecraft.util.thread.ProcessorHandle;
import net.minecraft.util.thread.ProcessorMailbox;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelHeightAccessor;
@ -38,9 +39,9 @@ import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource; import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.biome.OverworldBiomeSource;
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.ChunkStatus; 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;
@ -49,31 +50,24 @@ import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.SimpleRandomSource; import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.synth.ImprovedNoise; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.newbiome.area.Area;
import net.minecraft.world.level.newbiome.area.AreaFactory;
import net.minecraft.world.level.newbiome.context.BigContext;
import net.minecraft.world.level.newbiome.layer.Layer;
import net.minecraft.world.level.newbiome.layer.Layers;
import net.minecraft.world.level.newbiome.layer.traits.PixelTransformer;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer; import org.bukkit.Chunk;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.generator.CustomChunkGenerator; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.generator.CustomChunkGenerator;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -82,23 +76,25 @@ import java.util.Map;
import java.util.OptionalLong; import java.util.OptionalLong;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import java.util.function.LongFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
import static net.minecraft.core.registries.Registries.BIOME;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> { public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field worldsField; private static final Field serverWorldsField;
private static final Field paperConfigField; private static final Field paperConfigField;
private static final Field generateFlatBedrockField; private static final Field flatBedrockField;
private static final Field generatorSettingFlatField; private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField; private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField; private static final Field delegateField;
private static final Field chunkSourceField; private static final Field chunkSourceField;
private static final Field generatorStructureStateField;
private static final Field ringPositionsField;
private static final Field hasGeneratedPositionsField;
//list of chunk stati in correct order without FULL //list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>(); private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
@ -114,21 +110,21 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
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( /*chunkStati.put(
ChunkStatus.LIQUID_CARVERS, ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results ); // 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( 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.FULL); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 // chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try { try {
worldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField = CraftServer.class.getDeclaredField("worlds");
worldsField.setAccessible(true); serverWorldsField.setAccessible(true);
Field tmpPaperConfigField; Field tmpPaperConfigField;
Field tmpFlatBedrockField; Field tmpFlatBedrockField;
@ -143,20 +139,31 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
tmpFlatBedrockField = null; tmpFlatBedrockField = null;
} }
paperConfigField = tmpPaperConfigField; paperConfigField = tmpPaperConfigField;
generateFlatBedrockField = tmpFlatBedrockField; flatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "g")); "settings", "e"));
generatorSettingBaseSupplierField.setAccessible(true); generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "e")); generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d"));
generatorSettingFlatField.setAccessible(true); generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true); delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C")); chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
chunkSourceField.setAccessible(true); chunkSourceField.setAccessible(true);
generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v"));
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) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -168,7 +175,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private ServerLevel freshWorld; private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider; private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session; private LevelStorageSource.LevelStorageAccess session;
private StructureManager structureManager; private StructureTemplateManager structureTemplateManager;
private ThreadedLevelLightEngine threadedLevelLightEngine; private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator; private ChunkGenerator chunkGenerator;
@ -188,7 +195,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
//flat bedrock? (only on paper) //flat bedrock? (only on paper)
if (paperConfigField != null) { if (paperConfigField != null) {
try { try {
generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld)); generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
@ -200,6 +207,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
@Override @Override
@SuppressWarnings("unchecked")
protected boolean initNewWorld() throws Exception { protected boolean initNewWorld() throws Exception {
//world folder //world folder
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
@ -212,12 +220,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey); session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
WorldGenSettings originalOpts = originalWorldData.worldGenSettings(); WorldOptions originalOpts = originalWorldData.worldGenOptions();
WorldGenSettings newOpts = options.getSeed().isPresent() WorldOptions newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed)) ? originalOpts.withSeed(OptionalLong.of(seed))
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld", "faweregentempworld",
@ -226,9 +232,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
originalWorldData.settings.difficulty(), originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(), originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(), originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig() originalWorldData.settings.getDataConfiguration()
); );
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
originalWorldData.isFlatWorld()
? PrimaryLevelData.SpecialWorldProperty.FLAT
: originalWorldData.isDebugWorld()
? PrimaryLevelData.SpecialWorldProperty.DEBUG
: PrimaryLevelData.SpecialWorldProperty.NONE;
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable());
BiomeProvider biomeProvider = getBiomeProvider();
//init world //init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel( freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
@ -237,72 +253,79 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
session, session,
newWorldData, newWorldData,
originalServerWorld.dimension(), originalServerWorld.dimension(),
originalServerWorld.dimensionType(), DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow()
.getOrThrow(levelStemResourceKey),
new RegenNoOpWorldLoadListener(), new RegenNoOpWorldLoadListener(),
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
newOpts.dimensions().get(levelStemResourceKey).generator(),
originalServerWorld.isDebug(), originalServerWorld.isDebug(),
seed, seed,
ImmutableList.of(), ImmutableList.of(),
false, false,
originalServerWorld.getRandomSequences(),
environment, environment,
generator, generator,
biomeProvider biomeProvider
) { ) {
private final Biome singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(
options private final Holder<Biome> singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess()
.getBiomeType() .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
.getId())) : null; WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
) : null;
@Override @Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
} }
@Override @Override
public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) { if (options.hasBiomeType()) {
return singleBiome; return singleBiome;
} }
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ); return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
);
} }
}).get(); }).get();
freshWorld.noSave = true; freshWorld.noSave = true;
removeWorldFromWorldsMap(); removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) { if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig); paperConfigField.set(freshWorld, originalServerWorld.paperConfig());
} }
//generator ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
if (originalChunkProvider.getGenerator() instanceof FlatLevelSource) { if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = (FlatLevelGeneratorSettings) generatorSettingFlatField.get( FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
originalChunkProvider.getGenerator());
chunkGenerator = new FlatLevelSource(generatorSettingFlat); chunkGenerator = new FlatLevelSource(generatorSettingFlat);
} else if (originalChunkProvider.getGenerator() instanceof NoiseBasedChunkGenerator) { } else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
Supplier<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Supplier<NoiseGeneratorSettings>) generatorSettingBaseSupplierField Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField.get(
.get(originalChunkProvider.getGenerator()); originalGenerator);
BiomeSource biomeSource; BiomeSource biomeSource;
if (options.hasBiomeType()) { if (options.hasBiomeType()) {
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options
.getBiomeType() biomeSource = new FixedBiomeSource(
.getId()))); DedicatedServer.getServer().registryAccess()
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
)
);
} else { } else {
biomeSource = originalChunkProvider.getGenerator().getBiomeSource(); biomeSource = originalGenerator.getBiomeSource();
if (biomeSource instanceof OverworldBiomeSource) {
biomeSource = fastOverworldBiomeSource(biomeSource);
}
} }
chunkGenerator = new NoiseBasedChunkGenerator(biomeSource, seed, generatorSettingBaseSupplier); chunkGenerator = new NoiseBasedChunkGenerator(
} else if (originalChunkProvider.getGenerator() instanceof CustomChunkGenerator) { biomeSource,
chunkGenerator = (ChunkGenerator) delegateField.get(originalChunkProvider.getGenerator()); generatorSettingBaseSupplier
);
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
chunkGenerator = customChunkGenerator.getDelegate();
} else { } else {
LOGGER.error("Unsupported generator type {}", originalChunkProvider.getGenerator().getClass().getName()); LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
return false; return false;
} }
if (generator != null) { if (generator != null) {
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable(); generateConcurrent = generator.isParallelCapable();
} }
// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed
freshChunkProvider = new ServerChunkCache( freshChunkProvider = new ServerChunkCache(
freshWorld, freshWorld,
@ -312,6 +335,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
server.executor, server.executor,
chunkGenerator, chunkGenerator,
freshWorld.spigotConfig.viewDistance, freshWorld.spigotConfig.viewDistance,
freshWorld.spigotConfig.simulationDistance,
server.forceSynchronousWrites(), server.forceSynchronousWrites(),
new RegenNoOpWorldLoadListener(), new RegenNoOpWorldLoadListener(),
(chunkCoordIntPair, state) -> { (chunkCoordIntPair, state) -> {
@ -329,10 +353,26 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
}; };
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
// Optimisation for needless ring position calculation when the seed and biome is the same.
ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap);
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state);
if (hasGeneratedPositions) {
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> origPositions =
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(state);
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(
origPositions);
ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap);
ringPositionsField.set(newState, copy);
hasGeneratedPositionsField.setBoolean(newState, true);
}
}
chunkSourceField.set(freshWorld, freshChunkProvider); chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then //let's start then
structureManager = server.getStructureManager(); structureTemplateManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine(); threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
return true; return true;
} }
@ -349,7 +389,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
Fawe.instance().getQueueHandler().sync(() -> { Fawe.instance().getQueueHandler().sync(() -> {
try { try {
freshChunkProvider.close(false); freshChunkProvider.close(false);
} catch (IOException e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}); });
@ -371,9 +411,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
protected ProtoChunk createProtoChunk(int x, int z) { protected ProtoChunk createProtoChunk(int x, int z) {
return PaperLib.isPaper() return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
? new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, freshWorld) // paper this.freshWorld.registryAccess().registryOrThrow(BIOME), null
: new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld); // spigot );
} }
@Override @Override
@ -398,7 +438,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access // BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); TaskManager.taskManager().task(() -> {
final CraftWorld world = freshWorld.getWorld();
final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ);
blockPopulator.populate(world, random, chunk);
});
} }
@Override @Override
@ -416,7 +460,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private void removeWorldFromWorldsMap() { private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> { Fawe.instance().getQueueHandler().sync(() -> {
try { try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) worldsField.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);
@ -432,180 +476,6 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
}; };
} }
@SuppressWarnings({"unchecked", "rawtypes"})
private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception {
Field legacyBiomeInitLayerField = OverworldBiomeSource.class.getDeclaredField(
Refraction.pickName("legacyBiomeInitLayer", "i"));
legacyBiomeInitLayerField.setAccessible(true);
Field largeBiomesField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("largeBiomes", "j"));
largeBiomesField.setAccessible(true);
Field biomeRegistryField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("biomes", "k"));
biomeRegistryField.setAccessible(true);
Field areaLazyField = Layer.class.getDeclaredField(Refraction.pickName("area", "b"));
areaLazyField.setAccessible(true);
Method initAreaFactoryMethod = Layers.class.getDeclaredMethod(
Refraction.pickName("getDefaultLayer", "a"),
boolean.class,
int.class,
int.class,
LongFunction.class
);
initAreaFactoryMethod.setAccessible(true);
//init new WorldChunkManagerOverworld
boolean legacyBiomeInitLayer = legacyBiomeInitLayerField.getBoolean(biomeSource);
boolean largebiomes = largeBiomesField.getBoolean(biomeSource);
Registry<Biome> biomeRegistryMojang = (Registry<Biome>) biomeRegistryField.get(biomeSource);
Registry<Biome> biomeRegistry;
if (options.hasBiomeType()) {
Biome biome = BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options.getBiomeType().getId()));
biomeRegistry = new MappedRegistry<>(
ResourceKey.createRegistryKey(new ResourceLocation("fawe_biomes")),
Lifecycle.experimental()
);
((MappedRegistry) biomeRegistry).registerMapping(0, BuiltinRegistries.BIOME.getResourceKey(biome).get(), biome,
Lifecycle.experimental()
);
} else {
biomeRegistry = biomeRegistryMojang;
}
//replace genLayer
AreaFactory<FastAreaLazy> factory = (AreaFactory<FastAreaLazy>) initAreaFactoryMethod.invoke(
null,
legacyBiomeInitLayer,
largebiomes ? 6 : 4,
4,
(LongFunction) (salt -> new FastWorldGenContextArea(seed, salt))
);
biomeSource = new FastOverworldBiomeSource(biomeRegistry, new FastGenLayer(factory));
return biomeSource;
}
private static class FastOverworldBiomeSource extends BiomeSource {
private final Registry<Biome> biomeRegistry;
private final boolean isSingleRegistry;
private final FastGenLayer fastGenLayer;
public FastOverworldBiomeSource(
Registry<Biome> biomeRegistry,
FastGenLayer genLayer
) {
super(biomeRegistry.stream().collect(Collectors.toList()));
this.biomeRegistry = biomeRegistry;
this.isSingleRegistry = biomeRegistry.entrySet().size() == 1;
this.fastGenLayer = genLayer;
}
@Override
protected Codec<? extends BiomeSource> codec() {
return OverworldBiomeSource.CODEC;
}
@Override
public BiomeSource withSeed(final long seed) {
return null;
}
@Override
public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (this.isSingleRegistry) {
return this.biomeRegistry.byId(0);
}
return this.fastGenLayer.get(this.biomeRegistry, biomeX, biomeZ);
}
}
private static class FastWorldGenContextArea implements BigContext<FastAreaLazy> {
private final ConcurrentHashMap<Long, Integer> sharedAreaMap = new ConcurrentHashMap<>();
private final ImprovedNoise improvedNoise;
private final long magicrandom;
private final ConcurrentHashMap<Long, Long> map = new ConcurrentHashMap<>(); //needed for multithreaded generation
public FastWorldGenContextArea(long seed, long lconst) {
this.magicrandom = mix(seed, lconst);
this.improvedNoise = new ImprovedNoise(new SimpleRandomSource(seed));
}
private static long mix(long seed, long salt) {
long l = LinearCongruentialGenerator.next(salt, salt);
l = LinearCongruentialGenerator.next(l, salt);
l = LinearCongruentialGenerator.next(l, salt);
long m = LinearCongruentialGenerator.next(seed, l);
m = LinearCongruentialGenerator.next(m, l);
m = LinearCongruentialGenerator.next(m, l);
return m;
}
@Override
public FastAreaLazy createResult(PixelTransformer pixelTransformer) {
return new FastAreaLazy(sharedAreaMap, pixelTransformer);
}
@Override
public void initRandom(long x, long z) {
long l = this.magicrandom;
l = LinearCongruentialGenerator.next(l, x);
l = LinearCongruentialGenerator.next(l, z);
l = LinearCongruentialGenerator.next(l, x);
l = LinearCongruentialGenerator.next(l, z);
this.map.put(Thread.currentThread().getId(), l);
}
@Override
public int nextRandom(int y) {
long tid = Thread.currentThread().getId();
long e = this.map.computeIfAbsent(tid, i -> 0L);
int mod = (int) Math.floorMod(e >> 24L, (long) y);
this.map.put(tid, LinearCongruentialGenerator.next(e, this.magicrandom));
return mod;
}
@Override
public ImprovedNoise getBiomeNoise() {
return this.improvedNoise;
}
}
private static class FastGenLayer extends Layer {
private final FastAreaLazy fastAreaLazy;
public FastGenLayer(AreaFactory<FastAreaLazy> factory) {
super(() -> null);
this.fastAreaLazy = factory.make();
}
@Override
public Biome get(Registry<Biome> registry, int x, int z) {
ResourceKey<Biome> key = Biomes.byId(this.fastAreaLazy.get(x, z));
if (key == null) {
return registry.get(Biomes.byId(0));
}
Biome biome = registry.get(key);
if (biome == null) {
return registry.get(Biomes.byId(0));
}
return biome;
}
}
private record FastAreaLazy(ConcurrentHashMap<Long, Integer> sharedMap, PixelTransformer transformer) implements Area {
@Override
public int get(int x, int z) {
long zx = ChunkPos.asLong(x, z);
return this.sharedMap.computeIfAbsent(zx, i -> this.transformer.apply(x, z));
}
}
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener { private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
private RegenNoOpWorldLoadListener() { private RegenNoOpWorldLoadListener() {
@ -636,15 +506,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private class FastProtoChunk extends ProtoChunk { private class FastProtoChunk extends ProtoChunk {
// avoid warning on paper public FastProtoChunk(
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, ServerLevel serverLevel) { final ChunkPos pos,
super(pos, upgradeData, world, serverLevel); 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 // compatibility with spigot
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor) {
super(pos, upgradeData, levelHeightAccessor);
}
public boolean generateFlatBedrock() { public boolean generateFlatBedrock() {
return generateFlatBedrock; return generateFlatBedrock;
@ -673,7 +547,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
public String name() { public String name() {
return chunkStatus.getName(); return chunkStatus.toString();
} }
@Override @Override
@ -682,7 +556,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
Runnable::run, // TODO revisit, we might profit from this somehow? Runnable::run, // TODO revisit, we might profit from this somehow?
freshWorld, freshWorld,
chunkGenerator, chunkGenerator,
structureManager, structureTemplateManager,
threadedLevelLightEngine, threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)), c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks accessibleChunks
@ -691,4 +565,26 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
/**
* 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> lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) {
return CompletableFuture.completedFuture(chunk);
}
}
} }

Datei anzeigen

@ -1,7 +0,0 @@
plugins {
base
}
artifacts {
add("default", file("./src/main/resources/fastasyncworldedit-adapters.jar"))
}

Datei anzeigen

@ -141,20 +141,15 @@ tasks.named<Jar>("jar") {
addJarManifest(WorldEditKind.Plugin, includeClasspath = true) addJarManifest(WorldEditKind.Plugin, includeClasspath = true)
tasks.named<ShadowJar>("shadowJar") { tasks.named<ShadowJar>("shadowJar") {
dependsOn(project.project(":worldedit-bukkit:adapters").subprojects.map { it.tasks.named("assemble") }) configurations.add(adapters)
from(Callable {
adapters.resolve()
.map { f ->
zipTree(f).matching {
exclude("META-INF/")
}
}
})
archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}") archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}")
dependencies { dependencies {
// In tandem with not bundling log4j, we shouldn't relocate base package here. // In tandem with not bundling log4j, we shouldn't relocate base package here.
// relocate("org.apache.logging", "com.sk89q.worldedit.log4j") // relocate("org.apache.logging", "com.sk89q.worldedit.log4j")
relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4")
exclude(dependency("$group:$name"))
include(dependency(":worldedit-core")) include(dependency(":worldedit-core"))
include(dependency(":worldedit-libs:bukkit")) include(dependency(":worldedit-libs:bukkit"))
// Purposefully not included, we assume (even though no API exposes it) that Log4J will be present at runtime // Purposefully not included, we assume (even though no API exposes it) that Log4J will be present at runtime
@ -183,7 +178,7 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("org.lz4:lz4-java:1.8.0")) include(dependency("org.lz4:lz4-java:1.8.0"))
} }
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") { relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
include(dependency("net.kyori:adventure-nbt:4.14.0")) include(dependency("net.kyori:adventure-nbt:4.16.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"))
@ -192,6 +187,15 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("org.anarres:parallelgzip:1.0.5")) include(dependency("org.anarres:parallelgzip:1.0.5"))
} }
} }
project.project(":worldedit-bukkit:adapters").subprojects.forEach {
dependencies {
include(dependency("${it.group}:${it.name}"))
}
minimize {
exclude(dependency("${it.group}:${it.name}"))
}
}
} }
tasks.named("assemble").configure { tasks.named("assemble").configure {
@ -206,7 +210,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.2", "1.20.1", "1.20", "1.19.4", "1.18.2", "1.17.1", "1.16.5")) gameVersions.addAll(listOf("1.20.4", "1.20.3", "1.20.2", "1.20.1", "1.20", "1.19.4", "1.18.2"))
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}")

Datei anzeigen

@ -109,14 +109,6 @@ public class FaweBukkit implements IFawe, Listener {
if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) { if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) {
LOGGER.warn("Small-edits enabled (maximum y range of 0 -> 256) with 1.18 world heights. Are you sure?"); LOGGER.warn("Small-edits enabled (maximum y range of 0 -> 256) with 1.18 world heights. Are you sure?");
} }
if (version.isEqualOrLowerThan(MinecraftVersion.ONE_DOT_SIXTEEN_EOL)) {
LOGGER.warn("You are running Minecraft 1.16.5. This version has been released over two years ago (January 2021).");
LOGGER.warn("FastAsyncWorldEdit will stop operating on this version in the near future.");
LOGGER.warn("Neither Mojang, nor Spigot or other software vendors support this version anymore." +
"Please update your server to a newer version of Minecraft (1.20+) to continue receiving updates and " +
"support.");
}
} }
@Override @Override

Datei anzeigen

@ -0,0 +1,72 @@
package com.fastasyncworldedit.bukkit.adapter;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.TreeGenerator;
import org.bukkit.Material;
import org.bukkit.TreeType;
import org.bukkit.World;
import org.bukkit.block.BlockState;
import java.util.List;
/**
* A base class for version-specific implementations of the BukkitImplAdapter
*
* @param <TAG> the version-specific NBT tag type
* @param <SERVER_LEVEL> the version-specific ServerLevel type
*/
public abstract class FaweAdapter<TAG, SERVER_LEVEL> extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<TAG> {
@Override
public boolean generateTree(
final TreeGenerator.TreeType treeType,
final EditSession editSession,
BlockVector3 blockVector3,
final World world
) {
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) {
// bukkit skips the feature gen which does this offset normally, so we have to add it back
blockVector3 = blockVector3.add(BlockVector3.UNIT_Y);
}
BlockVector3 target = blockVector3;
SERVER_LEVEL serverLevel = getServerLevel(world);
List<BlockState> placed = TaskManager.taskManager().sync(() -> {
preCaptureStates(serverLevel);
try {
if (!world.generateTree(BukkitAdapter.adapt(world, target), bukkitType)) {
return null;
}
return getCapturedBlockStatesCopy(serverLevel);
} finally {
postCaptureBlockStates(serverLevel);
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (BlockState blockState : placed) {
if (blockState == null || blockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(blockState.getX(), blockState.getY(), blockState.getZ(),
BukkitAdapter.adapt(blockState.getBlockData())
);
}
return true;
}
protected abstract void preCaptureStates(SERVER_LEVEL serverLevel);
protected abstract List<BlockState> getCapturedBlockStatesCopy(SERVER_LEVEL serverLevel);
protected abstract void postCaptureBlockStates(SERVER_LEVEL serverLevel);
protected abstract SERVER_LEVEL getServerLevel(World world);
}

Datei anzeigen

@ -163,13 +163,22 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
final Location location = player.getLocation(); final Location location = player.getLocation();
final Set<ProtectedRegion> regions = this.getRegions(localplayer, location, isWhitelist); final Set<ProtectedRegion> regions = this.getRegions(localplayer, location, isWhitelist);
if (!regions.isEmpty()) { if (!regions.isEmpty()) {
RegionManager manager = WorldGuard
.getInstance()
.getPlatform()
.getRegionContainer()
.get(BukkitAdapter.adapt(location.getWorld()));
if (manager == null) {
return null;
}
Set<Region> result = new HashSet<>(); Set<Region> result = new HashSet<>();
for (ProtectedRegion myRegion : regions) { for (ProtectedRegion myRegion : regions) {
if (myRegion.getId().equals("__global__")) { if (myRegion.getId().equals("__global__")) {
return new FaweMask(RegionWrapper.GLOBAL()) { return new FaweMask(RegionWrapper.GLOBAL()) {
@Override @Override
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) { public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
return isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion); return manager.hasRegion(myRegion.getId())
&& isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion);
} }
}; };
} else { } else {
@ -185,7 +194,7 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) { public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player)); final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player));
for (ProtectedRegion myRegion : regions) { for (ProtectedRegion myRegion : regions) {
if (!isAllowed(localplayer, myRegion)) { if (!manager.hasRegion(myRegion.getId()) || !isAllowed(localplayer, myRegion)) {
return false; return false;
} }
} }

Datei anzeigen

@ -16,6 +16,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.FlatRegionFunction; import com.sk89q.worldedit.function.FlatRegionFunction;
@ -160,6 +161,10 @@ public class FaweDelegateRegionManager {
); );
editSession.setBlocks(onTop, air); editSession.setBlocks(onTop, air);
} }
FlatRegionFunction replace = new BiomeReplace(editSession, biome);
FlatRegionVisitor visitor = new FlatRegionVisitor((CuboidRegion) floorRegion, replace, editSession);
Operations.completeLegacy(visitor);
} }
if (hybridPlotWorld.PLOT_SCHEMATIC) { if (hybridPlotWorld.PLOT_SCHEMATIC) {
@ -213,7 +218,6 @@ public class FaweDelegateRegionManager {
) { ) {
TaskManager.taskManager().async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
//todo because of the following code this should probably be in the Bukkit module
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName())); World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
World pos3World = BukkitAdapter.adapt(getWorld(swapPos.getWorldName())); World pos3World = BukkitAdapter.adapt(getWorld(swapPos.getWorldName()));
EditSession sessionA = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World) EditSession sessionA = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
@ -232,14 +236,16 @@ public class FaweDelegateRegionManager {
CuboidRegion regionB = new CuboidRegion( CuboidRegion regionB = new CuboidRegion(
pos3World, pos3World,
swapPos.getBlockVector3(), swapPos.getBlockVector3(),
swapPos.getBlockVector3().add(pos2.getBlockVector3()).subtract(pos1.getBlockVector3()) swapPos.getBlockVector3().add(pos2.getBlockVector3().subtract(pos1.getBlockVector3())).withY(pos2.getY())
); );
Clipboard clipA = Clipboard.create(regionA, UUID.randomUUID()); Clipboard clipA = new BlockArrayClipboard(regionA, UUID.randomUUID());
Clipboard clipB = Clipboard.create(regionB, UUID.randomUUID()); Clipboard clipB = new BlockArrayClipboard(regionB, UUID.randomUUID());
ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint()); ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint());
ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint()); ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint());
copyA.setCopyingBiomes(true); copyA.setCopyingBiomes(true);
copyB.setCopyingBiomes(true); copyB.setCopyingBiomes(true);
copyA.setCopyingEntities(true);
copyB.setCopyingEntities(true);
try { try {
Operations.completeLegacy(copyA); Operations.completeLegacy(copyA);
Operations.completeLegacy(copyB); Operations.completeLegacy(copyB);
@ -253,17 +259,16 @@ public class FaweDelegateRegionManager {
sessionA.close(); sessionA.close();
sessionB.close(); sessionB.close();
} }
FaweAPI.fixLighting(pos1World, new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), null, FaweAPI.fixLighting(
pos1World,
regionA,
null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
FaweAPI.fixLighting(pos1World, new CuboidRegion( FaweAPI.fixLighting(
swapPos.getBlockVector3(), pos1World,
BlockVector3.at( regionB,
swapPos.getX() + pos2.getX() - pos1.getX(), null,
0,
swapPos.getZ() + pos2.getZ() - pos1.getZ()
)
), null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
if (whenDone != null) { if (whenDone != null) {

Datei anzeigen

@ -13,7 +13,6 @@ import java.util.regex.Pattern;
public class MinecraftVersion implements Comparable<MinecraftVersion> { public class MinecraftVersion implements Comparable<MinecraftVersion> {
public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16); public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16);
public static final MinecraftVersion ONE_DOT_SIXTEEN_EOL = new MinecraftVersion(1, 16, 5);
public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17); public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17);
public static final MinecraftVersion CAVES_18 = new MinecraftVersion(1, 18); public static final MinecraftVersion CAVES_18 = new MinecraftVersion(1, 18);
private static MinecraftVersion current = null; private static MinecraftVersion current = null;

Datei anzeigen

@ -307,9 +307,6 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser
if (!tickFluid) { if (!tickFluid) {
return null; return null;
} }
if (Settings.settings().QUEUE.NO_TICK_FASTMODE && fastMode) {
return null;
}
return this.plugin.getBukkitImplAdapter().getTickingPostProcessor(); return this.plugin.getBukkitImplAdapter().getTickingPostProcessor();
} }

Datei anzeigen

@ -327,12 +327,12 @@ public class BukkitWorld extends AbstractWorld {
treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_MUSHROOM, TreeType.BROWN_MUSHROOM); treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_MUSHROOM, TreeType.BROWN_MUSHROOM);
for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) { for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) {
if (treeTypeMapping.get(type) == null) { if (treeTypeMapping.get(type) == null) {
LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type);
//FAWE start //FAWE start
LOGGER.info("No TreeType mapping for TreeGenerator.TreeType." + type);
LOGGER.info("The above message is displayed because your FAWE version is newer than {}" + LOGGER.info("The above message is displayed because your FAWE version is newer than {}" +
" and contains features of future minecraft versions which do not exist in {} hence the tree type" + " and contains features of future minecraft versions which do not exist in {} hence the tree type" +
"{} is not available. This is not an error. This version will work on your version of Minecraft." + " {} is not available. This is not an error. This version of FAWE will work on your version of " +
"This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type); " Minecraft. This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type);
//FAWE end //FAWE end
} }
} }

Datei anzeigen

@ -21,7 +21,7 @@ permissions:
default: op default: op
children: children:
fawe.bypass.regions: true fawe.bypass.regions: true
fawe.limit.*: true fawe.limit.unlimited: true
fawe.tips: fawe.tips:
default: op default: op
fawe.admin: fawe.admin:

Datei anzeigen

@ -245,6 +245,11 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
@Override
public @Nullable Location getRespawnLocation() {
return null;
}
@Override @Override
public void incrementStatistic(@Nonnull Statistic statistic) throws IllegalArgumentException { public void incrementStatistic(@Nonnull Statistic statistic) throws IllegalArgumentException {
@ -365,4 +370,9 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible {
return null; return null;
} }
@Override
public @Nullable Location getLocation() {
return null;
}
} }

Datei anzeigen

@ -612,12 +612,38 @@ public enum FaweCache implements Trimable {
/* /*
Thread stuff Thread stuff
*/ */
/**
* Create a new blocking executor with default name and FaweCache logger
*
* @return new blocking executor
*/
public ThreadPoolExecutor newBlockingExecutor() { public ThreadPoolExecutor newBlockingExecutor() {
return newBlockingExecutor("FAWE Blocking Executor - %d");
}
/**
* Create a new blocking executor with specified name and FaweCache logger
*
* @return new blocking executor
* @since 2.9.0
*/
public ThreadPoolExecutor newBlockingExecutor(String name) {
return newBlockingExecutor(name, LOGGER);
}
/**
* Create a new blocking executor with specified name and logger
*
* @return new blocking executor
* @since 2.9.0
*/
public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) {
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS; int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true); ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true);
return new ThreadPoolExecutor(nThreads, nThreads, return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, queue, 0L, TimeUnit.MILLISECONDS, queue,
new ThreadFactoryBuilder().setNameFormat("FAWE Blocking Executor - %d").build(), new ThreadFactoryBuilder().setNameFormat(name).build(),
new ThreadPoolExecutor.CallerRunsPolicy() new ThreadPoolExecutor.CallerRunsPolicy()
) { ) {
@ -652,10 +678,10 @@ public enum FaweCache implements Trimable {
int hash = throwable.getMessage() != null ? throwable.getMessage().hashCode() : 0; int hash = throwable.getMessage() != null ? throwable.getMessage().hashCode() : 0;
if (hash != lastException) { if (hash != lastException) {
lastException = hash; lastException = hash;
LOGGER.catching(throwable); logger.catching(throwable);
count = 0; count = 0;
} else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) { } else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) {
LOGGER.warn(throwable.getMessage()); logger.warn(throwable.getMessage());
count++; count++;
} }
} }
@ -665,10 +691,10 @@ public enum FaweCache implements Trimable {
private void handleFaweException(FaweException e) { private void handleFaweException(FaweException e) {
FaweException.Type type = e.getType(); FaweException.Type type = e.getType();
if (e.getType() == FaweException.Type.OTHER) { if (e.getType() == FaweException.Type.OTHER) {
LOGGER.catching(e); logger.catching(e);
} else if (!faweExceptionReasonsUsed[type.ordinal()]) { } else if (!faweExceptionReasonsUsed[type.ordinal()]) {
faweExceptionReasonsUsed[type.ordinal()] = true; faweExceptionReasonsUsed[type.ordinal()] = true;
LOGGER.warn("FaweException: " + e.getMessage()); logger.warn("FaweException: " + e.getMessage());
} }
} }
}; };

Datei anzeigen

@ -67,11 +67,11 @@ public class ErodeBrush implements Brush {
final int by = target.getBlockY(); final int by = target.getBlockY();
final int bz = target.getBlockZ(); final int bz = target.getBlockZ();
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { for (int x = -brushSize, relx = 0; x <= brushSize && relx < buffer1.getWidth(); x++, relx++) {
int x0 = x + bx; int x0 = x + bx;
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { for (int y = -brushSize, rely = 0; y <= brushSize && rely < buffer1.getHeight(); y++, rely++) {
int y0 = y + by; int y0 = y + by;
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { for (int z = -brushSize, relz = 0; z <= brushSize && relz < buffer1.getLength(); z++, relz++) {
int z0 = z + bz; int z0 = z + bz;
BlockState state = es.getBlock(x0, y0, z0); BlockState state = es.getBlock(x0, y0, z0);
buffer1.setBlock(relx, rely, relz, state); buffer1.setBlock(relx, rely, relz, state);
@ -115,11 +115,11 @@ public class ErodeBrush implements Brush {
Clipboard current, Clipboard target Clipboard current, Clipboard target
) { ) {
int[] frequency = null; int[] frequency = null;
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) {
int x2 = x * x; int x2 = x * x;
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) {
int x2y2 = x2 + z * z; int x2y2 = x2 + z * z;
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) {
int cube = x2y2 + y * y; int cube = x2y2 + y * y;
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz)); target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
if (cube >= brushSizeSquared) { if (cube >= brushSizeSquared) {
@ -166,11 +166,11 @@ public class ErodeBrush implements Brush {
Clipboard current, Clipboard target Clipboard current, Clipboard target
) { ) {
int[] frequency = null; int[] frequency = null;
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) {
int x2 = x * x; int x2 = x * x;
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) {
int x2y2 = x2 + z * z; int x2y2 = x2 + z * z;
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) {
int cube = x2y2 + y * y; int cube = x2y2 + y * y;
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz)); target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
if (cube >= brushSizeSquared) { if (cube >= brushSizeSquared) {

Datei anzeigen

@ -53,7 +53,7 @@ public class HeightBrush implements Brush {
try { try {
heightMap = ScalableHeightMap.fromPNG(stream); heightMap = ScalableHeightMap.fromPNG(stream);
} catch (IOException e) { } catch (IOException e) {
throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid")); throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid", e.getMessage()));
} }
} else if (clipboard != null) { } else if (clipboard != null) {
heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY); heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY);

Datei anzeigen

@ -102,7 +102,7 @@ public class Settings extends Config {
public FaweLimit getLimit(Actor actor) { public FaweLimit getLimit(Actor actor) {
FaweLimit limit; FaweLimit limit;
if (actor.hasPermission("fawe.bypass") || actor.hasPermission("fawe.limit.unlimited")) { if (actor.hasPermission("fawe.limit.unlimited")) {
return FaweLimit.MAX.copy(); return FaweLimit.MAX.copy();
} }
limit = new FaweLimit(); limit = new FaweLimit();
@ -511,7 +511,7 @@ public class Settings extends Config {
" - A larger value will use slightly less CPU time", " - A larger value will use slightly less CPU time",
" - A smaller value will reduce memory usage", " - A smaller value will reduce memory usage",
" - A value too small may break some operations (deform?)", " - A value too small may break some operations (deform?)",
" - Values smaller than the configurated parallel-threads are not accepted", " - Values smaller than the configured parallel-threads are not accepted",
" - It is recommended this option be at least 4x greater than parallel-threads" " - It is recommended this option be at least 4x greater than parallel-threads"
}) })
@ -544,12 +544,6 @@ public class Settings extends Config {
}) })
public boolean POOL = true; public boolean POOL = true;
@Comment({
"When using fastmode do not bother to tick existing/placed blocks/fluids",
"Only works in versions up to 1.17.1"
})
public boolean NO_TICK_FASTMODE = true;
public static class PROGRESS { public static class PROGRESS {
@Comment({"Display constant titles about the progress of a user's edit", @Comment({"Display constant titles about the progress of a user's edit",
@ -721,6 +715,13 @@ public class Settings extends Config {
" - Requires clipboard.use-disk to be enabled" " - Requires clipboard.use-disk to be enabled"
}) })
public boolean SAVE_CLIPBOARD_NBT_TO_DISK = true; public boolean SAVE_CLIPBOARD_NBT_TO_DISK = true;
@Comment({
"Apply a file lock on the clipboard file (only relevant if clipboad.on-disk is enabled)",
" - Prevents other processes using the file whilst in use by FAWE",
" - This extends to other servers, useful if you have multiple servers using a unified clipboard folder",
" - May run into issues where a file lock is not correctly lifted"
})
public boolean LOCK_CLIPBOARD_FILE = false;
} }

Datei anzeigen

@ -159,15 +159,25 @@ public class RollbackDatabase extends AsyncNotifyQueue {
Future<Integer> future = call(() -> { Future<Integer> future = call(() -> {
try { try {
int count = 0; int count = 0;
String stmtStr = ascending ? uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND" + String stmtStr = """
" `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` , `id`" : SELECT * FROM `%sedits`
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND" + WHERE `time` > ?
" `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` ASC, `id` ASC" : AND `x2` >= ?
uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? " + AND `x1` <= ?
"AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` DESC, `id` DESC" : AND `z2` >= ?
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND" + AND `z1` <= ?
" `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC"; AND `y2` >= ?
try (PreparedStatement stmt = connection.prepareStatement(stmtStr)) { AND `y1` <= ?
""";
if (uuid != null) {
stmtStr += "\n AND `player`= ?";
}
if (ascending) {
stmtStr += "\n ORDER BY `time` ASC, `id` ASC";
} else {
stmtStr += "\n ORDER BY `time` DESC, `id` DESC";
}
try (PreparedStatement stmt = connection.prepareStatement(stmtStr.formatted(this.prefix))) {
stmt.setInt(1, (int) (minTime / 1000)); stmt.setInt(1, (int) (minTime / 1000));
stmt.setInt(2, pos1.getBlockX()); stmt.setInt(2, pos1.getBlockX());
stmt.setInt(3, pos2.getBlockX()); stmt.setInt(3, pos2.getBlockX());
@ -193,20 +203,20 @@ 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`<=?")) {
stmt.setInt(1, (int) (minTime / 1000));
stmt.setInt(2, pos1.getBlockX());
stmt.setInt(3, pos2.getBlockX());
stmt.setInt(4, pos1.getBlockZ());
stmt.setInt(5, pos2.getBlockZ());
// Keep 128 offset for backwards-compatibility
stmt.setInt(6, pos1.getBlockY() - 128);
stmt.setInt(7, pos2.getBlockY() - 128);
byte[] uuidBytes = ByteBuffer byte[] uuidBytes = ByteBuffer
.allocate(16) .allocate(16)
.putLong(uuid.getMostSignificantBits()) .putLong(uuid.getMostSignificantBits())
.putLong(uuid.getLeastSignificantBits()) .putLong(uuid.getLeastSignificantBits())
.array(); .array();
stmt.setBytes(8, uuidBytes); stmt.setBytes(1, uuidBytes);
stmt.setInt(2, (int) (minTime / 1000));
stmt.setInt(3, pos1.getBlockX());
stmt.setInt(4, pos2.getBlockX());
stmt.setInt(5, pos1.getBlockZ());
stmt.setInt(6, pos2.getBlockZ());
// Keep 128 offset for backwards-compatibility
stmt.setInt(7, pos1.getBlockY() - 128);
stmt.setInt(8, pos2.getBlockY() - 128);
} }
} }
return count; return count;

Datei anzeigen

@ -53,7 +53,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
} }
@Nonnull @Nonnull
private Function<String, Stream<? extends String>> extractArguments(String input) { private Function<String, Stream<? extends String>> extractArguments(String input, ParserContext context) {
return prefix -> { return prefix -> {
if (input.length() > prefix.length() && input.startsWith(prefix + "[")) { if (input.length() > prefix.length() && input.startsWith(prefix + "[")) {
// input already contains argument(s) -> extract them // input already contains argument(s) -> extract them
@ -65,7 +65,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
} }
String previous = prefix + builder; String previous = prefix + builder;
// read the suggestions for the last argument // read the suggestions for the last argument
return getSuggestions(strings[strings.length - 1], strings.length - 1) return getSuggestions(strings[strings.length - 1], strings.length - 1, context)
.map(suggestion -> previous + "[" + suggestion); .map(suggestion -> previous + "[" + suggestion);
} else { } else {
return Stream.of(prefix); return Stream.of(prefix);
@ -95,7 +95,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
public Stream<String> getSuggestions(String input) { public Stream<String> getSuggestions(String input) {
return Arrays.stream(this.prefixes) return Arrays.stream(this.prefixes)
.filter(validPrefix(input)) .filter(validPrefix(input))
.flatMap(extractArguments(input)); .flatMap(extractArguments(input, new ParserContext()));
} }
@Override @Override
@ -122,8 +122,25 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
* @param argumentInput the already provided input for the argument at the given index. * @param argumentInput the already provided input for the argument at the given index.
* @param index the index of the argument to get suggestions for. * @param index the index of the argument to get suggestions for.
* @return a stream of suggestions matching the given input for the argument at the given index. * @return a stream of suggestions matching the given input for the argument at the given index.
*
* @deprecated Use the version that takes a {@link ParserContext}, {@link #getSuggestions(String, int, ParserContext)}
*/ */
protected abstract Stream<String> getSuggestions(String argumentInput, int index); @Deprecated
protected Stream<String> getSuggestions(String argumentInput, int index) {
return Stream.empty();
}
/**
* Returns a stream of suggestions for the argument at the given index.
*
* @param argumentInput the already provided input for the argument at the given index.
* @param index the index of the argument to get suggestions for.
* @param context the context which may optionally be provided by a parser.
* @return a stream of suggestions matching the given input for the argument at the given index.
*/
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return getSuggestions(argumentInput, index);
}
/** /**
* Parses the already split arguments. * Parses the already split arguments.

Datei anzeigen

@ -97,11 +97,11 @@ public class RichMaskParser extends FaweParser<Mask> {
)), )),
() -> { () -> {
if (full.length() == 1) { if (full.length() == 1) {
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("")); return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
} }
return new ArrayList<>(worldEdit return new ArrayList<>(worldEdit
.getMaskFactory() .getMaskFactory()
.getSuggestions(command.toLowerCase(Locale.ROOT))); .getSuggestions(command.toLowerCase(Locale.ROOT), context));
} }
); );
} }
@ -164,11 +164,11 @@ public class RichMaskParser extends FaweParser<Mask> {
)), )),
() -> { () -> {
if (full.length() == 1) { if (full.length() == 1) {
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("")); return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
} }
return new ArrayList<>(worldEdit return new ArrayList<>(worldEdit
.getMaskFactory() .getMaskFactory()
.getSuggestions(command.toLowerCase(Locale.ROOT))); .getSuggestions(command.toLowerCase(Locale.ROOT), context));
} }
); );
} }

Datei anzeigen

@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser; import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.function.pattern.Linear2DBlockPattern; import com.fastasyncworldedit.core.math.random.Linear2DRandom;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.command.util.SuggestionHelper;
@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
public class Linear2DPatternParser extends RichParser<Pattern> { public class Linear2DPatternParser extends RichParser<Pattern> {
@ -59,9 +58,8 @@ public class Linear2DPatternParser extends RichParser<Pattern> {
zScale = Integer.parseInt(arguments[2]); zScale = Integer.parseInt(arguments[2]);
Preconditions.checkArgument(zScale != 0); Preconditions.checkArgument(zScale != 0);
} }
if (inner instanceof RandomPattern) { if (inner instanceof RandomPattern rp) {
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns(); return new RandomPattern(new Linear2DRandom(xScale, zScale), rp);
return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale);
} }
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with " + getPrefix())); + " cannot be used with " + getPrefix()));

Datei anzeigen

@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser; import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.function.pattern.Linear3DBlockPattern; import com.fastasyncworldedit.core.math.random.Linear3DRandom;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.command.util.SuggestionHelper;
@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
public class Linear3DPatternParser extends RichParser<Pattern> { public class Linear3DPatternParser extends RichParser<Pattern> {
@ -64,9 +63,8 @@ public class Linear3DPatternParser extends RichParser<Pattern> {
zScale = Integer.parseInt(arguments[3]); zScale = Integer.parseInt(arguments[3]);
Preconditions.checkArgument(zScale != 0); Preconditions.checkArgument(zScale != 0);
} }
if (inner instanceof RandomPattern) { if (inner instanceof RandomPattern rp) {
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns(); return new RandomPattern(new Linear3DRandom(xScale, yScale, zScale), rp);
return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale, zScale);
} }
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with " + getPrefix())); + " cannot be used with " + getPrefix()));

Datei anzeigen

@ -9,7 +9,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.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
public class BlockTranslateExtent extends AbstractDelegateExtent { public final class BlockTranslateExtent extends AbstractDelegateExtent {
private final int dx; private final int dx;
private final int dy; private final int dy;

Datei anzeigen

@ -29,7 +29,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor { public final class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor {
private static final BlockState RESERVED = BlockTypes.__RESERVED__.getDefaultState(); private static final BlockState RESERVED = BlockTypes.__RESERVED__.getDefaultState();
private final Set<PropertyRemap<?>> remaps; private final Set<PropertyRemap<?>> remaps;

Datei anzeigen

@ -4,7 +4,7 @@ import com.sk89q.worldedit.extent.Extent;
import java.util.Arrays; import java.util.Arrays;
public class ExtentHeightCacher extends PassthroughExtent { public final class ExtentHeightCacher extends PassthroughExtent {
private transient int cacheBotX = Integer.MIN_VALUE; private transient int cacheBotX = Integer.MIN_VALUE;
private transient int cacheBotZ = Integer.MIN_VALUE; private transient int cacheBotZ = Integer.MIN_VALUE;

Datei anzeigen

@ -6,14 +6,13 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.regions.RegionWrapper; import com.fastasyncworldedit.core.regions.RegionWrapper;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
public class HeightBoundExtent extends FaweRegionExtent { public final class HeightBoundExtent extends FaweRegionExtent {
private final int min; private final int min;
private final int max; private final int max;
@ -50,7 +49,8 @@ public class HeightBoundExtent extends FaweRegionExtent {
@Override @Override
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
if (trimY(set, min, max, true) | trimNBT(set, this::contains)) { BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
if (trimY(set, min, max, true) | trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)))) {
return set; return set;
} }
return null; return null;

Datei anzeigen

@ -25,7 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Stores changes to a {@link ChangeSet}. * Stores changes to a {@link ChangeSet}.
*/ */
public class HistoryExtent extends AbstractDelegateExtent { public final class HistoryExtent extends AbstractDelegateExtent {
private final MutableBlockVector3 mutable = new MutableBlockVector3(); private final MutableBlockVector3 mutable = new MutableBlockVector3();
private AbstractChangeSet changeSet; private AbstractChangeSet changeSet;

Datei anzeigen

@ -37,7 +37,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
public class LimitExtent extends AbstractDelegateExtent { public final class LimitExtent extends AbstractDelegateExtent {
private final FaweLimit limit; private final FaweLimit limit;
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];

Datei anzeigen

@ -8,7 +8,7 @@ import com.fastasyncworldedit.core.util.WEManager;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
public class MemoryCheckingExtent extends PassthroughExtent { public final class MemoryCheckingExtent extends PassthroughExtent {
private final Actor actor; private final Actor actor;

Datei anzeigen

@ -15,7 +15,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public class MultiRegionExtent extends FaweRegionExtent { public final class MultiRegionExtent extends FaweRegionExtent {
@Nullable @Nullable
private final RegionIntersection intersection; private final RegionIntersection intersection;

Datei anzeigen

@ -40,7 +40,7 @@ import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
//todo This should be removed in favor of com.sk89q.worldedit.extent.NullExtent //todo This should be removed in favor of com.sk89q.worldedit.extent.NullExtent
public class NullExtent extends FaweRegionExtent implements IBatchProcessor { public final class NullExtent extends FaweRegionExtent implements IBatchProcessor {
private final FaweException reason; private final FaweException reason;

Datei anzeigen

@ -26,7 +26,7 @@ import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class PassthroughExtent extends AbstractDelegateExtent { public abstract class PassthroughExtent extends AbstractDelegateExtent {
/** /**
* Create a new instance. * Create a new instance.

Datei anzeigen

@ -11,7 +11,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.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
public class PositionTransformExtent extends ResettableExtent { public final class PositionTransformExtent extends ResettableExtent {
private transient MutableBlockVector3 mutable = new MutableBlockVector3(); private transient MutableBlockVector3 mutable = new MutableBlockVector3();
private transient BlockVector3 min; private transient BlockVector3 min;

Datei anzeigen

@ -18,7 +18,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.UUID; import java.util.UUID;
public class ProcessedWEExtent extends AbstractDelegateExtent { public final class ProcessedWEExtent extends AbstractDelegateExtent {
private final FaweLimit limit; private final FaweLimit limit;
private final Extent extent; private final Extent extent;

Datei anzeigen

@ -14,7 +14,7 @@ import java.lang.reflect.Field;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public class ResettableExtent extends AbstractDelegateExtent implements Serializable { public abstract class ResettableExtent extends AbstractDelegateExtent implements Serializable {
public ResettableExtent(Extent parent) { public ResettableExtent(Extent parent) {
super(parent); super(parent);

Datei anzeigen

@ -11,7 +11,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public class SingleRegionExtent extends FaweRegionExtent { public final class SingleRegionExtent extends FaweRegionExtent {
private final Region region; private final Region region;

Datei anzeigen

@ -6,7 +6,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
public class SlowExtent extends AbstractDelegateExtent { public final class SlowExtent extends AbstractDelegateExtent {
private final long THRESHOLD = 50 * 1000000; // 1 tick private final long THRESHOLD = 50 * 1000000; // 1 tick
private final long nanos; private final long nanos;

Datei anzeigen

@ -9,7 +9,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public class SourceMaskExtent extends TemporalExtent { public final class SourceMaskExtent extends TemporalExtent {
private Mask mask; private Mask mask;
private final MutableBlockVector3 mutable = new MutableBlockVector3(); private final MutableBlockVector3 mutable = new MutableBlockVector3();

Datei anzeigen

@ -34,7 +34,7 @@ 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;
public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor { public final class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor {
private final Set<String> strip; private final Set<String> strip;

Datei anzeigen

@ -7,7 +7,7 @@ import java.util.function.Supplier;
/** /**
* An extent that delegates actions to another extent that may change at any time. * An extent that delegates actions to another extent that may change at any time.
*/ */
public class SupplyingExtent extends PassthroughExtent { public final class SupplyingExtent extends PassthroughExtent {
private final Supplier<Extent> extentSupplier; private final Supplier<Extent> extentSupplier;

Datei anzeigen

@ -8,7 +8,7 @@ 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.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
public class TemporalExtent extends PassthroughExtent { public abstract class TemporalExtent extends PassthroughExtent {
private int x; private int x;
private int y; private int y;

Datei anzeigen

@ -1,116 +0,0 @@
package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.math.MutableVector3;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
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;
public class TransformExtent extends BlockTransformExtent {
private final MutableVector3 mutable1 = new MutableVector3();
private final MutableBlockVector3 mutable2 = new MutableBlockVector3();
private BlockVector3 min;
public TransformExtent(Extent parent) {
super(parent);
}
@Override
public ResettableExtent setExtent(Extent extent) {
min = null;
return super.setExtent(extent);
}
@Override
public BlockVector3 getMinimumPoint() {
BlockVector3 pos1 = getPos(super.getMinimumPoint());
BlockVector3 pos2 = getPos(super.getMaximumPoint());
return pos1.getMinimum(pos2);
}
@Override
public BlockVector3 getMaximumPoint() {
BlockVector3 pos1 = getPos(super.getMinimumPoint());
BlockVector3 pos2 = getPos(super.getMaximumPoint());
return pos1.getMaximum(pos2);
}
@Override
public void setOrigin(BlockVector3 pos) {
this.min = pos;
}
public BlockVector3 getPos(BlockVector3 pos) {
if (min == null) {
min = pos;
}
mutable1.mutX(pos.getX() - min.getX());
mutable1.mutY(pos.getY() - min.getY());
mutable1.mutZ(pos.getZ() - min.getZ());
Vector3 tmp = getTransform().apply(mutable1);
mutable2.mutX(tmp.getX() + min.getX());
mutable2.mutY(tmp.getY() + min.getY());
mutable2.mutZ(tmp.getZ() + min.getZ());
return mutable2;
}
public BlockVector3 getPos(int x, int y, int z) {
if (min == null) {
min = BlockVector3.at(x, y, z);
}
mutable1.mutX(x - min.getX());
mutable1.mutY(y - min.getY());
mutable1.mutZ(z - min.getZ());
Vector3 tmp = getTransform().apply(mutable1);
mutable2.mutX(tmp.getX() + min.getX());
mutable2.mutY(tmp.getY() + min.getY());
mutable2.mutZ(tmp.getZ() + min.getZ());
return tmp.toBlockPoint();
}
@Override
public BlockState getBlock(int x, int y, int z) {
BlockVector3 p = getPos(x, y, z);
return transform(super.getBlock(p.getX(), p.getY(), p.getZ()));
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return transform(super.getFullBlock(getPos(position)));
}
@Override
public BiomeType getBiomeType(int x, int y, int z) {
BlockVector3 p = getPos(x, y, z);
return super.getBiomeType(p.getX(), y, p.getZ());
}
@Override
@SuppressWarnings("unchecked")
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException {
return super.setBlock(getPos(x, y, z), transformInverse(block));
}
@Override
@SuppressWarnings("unchecked")
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block)
throws WorldEditException {
return super.setBlock(getPos(location), transformInverse(block));
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
BlockVector3 p = getPos(x, y, z);
return super.setBiome(p.getX(), p.getY(), p.getZ(), biome);
}
}

Datei anzeigen

@ -305,22 +305,24 @@ public class DiskOptimizedClipboard extends LinearClipboard {
private void init() throws IOException { private void init() throws IOException {
if (this.fileChannel == null) { if (this.fileChannel == null) {
this.fileChannel = braf.getChannel(); this.fileChannel = braf.getChannel();
try { if (Settings.settings().CLIPBOARD.LOCK_CLIPBOARD_FILE) {
FileLock lock = this.fileChannel.lock(); try {
LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock)); FileLock lock = this.fileChannel.lock();
} catch (OverlappingFileLockException e) { LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock));
LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName()); } catch (OverlappingFileLockException e) {
if (existing != null) { LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName());
long ms = System.currentTimeMillis() - existing.lockHeldSince; if (existing != null) {
LOGGER.error( long ms = System.currentTimeMillis() - existing.lockHeldSince;
"Cannot lock clipboard file {} acquired by thread {}, {}ms ago", LOGGER.error(
file.getName(), "Cannot lock clipboard file {} acquired by thread {}, {}ms ago",
existing.thread, file.getName(),
ms existing.thread,
); ms
);
}
// Rethrow to prevent clipboard access
throw e;
} }
// Rethrow to prevent clipboard access
throw e;
} }
this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length()); this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length());
} }

Datei anzeigen

@ -19,12 +19,9 @@ import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -80,28 +77,18 @@ public class MultiBatchProcessor implements IBatchProcessor {
@Override @Override
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
Map<Integer, Set<IBatchProcessor>> ordered = new HashMap<>(); Map<Integer, List<IBatchProcessor>> ordered = new HashMap<>();
IChunkSet chunkSet = set; IChunkSet chunkSet = set;
for (IBatchProcessor processor : processors) { for (IBatchProcessor processor : processors) {
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) { if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
ordered.merge( ordered.computeIfAbsent(processor.getScope().intValue(), k -> new ArrayList<>())
processor.getScope().intValue(), .add(processor);
new HashSet<>(Collections.singleton(processor)),
(existing, theNew) -> {
existing.add(processor);
return existing;
}
);
continue; continue;
} }
chunkSet = processSet(processor, chunk, get, chunkSet); chunkSet = processSet(processor, chunk, get, chunkSet);
} }
if (ordered.size() > 0) { if (!ordered.isEmpty()) {
for (int i = 1; i <= 4; i++) { for (List<IBatchProcessor> processors : ordered.values()) {
Set<IBatchProcessor> processors = ordered.get(i);
if (processors == null) {
continue;
}
for (IBatchProcessor processor : processors) { for (IBatchProcessor processor : processors) {
chunkSet = processSet(processor, chunk, get, chunkSet); chunkSet = processSet(processor, chunk, get, chunkSet);
if (chunkSet == null) { if (chunkSet == null) {

Datei anzeigen

@ -7,10 +7,10 @@ import com.fastasyncworldedit.core.util.collection.RandomCollection;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import java.util.HashMap; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -20,10 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class RandomTransform extends SelectTransform { public class RandomTransform extends SelectTransform {
private final SimpleRandom random; private final SimpleRandom random;
private final Map<ResettableExtent, Double> weights = new HashMap<>(); private final List<RandomCollection.Weighted<ResettableExtent>> weights;
private transient RandomCollection<ResettableExtent> collection; private transient RandomCollection<ResettableExtent> collection;
private transient LinkedHashSet<ResettableExtent> extents = new LinkedHashSet<>();
public RandomTransform() { public RandomTransform() {
this(new TrueRandom()); this(new TrueRandom());
@ -36,27 +35,27 @@ public class RandomTransform extends SelectTransform {
*/ */
public RandomTransform(SimpleRandom random) { public RandomTransform(SimpleRandom random) {
this.random = random; this.random = random;
this.weights = new ArrayList<>();
} }
@Override @Override
public AbstractDelegateExtent getExtent(int x, int y, int z) { public AbstractDelegateExtent getExtent(int x, int y, int z) {
return collection.next(x, y, z); return collection.next(this.random, x, y, z);
} }
@Override @Override
public AbstractDelegateExtent getExtent(int x, int z) { public AbstractDelegateExtent getExtent(int x, int z) {
return collection.next(x, 0, z); return collection.next(this.random, x, 0, z);
} }
@Override @Override
public ResettableExtent setExtent(Extent extent) { public ResettableExtent setExtent(Extent extent) {
if (collection == null) { if (collection == null) {
collection = RandomCollection.of(weights, random); collection = RandomCollection.of(weights);
extents = new LinkedHashSet<>(weights.keySet());
} }
super.setExtent(extent); super.setExtent(extent);
for (ResettableExtent current : extents) { for (RandomCollection.Weighted<ResettableExtent> current : this.weights) {
current.setExtent(extent); current.value().setExtent(extent);
} }
return this; return this;
} }
@ -72,13 +71,12 @@ public class RandomTransform extends SelectTransform {
*/ */
public void add(ResettableExtent extent, double chance) { public void add(ResettableExtent extent, double chance) {
checkNotNull(extent); checkNotNull(extent);
weights.put(extent, chance); weights.add(new RandomCollection.Weighted<>(extent, chance));
collection = RandomCollection.of(weights, random); collection = RandomCollection.of(weights);
this.extents.add(extent);
} }
public Set<ResettableExtent> getExtents() { public Set<ResettableExtent> getExtents() {
return extents; return this.weights.stream().map(RandomCollection.Weighted::value).collect(Collectors.toSet());
} }
public RandomCollection<ResettableExtent> getCollection() { public RandomCollection<ResettableExtent> getCollection() {

Datei anzeigen

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.EvaluationException; import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
@ -57,4 +58,9 @@ public class ExpressionPattern extends AbstractPattern {
} }
} }
@Override
public Pattern fork() {
return new ExpressionPattern(this.expression.clone());
}
} }

Datei anzeigen

@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.Arrays;
import static java.lang.Math.floorDiv; import static java.lang.Math.floorDiv;
/**
* @deprecated replaced by {@link com.sk89q.worldedit.function.pattern.RandomPattern}
* combined with {@link com.fastasyncworldedit.core.math.random.Linear2DRandom}.
*/
@Deprecated(forRemoval = true, since = "TODO")
public class Linear2DBlockPattern extends AbstractPattern { public class Linear2DBlockPattern extends AbstractPattern {
private final Pattern[] patternsArray; private final Pattern[] patternsArray;
@ -47,4 +54,10 @@ public class Linear2DBlockPattern extends AbstractPattern {
return patternsArray[index].apply(extent, get, set); return patternsArray[index].apply(extent, get, set);
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear2DBlockPattern(forked, this.xScale, this.zScale);
}
} }

Datei anzeigen

@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.Arrays;
import static java.lang.Math.floorDiv; import static java.lang.Math.floorDiv;
/**
* @deprecated replaced by {@link com.sk89q.worldedit.function.pattern.RandomPattern}
* combined with {@link com.fastasyncworldedit.core.math.random.Linear3DRandom}.
*/
@Deprecated(forRemoval = true, since = "TODO")
public class Linear3DBlockPattern extends AbstractPattern { public class Linear3DBlockPattern extends AbstractPattern {
private final Pattern[] patternsArray; private final Pattern[] patternsArray;
@ -51,4 +58,10 @@ public class Linear3DBlockPattern extends AbstractPattern {
return patternsArray[index].apply(extent, get, set); return patternsArray[index].apply(extent, get, set);
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear3DBlockPattern(forked, this.xScale, this.yScale, this.zScale);
}
} }

Datei anzeigen

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
@ -7,6 +8,8 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.Arrays;
public class LinearBlockPattern extends AbstractPattern implements ResettablePattern { public class LinearBlockPattern extends AbstractPattern implements ResettablePattern {
private final Pattern[] patternsArray; private final Pattern[] patternsArray;
@ -15,7 +18,7 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
/** /**
* Create a new {@link Pattern} instance * Create a new {@link Pattern} instance
* *
* @param patterns array of patterns to linearly choose from based on x/z coordinates * @param patterns array of patterns to linearly choose from
*/ */
public LinearBlockPattern(Pattern[] patterns) { public LinearBlockPattern(Pattern[] patterns) {
this.patternsArray = patterns; this.patternsArray = patterns;
@ -23,18 +26,14 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
if (index == patternsArray.length) { index = (index + 1) % patternsArray.length;
index = 0; return patternsArray[index].applyBlock(position);
}
return patternsArray[index++].applyBlock(position);
} }
@Override @Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
if (index == patternsArray.length) { index = (index + 1) % patternsArray.length;
index = 0; return patternsArray[index].apply(extent, get, set);
}
return patternsArray[index++].apply(extent, get, set);
} }
@Override @Override
@ -42,4 +41,10 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
index = 0; index = 0;
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new LinearBlockPattern(forked);
}
} }

Datei anzeigen

@ -43,4 +43,9 @@ public class MaskedPattern extends AbstractPattern {
return secondary.apply(extent, get, set); return secondary.apply(extent, get, set);
} }
@Override
public Pattern fork() {
return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork());
}
} }

Datei anzeigen

@ -36,4 +36,9 @@ public class NoXPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoXPattern(this.pattern.fork());
}
} }

Datei anzeigen

@ -36,4 +36,9 @@ public class NoYPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoYPattern(this.pattern.fork());
}
} }

Datei anzeigen

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
@ -36,4 +37,9 @@ public class NoZPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoZPattern(this.pattern.fork());
}
} }

Datei anzeigen

@ -60,4 +60,9 @@ public class OffsetPattern extends AbstractPattern {
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }
@Override
public Pattern fork() {
return new OffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}
} }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen