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:
Commit
b735405b54
@ -342,7 +342,7 @@ ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
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_text = false
|
||||
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_text_wrap = normal
|
||||
|
||||
[{*.ats, *.ts}]
|
||||
[{*.ats,*.ts}]
|
||||
ij_continuation_indent_size = 4
|
||||
ij_typescript_align_imports = 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_wrap_comments = false
|
||||
|
||||
[{*.bash, *.sh, *.zsh}]
|
||||
[{*.bash,*.sh,*.zsh}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
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_switch_cases_indented = false
|
||||
|
||||
[{*.cjs, *.js}]
|
||||
[{*.cjs,*.js}]
|
||||
ij_continuation_indent_size = 4
|
||||
ij_javascript_align_imports = 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_wrap_comments = false
|
||||
|
||||
[{*.ft, *.vm, *.vsl}]
|
||||
[{*.ft,*.vm,*.vsl}]
|
||||
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_multiline_array_initializer_expression = 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_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_multiline_binary_operation = 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_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
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
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_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_align_attributes = true
|
||||
ij_html_align_text = false
|
||||
@ -1004,7 +1004,7 @@ ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
ij_html_uniform_ident = false
|
||||
|
||||
[{*.yaml, *.yml}]
|
||||
[{*.yaml,*.yml}]
|
||||
indent_size = 2
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
||||
|
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -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.
|
||||
multiple: false
|
||||
options:
|
||||
- '1.20.2'
|
||||
- '1.20.4'
|
||||
- '1.20'
|
||||
- '1.19.4'
|
||||
- '1.18.2'
|
||||
- '1.17.1'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
43
.github/renovate.json
vendored
43
.github/renovate.json
vendored
@ -1,11 +1,11 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
"$schema" : "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends" : [
|
||||
"config:recommended",
|
||||
":semanticCommitsDisabled"
|
||||
],
|
||||
"automerge": true,
|
||||
"ignoreDeps": [
|
||||
"automerge" : true,
|
||||
"ignoreDeps" : [
|
||||
"guava",
|
||||
"com.google.guava:guava",
|
||||
"rhino-runtime",
|
||||
@ -29,7 +29,34 @@
|
||||
"org.spongepowered:spongeapi",
|
||||
"org.yaml:snakeyaml"
|
||||
],
|
||||
"labels": ["Renovate"],
|
||||
"rebaseWhen": "conflicted",
|
||||
"schedule": ["on the first day of the month"]
|
||||
"labels" : [
|
||||
"Renovate"
|
||||
],
|
||||
"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+)$"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
4
.github/workflows/build-pr.yml
vendored
4
.github/workflows/build-pr.yml
vendored
@ -11,9 +11,9 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -11,9 +11,9 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
|
8
.github/workflows/codeql.yml
vendored
8
.github/workflows/codeql.yml
vendored
@ -21,16 +21,16 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
java-version: 17
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
2
.github/workflows/label-merge-conflicts.yaml
vendored
2
.github/workflows/label-merge-conflicts.yaml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Label conflicting PRs
|
||||
uses: eps1lon/actions-label-merge-conflict@v2.1.0
|
||||
uses: eps1lon/actions-label-merge-conflict@v3.0.0
|
||||
with:
|
||||
dirtyLabel: "unresolved-merge-conflict"
|
||||
repoToken: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
2
.github/workflows/release-drafter.yml
vendored
2
.github/workflows/release-drafter.yml
vendored
@ -12,6 +12,6 @@ jobs:
|
||||
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
6
.github/workflows/upload-release-assets.yml
vendored
6
.github/workflows/upload-release-assets.yml
vendored
@ -9,9 +9,9 @@ jobs:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
@ -19,7 +19,7 @@ jobs:
|
||||
- name: Clean Build
|
||||
run: ./gradlew clean build --no-daemon
|
||||
- name: Upload Release Assets
|
||||
uses: AButler/upload-release-assets@v2.0
|
||||
uses: AButler/upload-release-assets@v3.0
|
||||
with:
|
||||
files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer
|
||||
|
||||
plugins {
|
||||
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.2.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.2.3"
|
||||
}
|
||||
|
||||
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 revision: String by extra("")
|
||||
var buildNumber by extra("")
|
||||
@ -83,7 +83,7 @@ allprojects {
|
||||
}
|
||||
|
||||
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 {
|
||||
supportedVersions.forEach {
|
||||
@ -97,7 +97,7 @@ tasks {
|
||||
}
|
||||
}
|
||||
runServer {
|
||||
minecraftVersion("1.20.2")
|
||||
minecraftVersion("1.20.4")
|
||||
pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
|
||||
.toTypedArray())
|
||||
|
||||
|
@ -22,9 +22,9 @@ val properties = Properties().also { props ->
|
||||
|
||||
dependencies {
|
||||
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("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 {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
# Minecraft expectations
|
||||
paper = "1.20.2-R0.1-SNAPSHOT"
|
||||
paper = "1.20.4-R0.1-SNAPSHOT"
|
||||
fastutil = "8.5.9"
|
||||
guava = "31.1-jre"
|
||||
log4j = "2.19.0"
|
||||
@ -11,19 +11,19 @@ snakeyaml = "2.0"
|
||||
dummypermscompat = "1.10"
|
||||
worldguard-bukkit = "7.0.9"
|
||||
mapmanager = "1.8.0-SNAPSHOT"
|
||||
griefprevention = "16.18.1"
|
||||
griefprevention = "17.0.0"
|
||||
griefdefender = "2.1.0-SNAPSHOT"
|
||||
residence = "4.5._13.1"
|
||||
towny = "0.100.0.1"
|
||||
plotsquared = "7.1.0"
|
||||
towny = "0.100.1.23"
|
||||
plotsquared = "7.3.6"
|
||||
|
||||
# Third party
|
||||
bstats = "3.0.2"
|
||||
sparsebitset = "1.3"
|
||||
parallelgzip = "1.0.5"
|
||||
adventure = "4.14.0"
|
||||
adventure-bukkit = "4.3.1"
|
||||
checkerqual = "3.40.0"
|
||||
adventure = "4.16.0"
|
||||
adventure-bukkit = "4.3.2"
|
||||
checkerqual = "3.42.0"
|
||||
truezip = "6.8.4"
|
||||
auto-value = "1.10.4"
|
||||
findbugs = "3.0.2"
|
||||
@ -43,14 +43,14 @@ serverlib = "2.3.4"
|
||||
## Internal
|
||||
text-adapter = "3.0.6"
|
||||
text = "3.0.4"
|
||||
piston = "0.5.7"
|
||||
piston = "0.5.8"
|
||||
|
||||
# Tests
|
||||
mockito = "5.6.0"
|
||||
mockito = "5.11.0"
|
||||
|
||||
# Gradle plugins
|
||||
pluginyml = "0.6.0"
|
||||
minotaur = "2.8.4"
|
||||
minotaur = "2.8.7"
|
||||
|
||||
[libraries]
|
||||
# Minecraft expectations
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binäre Datei nicht angezeigt.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
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
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
20
gradlew.bat
vendored
20
gradlew.bat
vendored
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
@ -2,7 +2,7 @@ rootProject.name = "FastAsyncWorldEdit"
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -11,7 +11,7 @@ repositories {
|
||||
}
|
||||
|
||||
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")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
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.implementation.packet.ChunkPacket;
|
||||
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
||||
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.ext.fawe.v1_18_R2.PaperweightAdapter;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
|
||||
@ -111,8 +104,7 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
|
||||
public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
@ -235,11 +227,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -255,12 +246,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseBlock getFullBlock(final Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -337,10 +327,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightFaweWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -485,7 +472,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
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());
|
||||
if (map != null && map.wasAccessibleSinceLastSave()) {
|
||||
// PlayerChunk.d players = map.players;
|
||||
@ -522,7 +509,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
||||
return blockState1.hasPostProcess(
|
||||
((CraftWorld) world).getHandle(),
|
||||
getServerLevel(world),
|
||||
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
|
||||
);
|
||||
}
|
||||
@ -538,54 +525,33 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(
|
||||
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
|
||||
org.bukkit.World bukkitWorld
|
||||
) {
|
||||
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(() -> {
|
||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureTreeGeneration = true;
|
||||
serverLevel.captureBlockStates = true;
|
||||
try {
|
||||
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
|
||||
return null;
|
||||
}
|
||||
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
|
||||
} finally {
|
||||
|
||||
@Override
|
||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureBlockStates = false;
|
||||
serverLevel.captureTreeGeneration = false;
|
||||
serverLevel.capturedBlockStates.clear();
|
||||
}
|
||||
});
|
||||
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
|
||||
protected ServerLevel getServerLevel(final World world) {
|
||||
return ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
|
||||
// Quickly add each entity to a list copy.
|
||||
List<Entity> mcEntities = new ArrayList<>();
|
||||
((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<>();
|
||||
mcEntities.forEach((mcEnt) -> {
|
||||
|
@ -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.");
|
||||
}
|
||||
this.createCopy = createCopy;
|
||||
// Increment regardless of whether copy will be created or not to return null from getCopy()
|
||||
return ++this.copyKey;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ repositories {
|
||||
}
|
||||
|
||||
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")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
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.implementation.packet.ChunkPacket;
|
||||
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
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.ext.fawe.v1_19_R3.PaperweightAdapter;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
||||
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.entity.CraftEntity;
|
||||
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;
|
||||
|
||||
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
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 Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
||||
@ -244,11 +236,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -264,12 +255,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseBlock getFullBlock(final Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -298,10 +288,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightFaweWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -446,7 +433,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
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());
|
||||
if (map != null && wasAccessibleSinceLastSave(map)) {
|
||||
boolean flag = false;
|
||||
@ -484,7 +471,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
||||
return blockState1.hasPostProcess(
|
||||
((CraftWorld) world).getHandle(),
|
||||
getServerLevel(world),
|
||||
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
|
||||
);
|
||||
}
|
||||
@ -501,47 +488,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(
|
||||
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
|
||||
org.bukkit.World bukkitWorld
|
||||
) {
|
||||
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(() -> {
|
||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureTreeGeneration = true;
|
||||
serverLevel.captureBlockStates = true;
|
||||
try {
|
||||
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
|
||||
return null;
|
||||
}
|
||||
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
|
||||
} finally {
|
||||
|
||||
@Override
|
||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureBlockStates = false;
|
||||
serverLevel.captureTreeGeneration = false;
|
||||
serverLevel.capturedBlockStates.clear();
|
||||
}
|
||||
});
|
||||
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
|
||||
protected ServerLevel getServerLevel(final World world) {
|
||||
return ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.");
|
||||
}
|
||||
this.createCopy = createCopy;
|
||||
// Increment regardless of whether copy will be created or not to return null from getCopy()
|
||||
return ++this.copyKey;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
|
||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.1-R0.1-20230916.212543-167")
|
||||
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.1-R0.1-SNAPSHOT
|
||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.1-R0.1-20230921.165944-178")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
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.implementation.packet.ChunkPacket;
|
||||
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
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.ext.fawe.v1_20_R1.PaperweightAdapter;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
@ -111,8 +104,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
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 Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
||||
@ -244,11 +236,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -264,12 +255,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseBlock getFullBlock(final Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -298,10 +288,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightFaweWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -446,7 +433,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
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());
|
||||
if (map != null && wasAccessibleSinceLastSave(map)) {
|
||||
boolean flag = false;
|
||||
@ -484,7 +471,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
||||
return blockState1.hasPostProcess(
|
||||
((CraftWorld) world).getHandle(),
|
||||
getServerLevel(world),
|
||||
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
|
||||
);
|
||||
}
|
||||
@ -501,47 +488,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(
|
||||
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
|
||||
org.bukkit.World bukkitWorld
|
||||
) {
|
||||
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(() -> {
|
||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureTreeGeneration = true;
|
||||
serverLevel.captureBlockStates = true;
|
||||
try {
|
||||
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
|
||||
return null;
|
||||
}
|
||||
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
|
||||
} finally {
|
||||
|
||||
@Override
|
||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureBlockStates = false;
|
||||
serverLevel.captureTreeGeneration = false;
|
||||
serverLevel.capturedBlockStates.clear();
|
||||
}
|
||||
});
|
||||
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
|
||||
protected ServerLevel getServerLevel(final World world) {
|
||||
return ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.");
|
||||
}
|
||||
this.createCopy = createCopy;
|
||||
// Increment regardless of whether copy will be created or not to return null from getCopy()
|
||||
return ++this.copyKey;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
|
||||
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.2-R0.1-20231029.153906-63")
|
||||
// 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-20231203.034718-121")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
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.implementation.packet.ChunkPacket;
|
||||
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
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.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
|
||||
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.entity.CraftEntity;
|
||||
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;
|
||||
|
||||
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
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 Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
||||
@ -247,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -267,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseBlock getFullBlock(final Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -301,10 +291,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightFaweWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -449,7 +436,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
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());
|
||||
if (map != null && wasAccessibleSinceLastSave(map)) {
|
||||
boolean flag = false;
|
||||
@ -487,7 +474,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
||||
return blockState1.hasPostProcess(
|
||||
((CraftWorld) world).getHandle(),
|
||||
getServerLevel(world),
|
||||
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
|
||||
);
|
||||
}
|
||||
@ -504,47 +491,26 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(
|
||||
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
|
||||
org.bukkit.World bukkitWorld
|
||||
) {
|
||||
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(() -> {
|
||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureTreeGeneration = true;
|
||||
serverLevel.captureBlockStates = true;
|
||||
try {
|
||||
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
|
||||
return null;
|
||||
}
|
||||
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
|
||||
} finally {
|
||||
|
||||
@Override
|
||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureBlockStates = false;
|
||||
serverLevel.captureTreeGeneration = false;
|
||||
serverLevel.capturedBlockStates.clear();
|
||||
}
|
||||
});
|
||||
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
|
||||
protected ServerLevel getServerLevel(final World world) {
|
||||
return ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.");
|
||||
}
|
||||
this.createCopy = createCopy;
|
||||
// Increment regardless of whether copy will be created or not to return null from getCopy()
|
||||
return ++this.copyKey;
|
||||
}
|
||||
|
||||
|
@ -1,26 +1,17 @@
|
||||
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
|
||||
|
||||
applyPaperweightAdapterConfiguration()
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
applyPaperweightAdapterConfiguration()
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
}
|
@ -17,28 +17,23 @@
|
||||
* 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.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTConstants;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
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.extension.platform.Watchdog;
|
||||
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 net.minecraft.Util;
|
||||
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.resources.ResourceKey;
|
||||
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.Blocks;
|
||||
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.properties.DirectionProperty;
|
||||
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.LevelChunk;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.WorldOptions;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.PrimaryLevelData;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
@ -127,20 +124,19 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.spigotmc.SpigotConfig;
|
||||
import org.spigotmc.WatchdogThread;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@ -159,21 +155,21 @@ import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
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 Method getChunkFutureMainThreadMethod;
|
||||
private final Field mainThreadProcessorField;
|
||||
private final Field serverWorldsField;
|
||||
private final Method getChunkFutureMethod;
|
||||
private final Field chunkProviderExecutorField;
|
||||
private final Watchdog watchdog;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -185,24 +181,25 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
CraftServer.class.cast(Bukkit.getServer());
|
||||
|
||||
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
|
||||
if (dataVersion != 2730) {
|
||||
throw new UnsupportedClassVersionError("Not 1.17.1!");
|
||||
if (dataVersion != 3698 && dataVersion != 3700) {
|
||||
throw new UnsupportedClassVersionError("Not 1.20.(3/4)!");
|
||||
}
|
||||
|
||||
worldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
worldsField.setAccessible(true);
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
serverWorldsField.setAccessible(true);
|
||||
|
||||
getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread",
|
||||
getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod(
|
||||
Refraction.pickName("getChunkFutureMainThread", "c"),
|
||||
int.class, int.class, ChunkStatus.class, boolean.class
|
||||
);
|
||||
getChunkFutureMainThreadMethod.setAccessible(true);
|
||||
getChunkFutureMethod.setAccessible(true);
|
||||
|
||||
mainThreadProcessorField = ServerChunkCache.class.getDeclaredField(
|
||||
Refraction.pickName("mainThreadProcessor", "h")
|
||||
chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField(
|
||||
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;
|
||||
try {
|
||||
@ -240,16 +237,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
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.
|
||||
*
|
||||
@ -289,17 +276,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @param tag the tag
|
||||
*/
|
||||
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) {
|
||||
//FAWE start - avoid villager async catcher
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, tag);
|
||||
//FAWE end
|
||||
entity.save(tag);
|
||||
}
|
||||
|
||||
private static Block getBlockFromType(BlockType blockType) {
|
||||
return Registry.BLOCK.get(ResourceLocation.tryParse(blockType.getId()));
|
||||
|
||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.BLOCK).get(ResourceLocation.tryParse(blockType.getId()));
|
||||
}
|
||||
|
||||
private static Item getItemFromType(ItemType itemType) {
|
||||
return Registry.ITEM.get(ResourceLocation.tryParse(itemType.getId()));
|
||||
return DedicatedServer.getServer().registryAccess().registryOrThrow(Registries.ITEM).get(ResourceLocation.tryParse(itemType.getId()));
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final CraftBlockData blockData = chunk.getBlockState(blockPos).createCraftBlockData();
|
||||
BlockState state = BukkitAdapter.adapt(blockData);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
int internalId = Block.getId(blockData);
|
||||
BlockState state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||
if (state == null) {
|
||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
||||
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
||||
@ -357,21 +344,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
// Read the NBT data
|
||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||
if (te != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = te.save(new net.minecraft.nbt.CompoundTag());
|
||||
//FAWE start - BinaryTag
|
||||
net.minecraft.nbt.CompoundTag tag = te.saveWithId();
|
||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
private static final HashMap<BiomeType, Holder<Biome>> biomeTypeToNMSCache = new HashMap<>();
|
||||
private static final HashMap<Holder<Biome>, BiomeType> biomeTypeFromNMSCache = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightWorldNativeAccess(this, new WeakReference<>(((CraftWorld) world).getHandle()));
|
||||
}
|
||||
|
||||
private static net.minecraft.core.Direction adapt(Direction face) {
|
||||
@ -431,16 +416,19 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
CraftEntity craftEntity = ((CraftEntity) entity);
|
||||
Entity mcEntity = craftEntity.getHandle();
|
||||
|
||||
// Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity
|
||||
if (mcEntity.isPassenger()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String id = getEntityId(mcEntity);
|
||||
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
readEntityIntoTag(mcEntity, tag);
|
||||
//FAWE start - BinaryTag
|
||||
return new BaseEntity(
|
||||
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
|
||||
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
|
||||
);
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -455,9 +443,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle());
|
||||
|
||||
if (createdEntity != null) {
|
||||
CompoundTag nativeTag = state.getNbtData();
|
||||
CompoundBinaryTag nativeTag = state.getNbt();
|
||||
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) {
|
||||
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());
|
||||
|
||||
worldServer.addEntity(createdEntity, SpawnReason.CUSTOM);
|
||||
worldServer.addFreshEntity(createdEntity, SpawnReason.CUSTOM);
|
||||
return createdEntity.getBukkitEntity();
|
||||
} else {
|
||||
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
|
||||
public Component getRichBlockName(BlockType blockType) {
|
||||
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());
|
||||
}
|
||||
|
||||
@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<?>>() {
|
||||
@Override
|
||||
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) {
|
||||
return new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||
} else {
|
||||
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName());
|
||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -523,20 +527,29 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
@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
|
||||
public void sendFakeOP(Player player) {
|
||||
((CraftPlayer) player).getHandle().networkManager.send(new ClientboundEntityEventPacket(
|
||||
((CraftPlayer) player).getHandle().connection.send(new ClientboundEntityEventPacket(
|
||||
((CraftPlayer) player).getHandle(), (byte) 28
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack item) {
|
||||
ItemStack stack = new ItemStack(Registry.ITEM.get(ResourceLocation.tryParse(item.getType().getId())), item.getAmount());
|
||||
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())));
|
||||
return CraftItemStack.asCraftMirror(stack);
|
||||
}
|
||||
@ -555,7 +568,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||
weStack.setNbtData(((CompoundTag) toNative(nmsStack.getTag())));
|
||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
||||
return weStack;
|
||||
}
|
||||
|
||||
@ -578,20 +591,16 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
fakePlayer.setItemInHand(InteractionHand.MAIN_HAND, stack);
|
||||
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 Vec3 blockVec = Vec3.atLowerCornerOf(blockPos);
|
||||
final net.minecraft.core.Direction enumFacing = adapt(face);
|
||||
BlockHitResult rayTrace = new BlockHitResult(blockVec, enumFacing, blockPos, false);
|
||||
UseOnContext context = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, rayTrace);
|
||||
InteractionResult result = stack.placeItem(context, InteractionHand.MAIN_HAND);
|
||||
InteractionResult result = stack.useOn(context);
|
||||
if (result != InteractionResult.SUCCESS) {
|
||||
if (worldServer
|
||||
.getBlockState(blockPos)
|
||||
.use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace)
|
||||
.consumesAction()) {
|
||||
if (worldServer.getBlockState(blockPos).use(worldServer, fakePlayer, InteractionHand.MAIN_HAND, rayTrace).consumesAction()) {
|
||||
result = InteractionResult.SUCCESS;
|
||||
} else {
|
||||
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) {
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockData = Block.stateById(internalId);
|
||||
return blockData.canSurvive(
|
||||
((CraftWorld) world).getHandle(),
|
||||
new BlockPos(position.getX(), position.getY(), position.getZ())
|
||||
);
|
||||
return blockData.canSurvive(((CraftWorld) world).getHandle(), new BlockPos(position.getX(), position.getY(), position.getZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -626,18 +632,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
Environment env = bukkitWorld.getEnvironment();
|
||||
ChunkGenerator gen = bukkitWorld.getGenerator();
|
||||
|
||||
Path tempDir = Files.createTempDirectory("FastAsyncWorldEditWorldGen");
|
||||
Path tempDir = Files.createTempDirectory("WorldEditWorldGen");
|
||||
LevelStorageSource levelStorage = LevelStorageSource.createDefault(tempDir);
|
||||
ResourceKey<LevelStem> worldDimKey = getWorldDimKey(env);
|
||||
try (LevelStorageSource.LevelStorageAccess session = levelStorage.createAccess("faweregentempworld", worldDimKey)) {
|
||||
ServerLevel originalWorld = ((CraftWorld) bukkitWorld).getHandle();
|
||||
PrimaryLevelData levelProperties = (PrimaryLevelData) originalWorld.getServer()
|
||||
.getWorldData().overworldData();
|
||||
WorldGenSettings originalOpts = levelProperties.worldGenSettings();
|
||||
WorldOptions originalOpts = levelProperties.worldGenOptions();
|
||||
|
||||
long seed = options.getSeed().orElse(originalWorld.getSeed());
|
||||
WorldGenSettings newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(levelProperties.isHardcore(), OptionalLong.of(seed))
|
||||
WorldOptions newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(OptionalLong.of(seed))
|
||||
: originalOpts;
|
||||
|
||||
LevelSettings newWorldSettings = new LevelSettings(
|
||||
@ -647,23 +653,35 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
levelProperties.settings.difficulty(),
|
||||
levelProperties.settings.allowCommands(),
|
||||
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(
|
||||
originalWorld.getServer(),
|
||||
originalWorld.getServer().executor,
|
||||
session, newWorldData,
|
||||
originalWorld.dimension(),
|
||||
originalWorld.dimensionType(),
|
||||
new LevelStem(
|
||||
originalWorld.dimensionTypeRegistration(),
|
||||
originalWorld.getChunkSource().getGenerator()
|
||||
),
|
||||
new NoOpWorldLoadListener(),
|
||||
newOpts.dimensions().get(worldDimKey).generator(),
|
||||
originalWorld.isDebug(),
|
||||
seed,
|
||||
ImmutableList.of(),
|
||||
false,
|
||||
env, gen,
|
||||
originalWorld.getRandomSequences(),
|
||||
env,
|
||||
gen,
|
||||
bukkitWorld.getBiomeProvider()
|
||||
);
|
||||
try {
|
||||
@ -674,7 +692,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
} finally {
|
||||
try {
|
||||
@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");
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
@ -683,7 +701,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
private BiomeType adapt(ServerLevel serverWorld, Biome origBiome) {
|
||||
ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(origBiome);
|
||||
ResourceLocation key = serverWorld.registryAccess().registryOrThrow(Registries.BIOME).getKey(origBiome);
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
@ -691,12 +709,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws
|
||||
WorldEditException {
|
||||
private void regenForWorld(Region region, Extent extent, ServerLevel serverWorld, RegenOptions options) throws WorldEditException {
|
||||
List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld);
|
||||
BlockableEventLoop<Runnable> executor;
|
||||
try {
|
||||
executor = (BlockableEventLoop<Runnable>) mainThreadProcessorField.get(serverWorld.getChunkSource());
|
||||
executor = (BlockableEventLoop<Runnable>) chunkProviderExecutorField.get(serverWorld.getChunkSource());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("Couldn't get executor for chunk loading.", e);
|
||||
}
|
||||
@ -721,23 +738,17 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ());
|
||||
ChunkAccess chunk = chunks.get(new ChunkPos(pos));
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos);
|
||||
BlockStateHolder<?> state = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter()).adapt(blockData);
|
||||
int internalId = Block.getId(blockData);
|
||||
BlockStateHolder<?> state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||
Objects.requireNonNull(state);
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||
if (blockEntity != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
blockEntity.save(tag);
|
||||
//FAWE start - BinaryTag
|
||||
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
|
||||
state = state.toBaseBlock(((CompoundBinaryTag) toNativeBinary(tag)));
|
||||
//FAWE end
|
||||
}
|
||||
extent.setBlock(vec, state.toBaseBlock());
|
||||
if (options.shouldRegenBiomes()) {
|
||||
ChunkBiomeContainer biomeIndex = chunk.getBiomes();
|
||||
if (biomeIndex != null) {
|
||||
Biome origBiome = biomeIndex.getNoiseBiome(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ());
|
||||
Biome origBiome = chunk.getNoiseBiome(vec.getX(), vec.getY(), vec.getZ()).value();
|
||||
BiomeType adaptedBiome = adapt(serverWorld, origBiome);
|
||||
if (adaptedBiome != null) {
|
||||
extent.setBiome(vec, adaptedBiome);
|
||||
@ -745,7 +756,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<CompletableFuture<ChunkAccess>> submitChunkLoadTasks(Region region, ServerLevel serverWorld) {
|
||||
@ -754,9 +764,10 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
// Pre-gen all the chunks
|
||||
for (BlockVector2 chunk : region.getChunks()) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
chunkLoadings.add(
|
||||
((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))
|
||||
);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
@ -815,7 +826,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @param foreign non-native NMS NBT structure
|
||||
* @return native WorldEdit NBT structure
|
||||
*/
|
||||
//FAWE start - BinaryTag
|
||||
@Override
|
||||
public BinaryTag toNativeBinary(net.minecraft.nbt.Tag foreign) {
|
||||
if (foreign == null) {
|
||||
@ -848,7 +858,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
try {
|
||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||
return ListBinaryTag.empty();
|
||||
}
|
||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||
@ -873,7 +883,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
* @throws IllegalArgumentException on error
|
||||
*/
|
||||
private ListBinaryTag toNativeList(net.minecraft.nbt.ListTag foreign) throws SecurityException, IllegalArgumentException {
|
||||
ListBinaryTag.Builder<BinaryTag> values = ListBinaryTag.builder();
|
||||
ListBinaryTag.Builder values = ListBinaryTag.builder();
|
||||
|
||||
for (net.minecraft.nbt.Tag tag : foreign) {
|
||||
values.add(toNativeBinary(tag));
|
||||
@ -913,8 +923,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
return new net.minecraft.nbt.IntArrayTag(((IntArrayBinaryTag) foreign).value());
|
||||
} else if (foreign instanceof LongArrayBinaryTag) {
|
||||
return new net.minecraft.nbt.LongArrayTag(((LongArrayBinaryTag) foreign).value());
|
||||
} else if (foreign instanceof ListBinaryTag foreignList) {
|
||||
} else if (foreign instanceof ListBinaryTag) {
|
||||
net.minecraft.nbt.ListTag tag = new net.minecraft.nbt.ListTag();
|
||||
ListBinaryTag foreignList = (ListBinaryTag) foreign;
|
||||
for (BinaryTag t : foreignList) {
|
||||
tag.add(fromNativeBinary(t));
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
@Override
|
||||
public boolean supportsWatchdog() {
|
||||
@ -944,7 +954,6 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
}
|
||||
|
||||
private class SpigotWatchdog implements Watchdog {
|
||||
|
||||
private final Field instanceField;
|
||||
private final Field lastTickField;
|
||||
|
||||
@ -966,22 +975,23 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
WatchdogThread.tick();
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
LOGGER.log(Level.WARNING, "Failed to tick watchdog", e);
|
||||
logger.log(Level.WARNING, "Failed to tick watchdog", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class MojangWatchdog implements Watchdog {
|
||||
|
||||
private final DedicatedServer server;
|
||||
private final Field tickField;
|
||||
|
||||
MojangWatchdog(DedicatedServer server) throws NoSuchFieldException {
|
||||
this.server = server;
|
||||
Field tickField = MinecraftServer.class.getDeclaredField(
|
||||
Refraction.pickName("nextTickTime", "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);
|
||||
this.tickField = tickField;
|
||||
}
|
||||
@ -993,17 +1003,15 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class NoOpWorldLoadListener implements ChunkProgressListener {
|
||||
|
||||
@Override
|
||||
public void updateSpawnPos(ChunkPos spawnPos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
|
||||
public void onStatusChange(ChunkPos pos, @org.jetbrains.annotations.Nullable ChunkStatus status) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1017,7 +1025,5 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
@Override
|
||||
public void setChunkRadius(int radius) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
* 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.Maps;
|
||||
@ -29,17 +29,18 @@ import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.datafixers.DSL;
|
||||
import com.mojang.datafixers.DSL.TypeReference;
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import com.mojang.datafixers.DataFixerBuilder;
|
||||
import com.mojang.datafixers.schemas.Schema;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter;
|
||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
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.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
@ -63,20 +63,21 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executor;
|
||||
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)
|
||||
* <p>
|
||||
*
|
||||
* We register a DFU Fixer per Legacy Data Version and apply the fixes using legacy strategy
|
||||
* which is safer, faster and cleaner code.
|
||||
* <p>
|
||||
*
|
||||
* 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
|
||||
* receive the source version in the compound
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.worldedit.world.DataFixer {
|
||||
|
||||
//FAWE start - BinaryTag
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -120,12 +121,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
private String fixBlockState(String blockState, int srcVer) {
|
||||
net.minecraft.nbt.CompoundTag stateNBT = stateToNBT(blockState);
|
||||
Dynamic<net.minecraft.nbt.Tag> dynamic = new Dynamic<>(OPS_NBT, stateNBT);
|
||||
net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(
|
||||
References.BLOCK_STATE,
|
||||
dynamic,
|
||||
srcVer,
|
||||
DATA_VERSION
|
||||
).getValue();
|
||||
net.minecraft.nbt.CompoundTag fixed = (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(References.BLOCK_STATE, dynamic, srcVer, DATA_VERSION).getValue();
|
||||
return nbtToState(fixed);
|
||||
}
|
||||
|
||||
@ -135,11 +131,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
if (tagCompound.contains("Properties", 10)) {
|
||||
sb.append('[');
|
||||
net.minecraft.nbt.CompoundTag props = tagCompound.getCompound("Properties");
|
||||
sb.append(props
|
||||
.getAllKeys()
|
||||
.stream()
|
||||
.map(k -> k + "=" + props.getString(k).replace("\"", ""))
|
||||
.collect(Collectors.joining(",")));
|
||||
sb.append(props.getAllKeys().stream().map(k -> k + "=" + props.getString(k).replace("\"", "")).collect(Collectors.joining(",")));
|
||||
sb.append(']');
|
||||
}
|
||||
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 int LEGACY_VERSION = 1343;
|
||||
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<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);
|
||||
DATA_VERSION = dataVersion;
|
||||
INSTANCE = this;
|
||||
@ -225,13 +217,17 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
// Called after fixers are built and ready for FIXING
|
||||
@Override
|
||||
public DataFixer build(final Executor executor) {
|
||||
public DataFixer buildUnoptimized() {
|
||||
return this.fixer = new WrappedDataFixer(DataFixers.getDataFixer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFixer buildOptimized(final Set<DSL.TypeReference> requiredTypes, Executor executor) {
|
||||
return buildUnoptimized();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private class WrappedDataFixer implements DataFixer {
|
||||
|
||||
private final DataFixer realFixer;
|
||||
|
||||
WrappedDataFixer(DataFixer realFixer) {
|
||||
@ -252,12 +248,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
return realFixer.update(type, dynamic, sourceVer, targetVer);
|
||||
}
|
||||
|
||||
private net.minecraft.nbt.CompoundTag convert(
|
||||
LegacyType type,
|
||||
net.minecraft.nbt.CompoundTag cmp,
|
||||
int sourceVer,
|
||||
int desiredVersion
|
||||
) {
|
||||
private net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int desiredVersion) {
|
||||
List<DataConverter> converters = PaperweightDataConverters.this.converters.get(type);
|
||||
if (converters != null && !converters.isEmpty()) {
|
||||
for (DataConverter converter : converters) {
|
||||
@ -282,7 +273,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
public Schema getSchema(int i) {
|
||||
return realFixer.getSchema(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.CompoundTag convert(
|
||||
LegacyType type,
|
||||
net.minecraft.nbt.CompoundTag cmp,
|
||||
int sourceVer,
|
||||
int targetVer
|
||||
) {
|
||||
public static net.minecraft.nbt.CompoundTag convert(LegacyType type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
return convert(type.getDFUType(), cmp, sourceVer, targetVer);
|
||||
}
|
||||
|
||||
@ -311,25 +296,16 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
return convert(type, cmp, sourceVer, DATA_VERSION);
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.CompoundTag convert(
|
||||
TypeReference type,
|
||||
net.minecraft.nbt.CompoundTag cmp,
|
||||
int sourceVer,
|
||||
int targetVer
|
||||
) {
|
||||
public static net.minecraft.nbt.CompoundTag convert(TypeReference type, net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
if (sourceVer >= targetVer) {
|
||||
return cmp;
|
||||
}
|
||||
return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer
|
||||
.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer)
|
||||
.getValue();
|
||||
return (net.minecraft.nbt.CompoundTag) INSTANCE.fixer.update(type, new Dynamic<>(OPS_NBT, cmp), sourceVer, targetVer).getValue();
|
||||
}
|
||||
|
||||
|
||||
public interface DataInspector {
|
||||
|
||||
net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer);
|
||||
|
||||
}
|
||||
|
||||
public interface DataConverter {
|
||||
@ -337,7 +313,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
int getDataVersion();
|
||||
|
||||
net.minecraft.nbt.CompoundTag convert(net.minecraft.nbt.CompoundTag cmp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -615,13 +590,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
return key;
|
||||
}
|
||||
|
||||
private static void convertCompound(
|
||||
LegacyType type,
|
||||
net.minecraft.nbt.CompoundTag cmp,
|
||||
String key,
|
||||
int sourceVer,
|
||||
int targetVer
|
||||
) {
|
||||
private static void convertCompound(LegacyType type, net.minecraft.nbt.CompoundTag cmp, String key, int sourceVer, int 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 final Logger a = LogManager.getLogger(PaperweightDataConverters.class);
|
||||
|
||||
DataInspectorEntity() {
|
||||
}
|
||||
|
||||
@ -880,7 +846,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -900,12 +865,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
return cmp;
|
||||
}
|
||||
|
||||
abstract net.minecraft.nbt.CompoundTag inspectChecked(
|
||||
net.minecraft.nbt.CompoundTag nbttagcompound,
|
||||
int sourceVer,
|
||||
int targetVer
|
||||
);
|
||||
|
||||
abstract net.minecraft.nbt.CompoundTag inspectChecked(net.minecraft.nbt.CompoundTag nbttagcompound, int sourceVer, int targetVer);
|
||||
}
|
||||
|
||||
private static class DataInspectorItemList extends DataInspectorTagged {
|
||||
@ -924,7 +884,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorItem extends DataInspectorTagged {
|
||||
@ -943,7 +902,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterMaterialId implements DataConverter {
|
||||
@ -1344,7 +1302,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterBanner implements DataConverter {
|
||||
@ -1391,7 +1348,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 final List<String> a = Lists.newArrayList(
|
||||
"MinecartRideable",
|
||||
"MinecartChest",
|
||||
"MinecartFurnace",
|
||||
"MinecartTNT",
|
||||
"MinecartSpawner",
|
||||
"MinecartHopper",
|
||||
"MinecartCommandBlock"
|
||||
);
|
||||
private static final List<String> a = Lists.newArrayList("MinecartRideable", "MinecartChest", "MinecartFurnace", "MinecartTNT", "MinecartSpawner", "MinecartHopper", "MinecartCommandBlock");
|
||||
|
||||
DataConverterMinecart() {
|
||||
}
|
||||
@ -1701,7 +1649,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterMobSpawner implements DataConverter {
|
||||
@ -1746,7 +1693,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterUUID implements DataConverter {
|
||||
@ -1765,47 +1711,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterHealth implements DataConverter {
|
||||
|
||||
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"
|
||||
);
|
||||
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");
|
||||
|
||||
DataConverterHealth() {
|
||||
}
|
||||
@ -1834,7 +1744,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterSaddle implements DataConverter {
|
||||
@ -1859,7 +1768,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterHanging implements DataConverter {
|
||||
@ -1898,7 +1806,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterDropChances implements DataConverter {
|
||||
@ -1922,15 +1829,13 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
if (cmp.contains("ArmorDropChances", 9)) {
|
||||
nbttaglist = cmp.getList("ArmorDropChances", 5);
|
||||
if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(
|
||||
2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) {
|
||||
if (nbttaglist.size() == 4 && nbttaglist.getFloat(0) == 0.0F && nbttaglist.getFloat(1) == 0.0F && nbttaglist.getFloat(2) == 0.0F && nbttaglist.getFloat(3) == 0.0F) {
|
||||
cmp.remove("ArmorDropChances");
|
||||
}
|
||||
}
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterRiding implements DataConverter {
|
||||
@ -1966,7 +1871,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
nbttagcompound.remove("Riding");
|
||||
return nbttagcompound1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 ((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 {
|
||||
try {
|
||||
object = GsonHelper.fromJson(DataConverterSignText.a, s, Component.class, true);
|
||||
if (object == null) {
|
||||
object = new TextComponent("");
|
||||
object = Component.literal("");
|
||||
}
|
||||
} catch (JsonParseException jsonparseexception) {
|
||||
;
|
||||
@ -2019,11 +1923,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
object = new TextComponent(s);
|
||||
object = Component.literal(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object = new TextComponent("");
|
||||
object = Component.literal("");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterCookedFish implements DataConverter {
|
||||
@ -2056,7 +1959,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterZombie implements DataConverter {
|
||||
@ -2099,7 +2001,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
private int convert(int i) {
|
||||
return i >= 0 && i < 6 ? i : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterVBO implements DataConverter {
|
||||
@ -2115,7 +2016,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
cmp.putString("useVbo", "true");
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterGuardian implements DataConverter {
|
||||
@ -2138,7 +2038,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterSkeleton implements DataConverter {
|
||||
@ -2167,7 +2066,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterZombieType implements DataConverter {
|
||||
@ -2206,7 +2104,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterHorse implements DataConverter {
|
||||
@ -2249,7 +2146,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
String s = cmp.getString("id");
|
||||
|
||||
if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(
|
||||
s)) {
|
||||
if ("minecraft:potion".equals(s) || "minecraft:splash_potion".equals(s) || "minecraft:lingering_potion".equals(s) || "minecraft:tipped_arrow".equals(s)) {
|
||||
net.minecraft.nbt.CompoundTag nbttagcompound1 = cmp.getCompound("tag");
|
||||
|
||||
if (!nbttagcompound1.contains("Potion", 8)) {
|
||||
@ -2427,7 +2322,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterShulker implements DataConverter {
|
||||
@ -2446,12 +2340,11 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterShulkerBoxItem implements DataConverter {
|
||||
|
||||
public static final String[] a = new String[]{"minecraft:white_shulker_box", "minecraft:orange_shulker_box", "minecraft:magenta_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:yellow_shulker_box", "minecraft:lime_shulker_box", "minecraft:pink_shulker_box", "minecraft:gray_shulker_box", "minecraft:silver_shulker_box", "minecraft:cyan_shulker_box", "minecraft:purple_shulker_box", "minecraft:blue_shulker_box", "minecraft:brown_shulker_box", "minecraft:green_shulker_box", "minecraft:red_shulker_box", "minecraft:black_shulker_box"};
|
||||
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() {
|
||||
}
|
||||
@ -2488,7 +2381,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterShulkerBoxBlock implements DataConverter {
|
||||
@ -2507,7 +2399,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterLang implements DataConverter {
|
||||
@ -2526,7 +2417,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterTotem implements DataConverter {
|
||||
@ -2545,7 +2435,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterBedBlock implements DataConverter {
|
||||
@ -2593,7 +2482,6 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterBedItem implements DataConverter {
|
||||
@ -2612,16 +2500,14 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataConverterSignText implements DataConverter {
|
||||
|
||||
public static final Gson a = new GsonBuilder().registerTypeAdapter(Component.class, new JsonDeserializer() {
|
||||
MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws
|
||||
JsonParseException {
|
||||
MutableComponent a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException {
|
||||
if (jsonelement.isJsonPrimitive()) {
|
||||
return new TextComponent(jsonelement.getAsString());
|
||||
return Component.literal(jsonelement.getAsString());
|
||||
} else if (jsonelement.isJsonArray()) {
|
||||
JsonArray jsonarray = jsonelement.getAsJsonArray();
|
||||
MutableComponent ichatbasecomponent = null;
|
||||
@ -2629,11 +2515,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
JsonElement jsonelement1 = (JsonElement) iterator.next();
|
||||
MutableComponent ichatbasecomponent1 = this.a(
|
||||
jsonelement1,
|
||||
jsonelement1.getClass(),
|
||||
jsondeserializationcontext
|
||||
);
|
||||
MutableComponent ichatbasecomponent1 = this.a(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext);
|
||||
|
||||
if (ichatbasecomponent == null) {
|
||||
ichatbasecomponent = ichatbasecomponent1;
|
||||
@ -2648,11 +2530,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
}
|
||||
}
|
||||
|
||||
public Object deserialize(
|
||||
JsonElement jsonelement,
|
||||
Type type,
|
||||
JsonDeserializationContext jsondeserializationcontext
|
||||
) throws JsonParseException {
|
||||
public Object deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException {
|
||||
return this.a(jsonelement, type, jsondeserializationcontext);
|
||||
}
|
||||
}).create();
|
||||
@ -2681,12 +2559,12 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
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)) {
|
||||
object = new TextComponent(s1);
|
||||
object = Component.literal(s1);
|
||||
} else {
|
||||
try {
|
||||
object = GsonHelper.fromJson(DataConverterSignText.a, s1, Component.class, true);
|
||||
if (object == null) {
|
||||
object = new TextComponent("");
|
||||
object = Component.literal("");
|
||||
}
|
||||
} catch (JsonParseException jsonparseexception) {
|
||||
;
|
||||
@ -2709,20 +2587,18 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
object = new TextComponent(s1);
|
||||
object = Component.literal(s1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object = new TextComponent("");
|
||||
object = Component.literal("");
|
||||
}
|
||||
|
||||
nbttagcompound.putString(s, Component.Serializer.toJson(object));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorPlayerVehicle implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
if (cmp.contains("RootVehicle", 10)) {
|
||||
@ -2735,11 +2611,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorLevelPlayer implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
if (cmp.contains("Player", 10)) {
|
||||
@ -2748,11 +2622,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorStructure implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
net.minecraft.nbt.ListTag nbttaglist;
|
||||
@ -2783,11 +2655,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorChunks implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
if (cmp.contains("Level", 10)) {
|
||||
@ -2799,15 +2669,7 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
nbttaglist = nbttagcompound1.getList("Entities", 10);
|
||||
|
||||
for (j = 0; j < nbttaglist.size(); ++j) {
|
||||
nbttaglist.set(
|
||||
j,
|
||||
convert(
|
||||
LegacyType.ENTITY,
|
||||
(net.minecraft.nbt.CompoundTag) nbttaglist.get(j),
|
||||
sourceVer,
|
||||
targetVer
|
||||
)
|
||||
);
|
||||
nbttaglist.set(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);
|
||||
|
||||
for (j = 0; j < nbttaglist.size(); ++j) {
|
||||
nbttaglist.set(
|
||||
j,
|
||||
convert(
|
||||
LegacyType.BLOCK_ENTITY,
|
||||
(net.minecraft.nbt.CompoundTag) nbttaglist.get(j),
|
||||
sourceVer,
|
||||
targetVer
|
||||
)
|
||||
);
|
||||
nbttaglist.set(j, convert(LegacyType.BLOCK_ENTITY, (net.minecraft.nbt.CompoundTag) nbttaglist.get(j), sourceVer, targetVer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorEntityPassengers implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
if (cmp.contains("Passengers", 9)) {
|
||||
@ -2847,11 +2699,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorPlayer implements DataInspector {
|
||||
|
||||
@Override
|
||||
public net.minecraft.nbt.CompoundTag inspect(net.minecraft.nbt.CompoundTag cmp, int sourceVer, int targetVer) {
|
||||
convertItems(cmp, "Inventory", sourceVer, targetVer);
|
||||
@ -2866,11 +2716,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorVillagers implements DataInspector {
|
||||
|
||||
ResourceLocation entityVillager = getKey("EntityVillager");
|
||||
|
||||
@Override
|
||||
@ -2894,11 +2742,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorMobSpawnerMinecart implements DataInspector {
|
||||
|
||||
ResourceLocation entityMinecartMobSpawner = getKey("EntityMinecartMobSpawner");
|
||||
ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner");
|
||||
|
||||
@ -2913,11 +2759,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorMobSpawnerMobs implements DataInspector {
|
||||
|
||||
ResourceLocation tileEntityMobSpawner = getKey("TileEntityMobSpawner");
|
||||
|
||||
@Override
|
||||
@ -2938,11 +2782,9 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DataInspectorCommandBlock implements DataInspector {
|
||||
|
||||
ResourceLocation tileEntityCommand = getKey("TileEntityCommand");
|
||||
|
||||
@Override
|
||||
@ -2955,7 +2797,5 @@ class PaperweightDataConverters extends DataFixerBuilder implements com.sk89q.wo
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -17,18 +17,19 @@
|
||||
* 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 net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
|
||||
import net.minecraft.server.level.ClientInformation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.stats.Stat;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.player.ChatVisiblity;
|
||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
@ -37,15 +38,14 @@ import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
|
||||
class PaperweightFakePlayer extends ServerPlayer {
|
||||
|
||||
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
|
||||
UUID.nameUUIDFromBytes("worldedit".getBytes()),
|
||||
"[WorldEdit]"
|
||||
);
|
||||
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]");
|
||||
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
|
||||
private static final ClientInformation FAKE_CLIENT_INFO = new ClientInformation(
|
||||
"en_US", 16, ChatVisiblity.FULL, true, 0, HumanoidArm.LEFT, false, false
|
||||
);
|
||||
|
||||
PaperweightFakePlayer(ServerLevel world) {
|
||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
|
||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, FAKE_CLIENT_INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,17 +72,13 @@ class PaperweightFakePlayer extends ServerPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOptions(ServerboundClientInformationPacket packet) {
|
||||
public void updateOptions(ClientInformation clientOptions) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayClientMessage(Component message, boolean actionBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message, ChatType type, UUID sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void awardStat(Stat<?> stat, int amount) {
|
||||
}
|
||||
@ -97,7 +93,6 @@ class PaperweightFakePlayer extends ServerPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openTextEdit(SignBlockEntity sign) {
|
||||
public void openTextEdit(SignBlockEntity sign, boolean front) {
|
||||
}
|
||||
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe;
|
||||
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
@ -27,21 +27,19 @@ import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.FullChunkStatus;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PaperweightWorldNativeAccess implements
|
||||
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
|
||||
|
||||
public class PaperweightWorldNativeAccess implements WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
|
||||
private static final int UPDATE = 1;
|
||||
private static final int NOTIFY = 2;
|
||||
|
||||
@ -83,19 +81,12 @@ public class PaperweightWorldNativeAccess implements
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public net.minecraft.world.level.block.state.BlockState setBlockState(
|
||||
LevelChunk chunk,
|
||||
BlockPos position,
|
||||
net.minecraft.world.level.block.state.BlockState state
|
||||
) {
|
||||
return chunk.setType(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
public net.minecraft.world.level.block.state.BlockState setBlockState(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState state) {
|
||||
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
|
||||
net.minecraft.world.level.block.state.BlockState block,
|
||||
BlockPos position
|
||||
) {
|
||||
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(net.minecraft.world.level.block.state.BlockState block, BlockPos position) {
|
||||
return Block.updateFromNeighbourShapes(block, getWorld(), position);
|
||||
}
|
||||
|
||||
@ -115,12 +106,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBlockUpdate(
|
||||
LevelChunk chunk,
|
||||
BlockPos position,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void notifyBlockUpdate(LevelChunk chunk, BlockPos position, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
|
||||
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
@ -128,7 +114,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(LevelChunk chunk) {
|
||||
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
||||
return chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,11 +125,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void notifyNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||
ServerLevel world = getWorld();
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
world.updateNeighborsAt(pos, oldState.getBlock());
|
||||
@ -162,27 +144,21 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
}
|
||||
|
||||
// Not sure why neighborChanged is deprecated
|
||||
@SuppressWarnings("deprecation")
|
||||
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
|
||||
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNeighbors(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState,
|
||||
int recursionLimit
|
||||
) {
|
||||
public void updateNeighbors(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, int recursionLimit) {
|
||||
ServerLevel world = getWorld();
|
||||
// a == updateNeighbors
|
||||
// b == updateDiagonalNeighbors
|
||||
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
|
||||
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
|
||||
CraftWorld craftWorld = world.getWorld();
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(
|
||||
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
|
||||
CraftBlockData.fromData(newState)
|
||||
);
|
||||
BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState));
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
@ -193,11 +169,7 @@ public class PaperweightWorldNativeAccess implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockStateChange(
|
||||
BlockPos pos,
|
||||
net.minecraft.world.level.block.state.BlockState oldState,
|
||||
net.minecraft.world.level.block.state.BlockState newState
|
||||
) {
|
||||
public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState) {
|
||||
getWorld().onBlockStateChange(pos, oldState, newState);
|
||||
}
|
||||
|
@ -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.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.util.ReflectionUtil;
|
||||
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.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.EmptyBlockGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
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 {
|
||||
|
||||
private final Block block;
|
||||
private final BlockState blockState;
|
||||
private final Material material;
|
||||
private final boolean isTranslucent;
|
||||
private final CraftBlockData craftBlockData;
|
||||
private final org.bukkit.Material craftMaterial;
|
||||
private final int opacity;
|
||||
@ -35,14 +30,8 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
public PaperweightBlockMaterial(Block block, BlockState blockState) {
|
||||
this.block = block;
|
||||
this.blockState = blockState;
|
||||
this.material = blockState.getMaterial();
|
||||
this.craftBlockData = CraftBlockData.fromData(blockState);
|
||||
this.craftMaterial = craftBlockData.getMaterial();
|
||||
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
|
||||
"properties", "aP"));
|
||||
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
|
||||
Refraction.pickName("canOcclude", "n")
|
||||
);
|
||||
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
|
||||
BlockPos.ZERO,
|
||||
@ -50,7 +39,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
);
|
||||
tile = tileEntity == null
|
||||
? null
|
||||
: new PaperweightLazyCompoundTag(Suppliers.memoize(() -> tileEntity.save(new net.minecraft.nbt.CompoundTag())));
|
||||
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
@ -65,10 +54,6 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
return craftBlockData;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return blockState.isAir();
|
||||
@ -81,7 +66,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return material.isSolidBlocking();
|
||||
return blockState.canOcclude();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,12 +76,13 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isLiquid() {
|
||||
return material.isLiquid();
|
||||
return !blockState.getFluidState().is(Fluids.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return material.isSolid();
|
||||
// No access to world -> EmptyBlockGetter
|
||||
return blockState.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,12 +112,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isFragileWhenPushed() {
|
||||
return material.getPushReaction() == PushReaction.DESTROY;
|
||||
return blockState.getPistonPushReaction() == PushReaction.DESTROY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnpushable() {
|
||||
return material.getPushReaction() == PushReaction.BLOCK;
|
||||
return blockState.getPistonPushReaction() == PushReaction.BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,12 +127,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isMovementBlocker() {
|
||||
return material.isSolid();
|
||||
return craftMaterial.isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBurnable() {
|
||||
return material.isFlammable();
|
||||
return craftMaterial.isBurnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,12 +143,12 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
|
||||
@Override
|
||||
public boolean isReplacedDuringPlacement() {
|
||||
return material.isReplaceable();
|
||||
return blockState.canBeReplaced();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTranslucent() {
|
||||
return isTranslucent;
|
||||
return !blockState.canOcclude();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,7 +169,7 @@ public class PaperweightBlockMaterial implements BlockMaterial {
|
||||
@Override
|
||||
public int getMapColor() {
|
||||
// rgb field
|
||||
return material.getColor().col;
|
||||
return block.defaultMapColor().col;
|
||||
}
|
||||
|
||||
}
|
@ -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.IDelegateBukkitImplAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
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.implementation.packet.ChunkPacket;
|
||||
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
||||
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.ext.fawe.PaperweightAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen.PaperweightRegen;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.regen.PaperweightRegen;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
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.SideEffect;
|
||||
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.nbt.BinaryTag;
|
||||
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.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -110,12 +101,21 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.Tag, ServerLevel> {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
|
||||
|
||||
private 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
|
||||
// ------------------------------------------------------------------------
|
||||
@ -126,7 +126,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
private Map<String, List<Property<?>>> allBlockProperties = null;
|
||||
|
||||
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
|
||||
this.parent = new PaperweightAdapter();
|
||||
this.parent = new com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R3.PaperweightAdapter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -135,12 +135,15 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
return resourceLocation == null ? null : resourceLocation.toString();
|
||||
}
|
||||
|
||||
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
|
||||
entity.save(compoundTag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private synchronized boolean init() {
|
||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
||||
return false;
|
||||
@ -227,7 +230,8 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
}
|
||||
|
||||
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
|
||||
@ -235,11 +239,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BlockState getBlock(Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -255,12 +258,11 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseBlock getFullBlock(final Location location) {
|
||||
Preconditions.checkNotNull(location);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
@ -274,7 +276,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
// Read the NBT data
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -287,67 +289,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
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
|
||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||
return new PaperweightFaweWorldNativeAccess(
|
||||
this,
|
||||
new WeakReference<>(((CraftWorld) world).getHandle())
|
||||
);
|
||||
return new PaperweightFaweWorldNativeAccess(this, new WeakReference<>(getServerLevel(world)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -363,7 +307,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
||||
Supplier<CompoundBinaryTag> saveTag = () -> {
|
||||
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag);
|
||||
readEntityIntoTag(mcEntity, minecraftTag);
|
||||
//add Id for AbstractChangeSet to work
|
||||
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
|
||||
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
|
||||
@ -492,9 +436,9 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
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());
|
||||
if (map != null && map.wasAccessibleSinceLastSave()) {
|
||||
if (map != null && wasAccessibleSinceLastSave(map)) {
|
||||
boolean flag = false;
|
||||
// PlayerChunk.d players = map.players;
|
||||
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
|
||||
@ -504,7 +448,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
|
||||
.forEach(entityPlayer -> {
|
||||
synchronized (chunkPacket) {
|
||||
ClientboundLevelChunkPacket nmsPacket = (ClientboundLevelChunkPacket) chunkPacket.getNativePacket();
|
||||
ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
|
||||
if (nmsPacket == null) {
|
||||
nmsPacket = mapUtil.create(this, chunkPacket);
|
||||
chunkPacket.setNativePacket(nmsPacket);
|
||||
@ -530,7 +474,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
|
||||
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
|
||||
return blockState1.hasPostProcess(
|
||||
((CraftWorld) world).getHandle(),
|
||||
getServerLevel(world),
|
||||
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
|
||||
);
|
||||
}
|
||||
@ -538,72 +482,35 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
@Override
|
||||
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
|
||||
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()
|
||||
);
|
||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt())));
|
||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
|
||||
return CraftItemStack.asCraftMirror(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(
|
||||
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
|
||||
org.bukkit.World bukkitWorld
|
||||
) {
|
||||
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(() -> {
|
||||
protected void preCaptureStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureTreeGeneration = true;
|
||||
serverLevel.captureBlockStates = true;
|
||||
try {
|
||||
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
|
||||
return null;
|
||||
}
|
||||
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
|
||||
} finally {
|
||||
|
||||
@Override
|
||||
protected List<org.bukkit.block.BlockState> getCapturedBlockStatesCopy(final ServerLevel serverLevel) {
|
||||
return new ArrayList<>(serverLevel.capturedBlockStates.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postCaptureBlockStates(final ServerLevel serverLevel) {
|
||||
serverLevel.captureBlockStates = false;
|
||||
serverLevel.captureTreeGeneration = false;
|
||||
serverLevel.capturedBlockStates.clear();
|
||||
}
|
||||
});
|
||||
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
|
||||
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
|
||||
// Quickly add each entity to a list copy.
|
||||
List<Entity> mcEntities = new ArrayList<>();
|
||||
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
|
||||
|
||||
List<org.bukkit.entity.Entity> list = new ArrayList<>();
|
||||
mcEntities.forEach((mcEnt) -> {
|
||||
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity();
|
||||
if (bukkitEntity.isValid()) {
|
||||
list.add(bukkitEntity);
|
||||
}
|
||||
|
||||
});
|
||||
return list;
|
||||
protected ServerLevel getServerLevel(final World world) {
|
||||
return ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -642,7 +549,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
final Registry<Biome> registry = MinecraftServer
|
||||
.getServer()
|
||||
.registryAccess()
|
||||
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
|
||||
.registryOrThrow(BIOME);
|
||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
|
||||
Biome biome = registry.get(resourceLocation);
|
||||
return registry.getId(biome);
|
||||
@ -650,11 +557,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public Iterable<NamespacedKey> getRegisteredBiomes() {
|
||||
WritableRegistry<Biome> biomeRegistry = ((CraftServer) Bukkit.getServer())
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
|
||||
.getServer()
|
||||
.registryAccess()
|
||||
.ownedRegistryOrThrow(
|
||||
Registry.BIOME_REGISTRY);
|
||||
.registryOrThrow(BIOME);
|
||||
List<ResourceLocation> keys = biomeRegistry.stream()
|
||||
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
|
||||
List<NamespacedKey> namespacedKeys = new ArrayList<>();
|
||||
@ -670,18 +576,12 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
@Override
|
||||
public RelighterFactory getRelighterFactory() {
|
||||
try {
|
||||
Class.forName("ca.spottedleaf.starlight.light.StarLightEngine");
|
||||
if (PaperweightStarlightRelighter.isUsable()) {
|
||||
if (PaperLib.isPaper()) {
|
||||
return new PaperweightStarlightRelighterFactory();
|
||||
}
|
||||
} catch (ThreadDeath td) {
|
||||
throw td;
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
} else {
|
||||
return new NMSRelighterFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<Property<?>>> getAllProperties() {
|
||||
@ -702,4 +602,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
return new PaperweightPostProcessor();
|
||||
}
|
||||
|
||||
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
|
||||
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
|
||||
try {
|
||||
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
|
||||
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
||||
// fall-through
|
||||
}
|
||||
}
|
||||
// Papers new chunk system has no related replacement - therefor we assume true.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
|
||||
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
|
||||
|
||||
import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.math.IntPair;
|
||||
@ -15,14 +15,14 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.FullChunkStatus;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
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.. :( )
|
||||
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
|
||||
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
|
||||
cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ));
|
||||
boolean nextTick = lastTick.get() > currentTick;
|
||||
if (nextTick || cachedChanges.size() >= 1024) {
|
||||
if (nextTick) {
|
||||
@ -157,7 +157,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
|
||||
@Override
|
||||
public boolean isChunkTicking(LevelChunk levelChunk) {
|
||||
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
|
||||
return levelChunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
|
||||
}
|
||||
|
||||
@Override
|
@ -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.DelegateSemaphore;
|
||||
@ -20,22 +20,21 @@ import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.BitStorage;
|
||||
import net.minecraft.util.ZeroBitStorage;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
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.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
|
||||
import net.minecraft.world.level.chunk.DataLayer;
|
||||
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.LinearPalette;
|
||||
import net.minecraft.world.level.chunk.Palette;
|
||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
@ -81,14 +63,15 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static net.minecraft.core.registries.Registries.BIOME;
|
||||
|
||||
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private static final Function<BlockPos, BlockVector3> posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ());
|
||||
private static final Function<BlockEntity, CompoundTag> nmsTile2We =
|
||||
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(
|
||||
() -> tileEntity.save(new net.minecraft.nbt.CompoundTag())));
|
||||
tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
|
||||
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter());
|
||||
@ -101,6 +84,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
private final int maxHeight;
|
||||
private final int minSectionPosition;
|
||||
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 Object sendLock = new Object();
|
||||
private LevelChunkSection[] sections;
|
||||
@ -127,6 +112,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
this.maxSectionPosition = maxHeight >> 4;
|
||||
this.skyLight = new DataLayer[getSectionCount()];
|
||||
this.blockLight = new DataLayer[getSectionCount()];
|
||||
this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME);
|
||||
this.biomeHolderIdMap = biomeRegistry.asHolderIdMap();
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
this.createCopy = createCopy;
|
||||
// Increment regardless of whether copy will be created or not to return null from getCopy()
|
||||
return ++this.copyKey;
|
||||
}
|
||||
|
||||
@ -212,19 +200,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int y, int z) {
|
||||
ChunkBiomeContainer index = getChunk().getBiomes();
|
||||
Biome biomes = null;
|
||||
if (y == -1) {
|
||||
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;
|
||||
LevelChunkSection section = getSections(false)[(y >> 4) - getMinSectionPosition()];
|
||||
Holder<Biome> biomes = section.getNoiseBiome(x >> 2, (y & 15) >> 2, z >> 2);
|
||||
return PaperweightPlatformAdapter.adapt(biomes, serverLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -235,12 +213,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (dataLayer != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (dataLayer) {
|
||||
byte[] bytes = PaperLib.isPaper() ? dataLayer.getIfSet() : dataLayer.getData();
|
||||
if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) {
|
||||
byte[] bytes = dataLayer.getData();
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sky) {
|
||||
SectionPos sectionPos1 = SectionPos.of(getChunk().getPos(), layer);
|
||||
DataLayer dataLayer1 = serverLevel
|
||||
@ -251,14 +227,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (dataLayer1 != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (dataLayer1) {
|
||||
byte[] bytes = PaperLib.isPaper() ? dataLayer1.getIfSet() : dataLayer1.getData();
|
||||
if (!PaperLib.isPaper() || bytes != DataLayer.EMPTY_NIBBLE) {
|
||||
byte[] bytes = dataLayer1.getData();
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
@ -268,7 +242,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (blockEntity == null) {
|
||||
return null;
|
||||
}
|
||||
return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag())));
|
||||
return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,8 +271,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
|
||||
LightLayer.BLOCK,
|
||||
sectionPos,
|
||||
dataLayer,
|
||||
true
|
||||
dataLayer
|
||||
);
|
||||
}
|
||||
skyLight[alayer] = dataLayer;
|
||||
@ -325,7 +298,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
Arrays.fill(LAYER_COUNT, (byte) 15);
|
||||
dataLayer = new DataLayer(LAYER_COUNT);
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(LightLayer.BLOCK, sectionPos,
|
||||
dataLayer, true
|
||||
dataLayer
|
||||
);
|
||||
}
|
||||
blockLight[alayer] = dataLayer;
|
||||
@ -342,7 +315,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
|
||||
@Override
|
||||
public CompoundTag getEntity(UUID uuid) {
|
||||
Entity entity = serverLevel.getEntity(uuid);
|
||||
ensureLoaded(serverLevel, chunkX, chunkZ);
|
||||
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||
Entity entity = null;
|
||||
for (Entity e : entities) {
|
||||
if (e.getUUID().equals(uuid)) {
|
||||
entity = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entity != null) {
|
||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||
@ -357,6 +338,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
|
||||
@Override
|
||||
public Set<CompoundTag> getEntities() {
|
||||
ensureLoaded(serverLevel, chunkX, chunkZ);
|
||||
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||
if (entities.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
@ -393,7 +375,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
public Iterator<CompoundTag> iterator() {
|
||||
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(input, tag);
|
||||
input.save(tag);
|
||||
return (CompoundTag) adapter.toNative(tag);
|
||||
}).collect(Collectors.toList());
|
||||
return result.iterator();
|
||||
@ -426,7 +408,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
try {
|
||||
ServerLevel nmsWorld = serverLevel;
|
||||
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
|
||||
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;
|
||||
synchronized (nmsChunk) {
|
||||
LevelChunkSection[] levelChunkSections = nmsChunk.getSections();
|
||||
|
||||
for (int layerNo = getMinSectionPosition(); layerNo <= getMaxSectionPosition(); layerNo++) {
|
||||
|
||||
int getSectionIndex = layerNo - getMinSectionPosition();
|
||||
int setSectionIndex = layerNo - set.getMinSectionPosition();
|
||||
|
||||
if (!set.hasSection(layerNo)) {
|
||||
// No blocks, but might be biomes present. Handle this lazily.
|
||||
if (biomes == null) {
|
||||
continue;
|
||||
}
|
||||
int layer = layerNo - getMinSectionPosition();
|
||||
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());
|
||||
}
|
||||
|
||||
bitMask |= 1 << layer;
|
||||
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;
|
||||
}
|
||||
|
||||
bitMask |= 1 << getSectionIndex;
|
||||
|
||||
// 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.
|
||||
@ -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
|
||||
// submitted to keep loaded internal chunks to queue target size.
|
||||
synchronized (super.sectionLocks[layer]) {
|
||||
if (createCopy) {
|
||||
char[] tmpLoad = loadPrivately(layerNo);
|
||||
char[] copyArr = new char[4096];
|
||||
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||
copy.storeSection(layer, copyArr);
|
||||
}
|
||||
synchronized (super.sectionLocks[getSectionIndex]) {
|
||||
|
||||
LevelChunkSection newSection;
|
||||
LevelChunkSection existingSection = levelChunkSections[layer];
|
||||
LevelChunkSection existingSection = levelChunkSections[getSectionIndex];
|
||||
// Don't attempt to tick section whilst we're editing
|
||||
if (existingSection != null) {
|
||||
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) {
|
||||
newSection = PaperweightPlatformAdapter.newChunkSection(layerNo, setArr, fastmode, adapter);
|
||||
if (PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, null, newSection, layer)) {
|
||||
updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer);
|
||||
PalettedContainer<Holder<Biome>> biomeData = biomes == null ? new PalettedContainer<>(
|
||||
biomeHolderIdMap,
|
||||
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;
|
||||
} else {
|
||||
existingSection = levelChunkSections[layer];
|
||||
existingSection = levelChunkSections[getSectionIndex];
|
||||
if (existingSection == null) {
|
||||
LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ,
|
||||
+layer
|
||||
getSectionIndex
|
||||
);
|
||||
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);
|
||||
if (PaperLib.isPaper()) {
|
||||
existingSection.tickingList.clear();
|
||||
@ -532,10 +589,13 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
this.levelChunk = nmsChunk;
|
||||
this.sections = null;
|
||||
this.reset();
|
||||
} else if (existingSection != getSections(false)[layer]) {
|
||||
this.sections[layer] = existingSection;
|
||||
} else if (existingSection != getSections(false)[getSectionIndex]) {
|
||||
this.sections[getSectionIndex] = existingSection;
|
||||
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);
|
||||
/*} else if (lock.isModified()) {
|
||||
this.reset(layerNo);*/
|
||||
@ -543,56 +603,33 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
} finally {
|
||||
sectionLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
PalettedContainer<Holder<Biome>> biomeData = setBiomesToPalettedContainer(
|
||||
biomes,
|
||||
setSectionIndex,
|
||||
existingSection.getBiomes()
|
||||
);
|
||||
|
||||
newSection =
|
||||
PaperweightPlatformAdapter.newChunkSection(
|
||||
layerNo,
|
||||
this::loadPrivately,
|
||||
setArr,
|
||||
fastmode,
|
||||
adapter
|
||||
adapter,
|
||||
biomeRegistry,
|
||||
biomeData
|
||||
);
|
||||
if (!PaperweightPlatformAdapter.setSectionAtomic(
|
||||
levelChunkSections,
|
||||
existingSection,
|
||||
newSection,
|
||||
layer
|
||||
getSectionIndex
|
||||
)) {
|
||||
LOGGER.error("Skipping invalid null section. chunk: {}, {} layer: {}", chunkX, chunkZ,
|
||||
+layer
|
||||
getSectionIndex
|
||||
);
|
||||
} else {
|
||||
updateGet(nmsChunk, levelChunkSections, newSection, setArr, layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
updateGet(nmsChunk, levelChunkSections, newSection, setArr, getSectionIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -656,7 +693,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
|
||||
for (UUID uuid : entityRemoves) {
|
||||
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid);
|
||||
Entity entity = nmsWorld.getEntities().get(uuid);
|
||||
if (entity != null) {
|
||||
removeEntity(entity);
|
||||
}
|
||||
@ -705,7 +742,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
entity.load(tag);
|
||||
entity.absMoveTo(x, y, z, yaw, pitch);
|
||||
entity.setUUID(nativeTag.getUUID());
|
||||
if (!nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
|
||||
if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
|
||||
LOGGER.warn(
|
||||
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
|
||||
id,
|
||||
@ -768,7 +805,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
// Set Modified
|
||||
nmsChunk.setLightCorrect(true); // Set Modified
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markUnsaved();
|
||||
nmsChunk.setUnsaved(true);
|
||||
// send to player
|
||||
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
|
||||
this.send(finalMask, finalLightUpdate);
|
||||
@ -907,11 +944,18 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
try {
|
||||
lock.acquire();
|
||||
|
||||
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
||||
final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(blocks);
|
||||
final Palette<BlockState> palette = (Palette<BlockState>) PaperweightPlatformAdapter.fieldPalette.get(blocks);
|
||||
final PalettedContainer<BlockState> blocks = section.getStates();
|
||||
final Object dataObject = PaperweightPlatformAdapter.fieldData.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();
|
||||
|
||||
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) {
|
||||
return BlockTypesCache.ReservedIDs.AIR;
|
||||
} else {
|
||||
@ -1020,8 +1064,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
((LevelLightEngine) serverLevel.getChunkSource().getLightEngine()).queueSectionData(
|
||||
lightLayer,
|
||||
sectionPos,
|
||||
dataLayer,
|
||||
true
|
||||
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
|
||||
public boolean hasSection(int layer) {
|
||||
layer -= getMinSectionPosition();
|
||||
@ -1067,10 +1153,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
LevelChunkSection existing = getSections(true)[layer];
|
||||
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(
|
||||
blocksExisting);
|
||||
dataObject);
|
||||
int paletteSize;
|
||||
|
||||
if (palette instanceof LinearPalette || palette instanceof HashMapPalette) {
|
@ -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.queue.IBlocks;
|
||||
@ -8,18 +8,22 @@ import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_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.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import net.minecraft.world.level.chunk.PalettedContainerRO;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
@ -32,6 +36,8 @@ import java.util.concurrent.Future;
|
||||
|
||||
public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private final char[][] blocks;
|
||||
@ -39,7 +45,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
private final int maxHeight;
|
||||
final ServerLevel serverLevel;
|
||||
final LevelChunk levelChunk;
|
||||
private ChunkBiomeContainer chunkBiomeContainer;
|
||||
private PalettedContainer<Holder<Biome>>[] biomes = null;
|
||||
|
||||
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
|
||||
this.levelChunk = levelChunk;
|
||||
@ -56,7 +62,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
blockEntity.getBlockPos().getY(),
|
||||
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) {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag);
|
||||
entity.save(compoundTag);
|
||||
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||
}
|
||||
|
||||
@ -136,28 +142,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
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
|
||||
public BiomeType getBiomeType(int x, int y, int z) {
|
||||
Biome biome = null;
|
||||
if (y == -1) {
|
||||
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;
|
||||
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
|
||||
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,6 +171,21 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
||||
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
|
||||
public BaseBlock getFullBlock(int x, int y, int z) {
|
||||
BlockState state = BlockTypesCache.states[get(x, y, z)];
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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.extent.processor.ProcessorScope;
|
||||
@ -165,7 +165,7 @@ public class PaperweightPostProcessor implements IBatchProcessor {
|
||||
} else {
|
||||
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
|
||||
}
|
||||
serverLevel.getLiquidTicks().scheduleTick(
|
||||
serverLevel.scheduleTick(
|
||||
position,
|
||||
type,
|
||||
type.getTickDelay(serverLevel)
|
@ -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.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||
import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.server.level.TicketType;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
@ -21,31 +17,8 @@ import java.util.function.IntConsumer;
|
||||
|
||||
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 int LIGHT_LEVEL = MCUtil.getTicketLevelFor(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;
|
||||
}
|
||||
private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
|
||||
|
||||
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<?> 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(
|
||||
Set<ChunkPos> coords,
|
||||
Consumer<ChunkPos> chunkCallback,
|
||||
IntConsumer processCallback
|
||||
) {
|
||||
try {
|
||||
RELIGHT.invokeExact(
|
||||
serverLevel.getChunkSource().getLightEngine(),
|
||||
coords,
|
||||
chunkCallback, // callback per chunk
|
||||
processCallback // callback for all chunks
|
||||
);
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Error occurred on relighting", throwable);
|
||||
serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error occurred on relighting", e);
|
||||
}
|
||||
}
|
||||
|
@ -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.RelightMode;
|
||||
@ -7,7 +7,7 @@ import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -23,4 +23,3 @@ public class PaperweightStarlightRelighterFactory implements RelighterFactory {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.LazyCompoundTag;
|
@ -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.core.Fawe;
|
||||
import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_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.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.io.file.SafeFiles;
|
||||
import com.sk89q.worldedit.world.RegenOptions;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.data.worldgen.biome.Biomes;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.LinearCongruentialGenerator;
|
||||
import net.minecraft.util.thread.ProcessorHandle;
|
||||
import net.minecraft.util.thread.ProcessorMailbox;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
@ -38,9 +39,9 @@ import net.minecraft.world.level.LevelSettings;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.FixedBiomeSource;
|
||||
import net.minecraft.world.level.biome.OverworldBiomeSource;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
@ -49,31 +50,24 @@ import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.SimpleRandomSource;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.WorldOptions;
|
||||
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.levelgen.synth.ImprovedNoise;
|
||||
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.levelgen.structure.placement.ConcentricRingsStructurePlacement;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.PrimaryLevelData;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.generator.CustomChunkGenerator;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
|
||||
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.BlockPopulator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -82,23 +76,25 @@ import java.util.Map;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.LongFunction;
|
||||
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> {
|
||||
|
||||
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 generateFlatBedrockField;
|
||||
private static final Field flatBedrockField;
|
||||
private static final Field generatorSettingFlatField;
|
||||
private static final Field generatorSettingBaseSupplierField;
|
||||
private static final Field delegateField;
|
||||
private static final Field chunkSourceField;
|
||||
private static final Field generatorStructureStateField;
|
||||
private static final Field ringPositionsField;
|
||||
private static final Field hasGeneratedPositionsField;
|
||||
|
||||
//list of chunk stati in correct order without FULL
|
||||
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
|
||||
@ -114,21 +110,21 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
|
||||
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
|
||||
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
|
||||
chunkStati.put(
|
||||
/*chunkStati.put(
|
||||
ChunkStatus.LIQUID_CARVERS,
|
||||
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.LIGHT,
|
||||
Concurrency.FULL
|
||||
); // light: radius 1, but no writes to other chunks, only current chunk
|
||||
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
|
||||
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
|
||||
// chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
|
||||
|
||||
try {
|
||||
worldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
worldsField.setAccessible(true);
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
serverWorldsField.setAccessible(true);
|
||||
|
||||
Field tmpPaperConfigField;
|
||||
Field tmpFlatBedrockField;
|
||||
@ -143,20 +139,31 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
tmpFlatBedrockField = null;
|
||||
}
|
||||
paperConfigField = tmpPaperConfigField;
|
||||
generateFlatBedrockField = tmpFlatBedrockField;
|
||||
flatBedrockField = tmpFlatBedrockField;
|
||||
|
||||
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
|
||||
"settings", "g"));
|
||||
"settings", "e"));
|
||||
generatorSettingBaseSupplierField.setAccessible(true);
|
||||
|
||||
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "e"));
|
||||
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d"));
|
||||
generatorSettingFlatField.setAccessible(true);
|
||||
|
||||
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
|
||||
delegateField.setAccessible(true);
|
||||
|
||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C"));
|
||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I"));
|
||||
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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -168,7 +175,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
private ServerLevel freshWorld;
|
||||
private ServerChunkCache freshChunkProvider;
|
||||
private LevelStorageSource.LevelStorageAccess session;
|
||||
private StructureManager structureManager;
|
||||
private StructureTemplateManager structureTemplateManager;
|
||||
private ThreadedLevelLightEngine threadedLevelLightEngine;
|
||||
private ChunkGenerator chunkGenerator;
|
||||
|
||||
@ -188,7 +195,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
//flat bedrock? (only on paper)
|
||||
if (paperConfigField != null) {
|
||||
try {
|
||||
generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
|
||||
generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
@ -200,6 +207,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected boolean initNewWorld() throws Exception {
|
||||
//world folder
|
||||
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
|
||||
@ -212,12 +220,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
|
||||
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
|
||||
|
||||
BiomeProvider biomeProvider = getBiomeProvider();
|
||||
|
||||
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
|
||||
WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
|
||||
WorldGenSettings newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
|
||||
WorldOptions originalOpts = originalWorldData.worldGenOptions();
|
||||
WorldOptions newOpts = options.getSeed().isPresent()
|
||||
? originalOpts.withSeed(OptionalLong.of(seed))
|
||||
: originalOpts;
|
||||
LevelSettings newWorldSettings = new LevelSettings(
|
||||
"faweregentempworld",
|
||||
@ -226,9 +232,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
originalWorldData.settings.difficulty(),
|
||||
originalWorldData.settings.allowCommands(),
|
||||
originalWorldData.settings.gameRules(),
|
||||
originalWorldData.settings.getDataPackConfig()
|
||||
originalWorldData.settings.getDataConfiguration()
|
||||
);
|
||||
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
|
||||
|
||||
PrimaryLevelData.SpecialWorldProperty specialWorldProperty =
|
||||
originalWorldData.isFlatWorld()
|
||||
? PrimaryLevelData.SpecialWorldProperty.FLAT
|
||||
: originalWorldData.isDebugWorld()
|
||||
? PrimaryLevelData.SpecialWorldProperty.DEBUG
|
||||
: PrimaryLevelData.SpecialWorldProperty.NONE;
|
||||
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, specialWorldProperty, Lifecycle.stable());
|
||||
|
||||
BiomeProvider biomeProvider = getBiomeProvider();
|
||||
|
||||
|
||||
//init world
|
||||
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
|
||||
@ -237,72 +253,79 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
session,
|
||||
newWorldData,
|
||||
originalServerWorld.dimension(),
|
||||
originalServerWorld.dimensionType(),
|
||||
DedicatedServer.getServer().registryAccess().registry(Registries.LEVEL_STEM).orElseThrow()
|
||||
.getOrThrow(levelStemResourceKey),
|
||||
new RegenNoOpWorldLoadListener(),
|
||||
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
|
||||
newOpts.dimensions().get(levelStemResourceKey).generator(),
|
||||
originalServerWorld.isDebug(),
|
||||
seed,
|
||||
ImmutableList.of(),
|
||||
false,
|
||||
originalServerWorld.getRandomSequences(),
|
||||
environment,
|
||||
generator,
|
||||
biomeProvider
|
||||
) {
|
||||
private final Biome singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(
|
||||
options
|
||||
.getBiomeType()
|
||||
.getId())) : null;
|
||||
|
||||
private final Holder<Biome> singleBiome = options.hasBiomeType() ? DedicatedServer.getServer().registryAccess()
|
||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
|
||||
) : null;
|
||||
|
||||
@Override
|
||||
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
|
||||
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
|
||||
if (options.hasBiomeType()) {
|
||||
return singleBiome;
|
||||
}
|
||||
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ);
|
||||
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(
|
||||
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
|
||||
);
|
||||
}
|
||||
}).get();
|
||||
freshWorld.noSave = true;
|
||||
removeWorldFromWorldsMap();
|
||||
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
|
||||
if (paperConfigField != null) {
|
||||
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
|
||||
paperConfigField.set(freshWorld, originalServerWorld.paperConfig());
|
||||
}
|
||||
|
||||
//generator
|
||||
if (originalChunkProvider.getGenerator() instanceof FlatLevelSource) {
|
||||
FlatLevelGeneratorSettings generatorSettingFlat = (FlatLevelGeneratorSettings) generatorSettingFlatField.get(
|
||||
originalChunkProvider.getGenerator());
|
||||
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
|
||||
if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
|
||||
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
|
||||
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
|
||||
} else if (originalChunkProvider.getGenerator() instanceof NoiseBasedChunkGenerator) {
|
||||
Supplier<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Supplier<NoiseGeneratorSettings>) generatorSettingBaseSupplierField
|
||||
.get(originalChunkProvider.getGenerator());
|
||||
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
|
||||
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField.get(
|
||||
originalGenerator);
|
||||
BiomeSource biomeSource;
|
||||
if (options.hasBiomeType()) {
|
||||
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options
|
||||
.getBiomeType()
|
||||
.getId())));
|
||||
|
||||
biomeSource = new FixedBiomeSource(
|
||||
DedicatedServer.getServer().registryAccess()
|
||||
.registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow(
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
biomeSource = originalChunkProvider.getGenerator().getBiomeSource();
|
||||
if (biomeSource instanceof OverworldBiomeSource) {
|
||||
biomeSource = fastOverworldBiomeSource(biomeSource);
|
||||
biomeSource = originalGenerator.getBiomeSource();
|
||||
}
|
||||
}
|
||||
chunkGenerator = new NoiseBasedChunkGenerator(biomeSource, seed, generatorSettingBaseSupplier);
|
||||
} else if (originalChunkProvider.getGenerator() instanceof CustomChunkGenerator) {
|
||||
chunkGenerator = (ChunkGenerator) delegateField.get(originalChunkProvider.getGenerator());
|
||||
chunkGenerator = new NoiseBasedChunkGenerator(
|
||||
biomeSource,
|
||||
generatorSettingBaseSupplier
|
||||
);
|
||||
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
|
||||
chunkGenerator = customChunkGenerator.getDelegate();
|
||||
} else {
|
||||
LOGGER.error("Unsupported generator type {}", originalChunkProvider.getGenerator().getClass().getName());
|
||||
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
|
||||
return false;
|
||||
}
|
||||
if (generator != null) {
|
||||
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
|
||||
generateConcurrent = generator.isParallelCapable();
|
||||
}
|
||||
// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed
|
||||
|
||||
freshChunkProvider = new ServerChunkCache(
|
||||
freshWorld,
|
||||
@ -312,6 +335,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
server.executor,
|
||||
chunkGenerator,
|
||||
freshWorld.spigotConfig.viewDistance,
|
||||
freshWorld.spigotConfig.simulationDistance,
|
||||
server.forceSynchronousWrites(),
|
||||
new RegenNoOpWorldLoadListener(),
|
||||
(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);
|
||||
//let's start then
|
||||
structureManager = server.getStructureManager();
|
||||
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
||||
structureTemplateManager = server.getStructureManager();
|
||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -349,7 +389,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
try {
|
||||
freshChunkProvider.close(false);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
@ -371,9 +411,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
@Override
|
||||
protected ProtoChunk createProtoChunk(int x, int z) {
|
||||
return PaperLib.isPaper()
|
||||
? new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, freshWorld) // paper
|
||||
: new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld); // spigot
|
||||
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
|
||||
this.freshWorld.registryAccess().registryOrThrow(BIOME), null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -398,7 +438,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
@Override
|
||||
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
||||
// BlockPopulator#populate has to be called synchronously for TileEntity access
|
||||
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
|
||||
TaskManager.taskManager().task(() -> {
|
||||
final CraftWorld world = freshWorld.getWorld();
|
||||
final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ);
|
||||
blockPopulator.populate(world, random, chunk);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -416,7 +460,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
private void removeWorldFromWorldsMap() {
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
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");
|
||||
} catch (IllegalAccessException 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 RegenNoOpWorldLoadListener() {
|
||||
@ -636,15 +506,19 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
private class FastProtoChunk extends ProtoChunk {
|
||||
|
||||
// avoid warning on paper
|
||||
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, ServerLevel serverLevel) {
|
||||
super(pos, upgradeData, world, serverLevel);
|
||||
public FastProtoChunk(
|
||||
final ChunkPos pos,
|
||||
final UpgradeData upgradeData,
|
||||
final LevelHeightAccessor world,
|
||||
final Registry<Biome> biomeRegistry,
|
||||
@Nullable final BlendingData blendingData
|
||||
) {
|
||||
super(pos, upgradeData, world, biomeRegistry, blendingData);
|
||||
}
|
||||
|
||||
// avoid warning on paper
|
||||
|
||||
// compatibility with spigot
|
||||
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor) {
|
||||
super(pos, upgradeData, levelHeightAccessor);
|
||||
}
|
||||
|
||||
public boolean generateFlatBedrock() {
|
||||
return generateFlatBedrock;
|
||||
@ -673,7 +547,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return chunkStatus.getName();
|
||||
return chunkStatus.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -682,7 +556,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
Runnable::run, // TODO revisit, we might profit from this somehow?
|
||||
freshWorld,
|
||||
chunkGenerator,
|
||||
structureManager,
|
||||
structureTemplateManager,
|
||||
threadedLevelLightEngine,
|
||||
c -> CompletableFuture.completedFuture(Either.left(c)),
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
plugins {
|
||||
base
|
||||
}
|
||||
|
||||
artifacts {
|
||||
add("default", file("./src/main/resources/fastasyncworldedit-adapters.jar"))
|
||||
}
|
Binäre Datei nicht angezeigt.
@ -141,20 +141,15 @@ tasks.named<Jar>("jar") {
|
||||
addJarManifest(WorldEditKind.Plugin, includeClasspath = true)
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
dependsOn(project.project(":worldedit-bukkit:adapters").subprojects.map { it.tasks.named("assemble") })
|
||||
from(Callable {
|
||||
adapters.resolve()
|
||||
.map { f ->
|
||||
zipTree(f).matching {
|
||||
exclude("META-INF/")
|
||||
}
|
||||
}
|
||||
})
|
||||
configurations.add(adapters)
|
||||
archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}")
|
||||
dependencies {
|
||||
// In tandem with not bundling log4j, we shouldn't relocate base package here.
|
||||
// relocate("org.apache.logging", "com.sk89q.worldedit.log4j")
|
||||
relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4")
|
||||
|
||||
exclude(dependency("$group:$name"))
|
||||
|
||||
include(dependency(":worldedit-core"))
|
||||
include(dependency(":worldedit-libs:bukkit"))
|
||||
// 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"))
|
||||
}
|
||||
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") {
|
||||
include(dependency("com.zaxxer:SparseBitSet:1.3"))
|
||||
@ -192,6 +187,15 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
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 {
|
||||
@ -206,7 +210,7 @@ tasks {
|
||||
versionNumber.set("${project.version}")
|
||||
versionType.set("release")
|
||||
uploadFile.set(file("build/libs/${rootProject.name}-Bukkit-${project.version}.jar"))
|
||||
gameVersions.addAll(listOf("1.20.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"))
|
||||
changelog.set("The changelog is available on GitHub: https://github.com/IntellectualSites/" +
|
||||
"FastAsyncWorldEdit/releases/tag/${project.version}")
|
||||
|
@ -109,14 +109,6 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
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?");
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -163,13 +163,22 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
|
||||
final Location location = player.getLocation();
|
||||
final Set<ProtectedRegion> regions = this.getRegions(localplayer, location, isWhitelist);
|
||||
if (!regions.isEmpty()) {
|
||||
RegionManager manager = WorldGuard
|
||||
.getInstance()
|
||||
.getPlatform()
|
||||
.getRegionContainer()
|
||||
.get(BukkitAdapter.adapt(location.getWorld()));
|
||||
if (manager == null) {
|
||||
return null;
|
||||
}
|
||||
Set<Region> result = new HashSet<>();
|
||||
for (ProtectedRegion myRegion : regions) {
|
||||
if (myRegion.getId().equals("__global__")) {
|
||||
return new FaweMask(RegionWrapper.GLOBAL()) {
|
||||
@Override
|
||||
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 {
|
||||
@ -185,7 +194,7 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
|
||||
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
|
||||
final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player));
|
||||
for (ProtectedRegion myRegion : regions) {
|
||||
if (!isAllowed(localplayer, myRegion)) {
|
||||
if (!manager.hasRegion(myRegion.getId()) || !isAllowed(localplayer, myRegion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
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.io.ClipboardFormats;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
@ -160,6 +161,10 @@ public class FaweDelegateRegionManager {
|
||||
);
|
||||
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) {
|
||||
@ -213,7 +218,6 @@ public class FaweDelegateRegionManager {
|
||||
) {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
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 pos3World = BukkitAdapter.adapt(getWorld(swapPos.getWorldName()));
|
||||
EditSession sessionA = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
|
||||
@ -232,14 +236,16 @@ public class FaweDelegateRegionManager {
|
||||
CuboidRegion regionB = new CuboidRegion(
|
||||
pos3World,
|
||||
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 clipB = Clipboard.create(regionB, UUID.randomUUID());
|
||||
Clipboard clipA = new BlockArrayClipboard(regionA, UUID.randomUUID());
|
||||
Clipboard clipB = new BlockArrayClipboard(regionB, UUID.randomUUID());
|
||||
ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint());
|
||||
ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint());
|
||||
copyA.setCopyingBiomes(true);
|
||||
copyB.setCopyingBiomes(true);
|
||||
copyA.setCopyingEntities(true);
|
||||
copyB.setCopyingEntities(true);
|
||||
try {
|
||||
Operations.completeLegacy(copyA);
|
||||
Operations.completeLegacy(copyB);
|
||||
@ -253,17 +259,16 @@ public class FaweDelegateRegionManager {
|
||||
sessionA.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)
|
||||
);
|
||||
FaweAPI.fixLighting(pos1World, new CuboidRegion(
|
||||
swapPos.getBlockVector3(),
|
||||
BlockVector3.at(
|
||||
swapPos.getX() + pos2.getX() - pos1.getX(),
|
||||
0,
|
||||
swapPos.getZ() + pos2.getZ() - pos1.getZ()
|
||||
)
|
||||
), null,
|
||||
FaweAPI.fixLighting(
|
||||
pos1World,
|
||||
regionB,
|
||||
null,
|
||||
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
|
||||
);
|
||||
if (whenDone != null) {
|
||||
|
@ -13,7 +13,6 @@ import java.util.regex.Pattern;
|
||||
public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
|
||||
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_18 = new MinecraftVersion(1, 18);
|
||||
private static MinecraftVersion current = null;
|
||||
|
@ -307,9 +307,6 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser
|
||||
if (!tickFluid) {
|
||||
return null;
|
||||
}
|
||||
if (Settings.settings().QUEUE.NO_TICK_FASTMODE && fastMode) {
|
||||
return null;
|
||||
}
|
||||
return this.plugin.getBukkitImplAdapter().getTickingPostProcessor();
|
||||
}
|
||||
|
||||
|
@ -327,12 +327,12 @@ public class BukkitWorld extends AbstractWorld {
|
||||
treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_MUSHROOM, TreeType.BROWN_MUSHROOM);
|
||||
for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) {
|
||||
if (treeTypeMapping.get(type) == null) {
|
||||
LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type);
|
||||
//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 {}" +
|
||||
" 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." +
|
||||
"This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type);
|
||||
" {} is not available. This is not an error. This version of FAWE will work on your version of " +
|
||||
" Minecraft. This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type);
|
||||
//FAWE end
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ permissions:
|
||||
default: op
|
||||
children:
|
||||
fawe.bypass.regions: true
|
||||
fawe.limit.*: true
|
||||
fawe.limit.unlimited: true
|
||||
fawe.tips:
|
||||
default: op
|
||||
fawe.admin:
|
||||
|
@ -245,6 +245,11 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Location getRespawnLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(@Nonnull Statistic statistic) throws IllegalArgumentException {
|
||||
|
||||
@ -365,4 +370,9 @@ public class TestOfflinePermissible implements OfflinePlayer, Permissible {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -612,12 +612,38 @@ public enum FaweCache implements Trimable {
|
||||
/*
|
||||
Thread stuff
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new blocking executor with default name and FaweCache logger
|
||||
*
|
||||
* @return new blocking executor
|
||||
*/
|
||||
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;
|
||||
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true);
|
||||
return new ThreadPoolExecutor(nThreads, nThreads,
|
||||
0L, TimeUnit.MILLISECONDS, queue,
|
||||
new ThreadFactoryBuilder().setNameFormat("FAWE Blocking Executor - %d").build(),
|
||||
new ThreadFactoryBuilder().setNameFormat(name).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
) {
|
||||
|
||||
@ -652,10 +678,10 @@ public enum FaweCache implements Trimable {
|
||||
int hash = throwable.getMessage() != null ? throwable.getMessage().hashCode() : 0;
|
||||
if (hash != lastException) {
|
||||
lastException = hash;
|
||||
LOGGER.catching(throwable);
|
||||
logger.catching(throwable);
|
||||
count = 0;
|
||||
} else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) {
|
||||
LOGGER.warn(throwable.getMessage());
|
||||
logger.warn(throwable.getMessage());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -665,10 +691,10 @@ public enum FaweCache implements Trimable {
|
||||
private void handleFaweException(FaweException e) {
|
||||
FaweException.Type type = e.getType();
|
||||
if (e.getType() == FaweException.Type.OTHER) {
|
||||
LOGGER.catching(e);
|
||||
logger.catching(e);
|
||||
} else if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||
LOGGER.warn("FaweException: " + e.getMessage());
|
||||
logger.warn("FaweException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -67,11 +67,11 @@ public class ErodeBrush implements Brush {
|
||||
final int by = target.getBlockY();
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
BlockState state = es.getBlock(x0, y0, z0);
|
||||
buffer1.setBlock(relx, rely, relz, state);
|
||||
@ -115,11 +115,11 @@ public class ErodeBrush implements Brush {
|
||||
Clipboard current, Clipboard target
|
||||
) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
|
||||
if (cube >= brushSizeSquared) {
|
||||
@ -166,11 +166,11 @@ public class ErodeBrush implements Brush {
|
||||
Clipboard current, Clipboard target
|
||||
) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
|
||||
if (cube >= brushSizeSquared) {
|
||||
|
@ -53,7 +53,7 @@ public class HeightBrush implements Brush {
|
||||
try {
|
||||
heightMap = ScalableHeightMap.fromPNG(stream);
|
||||
} 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) {
|
||||
heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY);
|
||||
|
@ -102,7 +102,7 @@ public class Settings extends Config {
|
||||
|
||||
public FaweLimit getLimit(Actor actor) {
|
||||
FaweLimit limit;
|
||||
if (actor.hasPermission("fawe.bypass") || actor.hasPermission("fawe.limit.unlimited")) {
|
||||
if (actor.hasPermission("fawe.limit.unlimited")) {
|
||||
return FaweLimit.MAX.copy();
|
||||
}
|
||||
limit = new FaweLimit();
|
||||
@ -511,7 +511,7 @@ public class Settings extends Config {
|
||||
" - A larger value will use slightly less CPU time",
|
||||
" - A smaller value will reduce memory usage",
|
||||
" - 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"
|
||||
|
||||
})
|
||||
@ -544,12 +544,6 @@ public class Settings extends Config {
|
||||
})
|
||||
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 {
|
||||
|
||||
@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"
|
||||
})
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -159,15 +159,25 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
Future<Integer> future = call(() -> {
|
||||
try {
|
||||
int count = 0;
|
||||
String stmtStr = ascending ? uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND" +
|
||||
" `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` , `id`" :
|
||||
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND" +
|
||||
" `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` ASC, `id` ASC" :
|
||||
uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? " +
|
||||
"AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` DESC, `id` DESC" :
|
||||
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND" +
|
||||
" `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC";
|
||||
try (PreparedStatement stmt = connection.prepareStatement(stmtStr)) {
|
||||
String stmtStr = """
|
||||
SELECT * FROM `%sedits`
|
||||
WHERE `time` > ?
|
||||
AND `x2` >= ?
|
||||
AND `x1` <= ?
|
||||
AND `z2` >= ?
|
||||
AND `z1` <= ?
|
||||
AND `y2` >= ?
|
||||
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(2, pos1.getBlockX());
|
||||
stmt.setInt(3, pos2.getBlockX());
|
||||
@ -193,20 +203,20 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
if (delete && uuid != null) {
|
||||
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`<=?")) {
|
||||
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
|
||||
.allocate(16)
|
||||
.putLong(uuid.getMostSignificantBits())
|
||||
.putLong(uuid.getLeastSignificantBits())
|
||||
.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;
|
||||
|
@ -53,7 +53,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Function<String, Stream<? extends String>> extractArguments(String input) {
|
||||
private Function<String, Stream<? extends String>> extractArguments(String input, ParserContext context) {
|
||||
return prefix -> {
|
||||
if (input.length() > prefix.length() && input.startsWith(prefix + "[")) {
|
||||
// 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;
|
||||
// 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);
|
||||
} else {
|
||||
return Stream.of(prefix);
|
||||
@ -95,7 +95,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
public Stream<String> getSuggestions(String input) {
|
||||
return Arrays.stream(this.prefixes)
|
||||
.filter(validPrefix(input))
|
||||
.flatMap(extractArguments(input));
|
||||
.flatMap(extractArguments(input, new ParserContext()));
|
||||
}
|
||||
|
||||
@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 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.
|
||||
*
|
||||
* @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.
|
||||
|
@ -97,11 +97,11 @@ public class RichMaskParser extends FaweParser<Mask> {
|
||||
)),
|
||||
() -> {
|
||||
if (full.length() == 1) {
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||
}
|
||||
return new ArrayList<>(worldEdit
|
||||
.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) {
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||
}
|
||||
return new ArrayList<>(worldEdit
|
||||
.getMaskFactory()
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT)));
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT), context));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
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.sk89q.worldedit.WorldEdit;
|
||||
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 javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Linear2DPatternParser extends RichParser<Pattern> {
|
||||
@ -59,9 +58,8 @@ public class Linear2DPatternParser extends RichParser<Pattern> {
|
||||
zScale = Integer.parseInt(arguments[2]);
|
||||
Preconditions.checkArgument(zScale != 0);
|
||||
}
|
||||
if (inner instanceof RandomPattern) {
|
||||
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
|
||||
return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale);
|
||||
if (inner instanceof RandomPattern rp) {
|
||||
return new RandomPattern(new Linear2DRandom(xScale, zScale), rp);
|
||||
}
|
||||
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
|
||||
+ " cannot be used with " + getPrefix()));
|
||||
|
@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
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.sk89q.worldedit.WorldEdit;
|
||||
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 javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Linear3DPatternParser extends RichParser<Pattern> {
|
||||
@ -64,9 +63,8 @@ public class Linear3DPatternParser extends RichParser<Pattern> {
|
||||
zScale = Integer.parseInt(arguments[3]);
|
||||
Preconditions.checkArgument(zScale != 0);
|
||||
}
|
||||
if (inner instanceof RandomPattern) {
|
||||
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
|
||||
return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale, zScale);
|
||||
if (inner instanceof RandomPattern rp) {
|
||||
return new RandomPattern(new Linear3DRandom(xScale, yScale, zScale), rp);
|
||||
}
|
||||
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
|
||||
+ " cannot be used with " + getPrefix()));
|
||||
|
@ -9,7 +9,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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 dy;
|
||||
|
@ -29,7 +29,7 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
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 final Set<PropertyRemap<?>> remaps;
|
||||
|
@ -4,7 +4,7 @@ import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
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 cacheBotZ = Integer.MIN_VALUE;
|
||||
|
@ -6,14 +6,13 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
||||
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
import java.util.Collection;
|
||||
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 max;
|
||||
@ -50,7 +49,8 @@ public class HeightBoundExtent extends FaweRegionExtent {
|
||||
|
||||
@Override
|
||||
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 null;
|
||||
|
@ -25,7 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
/**
|
||||
* Stores changes to a {@link ChangeSet}.
|
||||
*/
|
||||
public class HistoryExtent extends AbstractDelegateExtent {
|
||||
public final class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
private final MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
private AbstractChangeSet changeSet;
|
||||
|
@ -37,7 +37,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class LimitExtent extends AbstractDelegateExtent {
|
||||
public final class LimitExtent extends AbstractDelegateExtent {
|
||||
|
||||
private final FaweLimit limit;
|
||||
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||
|
@ -8,7 +8,7 @@ import com.fastasyncworldedit.core.util.WEManager;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
public class MemoryCheckingExtent extends PassthroughExtent {
|
||||
public final class MemoryCheckingExtent extends PassthroughExtent {
|
||||
|
||||
private final Actor actor;
|
||||
|
||||
|
@ -15,7 +15,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class MultiRegionExtent extends FaweRegionExtent {
|
||||
public final class MultiRegionExtent extends FaweRegionExtent {
|
||||
|
||||
@Nullable
|
||||
private final RegionIntersection intersection;
|
||||
|
@ -40,7 +40,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
//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;
|
||||
|
||||
|
@ -26,7 +26,7 @@ import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PassthroughExtent extends AbstractDelegateExtent {
|
||||
public abstract class PassthroughExtent extends AbstractDelegateExtent {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
|
@ -11,7 +11,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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 BlockVector3 min;
|
||||
|
@ -18,7 +18,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
public final class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
|
||||
private final FaweLimit limit;
|
||||
private final Extent extent;
|
||||
|
@ -14,7 +14,7 @@ import java.lang.reflect.Field;
|
||||
|
||||
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) {
|
||||
super(parent);
|
||||
|
@ -11,7 +11,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class SingleRegionExtent extends FaweRegionExtent {
|
||||
public final class SingleRegionExtent extends FaweRegionExtent {
|
||||
|
||||
private final Region region;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
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 nanos;
|
||||
|
@ -9,7 +9,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class SourceMaskExtent extends TemporalExtent {
|
||||
public final class SourceMaskExtent extends TemporalExtent {
|
||||
|
||||
private Mask mask;
|
||||
private final MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
|
@ -34,7 +34,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
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;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
public class TemporalExtent extends PassthroughExtent {
|
||||
public abstract class TemporalExtent extends PassthroughExtent {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -305,6 +305,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
private void init() throws IOException {
|
||||
if (this.fileChannel == null) {
|
||||
this.fileChannel = braf.getChannel();
|
||||
if (Settings.settings().CLIPBOARD.LOCK_CLIPBOARD_FILE) {
|
||||
try {
|
||||
FileLock lock = this.fileChannel.lock();
|
||||
LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock));
|
||||
@ -322,6 +323,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
// Rethrow to prevent clipboard access
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length());
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,9 @@ import org.apache.logging.log4j.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
@ -80,28 +77,18 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
||||
|
||||
@Override
|
||||
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;
|
||||
for (IBatchProcessor processor : processors) {
|
||||
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
|
||||
ordered.merge(
|
||||
processor.getScope().intValue(),
|
||||
new HashSet<>(Collections.singleton(processor)),
|
||||
(existing, theNew) -> {
|
||||
existing.add(processor);
|
||||
return existing;
|
||||
}
|
||||
);
|
||||
ordered.computeIfAbsent(processor.getScope().intValue(), k -> new ArrayList<>())
|
||||
.add(processor);
|
||||
continue;
|
||||
}
|
||||
chunkSet = processSet(processor, chunk, get, chunkSet);
|
||||
}
|
||||
if (ordered.size() > 0) {
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
Set<IBatchProcessor> processors = ordered.get(i);
|
||||
if (processors == null) {
|
||||
continue;
|
||||
}
|
||||
if (!ordered.isEmpty()) {
|
||||
for (List<IBatchProcessor> processors : ordered.values()) {
|
||||
for (IBatchProcessor processor : processors) {
|
||||
chunkSet = processSet(processor, chunk, get, chunkSet);
|
||||
if (chunkSet == null) {
|
||||
|
@ -7,10 +7,10 @@ import com.fastasyncworldedit.core.util.collection.RandomCollection;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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 {
|
||||
|
||||
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 LinkedHashSet<ResettableExtent> extents = new LinkedHashSet<>();
|
||||
|
||||
public RandomTransform() {
|
||||
this(new TrueRandom());
|
||||
@ -36,27 +35,27 @@ public class RandomTransform extends SelectTransform {
|
||||
*/
|
||||
public RandomTransform(SimpleRandom random) {
|
||||
this.random = random;
|
||||
this.weights = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelegateExtent getExtent(int x, int y, int z) {
|
||||
return collection.next(x, y, z);
|
||||
return collection.next(this.random, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelegateExtent getExtent(int x, int z) {
|
||||
return collection.next(x, 0, z);
|
||||
return collection.next(this.random, x, 0, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResettableExtent setExtent(Extent extent) {
|
||||
if (collection == null) {
|
||||
collection = RandomCollection.of(weights, random);
|
||||
extents = new LinkedHashSet<>(weights.keySet());
|
||||
collection = RandomCollection.of(weights);
|
||||
}
|
||||
super.setExtent(extent);
|
||||
for (ResettableExtent current : extents) {
|
||||
current.setExtent(extent);
|
||||
for (RandomCollection.Weighted<ResettableExtent> current : this.weights) {
|
||||
current.value().setExtent(extent);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -72,13 +71,12 @@ public class RandomTransform extends SelectTransform {
|
||||
*/
|
||||
public void add(ResettableExtent extent, double chance) {
|
||||
checkNotNull(extent);
|
||||
weights.put(extent, chance);
|
||||
collection = RandomCollection.of(weights, random);
|
||||
this.extents.add(extent);
|
||||
weights.add(new RandomCollection.Weighted<>(extent, chance));
|
||||
collection = RandomCollection.of(weights);
|
||||
}
|
||||
|
||||
public Set<ResettableExtent> getExtents() {
|
||||
return extents;
|
||||
return this.weights.stream().map(RandomCollection.Weighted::value).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public RandomCollection<ResettableExtent> getCollection() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.fastasyncworldedit.core.function.pattern;
|
||||
|
||||
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.Expression;
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
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 {
|
||||
|
||||
private final Pattern[] patternsArray;
|
||||
@ -47,4 +54,10 @@ public class Linear2DBlockPattern extends AbstractPattern {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,15 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
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 {
|
||||
|
||||
private final Pattern[] patternsArray;
|
||||
@ -51,4 +58,10 @@ public class Linear3DBlockPattern extends AbstractPattern {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fastasyncworldedit.core.function.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.queue.Filter;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
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.world.block.BaseBlock;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LinearBlockPattern extends AbstractPattern implements ResettablePattern {
|
||||
|
||||
private final Pattern[] patternsArray;
|
||||
@ -15,7 +18,7 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
|
||||
/**
|
||||
* 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) {
|
||||
this.patternsArray = patterns;
|
||||
@ -23,18 +26,14 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
|
||||
|
||||
@Override
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
if (index == patternsArray.length) {
|
||||
index = 0;
|
||||
}
|
||||
return patternsArray[index++].applyBlock(position);
|
||||
index = (index + 1) % patternsArray.length;
|
||||
return patternsArray[index].applyBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
|
||||
if (index == patternsArray.length) {
|
||||
index = 0;
|
||||
}
|
||||
return patternsArray[index++].apply(extent, get, set);
|
||||
index = (index + 1) % patternsArray.length;
|
||||
return patternsArray[index].apply(extent, get, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,4 +41,10 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern fork() {
|
||||
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
|
||||
return new LinearBlockPattern(forked);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,4 +43,9 @@ public class MaskedPattern extends AbstractPattern {
|
||||
return secondary.apply(extent, get, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern fork() {
|
||||
return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,4 +36,9 @@ public class NoXPattern extends AbstractPattern {
|
||||
return pattern.apply(extent, mutable, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern fork() {
|
||||
return new NoXPattern(this.pattern.fork());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,4 +36,9 @@ public class NoYPattern extends AbstractPattern {
|
||||
return pattern.apply(extent, mutable, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern fork() {
|
||||
return new NoYPattern(this.pattern.fork());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.fastasyncworldedit.core.function.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||
import com.fastasyncworldedit.core.queue.Filter;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.pattern.AbstractPattern;
|
||||
@ -36,4 +37,9 @@ public class NoZPattern extends AbstractPattern {
|
||||
return pattern.apply(extent, mutable, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern fork() {
|
||||
return new NoZPattern(this.pattern.fork());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,4 +60,9 @@ public class OffsetPattern extends AbstractPattern {
|
||||
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
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren