feat!: Update for 1.18 (#1482)

* ci: Switch deployment to gh actions and use semver & java 17

* build: Update core dependencies

- Drop paranamer, you can access parameter names at runtime with Java 8+ natively

* ci: Snapshot builds are the default

* ci: Cleanup and finish transition

* ci: Trigger initial sync with the OSSRH

* revert: OSSRH snapshot deployment was successful, returning to baseline

This reverts commit 3a189f65f2.

* ci: Register javadoc jar for lib artifacts

* ci: Sign artifacts

* build: Set kotlin jvm toolchain

* style: Use minimized `version` output

* feat: Setup project structure for 1.18

* Exclude 1.17

* Port initial paperweight classes to 1.18 folder structure

* Move to Paper 1.18

* Update templates, address JEP deprecations and place a few TODOs

* Drop Guava 21 enforcement

* Make 1.18 to be effectively in a usable state (#1452)

* Update swathes of easy-to-update-sort-of-code.
 - Untested
 - Should compile but NMF broken something
 - Several todos:
  - biome history//better support (move to biome sections in core)
  - regen (haha lol no thanks, someone else can do that)
  - probably actually do the palette stuff that probably won't work in PaperweightPlatformAdapter

* ci: Provide basic Jenkinsfile for ghprb pipeline

* build: Update paperweight

* upstream: Update Upstream

de6fa17 Add getBrush helper for use with instanceof pattern matching (1926)

* FAWE will now load on startup

* it....works?

* Begin to allow biome edits (and fix biomes reverting to plains upon editing blocks)

* Add new blocks/block properties

* Only create biome palette if supplies is null

* Fix biome operations

* Finally get removing BlockID done (major version change allows it)

* refactor!: Drop PlotSquared v4

Fawe 2.0.0 and newer requires Java 17, PlotSquared v4 supports 1.13 and 1.14, Fawe wont work on these versions nevertheless and refuses to load due Java version incompatiblities with older versions. Newer versions can use PlotSquared v6.

* docs: Update readme

* Added and removed some comments

* Added and removed some comments

* refactor: Rename worldedit configuration

* build: Re-add 1.17 module

This the a very nasty commit

* chore: Implement missing methods

* build: Update paperweight

* upstream: Update upstream

6df194e Remove finalize, use a Cleaner instead (1943)
9843a4f Fix snapshots in 1.18 (1959)

* ci: Escape workflows

* build: Update paperweight to 1.18.1

* build: Update Paster

* Fix compilation

* Bump to 1.18.1

* Do both 1.18 and 1.18.1

Co-authored-by: Alex <mc.cache@web.de>

* Fix single-block lookups

* Reserve ordinals 0 through 3 for air/"reserved"

* Create block palette data with values

* Fix classpath for testing for starlight

* Correctly use block rather than sky light layer [not used in paper]

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>

* Update version (checking) for semver

* build: Fix release drafter base branch

* Trigger GHPRB

* tests: Add resource pack methods

* build: Update paperweight and add 1.17 again

* chore: Lazily change build delimiter

* build: Deploy API snapshots for 2.0.0

* Update adapters jar

* More verbosely get block data and ensure biome layer isn't null

* refactor: Address a few `TODO 1.18`'s

(cherry picked from commit 0b77932b6e46c825d78b8c7ccae2a68ad890564e)

* fix: Fix `/fawe debugpaste`

* refactor! Remove deprecations marked for removal that are not present in upstream (#1483)

* Reverse a "debug" change to BukkitImplLoader

* Fix parsing of build in FaweVersion

* refactor: Do prepared statements properly

- Update TextureUtil client jar to 1.18.1
- Limit the update checker to our domain

* Add classes with the correct minor version to the start of the adapter candidates list

* refactor: Deprecate `IMP` initializors in favor of builders

* Fix WEManager (#1487)

* Fix WeManager?

* Fix WeManager?

* Also register WEManager if not available, like TaskManager.

* refactor: Also deprecated `IMP` for DBHandler

* feat: Add a bunch of new types to the flora generator

* use spigot-compatible palette constructor

* use spigot-compatible packet constructor

* implement 1.18 regen

* return air instead of reserved on get blocks

* refactor: Shift `FileAlreadyExistsException` catch to a higher level

* read the actual block from ZeroBitStorage

* Add get default version min/max world height to platform
 - Fixes #1500

* Add methods to CLIPlatform

* Fix #1490

* Fix tests

* Don't force tick limiter enable/disable

* Use Math.floor instead of int cast 757bef1f7d2b16317ab3d18427ad22183344e28d

* More precise method names in MinecraftVersion
 - Also ensure correct comparisons are made in FaweBukkit and BukkitServerInterface
 - Fixes #1504

* Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved" (#1502)

* Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved"
Also:
 - Ensure that reserved is never returned in GET block operations
 - "empty" thus doesn't exist in the GET update methods; remove the needless checks
 - Allow GET/SET chunks to determine their own default values for non-present blocks/sections

* Add comments

* Remove mentions of NMS from compilation instruction

* Update log4j version, update jd links to use "latest"

* Move to BinaryTags where appropriate in adapters

* Add comments to changed code

* Rename worldedit to fawe where appropriate

* Use new language features

* chore: Format our loggers properly

* Remove unneeded comments

* Replace CachedChange class with record

* Remove/add some more comments

* Remove remaining keywords frm CachedChanged. IJ doesn't warn?

* Compress switch statements a bit using enhanced

* More enhanced switches

* Refactor: getVersionMin/MaxY -> versionMin/MaxY

* Throw, catch, and rethrow our own exception to make sure we're finding the culprit to a possible shaded-FAWE.

* Don't wrap Exception thrown upon invalid schematic path inside a RuntimeException
Fixes #1506

* docs: Put `since` annotation on newly introduced API

* docs: Drop clarified todos

* Warn user if using small-edit history setting with extended world heights

* Refactor: add javadoc to Clipboard#create and improve variables when delegating to another paste method

* Fix issue with offset/origin when pasting a clipboard via API without wrapping into a BlockArrayClipboard

* build: Remove drop our maven repository

* docs: Fix deprecation tag

* Fix incorrect toNative method in 1.17 adapter

* refactor: Deprecate tick limiter API for public use

* ci: dordsor does love rebasing here too

* docs: Document annotations

* Update upstream

fb5ec19 Fix error for snapshot restore missing chunk

* docs: Document a few undocumented annotations

* feat: Add worldedit.schematic.list.other permission and functionality (#1507)

* Add worldedit.schematic.list.other permission and functionality

* Implement StringMan#containsUuid

* Javadocs

* chore: Add since annotation

Co-authored-by: NotMyFault <mc.cache@web.de>

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
Co-authored-by: Aurélien <43724816+Aurelien30000@users.noreply.github.com>
Co-authored-by: SirYwell <hannesgreule@outlook.de>
Co-authored-by: JOO200 <github@joo200.de>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
This commit is contained in:
Alex 2022-01-05 16:58:30 +01:00 committed by GitHub
commit 8b973da7ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
234 changed files with 11428 additions and 4089 deletions

View File

@ -83,7 +83,7 @@ body:
attributes: attributes:
label: Fawe Version label: Fawe Version
description: What version of Fawe are you running? (`/version FastAsyncWorldEdit`) description: What version of Fawe are you running? (`/version FastAsyncWorldEdit`)
placeholder: "For example: FastAsyncWorldEdit version 1.17-89;8c01959" placeholder: "For example: FastAsyncWorldEdit version 2.0.0-SNAPSHOT-1"
validations: validations:
required: true required: true

2
.github/stale.yml vendored
View File

@ -1,4 +1,4 @@
daysUntilStale: 60 daysUntilStale: 30
daysUntilClose: 7 daysUntilClose: 7
only: issues only: issues
exemptLabels: exemptLabels:

View File

@ -1,34 +1,47 @@
name: "build" name: build
on: ["pull_request", "push"] on: [pull_request, push]
jobs: jobs:
build: build:
runs-on: "ubuntu-latest" runs-on: ubuntu-latest
steps: steps:
- name: "Checkout Repository" - name: Checkout Repository
uses: "actions/checkout@v2.3.4" uses: actions/checkout@v2.4.0
- name : "Validate Gradle Wrapper" - name : Validate Gradle Wrapper
uses : "gradle/wrapper-validation-action@v1.0.4" uses : gradle/wrapper-validation-action@v1.0.4
- name: "Grab SHA" - name: Setup Java
uses: "benjlevesque/short-sha@v1.2" uses: actions/setup-java@v2.4.0
id: "short-sha"
with: with:
length: "7" distribution: temurin
- name: "Echo SHA" cache: gradle
run: "echo $SHA" java-version: 17
- name: Clean Build
run: ./gradlew clean build --no-daemon
- name: Determine release status
if: ${{ runner.os == 'Linux' }}
run: |
if [ "$(./gradlew properties | awk '/^version:/ { print $2; }' | grep '\-SNAPSHOT')" ]; then
echo "STATUS=snapshot" >> $GITHUB_ENV
else
echo "STATUS=release" >> $GITHUB_ENV
fi
- name: Publish Release
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/major/2.0.0/1.18'}}
run: ./gradlew publishToSonatype closeSonatypeStagingRepository
env: env:
SHA: "${{ steps.short-sha.outputs.sha }}" ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
- name: "Setup Java" ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
uses: "actions/setup-java@v2.3.1" ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
with: ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
distribution: "temurin" - name: Publish Snapshot
cache: 'gradle' if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/major/2.0.0/1.18' }}
java-version: "17" run: ./gradlew publishToSonatype
- name: "Clean Build" env:
run: "./gradlew clean build --no-daemon" ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
- name: Archive Artifacts - name: Archive Artifacts
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2.3.1
with: with:
name: FastAsyncWorldEdit-Bukkit-1.17-${{ env.SHA }} name: FastAsyncWorldEdit-Bukkit-SNAPSHOT
path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-1.17-${{ env.SHA }}.jar path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar

20
.github/workflows/rebase.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Rebase Pull Request
on:
issue_comment:
types: [created]
jobs:
rebase:
name: Rebase
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') && github.event.comment.author_association == 'MEMBER'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2.4.0
with:
token: ${{ secrets.REBASE_TOKEN }}
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.REBASE_TOKEN }}

View File

@ -1,14 +1,14 @@
name: "draft release" name: draft release
on: on:
push: push:
branches: branches:
- "2.0.0" - main
jobs: jobs:
update_release_draft: update_release_draft:
runs-on: "ubuntu-latest" runs-on: ubuntu-latest
steps: steps:
- uses: "release-drafter/release-drafter@v5.15.0" - uses: release-drafter/release-drafter@v5.15.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,54 @@
:toc:
:toclevels: 2
= Fawe annotations explained
If we have modified parts of the WorldEdit codebase, we considered annotating it with different styles of comments, which
are explained in this document.
== In-line annotations
[source,java]
-----------------
public static Player adapt(com.sk89q.worldedit.entity.Player player) {
//FAWE start - Get player from PlayerProxy instead of BukkitPlayer if null
player = PlayerProxy.unwrap(player);
return player == null ? null : ((BukkitPlayer) player).getPlayer();
//FAWE end
}
-----------------
The `-sources` jar retains comments, if you add the FAWE API to your maven or gradle project, you can view differences between the projects with ease.
Behind the `//FAWE start - ` you can find a comment what has been changed and why it has been changed.
== Block annotations
[source,java]
-----------------
//FAWE start
@Override
public void setPermission(String permission, boolean value) {
}
//FAWE end
-----------------
Annotations can cover whole methods or go beyond the method and wrap around several added methods.
== Package annotations
Class additions are added under the `com.fastasyncworldedit` namespace, but sometimes classes need to be added in package private.
If that is done, you can find a `package-info.java` file within the package affected that outlines FAWE added classes:
[source,java]
-----------------
/**
* The following classes are FAWE additions:
*
* @see com.sk89q.worldedit.world.block.BlockTypesCache
*/
package com.sk89q.worldedit.world.block;
-----------------
== Undocumented annotations
Specific changes are not annotated:
* `com.fastasyncworldedit.core.configuration.Caption` in `com.sk89q.worldedit` packages have been changed from
`com.sk89q.worldedit.util.formatting.text.Text` to allow the usage of color codes for messages.
* Certain Log4J loggers have been adjusted to use the proper format of placeholders.

View File

@ -1,12 +1,12 @@
Compiling Compiling
========= =========
You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 16 installed. Gradle will download JDK 16 specifically if needed, You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed,
but it needs some version of Java to bootstrap from. but it needs some version of Java to bootstrap from.
Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 16. Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 16.
You can get the JDK 16 [here](https://adoptium.net/). You can get the JDK 17 [here](https://adoptium.net/).
The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules: The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules:
@ -16,10 +16,6 @@ The build process uses Gradle, which you do *not* need to download. FastAsyncWor
## To compile... ## To compile...
### NMS
FastAsyncWorldEdit uses NMS (net.minecraft.server) code in a variety of spots. NMS is not distributed via maven and therefore FastAsyncWorldEdit may not build without errors if you didn't install it into your local repository beforehand.
You can do that by either running Spigot's [BuildTools](https://www.spigotmc.org/wiki/buildtools/) targeting the versions needed or using Paper's [paperclip](https://papermc.io/downloads) with `java -Dpaperclip.install=true -jar paperclip.jar`.
### On Windows ### On Windows
1. Shift + right-click the folder with FastAsyncWorldEdit's files and click "Open command prompt". 1. Shift + right-click the folder with FastAsyncWorldEdit's files and click "Open command prompt".
@ -38,13 +34,13 @@ You will find:
* FastAsyncWorldEdit for Bukkit in **worldedit-bukkit/build/libs** * FastAsyncWorldEdit for Bukkit in **worldedit-bukkit/build/libs**
* the CLI version in **worldedit-cli/build/libs** * the CLI version in **worldedit-cli/build/libs**
If you want to use FastAsyncWorldEdit, use the `FastAsyncWorldEdit-1.17-<commitHash>` version obtained in **worldedit-bukkit/build/libs**. If you want to use FastAsyncWorldEdit, use the `FastAsyncWorldEdit-<identifier>` version obtained in **worldedit-bukkit/build/libs**.
(The `-#` version includes FastAsyncWorldEdit + necessary libraries.) (The `-#` version includes FastAsyncWorldEdit + necessary libraries.)
## Other commands ## Other commands
* `gradlew idea` will generate an [IntelliJ IDEA](http://www.jetbrains.com/idea/) module for each folder. * `gradlew idea` will generate an [IntelliJ IDEA](https://www.jetbrains.com/idea/) module for each folder.
_Possibly broken_: _Possibly broken_:
* `gradlew eclipse` will generate an [Eclipse](https://www.eclipse.org/downloads/) project for each folder. * `gradlew eclipse` will generate an [Eclipse](https://www.eclipse.org/downloads/) project for each folder.

10
Jenkinsfile vendored
View File

@ -1,10 +0,0 @@
pipeline {
agent any
stages {
stage('Build pull request') {
steps {
sh './gradlew clean build'
}
}
}
}

View File

@ -12,7 +12,7 @@ FastAsyncWorldEdit is a fork of WorldEdit that has huge speed and memory improve
* Use it in creative, survival in single player or on your server. * Use it in creative, survival in single player or on your server.
* Use it on your Minecraft server to fix grieving and mistakes. * Use it on your Minecraft server to fix grieving and mistakes.
Java Edition required. FastAsyncWorldEdit is compatible with Bukkit, Spigot, Paper, and Tuinity. Java Edition required. FastAsyncWorldEdit is compatible with Bukkit, Spigot and Paper.
## Download FastAsyncWorldEdit ## Download FastAsyncWorldEdit
* Spigot: https://www.spigotmc.org/resources/fast-async-worldedit.13932/ * Spigot: https://www.spigotmc.org/resources/fast-async-worldedit.13932/
@ -24,8 +24,8 @@ Java Edition required. FastAsyncWorldEdit is compatible with Bukkit, Spigot, Pap
* [Wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki) * [Wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki)
* [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit/issues) * [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit/issues)
* [Crowdin (Translations)](https://intellectualsites.crowdin.com/fastasyncworldedit) * [Crowdin (Translations)](https://intellectualsites.crowdin.com/fastasyncworldedit)
* [JavaDocs for the -bukkit module](https://ci.athion.net/job/FastAsyncWorldEdit-1.17-Bukkit-Javadocs/javadoc/) * [JavaDocs for the -bukkit module](https://javadoc.io/doc/com.fastasyncworldedit/FastAsyncWorldEdit-Bukkit/latest/index.html)
* [JavaDocs for the -core module](https://ci.athion.net/job/FastAsyncWorldEdit-1.17-Core-Javadocs/javadoc/) * [JavaDocs for the -core module](https://javadoc.io/doc/com.fastasyncworldedit/FastAsyncWorldEdit-Core/latest/index.html)
## Edit The Code ## Edit The Code

View File

@ -2,6 +2,11 @@ import org.ajoberstar.grgit.Grgit
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED
import java.net.URI
plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
}
logger.lifecycle(""" logger.lifecycle("""
******************************************* *******************************************
@ -17,7 +22,8 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("1.17") var rootVersion by extra("2.0.0")
var snapshot by extra("SNAPSHOT")
var revision: String by extra("") var revision: String by extra("")
var buildNumber by extra("") var buildNumber by extra("")
var date: String by extra("") var date: String by extra("")
@ -27,11 +33,10 @@ ext {
} }
date = git.head().dateTime.format(DateTimeFormatter.ofPattern("yy.MM.dd")) date = git.head().dateTime.format(DateTimeFormatter.ofPattern("yy.MM.dd"))
revision = "-${git.head().abbreviatedId}" revision = "-${git.head().abbreviatedId}"
val commit: String? = git.head().abbreviatedId
buildNumber = if (project.hasProperty("buildnumber")) { buildNumber = if (project.hasProperty("buildnumber")) {
project.properties["buildnumber"] as String snapshot + "-" + project.properties["buildnumber"] as String
} else { } else {
commit.toString() project.properties["snapshot"] as String
} }
} }
@ -66,3 +71,12 @@ allprojects {
} }
applyCommonConfiguration() applyCommonConfiguration()
nexusPublishing {
repositories {
sonatype {
nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}

View File

@ -8,14 +8,17 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven {
name = "PaperMC"
url = uri("https://papermc.io/repo/repository/maven-public/")
}
maven { maven {
name = "EngineHub" name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/") url = uri("https://maven.enginehub.org/repo/")
} }
maven {
name = "PaperMC"
url = uri("https://papermc.io/repo/repository/maven-public/")
content {
includeGroupByRegex("io\\.papermc\\..*")
}
}
} }
val properties = Properties().also { props -> val properties = Properties().also { props ->
@ -28,5 +31,11 @@ dependencies {
implementation(gradleApi()) implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:4.1.1") implementation("org.ajoberstar.grgit:grgit-gradle:4.1.1")
implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.1") implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.1")
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.1.14") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.3.3")
}
kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
}
} }

View File

@ -5,9 +5,7 @@ import org.gradle.kotlin.dsl.dependencies
// For specific version pinning, see // For specific version pinning, see
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ // https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
fun Project.applyPaperweightAdapterConfiguration( fun Project.applyPaperweightAdapterConfiguration() {
paperVersion: String
) {
applyCommonConfiguration() applyCommonConfiguration()
apply(plugin = "java-library") apply(plugin = "java-library")
applyCommonJavaConfiguration( applyCommonJavaConfiguration(
@ -17,7 +15,6 @@ fun Project.applyPaperweightAdapterConfiguration(
apply(plugin = "io.papermc.paperweight.userdev") apply(plugin = "io.papermc.paperweight.userdev")
dependencies { dependencies {
paperDevBundle(paperVersion)
"implementation"(project(":worldedit-bukkit")) "implementation"(project(":worldedit-bukkit"))
} }

View File

@ -10,12 +10,7 @@ fun Project.applyCommonConfiguration() {
version = rootProject.version version = rootProject.version
repositories { repositories {
mavenLocal()
mavenCentral() mavenCentral()
maven {
name = "IntellectualSites"
url = uri("https://mvn.intellectualsites.com/content/groups/public/")
}
maven { maven {
name = "EngineHub" name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/") url = uri("https://maven.enginehub.org/repo/")
@ -32,6 +27,7 @@ fun Project.applyCommonConfiguration() {
name = "Athion" name = "Athion"
url = uri("https://ci.athion.net/plugin/repository/tools/") url = uri("https://ci.athion.net/plugin/repository/tools/")
} }
mavenLocal()
} }
configurations.all { configurations.all {
@ -42,7 +38,7 @@ fun Project.applyCommonConfiguration() {
plugins.withId("java") { plugins.withId("java") {
the<JavaPluginExtension>().toolchain { the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(16)) languageVersion.set(JavaLanguageVersion.of(17))
} }
} }
@ -54,15 +50,15 @@ fun Project.applyCommonConfiguration() {
continue continue
} }
add(conf.name, "com.google.guava:guava") { add(conf.name, "com.google.guava:guava") {
version { require("21.0") } version { require("31.0.1-jre") }
because("Mojang provides Guava") because("Mojang provides Guava")
} }
add(conf.name, "com.google.code.gson:gson") { add(conf.name, "com.google.code.gson:gson") {
version { require("2.8.0") } version { require("2.8.8") }
because("Mojang provides Gson") because("Mojang provides Gson")
} }
add(conf.name, "it.unimi.dsi:fastutil") { add(conf.name, "it.unimi.dsi:fastutil") {
version { require("8.2.1") } version { require("8.5.6") }
because("Mojang provides FastUtil") because("Mojang provides FastUtil")
} }
} }

View File

@ -24,7 +24,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
val disabledLint = listOf( val disabledLint = listOf(
"processing", "path", "fallthrough", "serial" "processing", "path", "fallthrough", "serial"
) )
options.release.set(11) options.release.set(17)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true options.isDeprecation = true
options.encoding = "UTF-8" options.encoding = "UTF-8"
@ -32,7 +32,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
} }
configurations.all { configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 16) attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
} }
tasks.withType<Test>().configureEach { tasks.withType<Test>().configureEach {
@ -60,13 +60,12 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
options.encoding = "UTF-8" options.encoding = "UTF-8"
links( links(
"https://javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/", "https://javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/",
"https://jd.adventure.kyori.net/api/4.9.1/", "https://jd.adventure.kyori.net/api/latest/",
"https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/2.14.1/", "https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/latest/index.html",
"https://javadoc.io/doc/com.google.guava/guava/21.0/",
"https://www.antlr.org/api/Java/", "https://www.antlr.org/api/Java/",
"https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/", "https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/",
"https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/", "https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/",
"https://papermc.io/javadocs/paper/1.17/", "https://papermc.io/javadocs/paper/1.18/",
"https://ci.athion.net/job/FastAsyncWorldEdit-1.17-Core-Javadocs/javadoc/" // needed for other module linking "https://ci.athion.net/job/FastAsyncWorldEdit-1.17-Core-Javadocs/javadoc/" // needed for other module linking
) )
} }

View File

@ -21,6 +21,8 @@ import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.provideDelegate import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.the
import org.gradle.plugins.signing.SigningExtension
import javax.inject.Inject import javax.inject.Inject
fun Project.applyLibrariesConfiguration() { fun Project.applyLibrariesConfiguration() {
@ -28,6 +30,7 @@ fun Project.applyLibrariesConfiguration() {
apply(plugin = "java-base") apply(plugin = "java-base")
apply(plugin = "maven-publish") apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "signing")
configurations { configurations {
create("shade") create("shade")
@ -49,6 +52,7 @@ fun Project.applyLibrariesConfiguration() {
dependencies { dependencies {
exclude(dependency("com.google.guava:guava")) exclude(dependency("com.google.guava:guava"))
exclude(dependency("com.google.code.gson:gson")) exclude(dependency("com.google.code.gson:gson"))
exclude(dependency("com.google.errorprone:error_prone_annotations"))
exclude(dependency("org.checkerframework:checker-qual")) exclude(dependency("org.checkerframework:checker-qual"))
exclude(dependency("org.apache.logging.log4j:log4j-api")) exclude(dependency("org.apache.logging.log4j:log4j-api"))
exclude(dependency("com.google.code.findbugs:jsr305")) exclude(dependency("com.google.code.findbugs:jsr305"))
@ -94,8 +98,14 @@ fun Project.applyLibrariesConfiguration() {
archiveClassifier.set("sources") archiveClassifier.set("sources")
} }
// This a dummy jar to comply with the requirements of the OSSRH,
// libs are not API and therefore no "proper" javadoc jar is necessary
tasks.register<Jar>("javadocJar") {
archiveClassifier.set("javadoc")
}
tasks.named("assemble").configure { tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar") dependsOn("jar", "sourcesJar", "javadocJar")
} }
project.apply<LibsConfigPluginHack>() project.apply<LibsConfigPluginHack>()
@ -112,7 +122,7 @@ fun Project.applyLibrariesConfiguration() {
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11) attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
} }
outgoing.artifact(tasks.named("jar")) outgoing.artifact(tasks.named("jar"))
} }
@ -127,7 +137,7 @@ fun Project.applyLibrariesConfiguration() {
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11) attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
} }
outgoing.artifact(tasks.named("jar")) outgoing.artifact(tasks.named("jar"))
} }
@ -146,6 +156,20 @@ fun Project.applyLibrariesConfiguration() {
outgoing.artifact(tasks.named("sourcesJar")) outgoing.artifact(tasks.named("sourcesJar"))
} }
val javadocElements = project.configurations.register("javadocElements") {
isVisible = false
description = "Javadoc elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.JAVADOC))
}
outgoing.artifact(tasks.named("javadocJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) { libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile") mapToMavenScope("compile")
} }
@ -158,6 +182,22 @@ fun Project.applyLibrariesConfiguration() {
mapToMavenScope("runtime") mapToMavenScope("runtime")
} }
libsComponent.addVariantsFromConfiguration(javadocElements.get()) {
mapToMavenScope("runtime")
}
val publishingExtension = the<PublishingExtension>()
configure<SigningExtension> {
if (!version.toString().endsWith("-SNAPSHOT")) {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
isRequired
sign(publishingExtension.publications)
}
}
configure<PublishingExtension> { configure<PublishingExtension> {
publications { publications {
register<MavenPublication>("maven") { register<MavenPublication>("maven") {
@ -212,33 +252,6 @@ fun Project.applyLibrariesConfiguration() {
} }
} }
} }
repositories {
mavenLocal()
val nexusUsername: String? by project
val nexusPassword: String? by project
if (nexusUsername != null && nexusPassword != null) {
maven {
val releasesRepositoryUrl = "https://mvn.intellectualsites.com/content/repositories/releases/"
val snapshotRepositoryUrl = "https://mvn.intellectualsites.com/content/repositories/snapshots/"
/* Commenting this out for now - Fawe currently does not user semver or any sort of versioning that
differentiates between snapshots and releases, API & (past) deployment wise, this will come with a next major release.
url = uri(
if (version.toString().endsWith("-SNAPSHOT")) snapshotRepositoryUrl
else releasesRepositoryUrl
)
*/
url = uri(releasesRepositoryUrl)
credentials {
username = nexusUsername
password = nexusPassword
}
}
} else {
logger.warn("No nexus repository is added; nexusUsername or nexusPassword is null.")
}
}
} }
} }

View File

@ -12,6 +12,7 @@ import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.provideDelegate import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.the import org.gradle.kotlin.dsl.the
import org.gradle.plugins.signing.SigningExtension
fun Project.applyPlatformAndCoreConfiguration() { fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration() applyCommonConfiguration()
@ -20,6 +21,7 @@ fun Project.applyPlatformAndCoreConfiguration() {
apply(plugin = "idea") apply(plugin = "idea")
apply(plugin = "maven-publish") apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "signing")
applyCommonJavaConfiguration( applyCommonJavaConfiguration(
sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit"), sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit"),
@ -45,6 +47,18 @@ fun Project.applyPlatformAndCoreConfiguration() {
skip() skip()
} }
val publishingExtension = the<PublishingExtension>()
configure<SigningExtension> {
if (!version.toString().endsWith("-SNAPSHOT")) {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
isRequired
sign(publishingExtension.publications)
}
}
configure<PublishingExtension> { configure<PublishingExtension> {
publications { publications {
register<MavenPublication>("maven") { register<MavenPublication>("maven") {
@ -99,33 +113,6 @@ fun Project.applyPlatformAndCoreConfiguration() {
} }
} }
} }
repositories {
mavenLocal()
val nexusUsername: String? by project
val nexusPassword: String? by project
if (nexusUsername != null && nexusPassword != null) {
maven {
val releasesRepositoryUrl = "https://mvn.intellectualsites.com/content/repositories/releases/"
val snapshotRepositoryUrl = "https://mvn.intellectualsites.com/content/repositories/snapshots/"
/* Commenting this out for now - Fawe currently does not user semver or any sort of versioning that
differentiates between snapshots and releases, API & (past) deployment wise, this will come with a next major release.
url = uri(
if (version.toString().endsWith("-SNAPSHOT")) snapshotRepositoryUrl
else releasesRepositoryUrl
)
*/
url = uri(releasesRepositoryUrl)
credentials {
username = nexusUsername
password = nexusPassword
}
}
} else {
logger.warn("No nexus repository is added; nexusUsername or nexusPassword is null.")
}
}
} }
if (name != "worldedit-fabric") { if (name != "worldedit-fabric") {

View File

@ -1,12 +1,12 @@
[versions] [versions]
# Minecraft expectations # Minecraft expectations
fastutil = "8.2.1" fastutil = "8.5.6"
log4j = "2.17.0" log4j = "2.17.1"
guava = "21.0" guava = "31.0.1-jre"
gson = "2.8.0" gson = "2.8.8"
# Platform expectations # Platform expectations
paper = "1.17.1-R0.1-SNAPSHOT" paper = "1.18.1-R0.1-SNAPSHOT"
# Plugins # Plugins
vault = "1.7.1" vault = "1.7.1"
@ -20,15 +20,14 @@ residence = "4.5._13.1"
towny = "0.97.5.0" towny = "0.97.5.0"
protocollib = "4.7.0" protocollib = "4.7.0"
plotsquaredV6 = "6.2.0" plotsquaredV6 = "6.2.0"
plotsquaredV4 = "4.514"
redprotect = "1.9.6" redprotect = "1.9.6"
# Third party # Third party
flow-math = "1.0.3" flow-math = "1.0.3"
paperlib = "1.0.7" paperlib = "1.0.8-SNAPSHOT"
bstats = "2.2.1" bstats = "2.2.1"
serverlib = "2.3.1" serverlib = "2.3.1"
paster = "1.1.1" paster = "1.1.3"
sparsebitset = "1.2" sparsebitset = "1.2"
parallelgzip = "1.0.5" parallelgzip = "1.0.5"
adventure = "4.9.3" adventure = "4.9.3"
@ -39,7 +38,6 @@ rhino-runtime = "1.7.13"
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
antlr4 = "4.9.3" antlr4 = "4.9.3"
json-simple = "1.1.1" json-simple = "1.1.1"
paranamer = "2.8"
jlibnoise = "1.0.0" jlibnoise = "1.0.0"
jchronic = "0.2.4a" jchronic = "0.2.4a"
lz4-java = "1.8.0" lz4-java = "1.8.0"
@ -81,7 +79,6 @@ towny = { group = "com.github.TownyAdvanced", name = "Towny", version.ref = "tow
protocollib = { group = "com.comphenix.protocol", name = "ProtocolLib", version.ref = "protocollib" } protocollib = { group = "com.comphenix.protocol", name = "ProtocolLib", version.ref = "protocollib" }
plotsquaredV6Bukkit = { group = "com.plotsquared", name = "PlotSquared-Bukkit", version.ref = "plotsquaredV6" } plotsquaredV6Bukkit = { group = "com.plotsquared", name = "PlotSquared-Bukkit", version.ref = "plotsquaredV6" }
plotsquaredV6Core = { group = "com.plotsquared", name = "PlotSquared-Core", version.ref = "plotsquaredV6" } plotsquaredV6Core = { group = "com.plotsquared", name = "PlotSquared-Core", version.ref = "plotsquaredV6" }
plotsquaredV4 = { group = "com.github.intellectualsites.plotsquared", name = "PlotSquared-API", version.ref = "plotsquaredV4" }
redprotect = { group = "net.fabiozumbi12", name = "redprotect", version.ref = "redprotect" } redprotect = { group = "net.fabiozumbi12", name = "redprotect", version.ref = "redprotect" }
# Third Party # Third Party
@ -104,7 +101,6 @@ zstd = { group = "com.github.luben", name = "zstd-jni", version.ref = "zstd-jni"
antlr4 = { group = "org.antlr", name = "antlr4", version.ref = "antlr4" } antlr4 = { group = "org.antlr", name = "antlr4", version.ref = "antlr4" }
antlr4Runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" } antlr4Runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" }
jsonSimple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" } jsonSimple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" }
paranamer = { group = "com.thoughtworks.paranamer", name = "paranamer", version.ref = "paranamer" }
jlibnoise = { group = "com.sk89q.lib", name = "jlibnoise", version.ref = "jlibnoise" } jlibnoise = { group = "com.sk89q.lib", name = "jlibnoise", version.ref = "jlibnoise" }
jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" } jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" }
lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" } lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" }

View File

@ -10,7 +10,6 @@
"mockito-core", "mockito-core",
"org.antlr", "org.antlr",
"antlr4-runtime", "antlr4-runtime",
"paranamer",
"fastutil", "fastutil",
"it.unimi.dsi:fastutil", "it.unimi.dsi:fastutil",
"auto-value-annotations", "auto-value-annotations",

View File

@ -4,6 +4,7 @@ include("worldedit-libs")
include("worldedit-bukkit:adapters:adapter-legacy") include("worldedit-bukkit:adapters:adapter-legacy")
include("worldedit-bukkit:adapters:adapter-1_17_1") include("worldedit-bukkit:adapters:adapter-1_17_1")
include("worldedit-bukkit:adapters:adapter-1_18")
listOf("bukkit", "core", "cli").forEach { listOf("bukkit", "core", "cli").forEach {
include("worldedit-libs:$it") include("worldedit-libs:$it")

View File

@ -1,21 +1,27 @@
applyPaperweightAdapterConfiguration()
plugins { plugins {
java java
} }
applyPaperweightAdapterConfiguration(
"1.17.1-R0.1-20211210.043523-198"
)
repositories { repositories {
mavenCentral()
maven { maven {
name = "PaperMC" name = "PaperMC"
url = uri("https://papermc.io/repo/repository/maven-public/") url = uri("https://papermc.io/repo/repository/maven-public/")
content {
includeModule("io.papermc", "paperlib")
}
} }
} }
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
dependencies { dependencies {
paperDevBundle("1.17.1-R0.1-20211219.175449-201")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.bukkit.adapter.ext.fawe; package com.sk89q.worldedit.bukkit.adapter.ext.fawe;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -35,8 +36,10 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
@ -53,6 +56,7 @@ import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.io.file.SafeFiles; import com.sk89q.worldedit.util.io.file.SafeFiles;
@ -168,11 +172,11 @@ import static com.google.common.base.Preconditions.checkState;
public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> { public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft.nbt.Tag> {
private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName());
private final Field serverWorldsField; private final Field worldsField;
private final Method getChunkFutureMethod; private final Method getChunkFutureMainThreadMethod;
private final Field chunkProviderExecutorField; private final Field mainThreadProcessorField;
private final Watchdog watchdog; private final Watchdog watchdog;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -188,18 +192,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
throw new UnsupportedClassVersionError("Not 1.17.1!"); throw new UnsupportedClassVersionError("Not 1.17.1!");
} }
serverWorldsField = CraftServer.class.getDeclaredField("worlds"); worldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true); worldsField.setAccessible(true);
getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread", getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread",
int.class, int.class, ChunkStatus.class, boolean.class int.class, int.class, ChunkStatus.class, boolean.class
); );
getChunkFutureMethod.setAccessible(true); getChunkFutureMainThreadMethod.setAccessible(true);
chunkProviderExecutorField = ServerChunkCache.class.getDeclaredField( mainThreadProcessorField = ServerChunkCache.class.getDeclaredField(
Refraction.pickName("mainThreadProcessor", "h") Refraction.pickName("mainThreadProcessor", "h")
); );
chunkProviderExecutorField.setAccessible(true); mainThreadProcessorField.setAccessible(true);
new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool()); new PaperweightDataConverters(CraftMagicNumbers.INSTANCE.getDataVersion(), this).build(ForkJoinPool.commonPool());
@ -316,9 +320,31 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId); return combinedId == 0 && state.getBlockType() != BlockTypes.AIR ? OptionalInt.empty() : OptionalInt.of(combinedId);
} }
@Deprecated
@Override @Override
public BaseBlock getBlock(Location location) { public BlockState getBlock(Location location) {
checkNotNull(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();
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);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(Location location) {
BlockState state = getBlock(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld()); CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX(); int x = location.getBlockX();
@ -328,19 +354,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
final ServerLevel handle = craftWorld.getHandle(); final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z); final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
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());
}
// Read the NBT data // Read the NBT data
BlockEntity te = chunk.getBlockEntity(blockPos); BlockEntity te = chunk.getBlockEntity(blockPos);
if (te != null) { if (te != null) {
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = te.save(new net.minecraft.nbt.CompoundTag());
readTileEntityIntoTag(te, tag); // Load data
//FAWE start - BinaryTag //FAWE start - BinaryTag
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag)); return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
//FAWE end //FAWE end
@ -418,7 +436,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, tag);
return new BaseEntity(com.sk89q.worldedit.world.entity.EntityTypes.get(id), (CompoundTag) toNative(tag)); //FAWE start - BinaryTag
return new BaseEntity(
com.sk89q.worldedit.world.entity.EntityTypes.get(id),
LazyReference.from(() -> (CompoundBinaryTag) toNativeBinary(tag))
);
//FAWE end
} }
@Nullable @Nullable
@ -500,7 +523,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) { } else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
property = new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues())); property = new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
} else { } else {
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName()); throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state.getClass().getSimpleName());
} }
properties.put(property.getName(), property); properties.put(property.getName(), property);
@ -650,7 +673,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
} finally { } finally {
try { try {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer()); Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) worldsField.get(Bukkit.getServer());
map.remove("worldeditregentempworld"); map.remove("worldeditregentempworld");
} catch (IllegalAccessException ignored) { } catch (IllegalAccessException ignored) {
} }
@ -723,7 +746,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld); List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld);
BlockableEventLoop<Runnable> executor; BlockableEventLoop<Runnable> executor;
try { try {
executor = (BlockableEventLoop<Runnable>) chunkProviderExecutorField.get(serverWorld.getChunkSource()); executor = (BlockableEventLoop<Runnable>) mainThreadProcessorField.get(serverWorld.getChunkSource());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new IllegalStateException("Couldn't get executor for chunk loading.", e); throw new IllegalStateException("Couldn't get executor for chunk loading.", e);
} }
@ -748,8 +771,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ()); BlockPos pos = new BlockPos(vec.getBlockX(), vec.getBlockY(), vec.getBlockZ());
ChunkAccess chunk = chunks.get(new ChunkPos(pos)); ChunkAccess chunk = chunks.get(new ChunkPos(pos));
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos);
int internalId = Block.getId(blockData); BlockStateHolder<?> state = ((PaperweightFaweAdapter) WorldEditPlugin
BlockStateHolder<?> state = BlockStateIdAccess.getBlockStateById(internalId); .getInstance()
.getBukkitImplAdapter()).adapt(blockData);
Objects.requireNonNull(state); Objects.requireNonNull(state);
BlockEntity blockEntity = chunk.getBlockEntity(pos); BlockEntity blockEntity = chunk.getBlockEntity(pos);
if (blockEntity != null) { if (blockEntity != null) {
@ -783,7 +807,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
//noinspection unchecked //noinspection unchecked
chunkLoadings.add( chunkLoadings.add(
((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>) ((CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>)
getChunkFutureMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true)) getChunkFutureMainThreadMethod.invoke(chunkManager, chunk.getX(), chunk.getZ(), ChunkStatus.FEATURES, true))
.thenApply(either -> either.left().orElse(null)) .thenApply(either -> either.left().orElse(null))
); );
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
@ -875,7 +899,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
try { try {
return toNativeList((net.minecraft.nbt.ListTag) foreign); return toNativeList((net.minecraft.nbt.ListTag) foreign);
} catch (Throwable e) { } catch (Throwable e) {
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e); LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
return ListBinaryTag.empty(); return ListBinaryTag.empty();
} }
} else if (foreign instanceof net.minecraft.nbt.LongTag) { } else if (foreign instanceof net.minecraft.nbt.LongTag) {
@ -994,7 +1018,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
WatchdogThread.tick(); WatchdogThread.tick();
} }
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
logger.log(Level.WARNING, "Failed to tick watchdog", e); LOGGER.log(Level.WARNING, "Failed to tick watchdog", e);
} }
} }

View File

@ -11,8 +11,6 @@ import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
@ -40,6 +38,9 @@ import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -230,9 +231,29 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource())); return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
} }
@SuppressWarnings("deprecation") @Deprecated
@Override @Override
public BaseBlock getBlock(Location location) { 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();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location); Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld()); CraftWorld craftWorld = ((CraftWorld) location.getWorld());
@ -240,19 +261,22 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
int y = location.getBlockY(); int y = location.getBlockY();
int z = location.getBlockZ(); int z = location.getBlockZ();
final ServerLevel serverLevel = craftWorld.getHandle(); final ServerLevel handle = craftWorld.getHandle();
LevelChunk levelChunk = serverLevel.getChunk(x >> 4, z >> 4); LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z); final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock(); org.bukkit.block.Block bukkitBlock = location.getBlock();
BlockState state = BukkitAdapter.adapt(bukkitBlock.getBlockData()); state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
if (state.getBlockType().getMaterial().hasContainer()) { if (state.getBlockType().getMaterial().hasContainer()) {
// Read the NBT data // Read the NBT data
BlockEntity blockEntity = levelChunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) { if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); net.minecraft.nbt.CompoundTag tag = blockEntity.save(new net.minecraft.nbt.CompoundTag());
blockEntity.save(tag); // readTileEntityIntoTag - load data return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
return state.toBaseBlock((CompoundTag) toNative(tag));
} }
} }
@ -284,7 +308,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundTag compoundTag = state instanceof BaseBlock ? state.getNbtData() : null; CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) { if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0); level.setBlock(blockPos, blockState, 0);
// remove tile // remove tile
@ -293,7 +317,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
// though we do not do this on the Forge version // though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos); BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) { if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNative(compoundTag); net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x)); tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y)); tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z)); tag.put("z", IntTag.valueOf(z));
@ -337,14 +361,15 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
if (id != null) { if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> { Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag(); final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
final CompoundTag tag = (CompoundTag) toNative(minecraftTag); final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue()); final Map<String, BinaryTag> tags = new HashMap<>();
tags.put("Id", new StringTag(id)); tag.keySet().forEach(key -> tags.put(key, tag.get(key)));
return new CompoundTag(tags); tags.put("Id", StringBinaryTag.of(id));
return CompoundBinaryTag.from(tags);
}; };
return new LazyBaseEntity(type, saveTag); return new LazyBaseEntity(type, saveTag);
} else { } else {
@ -401,7 +426,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!", LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1 blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
); );
return 0; return BlockTypesCache.ReservedIDs.AIR;
} }
} }
} }
@ -486,10 +511,10 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
chunkPacket.setNativePacket(nmsPacket); chunkPacket.setNativePacket(nmsPacket);
} }
try { try {
FaweCache.IMP.CHUNK_FLAG.get().set(true); FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
entityPlayer.connection.send(nmsPacket); entityPlayer.connection.send(nmsPacket);
} finally { } finally {
FaweCache.IMP.CHUNK_FLAG.get().set(false); FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
} }
} }
}); });
@ -517,7 +542,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())), Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount() baseItemStack.getAmount()
); );
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData()))); stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt())));
return CraftItemStack.asCraftMirror(stack); return CraftItemStack.asCraftMirror(stack);
} }
@ -579,7 +604,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) { public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount()); final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
weStack.setNbtData(((CompoundTag) toNative(nmsStack.getTag()))); weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack; return weStack;
} }

View File

@ -250,7 +250,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
} }
} }
}; };
TaskManager.IMP.async(() -> TaskManager.IMP.sync(runnableVal)); TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
} }
@Override @Override
@ -269,27 +269,17 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
if (Fawe.isMainThread()) { if (Fawe.isMainThread()) {
runnableVal.run(); runnableVal.run();
} else { } else {
TaskManager.IMP.sync(runnableVal); TaskManager.taskManager().sync(runnableVal);
} }
cachedChanges.clear(); cachedChanges.clear();
cachedChunksToSend.clear(); cachedChunksToSend.clear();
} }
private static final class CachedChange { private record CachedChange(
private final LevelChunk levelChunk;
private final BlockPos blockPos;
private final net.minecraft.world.level.block.state.BlockState blockState;
private CachedChange(
LevelChunk levelChunk, LevelChunk levelChunk,
BlockPos blockPos, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState net.minecraft.world.level.block.state.BlockState blockState
) { ) {
this.levelChunk = levelChunk;
this.blockPos = blockPos;
this.blockState = blockState;
}
} }

View File

@ -25,7 +25,7 @@ import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import io.papermc.paper.event.block.BeaconDeactivatedEvent; import io.papermc.paper.event.block.BeaconDeactivatedEvent;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -151,7 +151,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (light != null) { if (light != null) {
lightUpdate = true; lightUpdate = true;
try { try {
fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition); fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -419,7 +419,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
try { try {
ServerLevel nmsWorld = serverLevel; ServerLevel nmsWorld = serverLevel;
LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE; boolean fastmode = set.isFastMode() && Settings.settings().QUEUE.NO_TICK_FASTMODE;
// Remove existing tiles. Create a copy so that we can remove blocks // Remove existing tiles. Create a copy so that we can remove blocks
Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities());
@ -546,17 +546,21 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
// Biomes // Biomes
BiomeType[] biomes = set.getBiomes(); BiomeType[][] biomes = set.getBiomes();
if (biomes != null) { if (biomes != null) {
// set biomes // set biomes
ChunkBiomeContainer currentBiomes = nmsChunk.getBiomes(); ChunkBiomeContainer currentBiomes = nmsChunk.getBiomes();
if (createCopy) { if (createCopy) {
copy.storeBiomes(currentBiomes); copy.storeBiomes(currentBiomes);
} }
for (int y = 0, i = 0; y < 64; y++) { 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 z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, i++) { for (int x = 0; x < 4; x++, i++) {
final BiomeType biome = biomes[i]; final BiomeType biome = biomes[layer][i];
if (biome != null) { if (biome != null) {
Biome nmsBiome = Biome nmsBiome =
nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get( nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get(
@ -564,7 +568,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (nmsBiome == null) { if (nmsBiome == null) {
throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId()); throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId());
} }
currentBiomes.setBiome(x, y, z, nmsBiome); currentBiomes.setBiome(x, (layer << 2) + y, z, nmsBiome);
}
} }
} }
} }
@ -722,7 +727,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
nmsChunk.mustNotSave = false; nmsChunk.mustNotSave = false;
nmsChunk.markUnsaved(); nmsChunk.markUnsaved();
// send to player // send to player
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING) {
this.send(finalMask, finalLightUpdate); this.send(finalMask, finalLightUpdate);
} }
if (finalizer != null) { if (finalizer != null) {
@ -731,7 +736,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
}; };
} }
if (syncTasks != null) { if (syncTasks != null) {
QueueHandler queueHandler = Fawe.get().getQueueHandler(); QueueHandler queueHandler = Fawe.instance().getQueueHandler();
Runnable[] finalSyncTasks = syncTasks; Runnable[] finalSyncTasks = syncTasks;
// Chain the sync tasks and the callback // Chain the sync tasks and the callback
@ -756,6 +761,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
throw e; throw e;
} }
}; };
//noinspection unchecked - required at compile time
return (T) (Future) queueHandler.sync(chain); return (T) (Future) queueHandler.sync(chain);
} else { } else {
if (callback == null) { if (callback == null) {
@ -840,16 +846,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
// Section is null, return empty array // Section is null, return empty array
if (section == null) { if (section == null) {
data = new char[4096]; data = new char[4096];
Arrays.fill(data, (char) 1); Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
return data; return data;
} }
if (data != null && data.length != 4096) { if (data != null && data.length != 4096) {
data = new char[4096]; data = new char[4096];
Arrays.fill(data, (char) 1); Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
} }
if (data == null || data == FaweCache.IMP.EMPTY_CHAR_4096) { if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) {
data = new char[4096]; data = new char[4096];
Arrays.fill(data, (char) 1); Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
} }
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section); DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section);
synchronized (lock) { synchronized (lock) {
@ -874,13 +880,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char paletteVal = data[i]; char paletteVal = data[i];
char ordinal = adapter.ibdIDToOrdinal(paletteVal); char ordinal = adapter.ibdIDToOrdinal(paletteVal);
// Don't read "empty". data[i] = ordinal;
data[i] = ordinal == 0 ? 1 : ordinal;
} }
return data; return data;
} }
char[] paletteToOrdinal = FaweCache.IMP.PALETTE_TO_BLOCK_CHAR.get(); char[] paletteToOrdinal = FaweCache.INSTANCE.PALETTE_TO_BLOCK_CHAR.get();
try { try {
if (num_palette != 1) { if (num_palette != 1) {
for (int i = 0; i < num_palette; i++) { for (int i = 0; i < num_palette; i++) {
@ -894,18 +899,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
val = ordinal(palette.valueFor(i), adapter); val = ordinal(palette.valueFor(i), adapter);
paletteToOrdinal[i] = val; paletteToOrdinal[i] = val;
} }
// Don't read "empty".
if (val == 0) {
val = 1;
}
data[i] = val; data[i] = val;
} }
} else { } else {
char ordinal = ordinal(palette.valueFor(0), adapter); char ordinal = ordinal(palette.valueFor(0), adapter);
// Don't read "empty".
if (ordinal == 0) {
ordinal = 1;
}
Arrays.fill(data, ordinal); Arrays.fill(data, ordinal);
} }
} finally { } finally {
@ -925,7 +922,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
private char ordinal(net.minecraft.world.level.block.state.BlockState ibd, PaperweightFaweAdapter adapter) { private char ordinal(net.minecraft.world.level.block.state.BlockState ibd, PaperweightFaweAdapter adapter) {
if (ibd == null) { if (ibd == null) {
return BlockTypes.AIR.getDefaultState().getOrdinalChar(); return BlockTypesCache.ReservedIDs.AIR;
} else { } else {
return adapter.adaptToChar(ibd); return adapter.adaptToChar(ibd);
} }

View File

@ -86,7 +86,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
private static final long fieldLockOffset; private static final long fieldLockOffset;
private static final Field fieldGameEventDispatcherSections; private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveTickingBlockEntity; private static final MethodHandle methodremoveBlockEntityTicker;
private static final Field fieldRemove; private static final Field fieldRemove;
@ -133,7 +133,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
), BlockPos.class ), BlockPos.class
); );
removeBlockEntityTicker.setAccessible(true); removeBlockEntityTicker.setAccessible(true);
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker); methodremoveBlockEntityTicker = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p")); fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true); fieldRemove.setAccessible(true);
@ -215,7 +215,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
e.printStackTrace(); e.printStackTrace();
} }
} }
return TaskManager.IMP.sync(() -> serverLevel.getChunk(chunkX, chunkZ)); return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
} }
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
@ -247,7 +247,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
return; return;
} }
LevelChunk levelChunk = optional.get(); LevelChunk levelChunk = optional.get();
TaskManager.IMP.task(() -> { TaskManager.taskManager().task(() -> {
ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk); ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk);
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket)); nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket));
if (lighting) { if (lighting) {
@ -283,10 +283,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
if (set == null) { if (set == null) {
return newChunkSection(layer); return newChunkSection(layer);
} }
final int[] blockToPalette = FaweCache.IMP.BLOCK_TO_PALETTE.get(); final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
final int[] paletteToBlock = FaweCache.IMP.PALETTE_TO_BLOCK.get(); final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
final long[] blockStates = FaweCache.IMP.BLOCK_STATES.get(); final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get();
final int[] blocksCopy = FaweCache.IMP.SECTION_BLOCKS.get(); final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get();
try { try {
int[] num_palette_buffer = new int[1]; int[] num_palette_buffer = new int[1];
Map<BlockVector3, Integer> ticking_blocks = new HashMap<>(); Map<BlockVector3, Integer> ticking_blocks = new HashMap<>();
@ -303,7 +303,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
int num_palette = num_palette_buffer[0]; int num_palette = num_palette_buffer[0];
// BlockStates // BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1); int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) { if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else { } else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
@ -440,7 +440,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
fieldRemove.set(beacon, true); fieldRemove.set(beacon, true);
} }
} }
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos()); methodremoveBlockEntityTicker.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) { } catch (Throwable throwable) {
throwable.printStackTrace(); throwable.printStackTrace();
} }

View File

@ -129,7 +129,7 @@ public class PaperweightStarlightRelighter implements Relighter {
while (iterator.hasNext()) { while (iterator.hasNext()) {
coords.add(new ChunkPos(iterator.nextLong())); coords.add(new ChunkPos(iterator.nextLong()));
} }
TaskManager.IMP.task(() -> { TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread // trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>(); List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) { for (ChunkPos pos : coords) {
@ -153,9 +153,9 @@ public class PaperweightStarlightRelighter implements Relighter {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
} }
// post process chunks on main thread // post process chunks on main thread
TaskManager.IMP.task(() -> postProcessChunks(coords)); TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads // call callback on our own threads
TaskManager.IMP.async(andThen); TaskManager.taskManager().async(andThen);
} }
) )
); );
@ -184,7 +184,7 @@ public class PaperweightStarlightRelighter implements Relighter {
* Also, if chunk packets are sent delayed, we need to do that here * Also, if chunk packets are sent delayed, we need to do that here
*/ */
private void postProcessChunks(Set<ChunkPos> coords) { private void postProcessChunks(Set<ChunkPos> coords) {
boolean delay = Settings.IMP.LIGHTING.DELAY_PACKET_SENDING; boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
for (ChunkPos pos : coords) { for (ChunkPos pos : coords) {
int x = pos.x; int x = pos.x;
int z = pos.z; int z = pos.z;

View File

@ -66,8 +66,8 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
public double asDouble(String key) { public double asDouble(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag) { if (tag instanceof NumericTag numTag) {
return ((NumericTag) tag).getAsDouble(); return numTag.getAsDouble();
} }
return 0; return 0;
} }
@ -86,20 +86,19 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
public int asInt(String key) { public int asInt(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag) { if (tag instanceof NumericTag numTag) {
return ((NumericTag) tag).getAsInt(); return numTag.getAsInt();
} }
return 0; return 0;
} }
public List<Tag> getList(String key) { public List<Tag> getList(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag) { if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
ArrayList<Tag> list = new ArrayList<>(); ArrayList<Tag> list = new ArrayList<>();
net.minecraft.nbt.ListTag nbtList = (net.minecraft.nbt.ListTag) tag;
for (net.minecraft.nbt.Tag elem : nbtList) { for (net.minecraft.nbt.Tag elem : nbtList) {
if (elem instanceof net.minecraft.nbt.CompoundTag) { if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
list.add(new PaperweightLazyCompoundTag((net.minecraft.nbt.CompoundTag) elem)); list.add(new PaperweightLazyCompoundTag(compoundTag));
} else { } else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem)); list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
} }
@ -137,8 +136,8 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
public long asLong(String key) { public long asLong(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key); net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag) { if (tag instanceof NumericTag numTag) {
return ((NumericTag) tag).getAsLong(); return numTag.getAsLong();
} }
return 0; return 0;
} }

View File

@ -90,13 +90,13 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field serverWorldsField; private static final Field worldsField;
private static final Field worldPaperConfigField; private static final Field paperConfigField;
private static final Field flatBedrockField; private static final Field generateFlatBedrockField;
private static final Field generatorSettingFlatField; private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField; private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField; private static final Field delegateField;
private static final Field chunkProviderField; private static final Field chunkSourceField;
//list of chunk stati in correct order without FULL //list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>(); private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
@ -125,8 +125,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try { try {
serverWorldsField = CraftServer.class.getDeclaredField("worlds"); worldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true); worldsField.setAccessible(true);
Field tmpPaperConfigField; Field tmpPaperConfigField;
Field tmpFlatBedrockField; Field tmpFlatBedrockField;
@ -140,8 +140,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
tmpPaperConfigField = null; tmpPaperConfigField = null;
tmpFlatBedrockField = null; tmpFlatBedrockField = null;
} }
worldPaperConfigField = tmpPaperConfigField; paperConfigField = tmpPaperConfigField;
flatBedrockField = tmpFlatBedrockField; generateFlatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "g")); "settings", "g"));
@ -153,8 +153,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true); delegateField.setAccessible(true);
chunkProviderField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C")); chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C"));
chunkProviderField.setAccessible(true); chunkSourceField.setAccessible(true);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -187,9 +187,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
//flat bedrock? (only on paper) //flat bedrock? (only on paper)
if (worldPaperConfigField != null) { if (paperConfigField != null) {
try { try {
generateFlatBedrock = flatBedrockField.getBoolean(worldPaperConfigField.get(originalServerWorld)); generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
@ -210,7 +210,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator(); org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir); LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment); ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
session = levelStorageSource.createAccess("worldeditregentempworld", levelStemResourceKey); session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData; PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
MinecraftServer server = originalServerWorld.getCraftServer().getServer(); MinecraftServer server = originalServerWorld.getCraftServer().getServer();
@ -221,7 +221,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
? PaperweightAdapter.replaceSeed(originalServerWorld, seed, originalOpts) ? PaperweightAdapter.replaceSeed(originalServerWorld, seed, originalOpts)
: originalOpts; : originalOpts;
LevelSettings newWorldSettings = new LevelSettings( LevelSettings newWorldSettings = new LevelSettings(
"worldeditregentempworld", "faweregentempworld",
originalWorldData.settings.gameType(), originalWorldData.settings.gameType(),
originalWorldData.settings.hardcore(), originalWorldData.settings.hardcore(),
originalWorldData.settings.difficulty(), originalWorldData.settings.difficulty(),
@ -232,7 +232,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable()); PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
//init world //init world
freshWorld = Fawe.get().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel( freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
server, server,
server.executor, server.executor,
session, session,
@ -270,8 +270,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
freshWorld.noSave = true; freshWorld.noSave = true;
removeWorldFromWorldsMap(); removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (worldPaperConfigField != null) { if (paperConfigField != null) {
worldPaperConfigField.set(freshWorld, originalServerWorld.paperConfig); paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
} }
//generator //generator
@ -319,7 +319,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
}; };
ReflectionUtils.unsafeSet(chunkProviderField, freshWorld, freshChunkProvider); ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
//let's start then //let's start then
structureManager = server.getStructureManager(); structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine(); threadedLevelLightEngine = freshChunkProvider.getLightEngine();
@ -336,7 +336,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
//shutdown chunk provider //shutdown chunk provider
try { try {
Fawe.get().getQueueHandler().sync(() -> { Fawe.instance().getQueueHandler().sync(() -> {
try { try {
freshChunkProvider.close(false); freshChunkProvider.close(false);
} catch (IOException e) { } catch (IOException e) {
@ -348,7 +348,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
//remove world from server //remove world from server
try { try {
Fawe.get().getQueueHandler().sync(this::removeWorldFromWorldsMap); Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@ -388,7 +388,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
@Override @Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access // BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.IMP.task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
} }
@Override @Override
@ -403,10 +403,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
//util //util
private void removeWorldFromWorldsMap() { private void removeWorldFromWorldsMap() {
Fawe.get().getQueueHandler().sync(() -> { Fawe.instance().getQueueHandler().sync(() -> {
try { try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer()); Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) worldsField.get(Bukkit.getServer());
map.remove("worldeditregentempworld"); map.remove("faweregentempworld");
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -414,15 +414,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
} }
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) { private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
switch (env) { return switch (env) {
case NETHER: case NETHER -> LevelStem.NETHER;
return LevelStem.NETHER; case THE_END -> LevelStem.END;
case THE_END: default -> LevelStem.OVERWORLD;
return LevelStem.END; };
case NORMAL:
default:
return LevelStem.OVERWORLD;
}
} }
private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception { private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception {

View File

@ -0,0 +1,17 @@
plugins {
java
}
applyPaperweightAdapterConfiguration()
repositories {
maven {
name = "PaperMC"
url = uri("https://papermc.io/repo/repository/maven-public/")
}
}
dependencies {
paperDevBundle("1.18.1-R0.1-20211221.093324-19")
compileOnly(libs.paperlib)
}

View File

@ -0,0 +1,103 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R1;
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.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stat;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.OptionalInt;
import java.util.UUID;
class PaperweightFakePlayer extends ServerPlayer {
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
UUID.nameUUIDFromBytes("worldedit".getBytes()),
"[WorldEdit]"
);
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
PaperweightFakePlayer(ServerLevel world) {
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
}
@Override
public Vec3 position() {
return ORIGIN;
}
@Override
public void tick() {
}
@Override
public void die(DamageSource damagesource) {
}
@Override
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
return this;
}
@Override
public OptionalInt openMenu(MenuProvider factory) {
return OptionalInt.empty();
}
@Override
public void updateOptions(ServerboundClientInformationPacket packet) {
}
@Override
public void displayClientMessage(Component message, boolean actionBar) {
}
@Override
public void sendMessage(Component message, ChatType type, UUID sender) {
}
@Override
public void awardStat(Stat<?> stat, int amount) {
}
@Override
public void awardStat(Stat<?> stat) {
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return true;
}
@Override
public void openTextEdit(SignBlockEntity sign) {
}
}

View File

@ -0,0 +1,209 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R1;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Objects;
public class PaperweightWorldNativeAccess implements
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private final PaperweightAdapter adapter;
private final WeakReference<ServerLevel> world;
private SideEffectSet sideEffectSet;
public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference<ServerLevel> world) {
this.adapter = adapter;
this.world = world;
}
private ServerLevel getWorld() {
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getWorld().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state);
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) {
return chunk.getBlockState(position);
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState state
) {
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState block,
BlockPos position
) {
return Block.updateFromNeighbourShapes(block, getWorld(), position);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos position) {
getWorld().getChunkSource().getLightEngine().checkBlock(position);
}
@Override
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
return false;
}
@Override
public void notifyBlockUpdate(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk chunk) {
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk chunk, BlockPos position) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().getChunkSource().blockChanged(position);
}
}
@Override
public void notifyNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
ServerLevel world = getWorld();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
world.updateNeighborsAt(pos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
Block block = oldState.getBlock();
fireNeighborChanged(pos, world, block, pos.west());
fireNeighborChanged(pos, world, block, pos.east());
fireNeighborChanged(pos, world, block, pos.below());
fireNeighborChanged(pos, world, block, pos.above());
fireNeighborChanged(pos, world, block, pos.north());
fireNeighborChanged(pos, world, block, pos.south());
}
if (newState.hasAnalogOutputSignal()) {
world.updateNeighbourForOutputSignal(pos, newState.getBlock());
}
}
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
}
@Override
public void updateNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
ServerLevel world = getWorld();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = world.getWorld();
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
CraftBlockData.fromData(newState)
);
world.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getWorld().onBlockStateChange(pos, oldState, newState);
}
@Override
public void flush() {
}
}

View File

@ -0,0 +1,189 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block;
private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial;
private final int opacity;
private final CompoundTag tile;
public PaperweightBlockMaterial(Block block) {
this(block, block.defaultBlockState());
}
public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block;
this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aP"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO,
blockState
);
tile = tileEntity == null
? null
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
}
public Block getBlock() {
return block;
}
public BlockState getState() {
return blockState;
}
public CraftBlockData getCraftBlockData() {
return craftBlockData;
}
public Material getMaterial() {
return material;
}
@Override
public boolean isAir() {
return blockState.isAir();
}
@Override
public boolean isFullCube() {
return craftMaterial.isOccluding();
}
@Override
public boolean isOpaque() {
return material.isSolidBlocking();
}
@Override
public boolean isPowerSource() {
return blockState.isSignalSource();
}
@Override
public boolean isLiquid() {
return material.isLiquid();
}
@Override
public boolean isSolid() {
return material.isSolid();
}
@Override
public float getHardness() {
return craftBlockData.getState().destroySpeed;
}
@Override
public float getResistance() {
return block.getExplosionResistance();
}
@Override
public float getSlipperiness() {
return block.getFriction();
}
@Override
public int getLightValue() {
return blockState.getLightEmission();
}
@Override
public int getLightOpacity() {
return opacity;
}
@Override
public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY;
}
@Override
public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK;
}
@Override
public boolean isTicksRandomly() {
return block.isRandomlyTicking(blockState);
}
@Override
public boolean isMovementBlocker() {
return material.isSolid();
}
@Override
public boolean isBurnable() {
return material.isFlammable();
}
@Override
public boolean isToolRequired() {
// Removed in 1.16.1, this is not present in higher versions
return false;
}
@Override
public boolean isReplacedDuringPlacement() {
return material.isReplaceable();
}
@Override
public boolean isTranslucent() {
return isTranslucent;
}
@Override
public boolean hasContainer() {
return block instanceof EntityBlock;
}
@Override
public boolean isTile() {
return block instanceof EntityBlock;
}
@Override
public CompoundTag getDefaultTile() {
return tile;
}
@Override
public int getMapColor() {
// rgb field
return material.getColor().col;
}
}

View File

@ -0,0 +1,689 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
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_R1.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.regen.PaperweightRegen;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.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 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.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
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.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_18_R1.CraftServer;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R1.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
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> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final PaperweightAdapter parent;
// ------------------------------------------------------------------------
// Code that may break between versions of Minecraft
// ------------------------------------------------------------------------
private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil();
private char[] ibdToStateOrdinal = null;
private int[] ordinalToIbdID = null;
private boolean initialised = false;
private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter();
}
@Nullable
private static String getEntityId(Entity entity) {
ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType());
return resourceLocation == null ? null : resourceLocation.toString();
}
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent;
}
private synchronized boolean init() {
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false;
}
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState blockState = BlockTypesCache.states[i];
PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial();
int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState());
char ordinal = blockState.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
}
Map<String, List<Property<?>>> properties = new HashMap<>();
try {
for (Field field : BlockStateProperties.class.getDeclaredFields()) {
Object obj = field.get(null);
if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property<?> state)) {
continue;
}
Property<?> property;
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
property = new BooleanProperty(
state.getName(),
(List<Boolean>) ImmutableList.copyOf(state.getPossibleValues())
);
} else if (state instanceof DirectionProperty) {
property = new DirectionalProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase()))
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
property = new EnumProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> ((StringRepresentable) e).getSerializedName())
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
property = new IntegerProperty(
state.getName(),
(List<Integer>) ImmutableList.copyOf(state.getPossibleValues())
);
} else {
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state
.getClass()
.getSimpleName());
}
properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> {
if (v == null) {
v = new ArrayList<>(Collections.singletonList(property));
} else {
v.add(property);
}
return v;
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
allBlockProperties = ImmutableMap.copyOf(properties);
}
initialised = true;
return true;
}
@Override
public BlockMaterial getMaterial(BlockType blockType) {
Block block = getBlock(blockType);
return new PaperweightBlockMaterial(block);
}
@Override
public synchronized BlockMaterial getMaterial(BlockState state) {
net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
return new PaperweightBlockMaterial(blockState.getBlock(), blockState);
}
public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
}
@Deprecated
@Override
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();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location);
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 net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
if (state.getBlockType().getMaterial().hasContainer()) {
// Read the NBT data
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
}
}
return state.toBaseBlock();
}
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
}
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess(
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
}
@Override
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
Preconditions.checkNotNull(entity);
CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle();
String id = getEntityId(mcEntity);
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = new HashMap<>();
tag.keySet().forEach(key -> tags.put(key, tag.get(key)));
tags.put("Id", StringBinaryTag.of(id));
return CompoundBinaryTag.from(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
return null;
}
}
@Override
public Component getRichBlockName(BlockType blockType) {
return parent.getRichBlockName(blockType);
}
@Override
public Component getRichItemName(ItemType itemType) {
return parent.getRichItemName(itemType);
}
@Override
public Component getRichItemName(BaseItemStack itemStack) {
return parent.getRichItemName(itemStack);
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState();
return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState));
}
@Override
public BlockState adapt(BlockData blockData) {
CraftBlockData cbd = ((CraftBlockData) blockData);
net.minecraft.world.level.block.state.BlockState ibd = cbd.getState();
return adapt(ibd);
}
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
return BlockTypesCache.states[adaptToChar(blockState)];
}
public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) {
int id = Block.BLOCK_STATE_REGISTRY.getId(blockState);
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
try {
init();
return ibdToStateOrdinal[id];
} catch (ArrayIndexOutOfBoundsException e1) {
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
);
return BlockTypesCache.ReservedIDs.AIR;
}
}
}
public char ibdIDToOrdinal(int id) {
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
init();
return ibdToStateOrdinal[id];
}
}
@Override
public char[] getIbdToStateOrdinal() {
if (initialised) {
return ibdToStateOrdinal;
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal;
}
init();
return ibdToStateOrdinal;
}
}
public int ordinalToIbdID(char ordinal) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
init();
return ordinalToIbdID[ordinal];
}
}
@Override
public int[] getOrdinalToIbdID() {
if (initialised) {
return ordinalToIbdID;
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID;
}
init();
return ordinalToIbdID;
}
}
@Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
return material.getCraftBlockData();
}
@Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle();
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) {
boolean flag = false;
// PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
*/ Stream.empty();
ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle();
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
.forEach(entityPlayer -> {
synchronized (chunkPacket) {
ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
if (nmsPacket == null) {
nmsPacket = mapUtil.create(this, chunkPacket);
chunkPacket.setNativePacket(nmsPacket);
}
try {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
entityPlayer.connection.send(nmsPacket);
} finally {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
}
}
});
}
}
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
return getParent().getProperties(blockType);
}
@Override
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
);
}
@Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount()
);
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();
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true;
boolean grownTree = bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, blockVector3), bukkitType);
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
if (!grownTree) {
serverLevel.capturedBlockStates.clear();
return false;
} else {
for (CraftBlockState craftBlockState : serverLevel.capturedBlockStates.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())
);
}
serverLevel.capturedBlockStates.clear();
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;
}
@Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack;
}
@Override
public Tag toNative(net.minecraft.nbt.Tag foreign) {
return parent.toNative(foreign);
}
@Override
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
if (foreign instanceof PaperweightLazyCompoundTag) {
return ((PaperweightLazyCompoundTag) foreign).get();
}
return parent.fromNative(foreign);
}
@Override
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
}
@Override
public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) {
return new PaperweightGetBlocks(world, chunkX, chunkZ);
}
@Override
public int getInternalBiomeId(BiomeType biomeType) {
if (biomeType.getId().startsWith("minecraft:")) {
Biome biomeBase = CraftBlock.biomeToBiomeBase(
MinecraftServer.getServer().registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY),
BukkitAdapter.adapt(biomeType)
);
return MinecraftServer.getServer().registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getId(biomeBase);
} else {
WritableRegistry<Biome> biomeRegistry = MinecraftServer.getServer().registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
ResourceLocation resourceLocation = biomeRegistry.keySet().stream()
.filter(resource -> resource.toString().equals(biomeType.getId()))
.findAny().orElse(null);
return biomeRegistry.getId(biomeRegistry.get(resourceLocation));
}
}
@Override
public Iterable<NamespacedKey> getRegisteredBiomes() {
WritableRegistry<Biome> biomeRegistry = ((CraftServer) Bukkit.getServer())
.getServer()
.registryAccess()
.ownedRegistryOrThrow(
Registry.BIOME_REGISTRY);
return biomeRegistry.stream()
.map(biomeRegistry::getKey)
.map(CraftNamespacedKey::fromMinecraft)
.collect(Collectors.toList());
}
@Override
public RelighterFactory getRelighterFactory() {
try {
Class.forName("ca.spottedleaf.starlight.common.light.StarLightEngine");
if (PaperweightStarlightRelighter.isUsable()) {
return new PaperweightStarlightRelighterFactory();
}
} catch (ThreadDeath td) {
throw td;
} catch (Throwable ignored) {
}
return new NMSRelighterFactory();
}
@Override
public Map<String, List<Property<?>>> getAllProperties() {
if (initialised) {
return allBlockProperties;
}
synchronized (this) {
if (initialised) {
return allBlockProperties;
}
init();
return allBlockProperties;
}
}
}

View File

@ -0,0 +1,286 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.task.RunnableVal;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private static final Direction[] NEIGHBOUR_ORDER = {
Direction.EAST,
Direction.WEST,
Direction.DOWN,
Direction.UP,
Direction.NORTH,
Direction.SOUTH
};
private final PaperweightFaweAdapter paperweightFaweAdapter;
private final WeakReference<Level> level;
private final AtomicInteger lastTick;
private final Set<CachedChange> cachedChanges = new HashSet<>();
private final Set<IntPair> cachedChunksToSend = new HashSet<>();
private SideEffectSet sideEffectSet;
public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference<Level> level) {
this.paperweightFaweAdapter = paperweightFaweAdapter;
this.level = level;
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
}
private Level getLevel() {
return Objects.requireNonNull(level.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getLevel().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) {
int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) {
return levelChunk.getBlockState(blockPos);
}
@Nullable
@Override
public synchronized net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
}
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) {
lastTick.set(currentTick);
}
flushAsync(nextTick);
}
return blockState;
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState blockState,
BlockPos blockPos
) {
return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos blockPos) {
getLevel().getChunkSource().getLightEngine().checkBlock(blockPos);
}
@Override
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
// We will assume that the tile entity was created for us,
// though we do not do this on the other versions
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
if (blockEntity == null) {
return false;
}
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
blockEntity.load((CompoundTag) nativeTag);
return true;
}
@Override
public void notifyBlockUpdate(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos);
}
}
@Override
public void notifyNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
Level level = getLevel();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
level.blockUpdated(blockPos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
// Un-nest neighbour updating
for (Direction direction : NEIGHBOUR_ORDER) {
BlockPos shifted = blockPos.relative(direction);
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
}
}
if (newState.hasAnalogOutputSignal()) {
level.updateNeighbourForOutputSignal(blockPos, newState.getBlock());
}
}
@Override
public void updateNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
Level level = getLevel();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = level.getWorld();
if (craftWorld != null) {
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
CraftBlockData.fromData(newState)
);
level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
}
newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getLevel().onBlockStateChange(blockPos, oldState, newState);
}
private synchronized void flushAsync(final boolean sendChunks) {
final Set<CachedChange> changes = Set.copyOf(cachedChanges);
cachedChanges.clear();
final Set<IntPair> toSend;
if (sendChunks) {
toSend = Set.copyOf(cachedChunksToSend);
cachedChunksToSend.clear();
} else {
toSend = Collections.emptySet();
}
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
if (!sendChunks) {
return;
}
for (IntPair chunk : toSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x, chunk.z, false);
}
}
};
TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
}
@Override
public synchronized void flush() {
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
for (IntPair chunk : cachedChunksToSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x, chunk.z, false);
}
}
};
if (Fawe.isMainThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
}
cachedChanges.clear();
cachedChunksToSend.clear();
}
private record CachedChange(
LevelChunk levelChunk,
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
}
}

View File

@ -0,0 +1,240 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.nbt.PaperweightLazyCompoundTag;
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.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.PalettedContainer;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet {
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks;
private final int minHeight;
private final int maxHeight;
private final ServerLevel serverLevel;
private PalettedContainer<Biome>[] biomes = null;
protected PaperweightGetBlocks_Copy(ServerLevel world) {
this.serverLevel = world;
this.minHeight = world.getMinBuildHeight();
this.maxHeight = world.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive.
this.blocks = new char[getSectionCount()][];
}
protected void storeTile(BlockEntity blockEntity) {
tiles.put(
BlockVector3.at(
blockEntity.getBlockPos().getX(),
blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ()
),
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
);
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return tiles;
}
@Override
@Nullable
public CompoundTag getTile(int x, int y, int z) {
return tiles.get(BlockVector3.at(x, y, z));
}
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
entities.add((CompoundTag) adapter.toNative(entity.save(compoundTag)));
}
@Override
public Set<CompoundTag> getEntities() {
return this.entities;
}
@Override
public CompoundTag getEntity(UUID uuid) {
for (CompoundTag tag : entities) {
UUID tagUUID;
if (tag.containsKey("UUID")) {
int[] arr = tag.getIntArray("UUID");
tagUUID = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
} else if (tag.containsKey("UUIDMost")) {
tagUUID = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
} else if (tag.containsKey("PersistentIDMSB")) {
tagUUID = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
} else {
return null;
}
if (uuid.equals(tagUUID)) {
return tag;
}
}
return null;
}
@Override
public boolean isCreateCopy() {
return false;
}
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setHeightmapToGet(HeightMapType type, int[] data) {
}
@Override
public int getMaxY() {
return maxHeight;
}
@Override
public int getMinY() {
return minHeight;
}
@Override
public int getMaxSectionPosition() {
return maxHeight >> 4;
}
@Override
public int getMinSectionPosition() {
return minHeight >> 4;
}
@Override
public BiomeType getBiomeType(int x, int y, int z) {
Biome biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
return biome != null ? PaperweightPlatformAdapter.adapt(biome, serverLevel) : null;
}
@Override
public void removeSectionLighting(int layer, boolean sky) {
}
@Override
public boolean trim(boolean aggressive, int layer) {
return false;
}
@Override
public IBlocks reset() {
return null;
}
@Override
public int getSectionCount() {
return serverLevel.getSectionsCount();
}
protected void storeSection(int layer, char[] data) {
blocks[layer] = data;
}
protected void storeBiomes(int layer, PalettedContainer<Biome> biomeData) {
if (biomes == null) {
biomes = new PalettedContainer[getSectionCount()];
}
biomes[layer] = biomeData;
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)];
return state.toBaseBlock(this, x, y, z);
}
@Override
public boolean hasSection(int layer) {
layer -= getMinSectionPosition();
return blocks[layer] != null;
}
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public char[] loadIfPresent(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)];
}
@Override
public int getSkyLight(int x, int y, int z) {
return 0;
}
@Override
public int getEmittedLight(int x, int y, int z) {
return 0;
}
@Override
public int[] getHeightMap(HeightMapType type) {
return new int[0];
}
@Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
return null;
}
public char get(int x, int y, int z) {
final int layer = (y >> 4) - getMinSectionPosition();
final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index];
}
@Override
public boolean trim(boolean aggressive) {
return false;
}
}

View File

@ -0,0 +1,35 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
//TODO un-very-break-this
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkWithLightPacket> {
public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a"));
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b"));
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c"));
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
fieldX.setAccessible(true);
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
}
@Override
public ClientboundLevelChunkWithLightPacket createPacket() {
// TODO ??? return new ClientboundLevelChunkPacket();
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,661 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
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.adapter.Refraction;
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.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.IdMap;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
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.util.BitStorage;
import net.minecraft.util.SimpleBitStorage;
import net.minecraft.util.ThreadingDetector;
import net.minecraft.util.ZeroBitStorage;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
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.gameevent.GameEventDispatcher;
import net.minecraft.world.level.gameevent.GameEventListener;
import org.bukkit.craftbukkit.v1_18_R1.CraftChunk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.misc.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.function.Function;
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;
public static final Field fieldTickingFluidCount;
public static final Field fieldTickingBlockCount;
public static final Field fieldNonEmptyBlockCount;
private static final MethodHandle methodGetVisibleChunk;
private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;
private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;
private static final Field fieldLock;
private static final long fieldLockOffset;
private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveTickingBlockEntity;
private static final Field fieldRemove;
static {
try {
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
fieldData.setAccessible(true);
Class<?> dataClazz = fieldData.getType();
dataConstructor = dataClazz.getDeclaredConstructors()[0];
dataConstructor.setAccessible(true);
fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b"));
fieldStorage.setAccessible(true);
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
fieldPalette.setAccessible(true);
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
fieldTickingFluidCount.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
fieldNonEmptyBlockCount.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
"getVisibleChunkIfPresent",
"b"
), long.class);
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
Unsafe unsafe = ReflectionUtils.getUnsafe();
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
"gameEventDispatcherSections", "t"));
fieldGameEventDispatcherSections.setAccessible(true);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName(
"removeBlockEntityTicker",
"m"
), BlockPos.class
);
removeBlockEntityTicker.setAccessible(true);
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} 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
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
}
return false;
}
static DelegateSemaphore applyLock(LevelChunkSection section) {
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(blocks,
fieldThreadingDetectorOffset) ;
synchronized(currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
if (currentLock instanceof DelegateSemaphore) {
return (DelegateSemaphore) currentLock;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, 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) {
return nmsChunk;
}
nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
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 = (CraftChunk) future.get();
return chunk.getHandle();
} catch (Throwable e) {
e.printStackTrace();
}
}
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
}
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);
}
}
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(() -> {
ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) {
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true,
false // last false is to not bother with x-ray
);
} else {
// deprecated on paper
//noinspection deprecation
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true
);
}
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
});
}
private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
}
/*
NMS conversion
*/
public static LevelChunkSection newChunkSection(
final int layer, final char[] blocks, boolean fastmode,
CachedBukkitAdapter adapter, Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Biome> biomes
) {
return newChunkSection(layer, null, blocks, fastmode, adapter, biomeRegistry, biomes);
}
public static LevelChunkSection newChunkSection(
final int layer, final Function<Integer, char[]> get, char[] set,
boolean fastmode, CachedBukkitAdapter adapter, Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<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_buffer = new int[1];
Map<BlockVector3, Integer> ticking_blocks = new HashMap<>();
int air;
if (get == null) {
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer,
set, ticking_blocks, fastmode, adapter
);
} else {
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy,
num_palette_buffer, get, set, ticking_blocks, fastmode, adapter
);
}
int num_palette = num_palette_buffer[0];
// BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
Object configuration =
PalettedContainer.Strategy.SECTION_STATES.getConfiguration(new FakeIdMapBlock(num_palette), bitsPerEntry);
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);
}
final Palette<net.minecraft.world.level.block.state.BlockState> blockStatePalette;
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
);
LevelChunkSection levelChunkSection;
try {
//fieldStorage.set(dataPaletteBlocks, nmsBits);
//fieldPalette.set(dataPaletteBlocks, blockStatePalettedContainer);
if (biomes == null) {
biomes = new PalettedContainer<>(
biomeRegistry,
biomeRegistry.getOrThrow(Biomes.PLAINS),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
}
levelChunkSection = new LevelChunkSection(layer, blockStatePalettedContainer, biomes);
setCount(ticking_blocks.size(), 4096 - air, levelChunkSection);
if (!fastmode) {
ticking_blocks.forEach((pos, ordinal) -> levelChunkSection.setBlockState(
pos.getBlockX(),
pos.getBlockY(),
pos.getBlockZ(),
Block.stateById(ordinal)
));
}
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
return levelChunkSection;
} catch (final Throwable e) {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
throw e;
}
}
private static LevelChunkSection newChunkSection(
int layer, Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Biome> biomes
) {
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
Blocks.AIR.defaultBlockState(),
PalettedContainer.Strategy.SECTION_STATES,
null
);
PalettedContainer<Biome> biomesPalette = biomes != null ? biomes : new PalettedContainer<>(
biomeRegistry,
biomeRegistry.getOrThrow(Biomes.PLAINS),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
return new LevelChunkSection(layer, dataPaletteBlocks, biomesPalette);
}
/**
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
*/
public static PalettedContainer<Biome> getBiomePalettedContainer(BiomeType[] biomes, Registry<Biome> biomeRegistry) {
if (biomes == null) {
return null;
}
// Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length
Map<BiomeType, Biome> palette = new HashMap<>();
for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) {
Biome biome;
if (biomeType == null) {
biome = biomeRegistry.getOrThrow(Biomes.PLAINS);
} else {
biome = biomeRegistry.get(ResourceLocation.tryParse(biomeType.getId()));
}
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<Biome> biomePalettedContainer = new PalettedContainer<>(
biomeRegistry,
biomeRegistry.getOrThrow(Biomes.PLAINS),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
final Palette<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;
}
Biome biome = biomeRegistry.get(ResourceLocation.tryParse(biomeType.getId()));
if (biome == null) {
continue;
}
biomePalettedContainer.set(x, y, z, biome);
}
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return biomePalettedContainer;
}
public static void setCount(final int tickingBlockCount, final int nonEmptyBlockCount, final LevelChunkSection section) throws
IllegalAccessException {
fieldTickingFluidCount.setShort(section, (short) 0); // TODO FIXME
fieldTickingBlockCount.setShort(section, (short) tickingBlockCount);
fieldNonEmptyBlockCount.setShort(section, (short) nonEmptyBlockCount);
}
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));
}
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try {
// Do the method ourselves to avoid trying to reflect generic method parameters
// similar to removeGameEventListener
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) {
if (!levelChunk.level.isClientSide) {
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);
}
}
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
static class FakeIdMapBlock implements IdMap<net.minecraft.world.level.block.state.BlockState> {
private final int size;
FakeIdMapBlock(int size) {
this.size = size;
}
@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;
}
@Override
public int size() {
return size;
}
@NotNull
@Override
public Iterator<net.minecraft.world.level.block.state.BlockState> iterator() {
return Collections.emptyIterator();
}
}
static class FakeIdMapBiome implements IdMap<Biome> {
private final int size;
FakeIdMapBiome(int size) {
this.size = size;
}
@Override
public int getId(final Biome entry) {
return 0;
}
@Nullable
@Override
public Biome byId(final int index) {
return null;
}
@Override
public int size() {
return size;
}
@NotNull
@Override
public Iterator<Biome> iterator() {
return Collections.emptyIterator();
}
}
}

View File

@ -0,0 +1,238 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.MCUtil;
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 org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
public class PaperweightStarlightRelighter implements Relighter {
public static final MethodHandle RELIGHT;
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32
private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting
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
)
);
} catch (NoSuchMethodException | IllegalAccessException e) {
LOGGER.error("Failed to locate 'relight' method in ThreadedLevelLightEngine. Is everything up to date?", e);
}
RELIGHT = tmp;
}
private final ServerLevel serverLevel;
private final ReentrantLock lock = new ReentrantLock();
private final Long2ObjectLinkedOpenHashMap<LongSet> regions = new Long2ObjectLinkedOpenHashMap<>();
private final ReentrantLock areaLock = new ReentrantLock();
private final NMSRelighter delegate;
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<IQueueChunk> queue) {
this.serverLevel = serverLevel;
this.delegate = new NMSRelighter(queue);
}
public static boolean isUsable() {
return RELIGHT != null;
}
@Override
public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) {
areaLock.lock();
try {
long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2);
// TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH?
LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2));
chunks.add(ChunkPos.asLong(cx, cz));
} finally {
areaLock.unlock();
}
return true;
}
@Override
public void addLightUpdate(int x, int y, int z) {
delegate.addLightUpdate(x, y, z);
}
/*
* This method is called "recursively", iterating and removing elements
* from the regions linked map. This way, chunks are loaded in batches to avoid
* OOMEs.
*/
@Override
public void fixLightingSafe(boolean sky) {
this.areaLock.lock();
try {
if (regions.isEmpty()) {
return;
}
LongSet first = regions.removeFirst();
fixLighting(first, () -> fixLightingSafe(true));
} finally {
this.areaLock.unlock();
}
}
/*
* Processes a set of chunks and runs an action afterwards.
* The action is run async, the chunks are partly processed on the main thread
* (as required by the server).
*/
private void fixLighting(LongSet chunks, Runnable andThen) {
// convert from long keys to ChunkPos
Set<ChunkPos> coords = new HashSet<>();
LongIterator iterator = chunks.iterator();
while (iterator.hasNext()) {
coords.add(new ChunkPos(iterator.nextLong()));
}
TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE
))
);
}
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v ->
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads
TaskManager.taskManager().async(andThen);
}
)
);
});
}
private void invokeRelight(
Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback,
IntConsumer processCallback
) {
try {
int unused = (int) 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);
}
}
/*
* Allow the server to unload the chunks again.
* Also, if chunk packets are sent delayed, we need to do that here
*/
private void postProcessChunks(Set<ChunkPos> coords) {
boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
for (ChunkPos pos : coords) {
int x = pos.x;
int z = pos.z;
if (delay) { // we still need to send the block changes of that chunk
PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false);
}
serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
}
}
@Override
public void clear() {
}
@Override
public void removeLighting() {
this.delegate.removeLighting();
}
@Override
public void fixBlockLighting() {
fixLightingSafe(true);
}
@Override
public void fixSkyLighting() {
fixLightingSafe(true);
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ReentrantLock getLock() {
return this.lock;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public void close() throws Exception {
fixLightingSafe(true);
}
}

View File

@ -0,0 +1,27 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import javax.annotation.Nonnull;
public class PaperweightStarlightRelighterFactory implements RelighterFactory {
@Override
public @Nonnull
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
org.bukkit.World w = Bukkit.getWorld(world.getName());
if (w == null) {
return NullRelighter.INSTANCE;
}
return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue);
}
}

View File

@ -0,0 +1,158 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.nbt;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.LazyCompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import net.minecraft.nbt.NumericTag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class PaperweightLazyCompoundTag extends LazyCompoundTag {
private final Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier;
private CompoundTag compoundTag;
public PaperweightLazyCompoundTag(Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier) {
super(new HashMap<>());
this.compoundTagSupplier = compoundTagSupplier;
}
public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) {
this(() -> compoundTag);
}
public net.minecraft.nbt.CompoundTag get() {
return compoundTagSupplier.get();
}
@Override
public Map<String, Tag> getValue() {
if (compoundTag == null) {
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
}
return compoundTag.getValue();
}
@Override
public CompoundBinaryTag asBinaryTag() {
getValue();
return compoundTag.asBinaryTag();
}
public boolean containsKey(String key) {
return compoundTagSupplier.get().contains(key);
}
public byte[] getByteArray(String key) {
return compoundTagSupplier.get().getByteArray(key);
}
public byte getByte(String key) {
return compoundTagSupplier.get().getByte(key);
}
public double getDouble(String key) {
return compoundTagSupplier.get().getDouble(key);
}
public double asDouble(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsDouble();
}
return 0;
}
public float getFloat(String key) {
return compoundTagSupplier.get().getFloat(key);
}
public int[] getIntArray(String key) {
return compoundTagSupplier.get().getIntArray(key);
}
public int getInt(String key) {
return compoundTagSupplier.get().getInt(key);
}
public int asInt(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsInt();
}
return 0;
}
public List<Tag> getList(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
ArrayList<Tag> list = new ArrayList<>();
for (net.minecraft.nbt.Tag elem : nbtList) {
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
list.add(new PaperweightLazyCompoundTag(compoundTag));
} else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
}
}
return list;
}
return Collections.emptyList();
}
public ListTag getListTag(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag) {
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
}
return new ListTag(StringTag.class, Collections.emptyList());
}
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
ListTag listTag = getListTag(key);
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
}
public long[] getLongArray(String key) {
return compoundTagSupplier.get().getLongArray(key);
}
public long getLong(String key) {
return compoundTagSupplier.get().getLong(key);
}
public long asLong(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsLong();
}
return 0;
}
public short getShort(String key) {
return compoundTagSupplier.get().getShort(key);
}
public String getString(String key) {
return compoundTagSupplier.get().getString(key);
}
@Override
public String toString() {
return compoundTagSupplier.get().toString();
}
}

View File

@ -0,0 +1,497 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Lifecycle;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R1.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R1.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 net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
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.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
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.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R1.CraftServer;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.generator.CustomChunkGenerator;
import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field serverWorldsField;
private static final Field paperConfigField;
private static final Field flatBedrockField;
private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField;
private static final Field chunkSourceField;
//list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
static {
chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
chunkStati.put(
ChunkStatus.STRUCTURE_REFERENCES,
Concurrency.FULL
); // structure refs: radius 8, but only writes to current chunk
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(
ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
chunkStati.put(
ChunkStatus.LIGHT,
Concurrency.FULL
); // light: radius 1, but no writes to other chunks, only current chunk
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try {
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true);
Field tmpPaperConfigField;
Field tmpFlatBedrockField;
try { //only present on paper
tmpPaperConfigField = Level.class.getDeclaredField("paperConfig");
tmpPaperConfigField.setAccessible(true);
tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock");
tmpFlatBedrockField.setAccessible(true);
} catch (Exception e) {
tmpPaperConfigField = null;
tmpFlatBedrockField = null;
}
paperConfigField = tmpPaperConfigField;
flatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "f"));
generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "e"));
generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "L"));
chunkSourceField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//runtime
private ServerLevel originalServerWorld;
private ServerChunkCache originalChunkProvider;
private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session;
private StructureManager structureManager;
private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator;
private Path tempDir;
private boolean generateFlatBedrock = false;
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
super(originalBukkitWorld, region, target, options);
}
@Override
protected boolean prepare() {
this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle();
originalChunkProvider = originalServerWorld.getChunkSource();
if (!(originalChunkProvider instanceof ServerChunkCache)) {
return false;
}
//flat bedrock? (only on paper)
if (paperConfigField != null) {
try {
generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) {
}
}
seed = options.getSeed().orElse(originalServerWorld.getSeed());
chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c));
return true;
}
@Override
protected boolean initNewWorld() throws Exception {
//world folder
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
//prepare for world init (see upstream implementation for reference)
org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment();
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
PrimaryLevelData levelProperties = (PrimaryLevelData) server.getWorldData();
WorldGenSettings originalOpts = levelProperties.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent()
? PaperweightAdapter.replaceSeed(originalServerWorld, seed, originalOpts)
: originalOpts;
LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld",
originalWorldData.settings.gameType(),
originalWorldData.settings.hardcore(),
originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig()
);
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
//init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
server,
server.executor,
session,
newWorldData,
originalServerWorld.dimension(),
originalServerWorld.dimensionType(),
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,
environment,
generator,
originalBukkitWorld.getBiomeProvider()
) {
private final Biome singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(
options
.getBiomeType()
.getId())) : null;
@Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
}
@Override
public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) {
return singleBiome;
}
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ,
PaperweightRegen.this.chunkGenerator.climateSampler()
);
}
}).get();
freshWorld.noSave = true;
removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
}
//generator
if (originalChunkProvider.getGenerator() instanceof FlatLevelSource flatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
} else if (originalChunkProvider.getGenerator() instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
Supplier<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Supplier<NoiseGeneratorSettings>) generatorSettingBaseSupplierField
.get(originalChunkProvider.getGenerator());
BiomeSource biomeSource = originalChunkProvider.getGenerator().getBiomeSource();
chunkGenerator = new NoiseBasedChunkGenerator(noiseBasedChunkGenerator.noises, biomeSource, seed,
generatorSettingBaseSupplier
);
} else if (originalChunkProvider.getGenerator() instanceof CustomChunkGenerator customChunkGenerator) {
chunkGenerator = customChunkGenerator.delegate;
} else {
LOGGER.error("Unsupported generator type {}", originalChunkProvider.getGenerator().getClass().getName());
return false;
}
if (generator != null) {
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable();
}
freshChunkProvider = new ServerChunkCache(
freshWorld,
session,
server.getFixerUpper(),
server.getStructureManager(),
server.executor,
chunkGenerator,
freshWorld.spigotConfig.viewDistance,
freshWorld.spigotConfig.simulationDistance,
server.forceSynchronousWrites(),
new RegenNoOpWorldLoadListener(),
(chunkCoordIntPair, state) -> {
},
() -> server.overworld().getDataStorage()
) {
// redirect to LevelChunks created in #createChunks
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean flag) {
return getChunkAt(x, z);
}
};
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
//let's start then
structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
return true;
}
@Override
protected void cleanup() {
try {
session.close();
} catch (Exception ignored) {
}
//shutdown chunk provider
try {
Fawe.instance().getQueueHandler().sync(() -> {
try {
freshChunkProvider.close(false);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (Exception ignored) {
}
//remove world from server
try {
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
} catch (Exception ignored) {
}
//delete directory
try {
SafeFiles.tryHardToDeleteDir(tempDir);
} catch (Exception ignored) {
}
}
@Override
protected ProtoChunk createProtoChunk(int x, int z) {
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null
);
}
@Override
protected LevelChunk createChunk(ProtoChunk protoChunk) {
return new LevelChunk(
freshWorld,
protoChunk,
null // we don't want to add entities
);
}
@Override
protected ChunkStatusWrap getFullChunkStatus() {
return new ChunkStatusWrap(ChunkStatus.FULL);
}
@Override
protected List<BlockPopulator> getBlockPopulators() {
return originalServerWorld.getWorld().getPopulators();
}
@Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
}
@Override
protected IChunkCache<IChunkGet> initSourceQueueCache() {
return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) {
@Override
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) {
return getChunkAt(x, z);
}
};
}
//util
private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> {
try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
map.remove("faweregentempworld");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
return switch (env) {
case NETHER -> LevelStem.NETHER;
case THE_END -> LevelStem.END;
default -> LevelStem.OVERWORLD;
};
}
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
private RegenNoOpWorldLoadListener() {
}
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
// TODO Paper only(?) @Override
public void setChunkRadius(int radius) {
}
}
private class FastProtoChunk extends ProtoChunk {
public FastProtoChunk(
final ChunkPos pos,
final UpgradeData upgradeData,
final LevelHeightAccessor world,
final Registry<Biome> biomeRegistry,
@Nullable final BlendingData blendingData
) {
super(pos, upgradeData, world, biomeRegistry, blendingData);
}
// avoid warning on paper
// compatibility with spigot
public boolean generateFlatBedrock() {
return generateFlatBedrock;
}
// no one will ever see the entities!
@Override
public List<CompoundTag> getEntities() {
return Collections.emptyList();
}
}
protected class ChunkStatusWrap extends ChunkStatusWrapper<ChunkAccess> {
private final ChunkStatus chunkStatus;
public ChunkStatusWrap(ChunkStatus chunkStatus) {
this.chunkStatus = chunkStatus;
}
@Override
public int requiredNeighborChunkRadius() {
return chunkStatus.getRange();
}
@Override
public String name() {
return chunkStatus.getName();
}
@Override
public CompletableFuture<?> processChunk(Long xz, List<ChunkAccess> accessibleChunks) {
return chunkStatus.generate(
Runnable::run, // TODO revisit, we might profit from this somehow?
freshWorld,
chunkGenerator,
structureManager,
threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks,
true
);
}
}
}

View File

@ -42,12 +42,6 @@ repositories {
flatDir { dir(File("src/main/resources")) } flatDir { dir(File("src/main/resources")) }
} }
configurations.all {
resolutionStrategy {
force("com.google.guava:guava:21.0")
}
}
val localImplementation = configurations.create("localImplementation") { val localImplementation = configurations.create("localImplementation") {
description = "Dependencies used locally, but provided by the runtime Bukkit implementation" description = "Dependencies used locally, but provided by the runtime Bukkit implementation"
isCanBeConsumed = false isCanBeConsumed = false
@ -108,7 +102,6 @@ dependencies {
compileOnly(libs.protocollib) { isTransitive = false } compileOnly(libs.protocollib) { isTransitive = false }
compileOnly(libs.plotsquaredV6Bukkit) { isTransitive = false } compileOnly(libs.plotsquaredV6Bukkit) { isTransitive = false }
compileOnly(libs.plotsquaredV6Core) { isTransitive = false } compileOnly(libs.plotsquaredV6Core) { isTransitive = false }
compileOnly(libs.plotsquaredV4) { isTransitive = false }
// Third party // Third party
compileOnly(libs.flowmath) { compileOnly(libs.flowmath) {
@ -187,7 +180,7 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.1")) include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.1"))
} }
relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") { relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") {
include(dependency("com.intellectualsites.paster:Paster:1.1.1")) include(dependency("com.intellectualsites.paster:Paster:1.1.3"))
} }
relocate("org.lz4", "com.fastasyncworldedit.core.lz4") { relocate("org.lz4", "com.fastasyncworldedit.core.lz4") {
include(dependency("org.lz4:lz4-java:1.8.0")) include(dependency("org.lz4:lz4-java:1.8.0"))

View File

@ -68,7 +68,6 @@ public class FaweBukkit implements IFawe, Listener {
public FaweBukkit(Plugin plugin) { public FaweBukkit(Plugin plugin) {
this.plugin = plugin; this.plugin = plugin;
try { try {
Settings.IMP.TICK_LIMITER.ENABLED = !Bukkit.hasWhitelist();
Fawe.set(this); Fawe.set(this);
Fawe.setupInjector(); Fawe.setupInjector();
try { try {
@ -76,7 +75,7 @@ public class FaweBukkit implements IFawe, Listener {
} catch (Throwable e) { } catch (Throwable e) {
LOGGER.error("Brush Listener Failed", e); LOGGER.error("Brush Listener Failed", e);
} }
if (PaperLib.isPaper() && Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) { if (PaperLib.isPaper() && Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) {
new RenderListener(plugin); new RenderListener(plugin);
} }
} catch (final Throwable e) { } catch (final Throwable e) {
@ -84,17 +83,19 @@ public class FaweBukkit implements IFawe, Listener {
Bukkit.getServer().shutdown(); Bukkit.getServer().shutdown();
} }
chunksStretched = new MinecraftVersion().isEqualOrHigher(MinecraftVersion.NETHER); MinecraftVersion version = new MinecraftVersion();
chunksStretched = version.isEqualOrHigherThan(MinecraftVersion.NETHER);
platformAdapter = new NMSAdapter(); platformAdapter = new NMSAdapter();
//PlotSquared support is limited to Spigot/Paper as of 02/20/2020 //PlotSquared support is limited to Spigot/Paper as of 02/20/2020
TaskManager.IMP.later(this::setupPlotSquared, 0); TaskManager.taskManager().later(this::setupPlotSquared, 0);
// Registered delayed Event Listeners // Registered delayed Event Listeners
TaskManager.IMP.task(() -> { TaskManager.taskManager().task(() -> {
// Fix for ProtocolSupport // Fix for ProtocolSupport
Settings.IMP.PROTOCOL_SUPPORT_FIX = Settings.settings().PROTOCOL_SUPPORT_FIX =
Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport"); Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
// This class // This class
@ -103,6 +104,11 @@ public class FaweBukkit implements IFawe, Listener {
// The tick limiter // The tick limiter
new ChunkListener9(); new ChunkListener9();
}); });
// Warn if small-edits are enabled with extended world heights
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?");
}
} }
@Override @Override
@ -141,7 +147,7 @@ public class FaweBukkit implements IFawe, Listener {
try { try {
this.itemUtil = tmp = new ItemUtil(); this.itemUtil = tmp = new ItemUtil();
} catch (Throwable e) { } catch (Throwable e) {
Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES = false; Settings.settings().EXPERIMENTAL.PERSISTENT_BRUSHES = false;
LOGGER.error("Persistent Brushes Failed", e); LOGGER.error("Persistent Brushes Failed", e);
} }
} }
@ -310,14 +316,12 @@ public class FaweBukkit implements IFawe, Listener {
if (plotSquared == null) { if (plotSquared == null) {
return; return;
} }
if (plotSquared.getClass().getPackage().toString().contains("intellectualsites")) { if (PlotSquared.get().getVersion().version[0] == 6) {
WEManager.IMP.addManager(new com.fastasyncworldedit.bukkit.regions.plotsquaredv4.PlotSquaredFeature()); WEManager.weManager().addManager(new com.fastasyncworldedit.bukkit.regions.plotsquared.PlotSquaredFeature());
LOGGER.info("Plugin 'PlotSquared' found. Using it now."); LOGGER.info("Plugin 'PlotSquared' v6 found. Using it now.");
} else if (PlotSquared.get().getVersion().version[0] == 6) {
WEManager.IMP.addManager(new com.fastasyncworldedit.bukkit.regions.plotsquared.PlotSquaredFeature());
LOGGER.info("Plugin 'PlotSquared' found. Using it now.");
} else { } else {
LOGGER.error("Incompatible version of PlotSquared found. Please use PlotSquared v6."); LOGGER.error("Incompatible version of PlotSquared found. Please use PlotSquared v6.");
LOGGER.info("https://www.spigotmc.org/resources/77506/");
} }
} }

View File

@ -389,7 +389,7 @@ public interface IBukkitAdapter {
* @return list of {@link org.bukkit.entity.Entity} * @return list of {@link org.bukkit.entity.Entity}
*/ */
default List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) { default List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
return TaskManager.IMP.sync(world::getEntities); return TaskManager.taskManager().sync(world::getEntities);
} }
} }

View File

@ -59,7 +59,7 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
} }
@Override @Override
default BaseBlock getBlock(Location location) { default BlockState getBlock(Location location) {
return getParent().getBlock(location); return getParent().getBlock(location);
} }

View File

@ -4,7 +4,6 @@ import com.fastasyncworldedit.core.FAWEPlatformAdapterImpl;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.world.block.BlockID;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
@ -24,8 +23,8 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
int num_palette = 0; int num_palette = 0;
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char ordinal = set[i]; char ordinal = set[i];
if (ordinal == BlockID.__RESERVED__) { if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
ordinal = BlockID.AIR; ordinal = BlockTypesCache.ReservedIDs.AIR;
} }
int palette = blockToPalette[ordinal]; int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) { if (palette == Integer.MAX_VALUE) {
@ -43,17 +42,15 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
} }
System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length); System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length);
} }
char lastOrdinal = BlockID.__RESERVED__; char lastOrdinal = 0;
boolean lastticking = false; boolean lastticking = false;
boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED; boolean tick_placed = Settings.settings().EXPERIMENTAL.ALLOW_TICK_PLACED;
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char ordinal = set[i]; char ordinal = set[i];
switch (ordinal) { switch (ordinal) {
case BlockID.__RESERVED__: case BlockTypesCache.ReservedIDs.__RESERVED__:
ordinal = BlockID.AIR; ordinal = BlockTypesCache.ReservedIDs.AIR;
case BlockID.AIR: case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
air++; air++;
break; break;
default: default:
@ -95,13 +92,13 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
char[] getArr = null; char[] getArr = null;
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char ordinal = set[i]; char ordinal = set[i];
if (ordinal == BlockID.__RESERVED__) { if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
if (getArr == null) { if (getArr == null) {
getArr = get.apply(layer); getArr = get.apply(layer);
} }
ordinal = getArr[i]; ordinal = getArr[i];
if (ordinal == BlockID.__RESERVED__) { if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
ordinal = BlockID.AIR; ordinal = BlockTypesCache.ReservedIDs.AIR;
} }
} }
int palette = blockToPalette[ordinal]; int palette = blockToPalette[ordinal];
@ -120,26 +117,23 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
} }
System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length); System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length);
} }
char lastOrdinal = BlockID.__RESERVED__; char lastOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
boolean lastticking = false; boolean lastticking = false;
boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED; boolean tick_placed = Settings.settings().EXPERIMENTAL.ALLOW_TICK_PLACED;
boolean tick_existing = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_EXISTING; boolean tick_existing = Settings.settings().EXPERIMENTAL.ALLOW_TICK_EXISTING;
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char ordinal = set[i]; char ordinal = set[i];
switch (ordinal) { switch (ordinal) {
case BlockID.__RESERVED__: { case BlockTypesCache.ReservedIDs.__RESERVED__ -> {
if (getArr == null) { if (getArr == null) {
getArr = get.apply(layer); getArr = get.apply(layer);
} }
ordinal = getArr[i]; set[i] = switch (ordinal = getArr[i]) {
switch (ordinal) { case BlockTypesCache.ReservedIDs.__RESERVED__:
case BlockID.__RESERVED__: ordinal = BlockTypesCache.ReservedIDs.AIR;
ordinal = BlockID.AIR; case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR:
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
air++; air++;
break; yield ordinal;
default: default:
if (!fastmode && !tick_placed && tick_existing) { if (!fastmode && !tick_placed && tick_existing) {
boolean ticking; boolean ticking;
@ -152,23 +146,19 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
} }
if (ticking) { if (ticking) {
BlockState state = BlockState.getFromOrdinal(ordinal); BlockState state = BlockState.getFromOrdinal(ordinal);
ticking_blocks ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15),
.put( WorldEditPlugin
BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), .getInstance()
WorldEditPlugin.getInstance().getBukkitImplAdapter() .getBukkitImplAdapter()
.getInternalBlockStateId(state).orElse(0) .getInternalBlockStateId(state)
.orElse(0)
); );
} }
} }
yield ordinal;
};
} }
set[i] = ordinal; case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR -> air++;
break;
}
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
air++;
break;
} }
if (!fastmode && tick_placed) { if (!fastmode && tick_placed) {
boolean ticking; boolean ticking;

View File

@ -18,7 +18,7 @@ public class NMSRelighterFactory implements RelighterFactory {
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) { Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
return new NMSRelighter( return new NMSRelighter(
queue, queue,
relightMode != null ? relightMode : RelightMode.valueOf(Settings.IMP.LIGHTING.MODE) relightMode != null ? relightMode : RelightMode.valueOf(Settings.settings().LIGHTING.MODE)
); );
} }

View File

@ -5,7 +5,10 @@ import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent; import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -32,6 +35,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -151,7 +155,10 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
private boolean generate() throws Exception { private boolean generate() throws Exception {
if (generateConcurrent) { if (generateConcurrent) {
//Using concurrent chunk generation //Using concurrent chunk generation
executor = Executors.newFixedThreadPool(Settings.IMP.QUEUE.PARALLEL_THREADS); executor = Executors.newFixedThreadPool(Settings.settings().QUEUE.PARALLEL_THREADS, new ThreadFactoryBuilder()
.setNameFormat("fawe-regen-%d")
.build()
);
} // else using sequential chunk generation, concurrent not supported } // else using sequential chunk generation, concurrent not supported
//TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)? //TODO: can we get that required radius down without affecting chunk generation (e.g. strucures, features, ...)?
@ -283,19 +290,52 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
private void copyToWorld() { private void copyToWorld() {
//Setting Blocks //Setting Blocks
long start = System.currentTimeMillis();
boolean genbiomes = options.shouldRegenBiomes(); boolean genbiomes = options.shouldRegenBiomes();
boolean hasBiome = options.hasBiomeType(); boolean hasBiome = options.hasBiomeType();
BiomeType biome = options.getBiomeType(); BiomeType biome = options.getBiomeType();
for (BlockVector3 vec : region) { if (!genbiomes && !hasBiome) {
BaseBlock block = source.getFullBlock(vec); target.setBlocks(region, new PlacementPattern());
target.setBlock(vec, block); }
if (hasBiome) { if (hasBiome) {
target.setBiome(vec, biome); target.setBlocks(region, new WithBiomePlacementPattern(ignored -> biome));
} else if (genbiomes) { } else if (genbiomes) {
target.setBiome(vec, source.getBiome(vec)); target.setBlocks(region, new WithBiomePlacementPattern(vec -> source.getBiome(vec)));
} }
} }
private class PlacementPattern implements Pattern {
@Override
public BaseBlock applyBlock(final BlockVector3 position) {
return source.getFullBlock(position);
}
@Override
public boolean apply(final Extent extent, final BlockVector3 get, final BlockVector3 set) throws WorldEditException {
return extent.setBlock(set.getX(), set.getY(), set.getZ(), source.getFullBlock(get.getX(), get.getY(), get.getZ()));
}
}
private class WithBiomePlacementPattern implements Pattern {
private final Function<BlockVector3, BiomeType> biomeGetter;
private WithBiomePlacementPattern(final Function<BlockVector3, BiomeType> biomeGetter) {
this.biomeGetter = biomeGetter;
}
@Override
public BaseBlock applyBlock(final BlockVector3 position) {
return source.getFullBlock(position);
}
@Override
public boolean apply(final Extent extent, final BlockVector3 get, final BlockVector3 set) throws WorldEditException {
return extent.setBlock(set.getX(), set.getY(), set.getZ(), source.getFullBlock(get.getX(), get.getY(), get.getZ()))
&& extent.setBiome(set.getX(), set.getY(), set.getZ(), biomeGetter.apply(get));
}
} }
//functions to be implemented by sub class //functions to be implemented by sub class

View File

@ -45,20 +45,25 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
/**
* @deprecated FAWE is not necessarily the tool you want to use to limit certain tick actions, e.g. fireworks or elytra flying.
* The code is untouched since the 1.12 era and there is no guarantee that it will work or will be maintained in the future.
*/
@Deprecated(since = "2.0.0")
public abstract class ChunkListener implements Listener { public abstract class ChunkListener implements Listener {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
protected int rateLimit = 0; protected int rateLimit = 0;
protected Location lastCancelPos; protected Location lastCancelPos;
private final int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS_MS, private final int[] badLimit = new int[]{Settings.settings().TICK_LIMITER.PHYSICS_MS,
Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS}; Settings.settings().TICK_LIMITER.FALLING, Settings.settings().TICK_LIMITER.ITEMS};
public ChunkListener() { public ChunkListener() {
if (Settings.IMP.TICK_LIMITER.ENABLED) { if (Settings.settings().TICK_LIMITER.ENABLED) {
PluginManager plm = Bukkit.getPluginManager(); PluginManager plm = Bukkit.getPluginManager();
Plugin plugin = Fawe.<FaweBukkit>imp().getPlugin(); Plugin plugin = Fawe.<FaweBukkit>platform().getPlugin();
plm.registerEvents(this, plugin); plm.registerEvents(this, plugin);
TaskManager.IMP.repeat(() -> { TaskManager.taskManager().repeat(() -> {
Location tmpLoc = lastCancelPos; Location tmpLoc = lastCancelPos;
if (tmpLoc != null) { if (tmpLoc != null) {
LOGGER.info("[FAWE Tick Limiter] Detected and cancelled physics lag source at {}", tmpLoc); LOGGER.info("[FAWE Tick Limiter] Detected and cancelled physics lag source at {}", tmpLoc);
@ -80,7 +85,7 @@ public abstract class ChunkListener implements Listener {
counter.put(key, badLimit); counter.put(key, badLimit);
} }
badChunks.clear(); badChunks.clear();
}, Settings.IMP.TICK_LIMITER.INTERVAL); }, Settings.settings().TICK_LIMITER.INTERVAL);
} }
} }
@ -88,7 +93,15 @@ public abstract class ChunkListener implements Listener {
protected abstract StackTraceElement getElement(Exception ex, int index); protected abstract StackTraceElement getElement(Exception ex, int index);
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public static boolean physicsFreeze = false; public static boolean physicsFreeze = false;
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public static boolean itemFreeze = false; public static boolean itemFreeze = false;
protected final Long2ObjectOpenHashMap<Boolean> badChunks = new Long2ObjectOpenHashMap<>(); protected final Long2ObjectOpenHashMap<Boolean> badChunks = new Long2ObjectOpenHashMap<>();
@ -97,6 +110,10 @@ public abstract class ChunkListener implements Listener {
private int lastZ = Integer.MIN_VALUE; private int lastZ = Integer.MIN_VALUE;
private int[] lastCount; private int[] lastCount;
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public int[] getCount(int cx, int cz) { public int[] getCount(int cx, int cz) {
if (lastX == cx && lastZ == cz) { if (lastX == cx && lastZ == cz) {
return lastCount; return lastCount;
@ -112,6 +129,10 @@ public abstract class ChunkListener implements Listener {
return tmp; return tmp;
} }
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public void cleanup(Chunk chunk) { public void cleanup(Chunk chunk) {
for (Entity entity : chunk.getEntities()) { for (Entity entity : chunk.getEntities()) {
if (entity.getType() == EntityType.DROPPED_ITEM) { if (entity.getType() == EntityType.DROPPED_ITEM) {
@ -128,6 +149,10 @@ public abstract class ChunkListener implements Listener {
protected long physStart; protected long physStart;
protected long physTick; protected long physTick;
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public final void reset() { public final void reset() {
physSkip = 0; physSkip = 0;
physStart = System.currentTimeMillis(); physStart = System.currentTimeMillis();
@ -241,13 +266,13 @@ public abstract class ChunkListener implements Listener {
if ((++physSkip & 1023) != 0) { if ((++physSkip & 1023) != 0) {
return; return;
} }
FaweTimer timer = Fawe.get().getTimer(); FaweTimer timer = Fawe.instance().getTimer();
if (timer.getTick() != physTick) { if (timer.getTick() != physTick) {
physTick = timer.getTick(); physTick = timer.getTick();
physStart = System.currentTimeMillis(); physStart = System.currentTimeMillis();
return; return;
} else if (System.currentTimeMillis() - physStart } else if (System.currentTimeMillis() - physStart
< Settings.IMP.TICK_LIMITER.PHYSICS_MS) { < Settings.settings().TICK_LIMITER.PHYSICS_MS) {
return; return;
} }
} }
@ -324,15 +349,15 @@ public abstract class ChunkListener implements Listener {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int[] count = getCount(cx, cz); int[] count = getCount(cx, cz);
if (count[1] >= Settings.IMP.TICK_LIMITER.FALLING) { if (count[1] >= Settings.settings().TICK_LIMITER.FALLING) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (event.getEntityType() == EntityType.FALLING_BLOCK) { if (event.getEntityType() == EntityType.FALLING_BLOCK) {
if (++count[1] >= Settings.IMP.TICK_LIMITER.FALLING) { if (++count[1] >= Settings.settings().TICK_LIMITER.FALLING) {
// Only cancel falling blocks when it's lagging // Only cancel falling blocks when it's lagging
if (Fawe.get().getTimer().getTPS() < 18) { if (Fawe.instance().getTimer().getTPS() < 18) {
cancelNearby(cx, cz); cancelNearby(cx, cz);
if (rateLimit <= 0) { if (rateLimit <= 0) {
rateLimit = 20; rateLimit = 20;
@ -351,7 +376,7 @@ public abstract class ChunkListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onChunkLoad(ChunkLoadEvent event) { public void onChunkLoad(ChunkLoadEvent event) {
if (!Settings.IMP.TICK_LIMITER.FIREWORKS_LOAD_CHUNKS) { if (!Settings.settings().TICK_LIMITER.FIREWORKS_LOAD_CHUNKS) {
Chunk chunk = event.getChunk(); Chunk chunk = event.getChunk();
Entity[] entities = chunk.getEntities(); Entity[] entities = chunk.getEntities();
World world = chunk.getWorld(); World world = chunk.getWorld();
@ -377,8 +402,8 @@ public abstract class ChunkListener implements Listener {
if (Math.abs(velocity.getX()) > vertical if (Math.abs(velocity.getX()) > vertical
|| Math.abs(velocity.getZ()) > vertical) { || Math.abs(velocity.getZ()) > vertical) {
LOGGER.warn( LOGGER.warn(
"[FAWE `tick-limiter`] Detected and cancelled rogue FireWork at " "[FAWE `tick-limiter`] Detected and cancelled rogue FireWork at {}",
+ ent.getLocation()); ent.getLocation());
ent.remove(); ent.remove();
} }
} }
@ -398,17 +423,17 @@ public abstract class ChunkListener implements Listener {
int cx = loc.getBlockX() >> 4; int cx = loc.getBlockX() >> 4;
int cz = loc.getBlockZ() >> 4; int cz = loc.getBlockZ() >> 4;
int[] count = getCount(cx, cz); int[] count = getCount(cx, cz);
if (count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) { if (count[2] >= Settings.settings().TICK_LIMITER.ITEMS) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (++count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) { if (++count[2] >= Settings.settings().TICK_LIMITER.ITEMS) {
cleanup(loc.getChunk()); cleanup(loc.getChunk());
cancelNearby(cx, cz); cancelNearby(cx, cz);
if (rateLimit <= 0) { if (rateLimit <= 0) {
rateLimit = 20; rateLimit = 20;
LOGGER.warn( LOGGER.warn(
"[FAWE `tick-limiter`] Detected and cancelled item lag source at " + loc); "[FAWE `tick-limiter`] Detected and cancelled item lag source at {}", loc);
} }
event.setCancelled(true); event.setCancelled(true);
} }

View File

@ -9,11 +9,20 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPhysicsEvent;
/**
* @deprecated FAWE is not necessarily the tool you want to use to limit certain tick actions, e.g. fireworks or elytra flying.
* The code is untouched since the 1.12 era and there is no guarantee that it will work or will be maintained in the future.
*/
@Deprecated(since = "2.0.0")
public class ChunkListener9 extends ChunkListener { public class ChunkListener9 extends ChunkListener {
private Exception exception; private Exception exception;
private StackTraceElement[] elements; private StackTraceElement[] elements;
/**
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener9} for an explanation of the deprecation
*/
@Deprecated(since = "2.0.0")
public ChunkListener9() { public ChunkListener9() {
super(); super();
} }
@ -37,13 +46,13 @@ public class ChunkListener9 extends ChunkListener {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (System.currentTimeMillis() - physStart > Settings.IMP.TICK_LIMITER.PHYSICS_MS) { if (System.currentTimeMillis() - physStart > Settings.settings().TICK_LIMITER.PHYSICS_MS) {
physCancelPair = pair; physCancelPair = pair;
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
} }
FaweTimer timer = Fawe.get().getTimer(); FaweTimer timer = Fawe.instance().getTimer();
if (timer.getTick() != physTick) { if (timer.getTick() != physTick) {
physTick = timer.getTick(); physTick = timer.getTick();
physStart = System.currentTimeMillis(); physStart = System.currentTimeMillis();
@ -52,7 +61,7 @@ public class ChunkListener9 extends ChunkListener {
return; return;
} }
if ((++physSkip & 1023) == 0) { if ((++physSkip & 1023) == 0) {
if (System.currentTimeMillis() - physStart > Settings.IMP.TICK_LIMITER.PHYSICS_MS) { if (System.currentTimeMillis() - physStart > Settings.settings().TICK_LIMITER.PHYSICS_MS) {
Block block = event.getBlock(); Block block = event.getBlock();
int cx = block.getX() >> 4; int cx = block.getX() >> 4;
int cz = block.getZ() >> 4; int cz = block.getZ() >> 4;

View File

@ -28,7 +28,7 @@ public class RenderListener implements Listener {
public RenderListener(Plugin plugin) { public RenderListener(Plugin plugin) {
Bukkit.getPluginManager().registerEvents(this, plugin); Bukkit.getPluginManager().registerEvents(this, plugin);
TaskManager.IMP.repeat(new Runnable() { TaskManager.taskManager().repeat(new Runnable() {
private long last = 0; private long last = 0;
@Override @Override
@ -38,7 +38,7 @@ public class RenderListener implements Listener {
} }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
int tps32 = (int) (Math.round(Fawe.get().getTimer().getTPS()) * 32); int tps32 = (int) (Math.round(Fawe.instance().getTimer().getTPS()) * 32);
long diff = now - last; long diff = now - last;
last = now; last = now;
if (diff > 75) { if (diff > 75) {
@ -56,7 +56,7 @@ public class RenderListener implements Listener {
if (entrySet == null || !entrySet.hasNext()) { if (entrySet == null || !entrySet.hasNext()) {
entrySet = views.entrySet().iterator(); entrySet = views.entrySet().iterator();
} }
int nowTick = (int) (Fawe.get().getTimer().getTick()); int nowTick = (int) (Fawe.instance().getTimer().getTick());
while (entrySet.hasNext()) { while (entrySet.hasNext()) {
Map.Entry<UUID, int[]> entry = entrySet.next(); Map.Entry<UUID, int[]> entry = entrySet.next();
Player player = Bukkit.getPlayer(entry.getKey()); Player player = Bukkit.getPlayer(entry.getKey());
@ -81,17 +81,17 @@ public class RenderListener implements Listener {
private void setViewDistance(Player player, int value) { private void setViewDistance(Player player, int value) {
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
if (value == Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING) { if (value == Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING) {
views.remove(uuid); views.remove(uuid);
} else { } else {
int[] val = views.get(uuid); int[] val = views.get(uuid);
if (val == null) { if (val == null) {
val = new int[]{value, (int) Fawe.get().getTimer().getTick()}; val = new int[]{value, (int) Fawe.instance().getTimer().getTick()};
UUID uid = player.getUniqueId(); UUID uid = player.getUniqueId();
views.put(uid, val); views.put(uid, val);
} else { } else {
if (value <= val[0]) { if (value <= val[0]) {
val[1] = (int) Fawe.get().getTimer().getTick(); val[1] = (int) Fawe.instance().getTimer().getTick();
} }
if (val[0] == value) { if (val[0] == value) {
return; return;
@ -105,7 +105,7 @@ public class RenderListener implements Listener {
private int getViewDistance(Player player) { private int getViewDistance(Player player) {
int[] value = views.get(player.getUniqueId()); int[] value = views.get(player.getUniqueId());
return value == null ? Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING : value[0]; return value == null ? Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING : value[0];
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@ -32,7 +32,7 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener
} }
@Override @Override
public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type) { public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
final Player player = BukkitAdapter.adapt(wePlayer); final Player player = BukkitAdapter.adapt(wePlayer);
final Location loc = player.getLocation(); final Location loc = player.getLocation();
final Vector3i vector = Vector3i.from(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); final Vector3i vector = Vector3i.from(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());

View File

@ -1,7 +1,9 @@
package com.fastasyncworldedit.bukkit.regions; package com.fastasyncworldedit.bukkit.regions;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
@ -30,7 +32,7 @@ public class GriefPreventionFeature extends BukkitMaskManager implements Listene
} }
@Override @Override
public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type) { public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
final Player player = BukkitAdapter.adapt(wePlayer); final Player player = BukkitAdapter.adapt(wePlayer);
final Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, null); final Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, null);
if (claim != null) { if (claim != null) {
@ -38,12 +40,12 @@ public class GriefPreventionFeature extends BukkitMaskManager implements Listene
claim.getGreaterBoundaryCorner().getBlockX(); claim.getGreaterBoundaryCorner().getBlockX();
final BlockVector3 pos1 = BlockVector3.at( final BlockVector3 pos1 = BlockVector3.at(
claim.getLesserBoundaryCorner().getBlockX(), claim.getLesserBoundaryCorner().getBlockX(),
0, player.getWorld().getMinHeight(),
claim.getLesserBoundaryCorner().getBlockZ() claim.getLesserBoundaryCorner().getBlockZ()
); );
final BlockVector3 pos2 = BlockVector3.at( final BlockVector3 pos2 = BlockVector3.at(
claim.getGreaterBoundaryCorner().getBlockX(), claim.getGreaterBoundaryCorner().getBlockX(),
256, player.getWorld().getMaxHeight(),
claim.getGreaterBoundaryCorner().getBlockZ() claim.getGreaterBoundaryCorner().getBlockZ()
); );
return new FaweMask(new CuboidRegion(pos1, pos2)) { return new FaweMask(new CuboidRegion(pos1, pos2)) {

View File

@ -33,13 +33,13 @@ public class ResidenceFeature extends BukkitMaskManager implements Listener {
return residence != null && return residence != null &&
(residence.getOwner().equals(player.getName()) || (residence.getOwner().equals(player.getName()) ||
residence.getOwner().equals(player.getUniqueId().toString()) || residence.getOwner().equals(player.getUniqueId().toString()) ||
type == MaskType.MEMBER && TaskManager.IMP.sync(() -> residence type == MaskType.MEMBER && TaskManager.taskManager().sync(() -> residence
.getPermissions() .getPermissions()
.playerHas(player, "build", false))); .playerHas(player, "build", false)));
} }
@Override @Override
public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, final MaskType type) { public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, final MaskType type, boolean isWhitelist) {
final Player player = BukkitAdapter.adapt(wePlayer); final Player player = BukkitAdapter.adapt(wePlayer);
final Location location = player.getLocation(); final Location location = player.getLocation();
ClaimedResidence residence = Residence.getInstance().getResidenceManager().getByLoc(location); ClaimedResidence residence = Residence.getInstance().getResidenceManager().getByLoc(location);

View File

@ -66,7 +66,7 @@ public class TownyFeature extends BukkitMaskManager implements Listener {
} }
@Override @Override
public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type) { public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
final Player player = BukkitAdapter.adapt(wePlayer); final Player player = BukkitAdapter.adapt(wePlayer);
final Location location = player.getLocation(); final Location location = player.getLocation();
try { try {

View File

@ -53,7 +53,7 @@ public class FaweDelegateRegionManager {
int maxY, int maxY,
Runnable whenDone Runnable whenDone
) { ) {
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
World world = BukkitAdapter.adapt(getWorld(area.getWorldName())); World world = BukkitAdapter.adapt(getWorld(area.getWorldName()));
EditSession session = WorldEdit.getInstance().newEditSessionBuilder().world(world).checkMemory(false). EditSession session = WorldEdit.getInstance().newEditSessionBuilder().world(world).checkMemory(false).
@ -67,14 +67,14 @@ public class FaweDelegateRegionManager {
session.flushQueue(); session.flushQueue();
for (CuboidRegion region : regions) { for (CuboidRegion region : regions) {
FaweAPI.fixLighting(world, region, null, FaweAPI.fixLighting(world, region, null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
} }
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
} }
} }
@ -92,7 +92,7 @@ public class FaweDelegateRegionManager {
@Nullable Runnable whenDone, @Nullable Runnable whenDone,
@Nonnull PlotManager manager @Nonnull PlotManager manager
) { ) {
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
final HybridPlotWorld hybridPlotWorld = ((HybridPlotManager) manager).getHybridPlotWorld(); final HybridPlotWorld hybridPlotWorld = ((HybridPlotManager) manager).getHybridPlotWorld();
World world = BukkitAdapter.adapt(getWorld(hybridPlotWorld.getWorldName())); World world = BukkitAdapter.adapt(getWorld(hybridPlotWorld.getWorldName()));
@ -176,10 +176,10 @@ public class FaweDelegateRegionManager {
world, world,
new CuboidRegion(plot.getBottomAbs().getBlockVector3(), plot.getTopAbs().getBlockVector3()), new CuboidRegion(plot.getBottomAbs().getBlockVector3(), plot.getTopAbs().getBlockVector3()),
null, null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
} }
}); });
@ -192,7 +192,7 @@ public class FaweDelegateRegionManager {
Location swapPos, Location swapPos,
final Runnable whenDone final Runnable whenDone
) { ) {
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
//todo because of the following code this should proably be in the Bukkit module //todo because of the following code this should proably be in the Bukkit module
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName())); World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
@ -220,18 +220,22 @@ public class FaweDelegateRegionManager {
Clipboard clipB = Clipboard.create(regionB, UUID.randomUUID()); Clipboard clipB = Clipboard.create(regionB, UUID.randomUUID());
ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint()); ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint());
ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint()); ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint());
copyA.setCopyingBiomes(true);
copyB.setCopyingBiomes(true);
try { try {
Operations.completeLegacy(copyA); Operations.completeLegacy(copyA);
Operations.completeLegacy(copyB); Operations.completeLegacy(copyB);
clipA.paste(sessionB, swapPos.getBlockVector3(), true); clipA.flush();
clipB.paste(sessionA, pos1.getBlockVector3(), true); clipB.flush();
sessionA.flushQueue(); clipA.paste(sessionB, swapPos.getBlockVector3(), true, true, true);
sessionB.flushQueue(); clipB.paste(sessionA, pos1.getBlockVector3(), true, true, true);
sessionA.close();
sessionB.close();
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
e.printStackTrace(); e.printStackTrace();
} }
FaweAPI.fixLighting(pos1World, new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), null, FaweAPI.fixLighting(pos1World, new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
FaweAPI.fixLighting(pos1World, new CuboidRegion( FaweAPI.fixLighting(pos1World, new CuboidRegion(
swapPos.getBlockVector3(), swapPos.getBlockVector3(),
@ -241,10 +245,10 @@ public class FaweDelegateRegionManager {
swapPos.getZ() + pos2.getZ() - pos1.getZ() swapPos.getZ() + pos2.getZ() - pos1.getZ()
) )
), null, ), null,
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE) RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
} }
}); });
@ -253,7 +257,7 @@ public class FaweDelegateRegionManager {
public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, String world, Runnable whenDone) { public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, String world, Runnable whenDone) {
region.expand(BlockVector3.at(extendBiome, 0, extendBiome)); region.expand(BlockVector3.at(extendBiome, 0, extendBiome));
region.expand(BlockVector3.at(-extendBiome, 0, -extendBiome)); region.expand(BlockVector3.at(-extendBiome, 0, -extendBiome));
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
EditSession editSession = WorldEdit EditSession editSession = WorldEdit
.getInstance() .getInstance()
@ -273,7 +277,7 @@ public class FaweDelegateRegionManager {
e.printStackTrace(); e.printStackTrace();
} }
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
} }
}); });
@ -285,7 +289,7 @@ public class FaweDelegateRegionManager {
final @NonNull Location pos3, final @NonNull Location pos3,
final @NonNull Runnable whenDone final @NonNull Runnable whenDone
) { ) {
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName())); World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
World pos3World = BukkitAdapter.adapt(getWorld(pos3.getWorldName())); World pos3World = BukkitAdapter.adapt(getWorld(pos3.getWorldName()));
@ -319,21 +323,21 @@ public class FaweDelegateRegionManager {
pos3.getBlockVector3(), pos3.getBlockVector3(),
pos3.getBlockVector3().add(pos2.getBlockVector3().subtract(pos1.getBlockVector3())) pos3.getBlockVector3().add(pos2.getBlockVector3().subtract(pos1.getBlockVector3()))
), ),
null, RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE) null, RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
); );
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
}); });
return true; return true;
} }
public boolean regenerateRegion(final Location pos1, final Location pos2, boolean ignore, final Runnable whenDone) { public boolean regenerateRegion(final Location pos1, final Location pos2, boolean ignore, final Runnable whenDone) {
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
synchronized (FaweDelegateRegionManager.class) { synchronized (FaweDelegateRegionManager.class) {
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName())); World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
try (EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World) try (EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
@ -350,7 +354,7 @@ public class FaweDelegateRegionManager {
editSession.flushQueue(); editSession.flushQueue();
} }
if (whenDone != null) { if (whenDone != null) {
TaskManager.IMP.task(whenDone); TaskManager.taskManager().task(whenDone);
} }
} }
}); });

View File

@ -132,7 +132,7 @@ public class FaweDelegateSchematicHandler {
} }
}; };
if (Fawe.isMainThread()) { if (Fawe.isMainThread()) {
com.fastasyncworldedit.core.util.TaskManager.IMP.async(r); com.fastasyncworldedit.core.util.TaskManager.taskManager().async(r);
} else { } else {
r.run(); r.run();
} }
@ -186,7 +186,7 @@ public class FaweDelegateSchematicHandler {
} }
return; return;
} }
final CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag); final CompoundTag weTag = (CompoundTag) FaweCache.INSTANCE.asTag(tag);
SchematicHandler.upload(uuid, file, "schem", new RunnableVal<>() { SchematicHandler.upload(uuid, file, "schem", new RunnableVal<>() {
@Override @Override
public void run(OutputStream output) { public void run(OutputStream output) {
@ -235,10 +235,8 @@ public class FaweDelegateSchematicHandler {
Clipboard clip = schematicReader.read(); Clipboard clip = schematicReader.read();
return new Schematic(clip); return new Schematic(clip);
} catch (IOException e3) { } catch (IOException e3) {
LOGGER.warn("{} | {} : {}", is, is.getClass().getCanonicalName(), e.getMessage());
e.printStackTrace(); e.printStackTrace();
LOGGER.warn(
is + " | " + is.getClass().getCanonicalName() + " is not in GZIP format : " + e
.getMessage());
} }
} }
} }

View File

@ -35,8 +35,8 @@ public class FaweQueueCoordinator extends QueueCoordinator {
public FaweQueueCoordinator(World world) { public FaweQueueCoordinator(World world) {
super(world); super(world);
this.world = world; this.world = world;
instance = Fawe.get().getQueueHandler().getQueue(world); instance = Fawe.instance().getQueueHandler().getQueue(world);
Fawe.get().getQueueHandler().unCache(); Fawe.instance().getQueueHandler().unCache();
} }
@Override @Override
@ -194,7 +194,7 @@ public class FaweQueueCoordinator extends QueueCoordinator {
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tag) { public boolean setTile(int x, int y, int z, CompoundTag tag) {
instance.setTile(x, y, z, (com.sk89q.jnbt.CompoundTag) FaweCache.IMP.asTag(tag)); instance.setTile(x, y, z, (com.sk89q.jnbt.CompoundTag) FaweCache.INSTANCE.asTag(tag));
return true; return true;
} }

View File

@ -37,7 +37,7 @@ public class FaweTrim extends SubCommand {
return false; return false;
} }
ran = true; ran = true;
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
try { try {
// TODO NOT IMPLEMENTED // TODO NOT IMPLEMENTED
//PlotTrim trim = new PlotTrim(plotPlayer, plotPlayer.getPlotAreaAbs(), strings[0], Boolean.parseBoolean(strings[1])); //PlotTrim trim = new PlotTrim(plotPlayer, plotPlayer.getPlotAreaAbs(), strings[0], Boolean.parseBoolean(strings[1]));

View File

@ -89,7 +89,7 @@ public class PlotSetBiome extends Command {
return; return;
} }
plot.addRunning(); plot.addRunning();
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
EditSession session = EditSession session =
WorldEdit WorldEdit
.getInstance() .getInstance()

View File

@ -4,9 +4,6 @@ import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.fastasyncworldedit.core.regions.FaweMaskManager; import com.fastasyncworldedit.core.regions.FaweMaskManager;
import com.fastasyncworldedit.core.regions.filter.RegionFilter;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
@ -62,6 +59,15 @@ public class PlotSquaredFeature extends FaweMaskManager {
*/ */
} }
/**
* Whether the player is allowed to use FAWE on a PlotSquared plot.
*
* @param player the {@link Player}
* @param plot the {@link Plot}
* @param type the {@link MaskType}
* @return {@code true} if the player is the plot owner, trusted, has the permission fawe.plotsquared.member
* or fawe.plotsquared.admin and the NoWorldeditFlag is not set; otherwise {@code false}
*/
public boolean isAllowed(Player player, Plot plot, MaskType type) { public boolean isAllowed(Player player, Plot plot, MaskType type) {
if (plot == null) { if (plot == null) {
return false; return false;
@ -121,7 +127,7 @@ public class PlotSquaredFeature extends FaweMaskManager {
} }
@Override @Override
public FaweMask getMask(Player player, MaskType type) { public FaweMask getMask(Player player, MaskType type, boolean isWhitelist) {
final PlotPlayer<org.bukkit.entity.Player> pp = PlotPlayer.from(BukkitAdapter.adapt(player)); final PlotPlayer<org.bukkit.entity.Player> pp = PlotPlayer.from(BukkitAdapter.adapt(player));
if (pp == null) { if (pp == null) {
return null; return null;

View File

@ -46,9 +46,9 @@ public class ReplaceAll extends Command {
plot.addRunning(); plot.addRunning();
FawePlayer<Object> fp = FawePlayer.wrap(player.getName()); FawePlayer<Object> fp = FawePlayer.wrap(player.getName());
Captions.TASK_START.send(player); Captions.TASK_START.send(player);
TaskManager.IMP.async(() -> fp.runAction(() -> { TaskManager.taskManager().async(() -> fp.runAction(() -> {
String worldName = plot.getWorldName(); String worldName = plot.getWorldName();
TaskManager.IMP.sync(new RunnableVal<Object>() { TaskManager.taskManager().sync(new RunnableVal<Object>() {
@Override @Override
public void run(Object value) { public void run(Object value) {
SetupUtils.manager.unload(worldName, true); SetupUtils.manager.unload(worldName, true);
@ -58,7 +58,7 @@ public class ReplaceAll extends Command {
String cmd = "/replaceallpattern " + worldName + " " + StringMan.join(args, " "); String cmd = "/replaceallpattern " + worldName + " " + StringMan.join(args, " ");
CommandEvent event = new CommandEvent(actor, cmd); CommandEvent event = new CommandEvent(actor, cmd);
PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event); PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event);
TaskManager.IMP.sync(new RunnableVal<Object>() { TaskManager.taskManager().sync(new RunnableVal<Object>() {
@Override @Override
public void run(Object value) { public void run(Object value) {
plot.teleportPlayer(player); plot.teleportPlayer(player);

View File

@ -1,172 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
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.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import java.util.concurrent.CompletableFuture;
import static org.bukkit.Bukkit.getWorld;
public class FaweChunkManager extends ChunkManager {
private final ChunkManager parent;
public FaweChunkManager(ChunkManager parent) {
this.parent = parent;
}
@Override
public int[] countEntities(Plot plot) {
return parent.countEntities(plot);
}
@Override
public CompletableFuture loadChunk(String world, BlockVector2 loc, boolean force) {
return parent.loadChunk(world, loc, force);
}
@Override
public void unloadChunk(String world, BlockVector2 loc, boolean save) {
parent.unloadChunk(world, loc, save);
}
@Override
public void clearAllEntities(Location pos1, Location pos2) {
parent.clearAllEntities(pos1, pos2);
}
@Override
public void swap(
final Location pos1,
final Location pos2,
final Location pos3,
final Location pos4,
final Runnable whenDone
) {
if (!Settings.IMP.PLOTSQUARED_INTEGRATION.COPY_AND_SWAP) {
parent.swap(pos1, pos2, pos3, pos4, whenDone);
}
TaskManager.IMP.async(() -> {
synchronized (FaweChunkManager.class) {
//todo because of the following code this should proably be in the Bukkit module
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorld()));
World pos3World = BukkitAdapter.adapt(getWorld(pos3.getWorld()));
EditSession sessionA = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build();
EditSession sessionB = WorldEdit.getInstance().newEditSessionBuilder().world(pos3World)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build();
CuboidRegion regionA = new CuboidRegion(
BlockVector3.at(pos1.getX(), pos1.getY(), pos1.getZ()),
BlockVector3.at(pos2.getX(), pos2.getY(), pos2.getZ())
);
CuboidRegion regionB = new CuboidRegion(
BlockVector3.at(pos3.getX(), pos3.getY(), pos3.getZ()),
BlockVector3.at(pos4.getX(), pos4.getY(), pos4.getZ())
);
ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, sessionB, regionB.getMinimumPoint());
ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, sessionA, regionA.getMinimumPoint());
try {
Operations.completeLegacy(copyA);
Operations.completeLegacy(copyB);
sessionA.flushQueue();
sessionB.flushQueue();
} catch (MaxChangedBlocksException e) {
e.printStackTrace();
}
TaskManager.IMP.task(whenDone);
}
});
}
@Override
public boolean copyRegion(final Location pos1, final Location pos2, final Location pos3, final Runnable whenDone) {
if (!Settings.IMP.PLOTSQUARED_INTEGRATION.COPY_AND_SWAP) {
return parent.copyRegion(pos1, pos2, pos3, whenDone);
}
TaskManager.IMP.async(() -> {
synchronized (FaweChunkManager.class) {
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorld()));
World pos3World = BukkitAdapter.adapt(getWorld(pos3.getWorld()));
EditSession from = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build();
EditSession to = WorldEdit.getInstance().newEditSessionBuilder().world(pos3World)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build();
CuboidRegion region = new CuboidRegion(
BlockVector3.at(pos1.getX(), pos1.getY(), pos1.getZ()),
BlockVector3.at(pos2.getX(), pos2.getY(), pos2.getZ())
);
ForwardExtentCopy copy = new ForwardExtentCopy(
from,
region,
to,
BlockVector3.at(pos3.getX(), pos3.getY(), pos3.getZ())
);
try {
Operations.completeLegacy(copy);
to.flushQueue();
} catch (MaxChangedBlocksException e) {
e.printStackTrace();
}
}
TaskManager.IMP.task(whenDone);
});
return true;
}
@Override
public boolean regenerateRegion(final Location pos1, final Location pos2, boolean ignore, final Runnable whenDone) {
TaskManager.IMP.async(() -> {
synchronized (FaweChunkManager.class) {
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorld()));
try (EditSession editSession = WorldEdit
.getInstance()
.newEditSessionBuilder()
.world(pos1World)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build()) {
CuboidRegion region = new CuboidRegion(
BlockVector3.at(pos1.getX(), pos1.getY(), pos1.getZ()),
BlockVector3.at(pos2.getX(), pos2.getY(), pos2.getZ())
);
editSession.regenerate(region);
editSession.flushQueue();
}
TaskManager.IMP.task(whenDone);
}
});
return true;
}
}

View File

@ -1,131 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
// TODO FIXME
public class FaweLocalBlockQueue extends LocalBlockQueue {
public final IQueueExtent<IQueueChunk> instance;
private final World world;
private final BlockVector3 mutable = new MutableBlockVector3();
public FaweLocalBlockQueue(String worldName) {
super(worldName);
this.world = FaweAPI.getWorld(worldName);
instance = Fawe.get().getQueueHandler().getQueue(world);
Fawe.get().getQueueHandler().unCache();
}
@Override
public boolean next() {
if (!instance.isEmpty()) {
instance.flush();
}
return false;
}
@Override
public void startSet(boolean parallel) {
Fawe.get().getQueueHandler().startSet(parallel);
}
@Override
public void endSet(boolean parallel) {
Fawe.get().getQueueHandler().endSet(parallel);
}
@Override
public int size() {
return instance.isEmpty() ? 0 : 1;
}
@Override
public void optimize() {
}
@Override
public void setModified(long l) {
}
@Override
public long getModified() {
return instance.size();
}
@Override
public boolean setBlock(final int x, final int y, final int z, final BlockState id) {
return instance.setBlock(x, y, z, id);
}
@Override
public boolean setBlock(int x, int y, int z, Pattern pattern) {
mutable.setComponents(x, y, z);
return pattern.apply(instance, mutable, mutable);
}
@Override
public boolean setBlock(final int x, final int y, final int z, final BaseBlock id) {
return instance.setBlock(x, y, z, id);
}
@Override
public BlockState getBlock(int x, int y, int z) {
return instance.getBlock(x, y, z);
}
@Override
public boolean setBiome(int x, int z, BiomeType biomeType) {
return instance.setBiome(x, 0, z, biomeType);
}
@Override
public String getWorld() {
return world.getId();
}
@Override
public void flush() {
instance.flush();
}
@Override
public boolean enqueue() {
boolean val = super.enqueue();
instance.enableQueue();
return val;
}
@Override
public void refreshChunk(int x, int z) {
world.refreshChunk(x, z);
}
@Override
public void fixChunkLighting(int x, int z) {
}
@Override
public void regenChunk(int x, int z) {
instance.regenerateChunk(x, z, null, null);
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tag) {
instance.setTile(x, y, z, (com.sk89q.jnbt.CompoundTag) FaweCache.IMP.asTag(tag));
return true;
}
}

View File

@ -1,154 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicWriter;
import com.fastasyncworldedit.core.jnbt.CompressedCompoundTag;
import com.fastasyncworldedit.core.jnbt.CompressedSchematicTag;
import com.fastasyncworldedit.core.util.IOUtil;
import com.fastasyncworldedit.core.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
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.BuiltInClipboardFormat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import net.jpountz.lz4.LZ4BlockInputStream;
import org.anarres.parallelgzip.ParallelGZIPOutputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static org.bukkit.Bukkit.getWorld;
public class FaweSchematicHandler extends SchematicHandler {
@Override
public boolean restoreTile(LocalBlockQueue queue, CompoundTag compoundTag, int x, int y, int z) {
if (queue instanceof FaweLocalBlockQueue) {
queue.setTile(x, y, z, compoundTag);
return true;
}
return false;
}
@Override
public void getCompoundTag(final String world, final Set<CuboidRegion> regions, final RunnableVal<CompoundTag> whenDone) {
TaskManager.IMP.async(() -> {
Location[] corners = MainUtil.getCorners(world, regions);
Location pos1 = corners[0];
Location pos2 = corners[1];
World adaptedWorld = BukkitAdapter.adapt(getWorld(world));
final CuboidRegion region = new CuboidRegion(
BlockVector3.at(pos1.getX(), pos1.getY(), pos1.getZ()),
BlockVector3.at(pos2.getX(), pos2.getY(), pos2.getZ())
);
final EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder().world(adaptedWorld)
.checkMemory(false)
.fastMode(true)
.limitUnlimited()
.changeSetNull()
.build();
ReadOnlyClipboard clipboard = ReadOnlyClipboard.of(editSession, region, false, true);
Clipboard holder = new BlockArrayClipboard(region, clipboard);
CompressedSchematicTag tag = new CompressedSchematicTag(holder);
whenDone.run(tag);
});
}
@Override
public boolean save(CompoundTag tag, String path) {
if (tag == null) {
PlotSquared.debug("&cCannot save empty tag");
return false;
}
try {
File tmp = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), path);
tmp.getParentFile().mkdirs();
if (tag instanceof CompressedCompoundTag) {
CompressedCompoundTag cTag = (CompressedCompoundTag) tag;
if (cTag instanceof CompressedSchematicTag) {
Clipboard clipboard = (Clipboard) cTag.getSource();
try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new BufferedOutputStream(
new ParallelGZIPOutputStream(stream)))) {
new FastSchematicWriter(output).write(clipboard);
}
} else {
try (OutputStream stream = new FileOutputStream(tmp); BufferedOutputStream output = new BufferedOutputStream(
new ParallelGZIPOutputStream(stream))) {
LZ4BlockInputStream is = cTag.adapt(cTag.getSource());
IOUtil.copy(is, stream);
}
}
} else {
try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new ParallelGZIPOutputStream(
stream))) {
Map<String, Tag> map = tag.getValue();
output.writeNamedTag("Schematic", map.getOrDefault("Schematic", tag));
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public void upload(final CompoundTag tag, final UUID uuid, final String file, final RunnableVal<URL> whenDone) {
if (tag == null) {
PlotSquared.debug("&cCannot save empty tag");
com.github.intellectualsites.plotsquared.plot.util.TaskManager.runTask(whenDone);
return;
}
CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag);
if (weTag instanceof CompressedSchematicTag) {
Clipboard clipboard = ((CompressedSchematicTag) weTag).getSource();
URL url = FaweAPI.upload(clipboard, BuiltInClipboardFormat.SPONGE_SCHEMATIC);
whenDone.run(url);
return;
}
MainUtil.upload(uuid, file, "schem", new RunnableVal<OutputStream>() {
@Override
public void run(OutputStream output) {
try {
try (ParallelGZIPOutputStream gzip = new ParallelGZIPOutputStream(output)) {
try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
Map<String, Tag> map = weTag.getValue();
nos.writeNamedTag("Schematic", map.getOrDefault("Schematic", weTag));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}, whenDone);
}
}

View File

@ -1,58 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.util.TaskManager;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
import com.github.intellectualsites.plotsquared.plot.commands.SubCommand;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
@CommandDeclaration(
command = "trimchunks",
permission = "plots.admin",
description = "Delete unmodified portions of your plotworld",
requiredType = RequiredType.PLAYER,
category = CommandCategory.ADMINISTRATION)
public class FaweTrim extends SubCommand {
private boolean ran = false;
@Override
public boolean onCommand(final PlotPlayer plotPlayer, final String[] strings) {
if (ran) {
plotPlayer.sendMessage("Already running!");
return false;
}
if (strings.length != 2) {
plotPlayer.sendMessage(
"First make a backup of your world called <world-copy> then stand in the middle of an empty plot");
plotPlayer.sendMessage("use /plot trimall <world> <boolean-delete-unowned>");
return false;
}
if (!WorldUtil.IMP.isWorld(strings[0])) {
Captions.NOT_VALID_PLOT_WORLD.send(plotPlayer, strings[0]);
return false;
}
ran = true;
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
try {
// TODO NOT IMPLEMENTED
// PlotTrim trim = new PlotTrim(plotPlayer, plotPlayer.getPlotAreaAbs(), strings[0], Boolean.parseBoolean(strings[1]));
// Location loc = plotPlayer.getLocation();
// trim.setChunk(loc.getX() >> 4, loc.getZ() >> 4);
// trim.run();
// plotPlayer.sendMessage("Done!");
} catch (Throwable e) {
e.printStackTrace();
}
ran = false;
}
});
return true;
}
}

View File

@ -1,105 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.util.TaskManager;
import com.github.intellectualsites.plotsquared.commands.Command;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;
import com.github.intellectualsites.plotsquared.plot.commands.MainCommand;
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.biome.Biomes;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import org.bukkit.Bukkit;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
@CommandDeclaration(
command = "generatebiome",
permission = "plots.generatebiome",
category = CommandCategory.APPEARANCE,
requiredType = RequiredType.NONE,
description = "Generate a biome in your plot",
aliases = {"bg", "gb"},
usage = "/plots generatebiome <biome>"
)
public class PlotSetBiome extends Command {
public PlotSetBiome() {
super(MainCommand.getInstance(), true);
}
@Override
public CompletableFuture<Boolean> execute(
final PlotPlayer player,
String[] args,
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) throws CommandException {
final Plot plot = check(player.getCurrentPlot(), Captions.NOT_IN_PLOT);
checkTrue(plot.isOwner(player.getUUID()) || Permissions
.hasPermission(player, "plots.admin.command.generatebiome"), Captions.NO_PLOT_PERMS);
if (plot.getRunning() != 0) {
Captions.WAIT_FOR_TIMER.send(player);
return null;
}
checkTrue(args.length == 1, Captions.COMMAND_SYNTAX, getUsage());
final Set<CuboidRegion> regions = plot.getRegions();
BiomeRegistry biomeRegistry = WorldEdit
.getInstance()
.getPlatformManager()
.queryCapability(Capability.GAME_HOOKS)
.getRegistries()
.getBiomeRegistry();
Collection<BiomeType> knownBiomes = BiomeTypes.values();
final BiomeType biome = Biomes.findBiomeByName(knownBiomes, args[0], biomeRegistry);
if (biome == null) {
String biomes = StringMan
.join(BiomeType.REGISTRY.values(), Captions.BLOCK_LIST_SEPARATOR.getTranslated());
Captions.NEED_BIOME.send(player);
MainUtil.sendMessage(player, Captions.SUBCOMMAND_SET_OPTIONS_HEADER + biomes);
return CompletableFuture.completedFuture(false);
}
confirm.run(this, () -> {
if (plot.getRunning() != 0) {
Captions.WAIT_FOR_TIMER.send(player);
return;
}
plot.addRunning();
TaskManager.IMP.async(() -> {
EditSession session = WorldEdit.getInstance().newEditSessionBuilder().world(BukkitAdapter.adapt(Bukkit.getWorld(
plot.getArea().worldname)))
.checkMemory(false)
.allowedRegionsEverywhere()
.actor(BukkitAdapter.adapt(Bukkit.getPlayer(player.getUUID())))
.limitUnlimited()
.build();
long seed = ThreadLocalRandom.current().nextLong();
for (CuboidRegion region : regions) {
session.regenerate(region, biome, seed);
}
session.flushQueue();
plot.removeRunning();
});
}, null);
return CompletableFuture.completedFuture(true);
}
}

View File

@ -1,225 +0,0 @@
package com.fastasyncworldedit.bukkit.regions.plotsquaredv4;
import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.regions.FaweMask;
import com.fastasyncworldedit.core.regions.FaweMaskManager;
import com.fastasyncworldedit.core.regions.RegionWrapper;
import com.github.intellectualsites.plotsquared.plot.commands.MainCommand;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.listener.WEManager;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionIntersection;
import com.sk89q.worldedit.world.World;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class PlotSquaredFeature extends FaweMaskManager {
private static final Logger LOGGER = LogManagerCompat.getLogger();
public PlotSquaredFeature() {
super("PlotSquared");
LOGGER.info("Optimizing PlotSquared");
if (com.fastasyncworldedit.core.configuration.Settings.IMP.ENABLED_COMPONENTS.PLOTSQUARED_V4_HOOK) {
Settings.Enabled_Components.WORLDEDIT_RESTRICTIONS = false;
try {
setupBlockQueue();
setupSchematicHandler();
setupChunkManager();
} catch (Throwable ignored) {
LOGGER.info("Please update PlotSquared: https://www.spigotmc.org/resources/77506/");
}
if (Settings.PLATFORM.toLowerCase(Locale.ROOT).startsWith("bukkit")) {
new FaweTrim();
}
if (MainCommand.getInstance().getCommand("generatebiome") == null) {
new PlotSetBiome();
}
}
// TODO: revisit this later on
/*
try {
if (Settings.Enabled_Components.WORLDS) {
new ReplaceAll();
}
} catch (Throwable e) {
log.debug("You need to update PlotSquared to access the CFI and REPLACEALL commands");
}
*/
}
public static String getName(UUID uuid) {
return UUIDHandler.getName(uuid);
}
private void setupBlockQueue() throws RuntimeException {
// If it's going to fail, throw an error now rather than later
//QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null);
//GlobalBlockQueue.IMP.setProvider(provider);
//HybridPlotManager.REGENERATIVE_CLEAR = false;
//log.debug(" - QueueProvider: " + FaweLocalBlockQueue.class);
//log.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR);
}
private void setupChunkManager() throws RuntimeException {
ChunkManager.manager = new FaweChunkManager(ChunkManager.manager);
LOGGER.info(" - ChunkManager: {}", ChunkManager.manager);
}
private void setupSchematicHandler() throws RuntimeException {
SchematicHandler.manager = new FaweSchematicHandler();
LOGGER.info(" - SchematicHandler: {}", SchematicHandler.manager);
}
public boolean isAllowed(Player player, Plot plot, MaskType type) {
if (plot == null) {
return false;
}
UUID uid = player.getUniqueId();
if (Flags.NO_WORLDEDIT.isTrue(plot)) {
player.print(Caption.of(
"fawe.cancel.reason.no.region.reason",
Caption.of("fawe.cancel.reason.no.region.plot.noworldeditflag")
));
return false;
}
if (plot.isOwner(uid) || player.hasPermission("fawe.plotsquared.admin")) {
return true;
}
if (type != MaskType.MEMBER) {
player.print(Caption.of(
"fawe.cancel.reason.no.region.reason",
Caption.of("fawe.cancel.reason.no.region.plot.owner.only")
));
return false;
}
if (plot.getTrusted().contains(uid) || plot.getTrusted().contains(DBFunc.EVERYONE)) {
return true;
}
if (plot.getMembers().contains(uid) || plot.getMembers().contains(DBFunc.EVERYONE)) {
if (!player.hasPermission("fawe.plotsquared.member")) {
player.print(Caption.of(
"fawe.cancel.reason.no.region.reason",
Caption.of("fawe.error.no-perm", "fawe.plotsquared.member")
));
return false;
}
if (!plot.getOwners().isEmpty() && plot.getOwners().stream().anyMatch(this::playerOnline)) {
return true;
} else {
player.print(Caption.of(
"fawe.cancel.reason.no.region.reason",
Caption.of("fawe.cancel.reason.no.region.plot.owner.offline")
));
return false;
}
}
player.print(Caption.of(
"fawe.cancel.reason.no.region.reason",
Caption.of("fawe.cancel.reason.no.region.not.added")
));
return false;
}
private boolean playerOnline(UUID uuid) {
if (uuid == null) {
return false;
}
org.bukkit.entity.Player player = Bukkit.getPlayer(uuid);
return player != null && player.isOnline();
}
@Override
public FaweMask getMask(Player player, MaskType type) {
final PlotPlayer pp = PlotPlayer.wrap(player.getUniqueId());
if (pp == null) {
return null;
}
final Set<CuboidRegion> regions;
Plot plot = pp.getCurrentPlot();
if (isAllowed(player, plot, type)) {
regions = plot.getRegions();
} else {
plot = null;
regions = WEManager.getMask(pp);
if (regions.size() == 1) {
CuboidRegion region = regions.iterator().next();
if (region.getMinimumPoint().getX() == Integer.MIN_VALUE && region
.getMaximumPoint()
.getX() == Integer.MAX_VALUE) {
regions.clear();
}
}
}
if (regions.isEmpty()) {
return null;
}
PlotArea area = pp.getApplicablePlotArea();
int min = area != null ? area.MIN_BUILD_HEIGHT : 0;
int max = area != null ? Math.min(255, area.MAX_BUILD_HEIGHT) : 255;
final HashSet<RegionWrapper> faweRegions = new HashSet<>();
for (CuboidRegion current : regions) {
faweRegions.add(new RegionWrapper(
current.getMinimumX(),
current.getMaximumX(),
min,
max,
current.getMinimumZ(),
current.getMaximumZ()
));
}
final CuboidRegion region = regions.iterator().next();
final BlockVector3 pos1 = BlockVector3.at(region.getMinimumX(), min, region.getMinimumZ());
final BlockVector3 pos2 = BlockVector3.at(region.getMaximumX(), max, region.getMaximumZ());
final Plot finalPlot = plot;
if (Settings.Done.RESTRICT_BUILDING && Flags.DONE.isSet(finalPlot) || regions.isEmpty()) {
return null;
}
Region maskedRegion;
if (regions.size() == 1) {
maskedRegion = new CuboidRegion(pos1, pos2);
} else {
World world = FaweAPI.getWorld(area.worldname);
List<Region> weRegions = regions.stream()
.map(r -> new CuboidRegion(
world,
BlockVector3.at(r.getMinimumX(), r.getMinimumY(), r.getMinimumZ()),
BlockVector3.at(r.getMaximumX(), r.getMaximumY(), r.getMaximumZ())
))
.collect(Collectors.toList());
maskedRegion = new RegionIntersection(world, weRegions);
}
return new FaweMask(maskedRegion) {
@Override
public boolean isValid(Player player, MaskType type) {
if (Settings.Done.RESTRICT_BUILDING && Flags.DONE.isSet(finalPlot)) {
return false;
}
return isAllowed(player, finalPlot, type);
}
};
}
}

View File

@ -34,7 +34,7 @@ public class BukkitItemStack extends BaseItemStack {
@Nullable @Nullable
@Override @Override
public Object getNativeItem() { public Object getNativeItem() {
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil(); ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
if (util != null && nativeItem == null) { if (util != null && nativeItem == null) {
return nativeItem = util.getNMSItem(stack); return nativeItem = util.getNMSItem(stack);
} }
@ -58,7 +58,7 @@ public class BukkitItemStack extends BaseItemStack {
public CompoundTag getNbtData() { public CompoundTag getNbtData() {
if (!loadedNBT) { if (!loadedNBT) {
loadedNBT = true; loadedNBT = true;
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil(); ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
if (util != null) { if (util != null) {
super.setNbtData(util.getNBT(stack)); super.setNbtData(util.getNBT(stack));
} }
@ -68,7 +68,7 @@ public class BukkitItemStack extends BaseItemStack {
@Override @Override
public void setNbtData(@Nullable CompoundTag nbtData) { public void setNbtData(@Nullable CompoundTag nbtData) {
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil(); ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
if (util != null) { if (util != null) {
stack = util.setNBT(stack, nbtData); stack = util.setNBT(stack, nbtData);
nativeItem = null; nativeItem = null;

View File

@ -12,6 +12,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16); public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16);
public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17); public static final MinecraftVersion CAVES_17 = new MinecraftVersion(1, 17);
public static final MinecraftVersion CAVES_18 = new MinecraftVersion(1, 18);
private final int major; private final int major;
private final int minor; private final int minor;
@ -68,7 +69,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
* @param other The other version to compare against. * @param other The other version to compare against.
* @return {@code true} if this version is higher or equal compared to the other version. * @return {@code true} if this version is higher or equal compared to the other version.
*/ */
public boolean isEqualOrHigher(MinecraftVersion other) { public boolean isEqualOrHigherThan(MinecraftVersion other) {
return compareTo(other) >= 0; return compareTo(other) >= 0;
} }
@ -76,7 +77,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
* @param other The other version to compare against. * @param other The other version to compare against.
* @return {@code true} if this version is lower or equal compared to the other version. * @return {@code true} if this version is lower or equal compared to the other version.
*/ */
public boolean isEqualOrLower(MinecraftVersion other) { public boolean isEqualOrLowerThan(MinecraftVersion other) {
return compareTo(other) <= 0; return compareTo(other) <= 0;
} }
@ -84,7 +85,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
* @param other The other version to compare against. * @param other The other version to compare against.
* @return {@code true} if this version is higher than the other version. * @return {@code true} if this version is higher than the other version.
*/ */
public boolean isHigher(MinecraftVersion other) { public boolean isHigherThan(MinecraftVersion other) {
return compareTo(other) > 0; return compareTo(other) > 0;
} }
@ -92,7 +93,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
* @param other The other version to compare against. * @param other The other version to compare against.
* @return {@code true} if this version is lower than to the other version. * @return {@code true} if this version is lower than to the other version.
*/ */
public boolean isLower(MinecraftVersion other) { public boolean isLowerThan(MinecraftVersion other) {
return compareTo(other) < 0; return compareTo(other) < 0;
} }
@ -139,6 +140,11 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
return getRelease() == that.getRelease(); return getRelease() == that.getRelease();
} }
@Override
public String toString() {
return major + "." + minor + "." + release;
}
/** /**
* Determines the server version based on the CraftBukkit package path, e.g. {@code org.bukkit.craftbukkit.v1_16_R3}, * Determines the server version based on the CraftBukkit package path, e.g. {@code org.bukkit.craftbukkit.v1_16_R3},
* where v1_16_R3 is the resolved version. * where v1_16_R3 is the resolved version.

View File

@ -107,7 +107,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
this.player = player; this.player = player;
//FAWE start //FAWE start
this.permAttachment = plugin.getPermissionAttachmentManager().getOrAddAttachment(player); this.permAttachment = plugin.getPermissionAttachmentManager().getOrAddAttachment(player);
if (player != null && Settings.IMP.CLIPBOARD.USE_DISK) { if (player != null && Settings.settings().CLIPBOARD.USE_DISK) {
BukkitPlayer cached = WorldEditPlugin.getInstance().getCachedPlayer(player); BukkitPlayer cached = WorldEditPlugin.getInstance().getCachedPlayer(player);
if (cached == null) { if (cached == null) {
loadClipboardFromDisk(); loadClipboardFromDisk();
@ -169,7 +169,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
player.getInventory().setItemInMainHand(newItem); player.getInventory().setItemInMainHand(newItem);
HashMap<Integer, ItemStack> overflow = inv.addItem(item); HashMap<Integer, ItemStack> overflow = inv.addItem(item);
if (!overflow.isEmpty()) { if (!overflow.isEmpty()) {
TaskManager.IMP.sync(new RunnableVal<>() { TaskManager.taskManager().sync(new RunnableVal<>() {
@Override @Override
public void run(Object value) { public void run(Object value) {
for (Map.Entry<Integer, ItemStack> entry : overflow.entrySet()) { for (Map.Entry<Integer, ItemStack> entry : overflow.entrySet()) {
@ -243,7 +243,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
} }
org.bukkit.World finalWorld = world; org.bukkit.World finalWorld = world;
//FAWE end //FAWE end
return TaskManager.IMP.sync(() -> player.teleport(new Location( return TaskManager.taskManager().sync(() -> player.teleport(new Location(
finalWorld, finalWorld,
pos.getX(), pos.getX(),
pos.getY(), pos.getY(),

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.sk89q.bukkit.util.CommandInfo; import com.sk89q.bukkit.util.CommandInfo;
@ -274,9 +275,19 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser
RelighterFactory getRelighterFactory() { RelighterFactory getRelighterFactory() {
if (this.relighterFactory == null) { if (this.relighterFactory == null) {
this.relighterFactory = this.plugin.getBukkitImplAdapter().getRelighterFactory(); this.relighterFactory = this.plugin.getBukkitImplAdapter().getRelighterFactory();
LOGGER.info("Using " + this.relighterFactory.getClass().getCanonicalName() + " as relighter factory."); LOGGER.info("Using {} as relighter factory.", this.relighterFactory.getClass().getCanonicalName());
} }
return this.relighterFactory; return this.relighterFactory;
} }
@Override
public int versionMinY() {
return new MinecraftVersion().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? -64 : 0;
}
@Override
public int versionMaxY() {
return new MinecraftVersion().isEqualOrHigherThan(MinecraftVersion.CAVES_18) ? 319 : 255;
}
//FAWE end //FAWE end
} }

View File

@ -301,10 +301,10 @@ public class BukkitWorld extends AbstractWorld {
if (treeTypeMapping.get(type) == null) { if (treeTypeMapping.get(type) == null) {
LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type); LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type);
//FAWE start //FAWE start
LOGGER.info("The above message is displayed because your FAWE version is newer than " + Bukkit.getVersion() + 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 " " and contains features of future minecraft versions which do not exist in {} hence the tree type" +
+ Bukkit.getVersion() + ", hence the tree type " + type + " is not available. This is not an error. " + "{} is not available. This is not an error. This version will work on your version of Minecraft." +
"This version will work on your version of Minecraft. This is an informative message only"); "This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type);
//FAWE end //FAWE end
} }
} }
@ -317,7 +317,7 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) { public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) {
//FAWE start - allow tree commands to be undone and obey region restrictions //FAWE start - allow tree commands to be undone and obey region restrictions
return TaskManager.IMP.sync(() -> WorldEditPlugin.getInstance().getBukkitImplAdapter().generateTree(type, editSession, pt, return TaskManager.taskManager().sync(() -> WorldEditPlugin.getInstance().getBukkitImplAdapter().generateTree(type, editSession, pt,
getWorld() getWorld()
)); ));
//FAWE end //FAWE end
@ -520,7 +520,7 @@ public class BukkitWorld extends AbstractWorld {
public BaseBlock getFullBlock(BlockVector3 position) { public BaseBlock getFullBlock(BlockVector3 position) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
return adapter.getBlock(BukkitAdapter.adapt(getWorld(), position)); return adapter.getFullBlock(BukkitAdapter.adapt(getWorld(), position));
} else { } else {
return getBlock(position).toBaseBlock(); return getBlock(position).toBaseBlock();
} }
@ -555,7 +555,7 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean fullySupports3DBiomes() { public boolean fullySupports3DBiomes() {
// Supports if API does and we're not in the overworld // Supports if API does and we're not in the overworld
return HAS_3D_BIOMES && getWorld().getEnvironment() != World.Environment.NORMAL; return HAS_3D_BIOMES && getWorld().getEnvironment() != World.Environment.NORMAL || PaperLib.isVersion(18);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View File

@ -138,12 +138,12 @@ public class WorldEditPlugin extends JavaPlugin {
platform = new BukkitServerInterface(this, getServer()); platform = new BukkitServerInterface(this, getServer());
worldEdit.getPlatformManager().register(platform); worldEdit.getPlatformManager().register(platform);
//FAWE start - Rename config to config-legacy.yml TODO: Chose a better name in the future //FAWE start - Migrate from config-legacy to worldedit-config
createDefaultConfiguration("config-legacy.yml"); // Create the default configuration file for WorldEdit, for us it's 'config-legacy.yml' migrateLegacyConfig();
//FAWE end //FAWE end
//FAWE start - Modify WorldEdit config name //FAWE start - Modify WorldEdit config name
config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config-legacy.yml"), true), this); config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "worldedit-config.yml"), true), this);
//FAWE end //FAWE end
//FAWE start - Setup permission attachments //FAWE start - Setup permission attachments
@ -220,8 +220,6 @@ public class WorldEditPlugin extends JavaPlugin {
// Enable metrics // Enable metrics
new Metrics(this, BSTATS_ID); new Metrics(this, BSTATS_ID);
// Check whether the server runs on 11 or greater
ServerLib.checkJavaLTS();
// Check if we are in a safe environment // Check if we are in a safe environment
ServerLib.checkUnsafeForks(); ServerLib.checkUnsafeForks();
// Check if a new build is available // Check if a new build is available
@ -369,8 +367,8 @@ public class WorldEditPlugin extends JavaPlugin {
} else { } else {
//FAWE start - Identify as FAWE //FAWE start - Identify as FAWE
LOGGER.info("FastAsyncWorldEdit could not find a Bukkit adapter for this MC version, " LOGGER.info("FastAsyncWorldEdit could not find a Bukkit adapter for this MC version, "
+ "but it seems that you have another implementation of FastAsyncWorldEdit installed (" + platform.getPlatformName() + ") " + "but it seems that you have another implementation of FastAsyncWorldEdit installed ({}) "
+ "that handles the world editing."); + "that handles the world editing.", platform.getPlatformName());
//FAWE end //FAWE end
} }
this.adapter.invalidate(); this.adapter.invalidate();
@ -382,7 +380,7 @@ public class WorldEditPlugin extends JavaPlugin {
*/ */
@Override @Override
public void onDisable() { public void onDisable() {
Fawe.get().onDisable(); Fawe.instance().onDisable();
WorldEdit worldEdit = WorldEdit.getInstance(); WorldEdit worldEdit = WorldEdit.getInstance();
worldEdit.getSessionManager().unload(); worldEdit.getSessionManager().unload();
if (platform != null) { if (platform != null) {
@ -424,6 +422,19 @@ public class WorldEditPlugin extends JavaPlugin {
} }
} }
private void migrateLegacyConfig() {
File legacy = new File(getDataFolder(), "config-legacy.yml");
if (legacy.exists()) {
try {
legacy.renameTo(new File(getDataFolder(), "worldedit-config.yml"));
LOGGER.info("Migrated config-legacy.yml to worldedit-config.yml");
} catch (Exception e) {
LOGGER.error("Unable to rename legacy config file", e);
}
}
createDefaultConfiguration("worldedit-config.yml");
}
private void copyDefaultConfig(InputStream input, File actual, String name) { private void copyDefaultConfig(InputStream input, File actual, String name) {
try (FileOutputStream output = new FileOutputStream(actual)) { try (FileOutputStream output = new FileOutputStream(actual)) {
byte[] buf = new byte[8192]; byte[] buf = new byte[8192];

View File

@ -106,7 +106,15 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
* @param location the location * @param location the location
* @return the block * @return the block
*/ */
BaseBlock getBlock(Location location); BlockState getBlock(Location location);
/**
* Get the block at the given location.
*
* @param location the location
* @return the block
*/
BaseBlock getFullBlock(Location location);
/** /**
* Create a {@link WorldNativeAccess} for the given world reference. * Create a {@link WorldNativeAccess} for the given world reference.
@ -306,7 +314,7 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
@Nullable @Nullable
default World createWorld(WorldCreator creator) { default World createWorld(WorldCreator creator) {
return ((FaweBukkit) Fawe.imp()).createWorldUnloaded(creator::createWorld); return ((FaweBukkit) Fawe.platform()).createWorldUnloaded(creator::createWorld);
} }
/** /**

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.bukkit.adapter; package com.sk89q.worldedit.bukkit.adapter;
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.Closer;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -39,6 +40,8 @@ public class BukkitImplLoader {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private final List<String> adapterCandidates = new ArrayList<>(); private final List<String> adapterCandidates = new ArrayList<>();
private final String minorMCVersion = String.valueOf(new MinecraftVersion().getMinor());
private int zeroth = 0;
private String customCandidate; private String customCandidate;
private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.bukkit.adapter.impl.fawe"; private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.bukkit.adapter.impl.fawe";
@ -73,6 +76,7 @@ public class BukkitImplLoader {
String className = System.getProperty("worldedit.bukkit.adapter"); String className = System.getProperty("worldedit.bukkit.adapter");
if (className != null) { if (className != null) {
customCandidate = className; customCandidate = className;
zeroth = 1;
adapterCandidates.add(className); adapterCandidates.add(className);
LOGGER.info("-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters"); LOGGER.info("-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters");
} }
@ -101,8 +105,12 @@ public class BukkitImplLoader {
int beginIndex = 0; int beginIndex = 0;
int endIndex = className.length() - CLASS_SUFFIX.length(); int endIndex = className.length() - CLASS_SUFFIX.length();
className = className.substring(beginIndex, endIndex); className = className.substring(beginIndex, endIndex);
if (className.contains(minorMCVersion)) {
adapterCandidates.add(zeroth, className);
} else {
adapterCandidates.add(className); adapterCandidates.add(className);
} }
}
} finally { } finally {
closer.close(); closer.close();
} }
@ -142,9 +150,13 @@ public class BukkitImplLoader {
int beginIndex = 0; int beginIndex = 0;
int endIndex = resource.length() - CLASS_SUFFIX.length(); int endIndex = resource.length() - CLASS_SUFFIX.length();
String className = resource.substring(beginIndex, endIndex); String className = resource.substring(beginIndex, endIndex);
if (className.contains(minorMCVersion)) {
adapterCandidates.add(zeroth, className);
} else {
adapterCandidates.add(className); adapterCandidates.add(className);
} }
} }
}
/** /**
* Iterate through the list of candidates and load an adapter. * Iterate through the list of candidates and load an adapter.

View File

@ -10,39 +10,39 @@
# in categories, like "max-blocks-changed", are placed in the "limits" # in categories, like "max-blocks-changed", are placed in the "limits"
# category. # category.
# - If you want to check the format of this file before putting it # - If you want to check the format of this file before putting it
# into WorldEdit, paste it into http://yaml-online-parser.appspot.com/ # into WorldEdit, paste it into https://yaml-online-parser.appspot.com/
# and see if it gives you "ERROR:". # and see if it gives you "ERROR:".
# - Lines starting with # are comments, so they are ignored. # - Lines starting with # are comments, so they are ignored.
# - If you want to allow blocks, make sure to change "disallowed-blocks" to [] # - If you want to allow blocks, make sure to change "disallowed-blocks" to []
# #
limits : limits:
max-blocks-changed : max-blocks-changed:
# Ignored, use FAWE config limits # Ignored, use FAWE config limits
default : -1 default: -1
maximum : -1 maximum: -1
max-polygonal-points : max-polygonal-points:
default : -1 default: -1
maximum : 20 maximum: 20
max-radius : -1 max-radius: -1
max-super-pickaxe-size : 5 max-super-pickaxe-size: 5
max-brush-radius : 100 max-brush-radius: 100
butcher-radius : butcher-radius:
default : -1 default: -1
maximum : -1 maximum: -1
disallowed-blocks : disallowed-blocks:
- "minecraft:wheat" - "minecraft:wheat"
- "minecraft:fire" - "minecraft:fire"
- "minecraft:redstone_wire" - "minecraft:redstone_wire"
use-inventory : use-inventory:
enable : false enable: false
allow-override : true allow-override: true
creative-mode-overrides : false creative-mode-overrides: false
logging : logging:
log-commands : false log-commands: false
file : worldedit.log file: worldedit.log
# The format of custom log message. This is java general format string (java.util.Formatter). Arguments are: # The format of custom log message. This is java general format string (java.util.Formatter). Arguments are:
# 1$ : date - a Date object representing event time of the log record. # 1$ : date - a Date object representing event time of the log record.
# 2$ : source - a string representing the caller, if available; otherwise, the logger's name. # 2$ : source - a string representing the caller, if available; otherwise, the logger's name.
@ -53,44 +53,44 @@ logging :
# For details see: # For details see:
# https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html # https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html
# https://docs.oracle.com/javase/8/docs/api/java/util/logging/SimpleFormatter.html#format-java.util.logging.LogRecord- # https://docs.oracle.com/javase/8/docs/api/java/util/logging/SimpleFormatter.html#format-java.util.logging.LogRecord-
format : "[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s]: %5$s%6$s%n" format: "[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s]: %5$s%6$s%n"
super-pickaxe : super-pickaxe:
drop-items : true drop-items: true
many-drop-items : false many-drop-items: false
snapshots : snapshots:
directory : directory:
navigation-wand : navigation-wand:
item : minecraft:compass item: minecraft:compass
max-distance : 100 max-distance: 100
scripting : scripting:
timeout : 3000 timeout: 3000
dir : craftscripts dir: craftscripts
saving : saving:
dir : schematics dir: schematics
files : files:
allow-symbolic-links : false allow-symbolic-links: false
history : history:
size : 15 size: 15
expiration : 10 expiration: 10
calculation : calculation:
timeout : 100 timeout: 100
debugging : debugging:
trace-unflushed-sessions : false trace-unflushed-sessions: false
wand-item : minecraft:wooden_axe wand-item: minecraft:wooden_axe
shell-save-type : shell-save-type:
no-double-slash : false no-double-slash: false
no-op-permissions : false no-op-permissions: false
debug : false debug: false
show-help-on-first-use : true show-help-on-first-use: true
server-side-cui : true server-side-cui: true
command-block-support : false command-block-support: false

View File

@ -20,14 +20,14 @@ public class MinecraftVersionTest {
@Test @Test
public void testEqualOrHigher() { public void testEqualOrHigher() {
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 3))); assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 3)));
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 2))); assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 2)));
assertFalse(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 4))); assertFalse(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 4)));
} }
@Test @Test
public void testEqualOrHigherWithoutRelease() { public void testEqualOrHigherWithoutRelease() {
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16))); assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16)));
} }
@Test @Test
@ -39,15 +39,15 @@ public class MinecraftVersionTest {
@Test @Test
public void testEqualOrLower() { public void testEqualOrLower() {
assertTrue(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 3))); assertTrue(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 3)));
assertTrue(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 4))); assertTrue(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 4)));
assertFalse(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 2))); assertFalse(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 2)));
} }
@Test @Test
public void testForChunkStretched() { public void testForChunkStretched() {
assertTrue(latestVersion.isEqualOrHigher(MinecraftVersion.NETHER)); assertTrue(latestVersion.isEqualOrHigherThan(MinecraftVersion.NETHER));
assertFalse(latestVersion.isLower(new MinecraftVersion(1, 14, 2))); assertFalse(latestVersion.isLowerThan(new MinecraftVersion(1, 14, 2)));
} }
} }

View File

@ -118,6 +118,11 @@ public class StubServer implements Server {
return 0; return 0;
} }
@Override
public int getSimulationDistance() {
return 12;
}
@Override @Override
public @NotNull public @NotNull
String getIp() { String getIp() {
@ -150,6 +155,26 @@ public class StubServer implements Server {
return false; return false;
} }
@Override
public @NotNull String getResourcePack() {
return null;
}
@Override
public @NotNull String getResourcePackHash() {
return null;
}
@Override
public @NotNull String getResourcePackPrompt() {
return null;
}
@Override
public boolean isResourcePackRequired() {
return false;
}
@Override @Override
public boolean hasWhitelist() { public boolean hasWhitelist() {
return false; return false;
@ -465,6 +490,11 @@ public class StubServer implements Server {
} }
@Override
public boolean getHideOnlinePlayers() {
return false;
}
@Override @Override
public boolean getOnlineMode() { public boolean getOnlineMode() {
return false; return false;

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlatform; import com.sk89q.worldedit.extension.platform.AbstractPlatform;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -169,6 +170,16 @@ class CLIPlatform extends AbstractPlatform {
return (_a, _b, _c) -> NullRelighter.INSTANCE; return (_a, _b, _c) -> NullRelighter.INSTANCE;
} }
@Override
public int versionMinY() {
return dataVersion >= Constants.DATA_VERSION_MC_1_18 ? -64 : 0;
}
@Override
public int versionMaxY() {
return dataVersion >= Constants.DATA_VERSION_MC_1_18 ? 319 : 255;
}
public void addWorld(World world) { public void addWorld(World world) {
worlds.add(world); worlds.add(world);
} }

View File

@ -190,7 +190,7 @@ public class CLIWorldEdit {
this.commandSender = new CLICommandSender(this, LOGGER); this.commandSender = new CLICommandSender(this, LOGGER);
this.platform = new CLIPlatform(this); this.platform = new CLIPlatform(this);
//FAWE start - identify as Fawe //FAWE start - identify as Fawe
LOGGER.info("FastAsyncWorldEdit CLI (version " + getInternalVersion() + ") is loaded"); LOGGER.info("FastAsyncWorldEdit CLI (version {}) is loaded", getInternalVersion());
//FAWE end //FAWE end
} }

View File

@ -12,7 +12,7 @@ applyPlatformAndCoreConfiguration()
dependencies { dependencies {
constraints { constraints {
implementation("org.yaml:snakeyaml") { implementation("org.yaml:snakeyaml") {
version { strictly("1.28") } version { strictly("1.30") }
because("Bukkit provides SnakeYaml") because("Bukkit provides SnakeYaml")
} }
} }
@ -37,7 +37,6 @@ dependencies {
// Plugins // Plugins
compileOnly(libs.redprotect) { isTransitive = false } compileOnly(libs.redprotect) { isTransitive = false }
compileOnly(libs.plotsquaredV4) { isTransitive = false }
compileOnly(libs.plotsquaredV6Core) { isTransitive = false } compileOnly(libs.plotsquaredV6Core) { isTransitive = false }
// ensure this is on the classpath for the AP // ensure this is on the classpath for the AP

View File

@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.5.0-RC" kotlin("jvm") version "1.5.30"
application application
} }

View File

@ -101,17 +101,17 @@ public class Fawe {
this.setupConfigs(); this.setupConfigs();
TaskManager.IMP = this.implementation.getTaskManager(); TaskManager.IMP = this.implementation.getTaskManager();
TaskManager.IMP.async(() -> { TaskManager.taskManager().async(() -> {
MainUtil.deleteOlder( MainUtil.deleteOlder(
MainUtil.getFile(this.implementation MainUtil.getFile(this.implementation
.getDirectory(), Settings.IMP.PATHS.HISTORY), .getDirectory(), Settings.settings().PATHS.HISTORY),
TimeUnit.DAYS.toMillis(Settings.IMP.HISTORY.DELETE_AFTER_DAYS), TimeUnit.DAYS.toMillis(Settings.settings().HISTORY.DELETE_AFTER_DAYS),
false false
); );
MainUtil.deleteOlder( MainUtil.deleteOlder(
MainUtil.getFile(this.implementation MainUtil.getFile(this.implementation
.getDirectory(), Settings.IMP.PATHS.CLIPBOARD), .getDirectory(), Settings.settings().PATHS.CLIPBOARD),
TimeUnit.DAYS.toMillis(Settings.IMP.CLIPBOARD.DELETE_AFTER_DAYS), TimeUnit.DAYS.toMillis(Settings.settings().CLIPBOARD.DELETE_AFTER_DAYS),
false false
); );
}); });
@ -123,28 +123,49 @@ public class Fawe {
this.timer = new FaweTimer(); this.timer = new FaweTimer();
// Delayed worldedit setup // Delayed worldedit setup
TaskManager.IMP.later(() -> { TaskManager.taskManager().later(() -> {
try { try {
WEManager.IMP.addManagers(Fawe.this.implementation.getMaskManagers()); WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers());
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }
}, 0); }, 0);
TaskManager.IMP.repeat(timer, 1); TaskManager.taskManager().repeat(timer, 1);
} }
/** /**
* Get the implementation specific class. * Get the implementation specific class.
* @deprecated use {@link #platform()}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Deprecated(forRemoval = true, since = "2.0.0")
public static <T extends IFawe> T imp() { public static <T extends IFawe> T imp() {
return instance != null ? (T) instance.implementation : null; return instance != null ? (T) instance.implementation : null;
} }
/**
* Get the implementation specific class.
* @since 2.0.0
*/
@SuppressWarnings("unchecked")
public static <T extends IFawe> T platform() {
return instance != null ? (T) instance.implementation : null;
}
/**
* Get the implementation independent class.
* @deprecated use {@link #instance()}
*/
@Deprecated(forRemoval = true, since = "2.0.0")
public static Fawe get() {
return instance;
}
/** /**
* Get the implementation independent class. * Get the implementation independent class.
*/ */
public static Fawe get() { public static Fawe instance() {
return instance; return instance;
} }
@ -225,8 +246,8 @@ public class Fawe {
} }
public void onDisable() { public void onDisable() {
if (imp().getPreloader(false) != null) { if (platform().getPreloader(false) != null) {
imp().getPreloader(false).cancel(); platform().getPreloader(false).cancel();
} }
} }
@ -296,7 +317,7 @@ public class Fawe {
MainUtil.copyFile(MainUtil.getJarFile(), "lang/strings.json", null); MainUtil.copyFile(MainUtil.getJarFile(), "lang/strings.json", null);
// Setting up config.yml // Setting up config.yml
File file = new File(this.implementation.getDirectory(), "config.yml"); File file = new File(this.implementation.getDirectory(), "config.yml");
Settings.IMP.PLATFORM = implementation.getPlatform().replace("\"", ""); Settings.settings().PLATFORM = implementation.getPlatform().replace("\"", "");
try (InputStream stream = getClass().getResourceAsStream("/fawe.properties"); try (InputStream stream = getClass().getResourceAsStream("/fawe.properties");
BufferedReader br = new BufferedReader(new InputStreamReader(stream))) { BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
String versionString = br.readLine(); String versionString = br.readLine();
@ -304,17 +325,17 @@ public class Fawe {
String dateString = br.readLine(); String dateString = br.readLine();
br.close(); br.close();
this.version = FaweVersion.tryParse(versionString, commitString, dateString); this.version = FaweVersion.tryParse(versionString, commitString, dateString);
Settings.IMP.DATE = new Date(100 + version.year, version.month, version.day).toString(); Settings.settings().DATE = new Date(100 + version.year, version.month, version.day).toString();
Settings.IMP.BUILD = "https://ci.athion.net/job/FastAsyncWorldEdit-1.17/" + version.build; Settings.settings().BUILD = "https://ci.athion.net/job/FastAsyncWorldEdit/" + version.build;
Settings.IMP.COMMIT = "https://github.com/IntellectualSites/FastAsyncWorldEdit/commit/" + Integer.toHexString(version.hash); Settings.settings().COMMIT = "https://github.com/IntellectualSites/FastAsyncWorldEdit/commit/" + Integer.toHexString(version.hash);
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }
try { try {
Settings.IMP.reload(file); Settings.settings().reload(file);
} catch (Throwable e) { } catch (Throwable e) {
LOGGER.error("Failed to load config.", e); LOGGER.error("Failed to load config.", e);
} }
Settings.IMP.QUEUE.TARGET_SIZE = Math.max(Settings.IMP.QUEUE.TARGET_SIZE, Settings.IMP.QUEUE.PARALLEL_THREADS); Settings.settings().QUEUE.TARGET_SIZE = Math.max(Settings.settings().QUEUE.TARGET_SIZE, Settings.settings().QUEUE.PARALLEL_THREADS);
try { try {
byte[] in = new byte[0]; byte[] in = new byte[0];
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in); byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in);
@ -332,14 +353,14 @@ public class Fawe {
assert (Zstd.decompress(ob, compressed) == 0); assert (Zstd.decompress(ob, compressed) == 0);
LOGGER.info("ZSTD Compression Binding loaded successfully"); LOGGER.info("ZSTD Compression Binding loaded successfully");
} catch (Throwable e) { } catch (Throwable e) {
if (Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL > 6 || Settings.IMP.HISTORY.COMPRESSION_LEVEL > 6) { if (Settings.settings().CLIPBOARD.COMPRESSION_LEVEL > 6 || Settings.settings().HISTORY.COMPRESSION_LEVEL > 6) {
Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL); Settings.settings().CLIPBOARD.COMPRESSION_LEVEL = Math.min(6, Settings.settings().CLIPBOARD.COMPRESSION_LEVEL);
Settings.IMP.HISTORY.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.HISTORY.COMPRESSION_LEVEL); Settings.settings().HISTORY.COMPRESSION_LEVEL = Math.min(6, Settings.settings().HISTORY.COMPRESSION_LEVEL);
LOGGER.error("ZSTD Compression Binding Not Found.\n" LOGGER.error("ZSTD Compression Binding Not Found.\n"
+ "FAWE will still work but compression won't work as well.", e); + "FAWE will still work but compression won't work as well.", e);
} }
} }
Settings.IMP.save(file); Settings.settings().save(file);
} }
public WorldEdit getWorldEdit() { public WorldEdit getWorldEdit() {
@ -347,7 +368,7 @@ public class Fawe {
} }
private void setupMemoryListener() { private void setupMemoryListener() {
if (Settings.IMP.MAX_MEMORY_PERCENT < 1 || Settings.IMP.MAX_MEMORY_PERCENT > 99) { if (Settings.settings().MAX_MEMORY_PERCENT < 1 || Settings.settings().MAX_MEMORY_PERCENT > 99) {
return; return;
} }
try { try {
@ -371,7 +392,7 @@ public class Fawe {
if (max < 0) { if (max < 0) {
continue; continue;
} }
final long alert = (max * Settings.IMP.MAX_MEMORY_PERCENT) / 100; final long alert = (max * Settings.settings().MAX_MEMORY_PERCENT) / 100;
mp.setUsageThreshold(alert); mp.setUsageThreshold(alert);
} }
} }

View File

@ -11,7 +11,6 @@ import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent; import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
import com.fastasyncworldedit.core.regions.FaweMaskManager; import com.fastasyncworldedit.core.regions.FaweMaskManager;
import com.fastasyncworldedit.core.regions.RegionWrapper; import com.fastasyncworldedit.core.regions.RegionWrapper;
import com.fastasyncworldedit.core.util.EditSessionBuilder;
import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.MemUtil; import com.fastasyncworldedit.core.util.MemUtil;
import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TaskManager;
@ -60,24 +59,13 @@ public class FaweAPI {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
/**
* Offers a lot of options for building an EditSession.
*
* @return A new EditSessionBuilder
* @deprecated See {@link WorldEdit#newEditSessionBuilder()}
*/
@Deprecated(forRemoval = true)
public static EditSessionBuilder getEditSessionBuilder(World world) {
return new EditSessionBuilder(world);
}
/** /**
* The TaskManager has some useful methods for doing things asynchronously. * The TaskManager has some useful methods for doing things asynchronously.
* *
* @return TaskManager * @return TaskManager
*/ */
public static TaskManager getTaskManager() { public static TaskManager getTaskManager() {
return TaskManager.IMP; return TaskManager.taskManager();
} }
/** /**
@ -93,7 +81,7 @@ public class FaweAPI {
* @return the queue extent * @return the queue extent
*/ */
public static IQueueExtent<IQueueChunk> createQueue(World world, boolean autoQueue) { public static IQueueExtent<IQueueChunk> createQueue(World world, boolean autoQueue) {
IQueueExtent<IQueueChunk> queue = Fawe.get().getQueueHandler().getQueue(world); IQueueExtent<IQueueChunk> queue = Fawe.instance().getQueueHandler().getQueue(world);
if (!autoQueue) { if (!autoQueue) {
queue.disableQueue(); queue.disableQueue();
} }
@ -139,7 +127,7 @@ public class FaweAPI {
* @return Set of FaweMaskManager * @return Set of FaweMaskManager
*/ */
public static Set<FaweMaskManager> getMaskManagers() { public static Set<FaweMaskManager> getMaskManagers() {
return new HashSet<>(WEManager.IMP.getManagers()); return new HashSet<>(WEManager.weManager().getManagers());
} }
/** /**
@ -155,7 +143,7 @@ public class FaweAPI {
* Get a player's allowed WorldEdit region(s). * Get a player's allowed WorldEdit region(s).
*/ */
public static Region[] getRegions(Player player) { public static Region[] getRegions(Player player) {
return WEManager.IMP.getMask(player); return WEManager.weManager().getMask(player);
} }
/** /**
@ -167,7 +155,7 @@ public class FaweAPI {
* @return array of allowed regions if whitelist, else of disallowed regions. * @return array of allowed regions if whitelist, else of disallowed regions.
*/ */
public static Region[] getRegions(Player player, FaweMaskManager.MaskType type, boolean isWhiteList) { public static Region[] getRegions(Player player, FaweMaskManager.MaskType type, boolean isWhiteList) {
return WEManager.IMP.getMask(player, type, isWhiteList); return WEManager.weManager().getMask(player, type, isWhiteList);
} }
/** /**
@ -182,13 +170,13 @@ public class FaweAPI {
*/ */
public static void cancelEdit(AbstractDelegateExtent extent, Component reason) { public static void cancelEdit(AbstractDelegateExtent extent, Component reason) {
try { try {
WEManager.IMP.cancelEdit(extent, new FaweException(reason)); WEManager.weManager().cancelEdit(extent, new FaweException(reason));
} catch (WorldEditException ignored) { } catch (WorldEditException ignored) {
} }
} }
public static void addMaskManager(FaweMaskManager maskMan) { public static void addMaskManager(FaweMaskManager maskMan) {
WEManager.IMP.addManager(maskMan); WEManager.weManager().addManager(maskMan);
} }
/** /**
@ -198,7 +186,7 @@ public class FaweAPI {
if (!file.exists() || file.isDirectory()) { if (!file.exists() || file.isDirectory()) {
throw new IllegalArgumentException("Not a file!"); throw new IllegalArgumentException("Not a file!");
} }
if (Settings.IMP.HISTORY.USE_DISK) { if (Settings.settings().HISTORY.USE_DISK) {
throw new IllegalArgumentException("History on disk not enabled!"); throw new IllegalArgumentException("History on disk not enabled!");
} }
if (!file.getName().toLowerCase(Locale.ROOT).endsWith(".bd")) { if (!file.getName().toLowerCase(Locale.ROOT).endsWith(".bd")) {
@ -236,11 +224,10 @@ public class FaweAPI {
*/ */
public static List<DiskStorageHistory> getBDFiles(Location origin, UUID user, int radius, long timediff, boolean shallow) { public static List<DiskStorageHistory> getBDFiles(Location origin, UUID user, int radius, long timediff, boolean shallow) {
Extent extent = origin.getExtent(); Extent extent = origin.getExtent();
if (!(extent instanceof World)) { if (!(extent instanceof World world)) {
throw new IllegalArgumentException("Origin is not a valid world"); throw new IllegalArgumentException("Origin is not a valid world");
} }
World world = (World) extent; File history = MainUtil.getFile(Fawe.platform().getDirectory(), Settings.settings().PATHS.HISTORY + File.separator + world.getName());
File history = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + world.getName());
if (!history.exists()) { if (!history.exists()) {
return new ArrayList<>(); return new ArrayList<>();
} }
@ -364,12 +351,12 @@ public class FaweAPI {
World unwrapped = WorldWrapper.unwrap(world); World unwrapped = WorldWrapper.unwrap(world);
if (unwrapped instanceof IQueueExtent) { if (unwrapped instanceof IQueueExtent) {
queue = (IQueueExtent) unwrapped; queue = (IQueueExtent) unwrapped;
} else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1) { } else if (Settings.settings().QUEUE.PARALLEL_THREADS > 1) {
ParallelQueueExtent parallel = ParallelQueueExtent parallel =
new ParallelQueueExtent(Fawe.get().getQueueHandler(), world, true); new ParallelQueueExtent(Fawe.instance().getQueueHandler(), world, true);
queue = parallel.getExtent(); queue = parallel.getExtent();
} else { } else {
queue = Fawe.get().getQueueHandler().getQueue(world); queue = Fawe.instance().getQueueHandler().getQueue(world);
} }
} }
@ -384,7 +371,7 @@ public class FaweAPI {
} }
} }
if (mode != RelightMode.NONE) { if (mode != RelightMode.NONE) {
if (Settings.IMP.LIGHTING.REMOVE_FIRST) { if (Settings.settings().LIGHTING.REMOVE_FIRST) {
relighter.removeAndRelight(true); relighter.removeAndRelight(true);
} else { } else {
relighter.fixSkyLighting(); relighter.fixSkyLighting();

View File

@ -59,7 +59,15 @@ import java.util.function.Supplier;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public enum FaweCache implements Trimable { public enum FaweCache implements Trimable {
IMP; // singleton /**
* @deprecated Use {@link #INSTANCE} to get an instance.
*/
@Deprecated(forRemoval = true, since = "2.0.0")
IMP,
/**
* @since 2.0.0
*/
INSTANCE;
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
@ -301,7 +309,7 @@ public enum FaweCache implements Trimable {
// BlockStates // BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1); int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) { if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else { } else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
@ -387,7 +395,7 @@ public enum FaweCache implements Trimable {
// BlockStates // BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1); int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) { if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else { } else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
@ -568,7 +576,7 @@ public enum FaweCache implements Trimable {
Thread stuff Thread stuff
*/ */
public ThreadPoolExecutor newBlockingExecutor() { public ThreadPoolExecutor newBlockingExecutor() {
int nThreads = Settings.IMP.QUEUE.PARALLEL_THREADS; int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true); ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true);
return new ThreadPoolExecutor(nThreads, nThreads, return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, queue, 0L, TimeUnit.MILLISECONDS, queue,
@ -609,7 +617,7 @@ public enum FaweCache implements Trimable {
lastException = hash; lastException = hash;
LOGGER.catching(throwable); LOGGER.catching(throwable);
count = 0; count = 0;
} else if (count < Settings.IMP.QUEUE.PARALLEL_THREADS) { } else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) {
LOGGER.warn(throwable.getMessage()); LOGGER.warn(throwable.getMessage());
count++; count++;
} }

View File

@ -1,5 +1,9 @@
package com.fastasyncworldedit.core; package com.fastasyncworldedit.core;
import com.fastasyncworldedit.core.util.StringMan;
import java.util.Locale;
/** /**
* An internal FAWE class not meant for public use. * An internal FAWE class not meant for public use.
**/ **/
@ -10,28 +14,35 @@ public class FaweVersion {
public final int day; public final int day;
public final int hash; public final int hash;
public final int build; public final int build;
public final int[] semver;
public final boolean snapshot;
public FaweVersion(int year, int month, int day, int hash, int build) { public FaweVersion(int year, int month, int day, int[] semver, boolean snapshot, int hash, int build) {
this.year = year; this.year = year;
this.month = month; this.month = month;
this.day = day; this.day = day;
this.hash = hash; this.hash = hash;
this.build = build; this.build = build;
this.semver = semver;
this.snapshot = snapshot;
} }
public FaweVersion(String version, String commit, String date) { public FaweVersion(String version, String commit, String date) {
String[] split = version.substring(version.indexOf('=') + 1).split("-"); String[] split = version.substring(version.indexOf('=') + 1).split("-");
int build = 0; String[] split1 = split[0].split("\\.");
try { int[] ver = new int[3];
build = Integer.parseInt(split[1]); for (int i = 0; i < 3; i++) {
} catch (NumberFormatException ignored) { ver[i] = Integer.parseInt(split1[i]);
} }
this.build = build; this.semver = ver;
this.snapshot = split.length > 1 && split[1].toLowerCase(Locale.ROOT).contains("snapshot");
int buildIndex = this.snapshot ? 2 : 1;
this.build = split.length == buildIndex + 1 ? Integer.parseInt(split[buildIndex]) : 0;
this.hash = Integer.parseInt(commit.substring(commit.indexOf('=') + 1), 16); this.hash = Integer.parseInt(commit.substring(commit.indexOf('=') + 1), 16);
String[] split1 = date.substring(date.indexOf('=') + 1).split("\\."); String[] split2 = date.substring(date.indexOf('=') + 1).split("\\.");
this.year = Integer.parseInt(split1[0]); this.year = Integer.parseInt(split2[0]);
this.month = Integer.parseInt(split1[1]); this.month = Integer.parseInt(split2[1]);
this.day = Integer.parseInt(split1[2]); this.day = Integer.parseInt(split2[2]);
} }
public static FaweVersion tryParse(String version, String commit, String date) { public static FaweVersion tryParse(String version, String commit, String date) {
@ -39,28 +50,42 @@ public class FaweVersion {
return new FaweVersion(version, commit, date); return new FaweVersion(version, commit, date);
} catch (Exception exception) { } catch (Exception exception) {
exception.printStackTrace(); exception.printStackTrace();
return new FaweVersion(0, 0, 0, 0, 0); return new FaweVersion(0, 0, 0, null, true, 0, 0);
} }
} }
@Override @Override
public String toString() { public String toString() {
if (hash == 0 && build == 0) { if (semver == null) {
return getSimpleVersionName() + "-NoVer-SNAPSHOT"; return "FastAsyncWorldEdit-NoVer-SNAPSHOT";
} else { } else {
return getSimpleVersionName() + "-" + build; String snapshot = this.snapshot ? "-SNAPSHOT" : "";
String build = this.build > 0 ? "-" + this.build : "";
return "FastAsyncWorldEdit-" + StringMan.join(semver, ".") + snapshot + build;
} }
} }
/** /**
* @return The qualified version name * Returns if another FaweVersion is newer than this one
*/ */
public String getSimpleVersionName() {
return "FastAsyncWorldEdit-1.17";
}
public boolean isNewer(FaweVersion other) { public boolean isNewer(FaweVersion other) {
return other.build < this.build; if (other.semver == null) {
return other.build > this.build;
}
if (this.semver == null) {
return true;
}
if (other.semver[0] != this.semver[0]) {
return other.semver[0] > this.semver[0];
} else if (other.semver[1] != this.semver[1]) {
return other.semver[1] > this.semver[1];
} else if (other.semver[2] != this.semver[2]) {
return other.semver[2] > this.semver[2];
}
if (other.snapshot == this.snapshot) {
return other.build > this.build;
}
return !other.snapshot;
} }
} }

View File

@ -531,7 +531,7 @@ public class AnvilCommands {
// }); // });
// if (useData) { // if (useData) {
// for (long[] c : map) { // for (long[] c : map) {
// BaseBlock block = FaweCache.IMP.CACHE_BLOCK[(int) c[0]]; // BaseBlock block = FaweCache.INSTANCE.CACHE_BLOCK[(int) c[0]];
// String name = BlockType.fromID(block.getId()).getName(); // String name = BlockType.fromID(block.getId()).getName();
// String str = String.format("%-7s (%.3f%%) %s #%d:%d", // String str = String.format("%-7s (%.3f%%) %s #%d:%d",
// String.valueOf(c[1]), // String.valueOf(c[1]),

View File

@ -147,7 +147,7 @@
// CFISettings settings = getSettings(player).remove(); // CFISettings settings = getSettings(player).remove();
// generator.setPacketViewer(player); // generator.setPacketViewer(player);
// settings.setGenerator(generator).bind(); // settings.setGenerator(generator).bind();
// generator.setImageViewer(Fawe.imp().getImageViewer(player)); // generator.setImageViewer(Fawe.platform().getImageViewer(player));
// generator.update(); // generator.update();
// mainMenu(player); // mainMenu(player);
// } // }
@ -226,7 +226,7 @@
// World world = FaweAPI.getWorld(folder.getName()); // World world = FaweAPI.getWorld(folder.getName());
// if (world != null) { // if (world != null) {
// if (player.getWorld() != world) { // if (player.getWorld() != world) {
// TaskManager.IMP.sync(new RunnableVal<Object>() { // TaskManager.taskManager().sync(new RunnableVal<Object>() {
// @Override // @Override
// public void run(Object value) { // public void run(Object value) {
// Location spawn = new Location(world, world.getSpawnPosition().toVector3()); // Location spawn = new Location(world, world.getSpawnPosition().toVector3());
@ -425,7 +425,7 @@
// switch (argOpt.toLowerCase(Locale.ROOT)) { // switch (argOpt.toLowerCase(Locale.ROOT)) {
// case "true": // case "true":
// case "*": { // case "*": {
// generator.setTextureUtil(Fawe.get().getTextureUtil()); // generator.setTextureUtil(Fawe.instance().getTextureUtil());
// return; // return;
// } // }
// case "#clipboard": { // case "#clipboard": {
@ -453,7 +453,7 @@
// parserContext.setExtent(extent); // parserContext.setExtent(extent);
// Request.request().setExtent(extent); // Request.request().setExtent(extent);
// Mask mask = worldEdit.getMaskFactory().parseFromInput(argOpt, parserContext); // Mask mask = worldEdit.getMaskFactory().parseFromInput(argOpt, parserContext);
// TextureUtil tu = Fawe.get().getTextureUtil(); // TextureUtil tu = Fawe.instance().getTextureUtil();
// for (int typeId : tu.getValidBlockIds()) { // for (int typeId : tu.getValidBlockIds()) {
// BlockType type = BlockTypes.get(typeId); // BlockType type = BlockTypes.get(typeId);
// extent.init(0, 0, 0, type.getDefaultState().toBaseBlock()); // extent.init(0, 0, 0, type.getDefaultState().toBaseBlock());
@ -464,7 +464,7 @@
// break; // break;
// } // }
// } // }
// generator.setTextureUtil(new FilteredTextureUtil(Fawe.get().getTextureUtil(), blocks)); // generator.setTextureUtil(new FilteredTextureUtil(Fawe.instance().getTextureUtil(), blocks));
// coloring(player); // coloring(player);
// } // }
// //
@ -493,9 +493,9 @@
// public void complexity(Player player, int min, int max) throws FileNotFoundException { // public void complexity(Player player, int min, int max) throws FileNotFoundException {
// HeightMapMCAGenerator gen = assertSettings(player).getGenerator(); // HeightMapMCAGenerator gen = assertSettings(player).getGenerator();
// if (min == 0 && max == 100) { // if (min == 0 && max == 100) {
// gen.setTextureUtil(Fawe.get().getTextureUtil()); // gen.setTextureUtil(Fawe.instance().getTextureUtil());
// } else { // } else {
// gen.setTextureUtil(new CleanTextureUtil(Fawe.get().getTextureUtil(), min, max)); // gen.setTextureUtil(new CleanTextureUtil(Fawe.instance().getTextureUtil(), min, max));
// } // }
// coloring(player); // coloring(player);
// } // }
@ -1201,7 +1201,7 @@
// whiteOnly = true; // whiteOnly = true;
// maskArg = null; // maskArg = null;
// imageMaskArg = null; // imageMaskArg = null;
// generator.setTextureUtil(Fawe.get().getTextureUtil()); // generator.setTextureUtil(Fawe.instance().getTextureUtil());
// } // }
// //
// public void resetComponent() { // public void resetComponent() {

View File

@ -95,7 +95,7 @@ public class ListFilters {
} }
String firstArg = finalArg.substring(0, finalArg.length() - File.separator.length()); String firstArg = finalArg.substring(0, finalArg.length() - File.separator.length());
if (firstArg.length() > 3 && firstArg.length() <= 16) { if (firstArg.length() > 3 && firstArg.length() <= 16) {
UUID fromName = Fawe.imp().getUUID(finalArg); UUID fromName = Fawe.platform().getUUID(finalArg);
if (fromName != null) { if (fromName != null) {
newRoot = new File(root, finalArg); newRoot = new File(root, finalArg);
if (newRoot.exists()) { if (newRoot.exists()) {

View File

@ -45,7 +45,7 @@
// PlotPlayer player = PlotPlayer.get(actor.getName()); // PlotPlayer player = PlotPlayer.get(actor.getName());
// //
// actor.print("Claiming world"); // actor.print("Claiming world");
// Plot plot = TaskManager.IMP.sync(new RunnableVal<Plot>() { // Plot plot = TaskManager.taskManager().sync(new RunnableVal<Plot>() {
// @Override // @Override
// public void run(Plot o) { // public void run(Plot o) {
// int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() // int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount()
@ -73,7 +73,7 @@
// File folder = CFICommands.getFolder(plot.getWorldName()); // File folder = CFICommands.getFolder(plot.getWorldName());
// Boolean result = createTask.apply(folder); // Boolean result = createTask.apply(folder);
// if (result == Boolean.TRUE) { // if (result == Boolean.TRUE) {
// TaskManager.IMP.sync(() -> plot.teleportPlayer(player)); // TaskManager.taskManager().sync(() -> plot.teleportPlayer(player));
// } // }
// return; // return;
// } // }

View File

@ -90,7 +90,7 @@ public class BrushSettings {
// } // }
// if (settings.containsKey(SettingType.TRANSFORM.name())) { // if (settings.containsKey(SettingType.TRANSFORM.name())) {
// String transformArgs = (String) settings.get(SettingType.TRANSFORM.name()); // String transformArgs = (String) settings.get(SettingType.TRANSFORM.name());
// ResettableExtent extent = Fawe.get().getTransformParser().parseFromInput(transformArgs, parserContext); // ResettableExtent extent = Fawe.instance().getTransformParser().parseFromInput(transformArgs, parserContext);
// bs.setTransform(extent); // bs.setTransform(extent);
// bs.constructor.put(SettingType.TRANSFORM, transformArgs); // bs.constructor.put(SettingType.TRANSFORM, transformArgs);
// } // }

View File

@ -68,7 +68,7 @@ public class InspectBrush extends BrushTool {
player.print(Caption.of("fawe.error.no-perm", "worldedit.tool.inspect")); player.print(Caption.of("fawe.error.no-perm", "worldedit.tool.inspect"));
return false; return false;
} }
if (!Settings.IMP.HISTORY.USE_DATABASE) { if (!Settings.settings().HISTORY.USE_DATABASE) {
player.print(Caption.of( player.print(Caption.of(
"fawe.error.setting.disable", "fawe.error.setting.disable",
"history.use-database (Import with /history import )" "history.use-database (Import with /history import )"
@ -81,7 +81,7 @@ public class InspectBrush extends BrushTool {
final int y = target.getBlockY(); final int y = target.getBlockY();
final int z = target.getBlockZ(); final int z = target.getBlockZ();
World world = player.getWorld(); World world = player.getWorld();
RollbackDatabase db = DBHandler.IMP.getDatabase(world); RollbackDatabase db = DBHandler.dbHandler().getDatabase(world);
int count = 0; int count = 0;
for (Supplier<RollbackOptimizedHistory> supplier : db.getEdits(target, false)) { for (Supplier<RollbackOptimizedHistory> supplier : db.getEdits(target, false)) {
count++; count++;
@ -95,7 +95,7 @@ public class InspectBrush extends BrushTool {
int from = change.from; int from = change.from;
int to = change.to; int to = change.to;
UUID uuid = edit.getUUID(); UUID uuid = edit.getUUID();
String name = Fawe.imp().getName(uuid); String name = Fawe.platform().getName(uuid);
int index = edit.getIndex(); int index = edit.getIndex();
long age = System.currentTimeMillis() - edit.getBDFile().lastModified(); long age = System.currentTimeMillis() - edit.getBDFile().lastModified();
String ageFormatted = MainUtil.secToTime(age / 1000); String ageFormatted = MainUtil.secToTime(age / 1000);

View File

@ -34,7 +34,7 @@ public class Config {
/** /**
* Get the value for a node. Probably throws some error if you try to get a non-existent key. * Get the value for a node. Probably throws some error if you try to get a non-existent key.
*/ */
private <T> T get(String key, Class root) { private <T> T get(String key, Class<?> root) {
String[] split = key.split("\\."); String[] split = key.split("\\.");
Object instance = getInstance(split, root); Object instance = getInstance(split, root);
if (instance != null) { if (instance != null) {
@ -57,7 +57,7 @@ public class Config {
* @param key config node * @param key config node
* @param value value * @param value value
*/ */
private void set(String key, Object value, Class root) { private void set(String key, Object value, Class<?> root) {
String[] split = key.split("\\."); String[] split = key.split("\\.");
Object instance = getInstance(split, root); Object instance = getInstance(split, root);
if (instance != null) { if (instance != null) {
@ -201,7 +201,7 @@ public class Config {
/** /**
* Get the static fields in a section. * Get the static fields in a section.
*/ */
private Map<String, Object> getFields(Class clazz) { private Map<String, Object> getFields(Class<?> clazz) {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
for (Field field : clazz.getFields()) { for (Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) { if (Modifier.isStatic(field.getModifiers())) {
@ -223,12 +223,11 @@ public class Config {
} }
StringBuilder m = new StringBuilder(); StringBuilder m = new StringBuilder();
for (Object obj : listValue) { for (Object obj : listValue) {
m.append(System.lineSeparator() + spacing + "- " + toYamlString(obj, spacing)); m.append(System.lineSeparator()).append(spacing).append("- ").append(toYamlString(obj, spacing));
} }
return m.toString(); return m.toString();
} }
if (value instanceof String) { if (value instanceof String stringValue) {
String stringValue = (String) value;
if (stringValue.isEmpty()) { if (stringValue.isEmpty()) {
return "''"; return "''";
} }
@ -237,11 +236,11 @@ public class Config {
return value != null ? value.toString() : "null"; return value != null ? value.toString() : "null";
} }
private void save(PrintWriter writer, Class clazz, final Object instance, int indent) { private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent) {
try { try {
String CTRF = System.lineSeparator(); String CTRF = System.lineSeparator();
String spacing = StringMan.repeat(" ", indent); String spacing = StringMan.repeat(" ", indent);
HashMap<Class, Object> instances = new HashMap<>(); HashMap<Class<?>, Object> instances = new HashMap<>();
for (Field field : clazz.getFields()) { for (Field field : clazz.getFields()) {
if (field.getAnnotation(Ignore.class) != null) { if (field.getAnnotation(Ignore.class) != null) {
continue; continue;
@ -272,7 +271,7 @@ public class Config {
configBlock = new ConfigBlock(); configBlock = new ConfigBlock();
field.set(instance, configBlock); field.set(instance, configBlock);
for (String blockName : blockNames.value()) { for (String blockName : blockNames.value()) {
configBlock.put(blockName, current.newInstance()); configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
} }
} }
// Save each instance // Save each instance
@ -299,11 +298,10 @@ public class Config {
} }
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
if (value == null) { if (value == null) {
field.set(instance, value = current.newInstance()); field.set(instance, value = current.getDeclaredConstructor().newInstance());
instances.put(current, value); instances.put(current, value);
} }
save(writer, current, value, indent + 2); save(writer, current, value, indent + 2);
continue;
} else { } else {
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString( writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
field.get(instance), field.get(instance),
@ -321,7 +319,7 @@ public class Config {
* *
* @param split the node (split by period) * @param split the node (split by period)
*/ */
private Field getField(String[] split, Class root) { private Field getField(String[] split, Class<?> root) {
Object instance = getInstance(split, root); Object instance = getInstance(split, root);
if (instance == null) { if (instance == null) {
return null; return null;
@ -352,32 +350,23 @@ public class Config {
} }
} }
private Object getInstance(Object instance, Class clazz) throws IllegalAccessException, InstantiationException {
try {
Field instanceField = clazz.getDeclaredField(clazz.getSimpleName());
} catch (Throwable ignored) {
}
return clazz.newInstance();
}
/** /**
* Get the instance for a specific config node. * Get the instance for a specific config node.
* *
* @param split the node (split by period) * @param split the node (split by period)
* @return The instance or null * @return The instance or null
*/ */
private Object getInstance(String[] split, Class root) { private Object getInstance(String[] split, Class<?> root) {
try { try {
Class<?> clazz = root == null ? MethodHandles.lookup().lookupClass() : root; Class<?> clazz = root == null ? MethodHandles.lookup().lookupClass() : root;
Object instance = this; Object instance = this;
while (split.length > 0) { while (split.length > 0) {
switch (split.length) { if (split.length == 1) {
case 1:
return instance; return instance;
default: }
Class found = null; Class<?> found = null;
Class<?>[] classes = clazz.getDeclaredClasses(); Class<?>[] classes = clazz.getDeclaredClasses();
for (Class current : classes) { for (Class<?> current : classes) {
if (StringMan.isEqual(current.getSimpleName(), toFieldName(split[0]))) { if (StringMan.isEqual(current.getSimpleName(), toFieldName(split[0]))) {
found = current; found = current;
break; break;
@ -389,7 +378,7 @@ public class Config {
if (instanceField.getType() != ConfigBlock.class) { if (instanceField.getType() != ConfigBlock.class) {
Object value = instanceField.get(instance); Object value = instanceField.get(instance);
if (value == null) { if (value == null) {
value = found.newInstance(); value = found.getDeclaredConstructor().newInstance();
instanceField.set(instance, value); instanceField.set(instance, value);
} }
clazz = found; clazz = found;
@ -404,7 +393,7 @@ public class Config {
} }
instance = value.get(split[1]); instance = value.get(split[1]);
if (instance == null) { if (instance == null) {
instance = found.newInstance(); instance = found.getDeclaredConstructor().newInstance();
value.put(split[1], instance); value.put(split[1], instance);
} }
clazz = found; clazz = found;
@ -415,12 +404,11 @@ public class Config {
if (found != null) { if (found != null) {
split = Arrays.copyOfRange(split, 1, split.length); split = Arrays.copyOfRange(split, 1, split.length);
clazz = found; clazz = found;
instance = clazz.newInstance(); instance = clazz.getDeclaredConstructor().newInstance();
continue; continue;
} }
return null; return null;
} }
}
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -9,12 +9,28 @@ import java.util.concurrent.ConcurrentHashMap;
public class DBHandler { public class DBHandler {
private static final Logger LOGGER = LogManagerCompat.getLogger(); /**
* @deprecated Use {@link #dbHandler()} instead.
*/
@Deprecated(forRemoval = true, since = "2.0.0")
public static final DBHandler IMP = new DBHandler(); public static final DBHandler IMP = new DBHandler();
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static DBHandler INSTANCE;
private final Map<World, RollbackDatabase> databases = new ConcurrentHashMap<>(8, 0.9f, 1); private final Map<World, RollbackDatabase> databases = new ConcurrentHashMap<>(8, 0.9f, 1);
/**
* Get an instance of the DBHandler.
*
* @return an instance of the DBHandler.
* @since 2.0.0
*/
public static DBHandler dbHandler() {
if (INSTANCE == null) {
INSTANCE = new DBHandler();
}
return INSTANCE;
}
public RollbackDatabase getDatabase(World world) { public RollbackDatabase getDatabase(World world) {
RollbackDatabase database = databases.get(world); RollbackDatabase database = databases.get(world);
if (database != null) { if (database != null) {

Some files were not shown because too many files have changed in this diff Show More