Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-03 01:50:07 +01:00
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>
Dieser Commit ist enthalten in:
Commit
8b973da7ee
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -83,7 +83,7 @@ body:
|
||||
attributes:
|
||||
label: Fawe Version
|
||||
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:
|
||||
required: true
|
||||
|
||||
|
2
.github/stale.yml
vendored
2
.github/stale.yml
vendored
@ -1,4 +1,4 @@
|
||||
daysUntilStale: 60
|
||||
daysUntilStale: 30
|
||||
daysUntilClose: 7
|
||||
only: issues
|
||||
exemptLabels:
|
||||
|
63
.github/workflows/build.yml
vendored
63
.github/workflows/build.yml
vendored
@ -1,34 +1,47 @@
|
||||
name: "build"
|
||||
name: build
|
||||
|
||||
on: ["pull_request", "push"]
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: "actions/checkout@v2.3.4"
|
||||
- name : "Validate Gradle Wrapper"
|
||||
uses : "gradle/wrapper-validation-action@v1.0.4"
|
||||
- name: "Grab SHA"
|
||||
uses: "benjlevesque/short-sha@v1.2"
|
||||
id: "short-sha"
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2.4.0
|
||||
- name : Validate Gradle Wrapper
|
||||
uses : gradle/wrapper-validation-action@v1.0.4
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v2.4.0
|
||||
with:
|
||||
length: "7"
|
||||
- name: "Echo SHA"
|
||||
run: "echo $SHA"
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
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:
|
||||
SHA: "${{ steps.short-sha.outputs.sha }}"
|
||||
- name: "Setup Java"
|
||||
uses: "actions/setup-java@v2.3.1"
|
||||
with:
|
||||
distribution: "temurin"
|
||||
cache: 'gradle'
|
||||
java-version: "17"
|
||||
- name: "Clean Build"
|
||||
run: "./gradlew clean build --no-daemon"
|
||||
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
|
||||
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
|
||||
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
|
||||
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
|
||||
- name: Publish Snapshot
|
||||
if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/major/2.0.0/1.18' }}
|
||||
run: ./gradlew publishToSonatype
|
||||
env:
|
||||
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
|
||||
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
|
||||
- name: Archive Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v2.3.1
|
||||
with:
|
||||
name: FastAsyncWorldEdit-Bukkit-1.17-${{ env.SHA }}
|
||||
path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-1.17-${{ env.SHA }}.jar
|
||||
name: FastAsyncWorldEdit-Bukkit-SNAPSHOT
|
||||
path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar
|
||||
|
20
.github/workflows/rebase.yml
vendored
Normale Datei
20
.github/workflows/rebase.yml
vendored
Normale Datei
@ -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 }}
|
8
.github/workflows/release-drafter.yml
vendored
8
.github/workflows/release-drafter.yml
vendored
@ -1,14 +1,14 @@
|
||||
name: "draft release"
|
||||
name: draft release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "2.0.0"
|
||||
- main
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: "release-drafter/release-drafter@v5.15.0"
|
||||
- uses: release-drafter/release-drafter@v5.15.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
54
Annotation-Explanation.adoc
Normale Datei
54
Annotation-Explanation.adoc
Normale Datei
@ -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.
|
12
COMPILING.md
12
COMPILING.md
@ -1,12 +1,12 @@
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
@ -16,10 +16,6 @@ The build process uses Gradle, which you do *not* need to download. FastAsyncWor
|
||||
|
||||
## 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
|
||||
|
||||
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**
|
||||
* 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.)
|
||||
|
||||
## 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_:
|
||||
* `gradlew eclipse` will generate an [Eclipse](https://www.eclipse.org/downloads/) project for each folder.
|
||||
|
10
Jenkinsfile
vendored
10
Jenkinsfile
vendored
@ -1,10 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('Build pull request') {
|
||||
steps {
|
||||
sh './gradlew clean build'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 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
|
||||
* 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)
|
||||
* [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit/issues)
|
||||
* [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 -core module](https://ci.athion.net/job/FastAsyncWorldEdit-1.17-Core-Javadocs/javadoc/)
|
||||
* [JavaDocs for the -bukkit module](https://javadoc.io/doc/com.fastasyncworldedit/FastAsyncWorldEdit-Bukkit/latest/index.html)
|
||||
* [JavaDocs for the -core module](https://javadoc.io/doc/com.fastasyncworldedit/FastAsyncWorldEdit-Core/latest/index.html)
|
||||
|
||||
## Edit The Code
|
||||
|
||||
|
@ -2,6 +2,11 @@ import org.ajoberstar.grgit.Grgit
|
||||
import java.time.format.DateTimeFormatter
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
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("""
|
||||
*******************************************
|
||||
@ -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 buildNumber by extra("")
|
||||
var date: String by extra("")
|
||||
@ -27,11 +33,10 @@ ext {
|
||||
}
|
||||
date = git.head().dateTime.format(DateTimeFormatter.ofPattern("yy.MM.dd"))
|
||||
revision = "-${git.head().abbreviatedId}"
|
||||
val commit: String? = git.head().abbreviatedId
|
||||
buildNumber = if (project.hasProperty("buildnumber")) {
|
||||
project.properties["buildnumber"] as String
|
||||
snapshot + "-" + project.properties["buildnumber"] as String
|
||||
} else {
|
||||
commit.toString()
|
||||
project.properties["snapshot"] as String
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,3 +71,12 @@ allprojects {
|
||||
}
|
||||
|
||||
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/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,17 @@ plugins {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven {
|
||||
name = "PaperMC"
|
||||
url = uri("https://papermc.io/repo/repository/maven-public/")
|
||||
}
|
||||
maven {
|
||||
name = "EngineHub"
|
||||
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 ->
|
||||
@ -28,5 +31,11 @@ dependencies {
|
||||
implementation(gradleApi())
|
||||
implementation("org.ajoberstar.grgit:grgit-gradle:4.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))
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,7 @@ import org.gradle.kotlin.dsl.dependencies
|
||||
|
||||
// For specific version pinning, see
|
||||
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
|
||||
fun Project.applyPaperweightAdapterConfiguration(
|
||||
paperVersion: String
|
||||
) {
|
||||
fun Project.applyPaperweightAdapterConfiguration() {
|
||||
applyCommonConfiguration()
|
||||
apply(plugin = "java-library")
|
||||
applyCommonJavaConfiguration(
|
||||
@ -17,7 +15,6 @@ fun Project.applyPaperweightAdapterConfiguration(
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
dependencies {
|
||||
paperDevBundle(paperVersion)
|
||||
"implementation"(project(":worldedit-bukkit"))
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,7 @@ fun Project.applyCommonConfiguration() {
|
||||
version = rootProject.version
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "IntellectualSites"
|
||||
url = uri("https://mvn.intellectualsites.com/content/groups/public/")
|
||||
}
|
||||
maven {
|
||||
name = "EngineHub"
|
||||
url = uri("https://maven.enginehub.org/repo/")
|
||||
@ -32,6 +27,7 @@ fun Project.applyCommonConfiguration() {
|
||||
name = "Athion"
|
||||
url = uri("https://ci.athion.net/plugin/repository/tools/")
|
||||
}
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
@ -42,7 +38,7 @@ fun Project.applyCommonConfiguration() {
|
||||
|
||||
plugins.withId("java") {
|
||||
the<JavaPluginExtension>().toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(16))
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,15 +50,15 @@ fun Project.applyCommonConfiguration() {
|
||||
continue
|
||||
}
|
||||
add(conf.name, "com.google.guava:guava") {
|
||||
version { require("21.0") }
|
||||
version { require("31.0.1-jre") }
|
||||
because("Mojang provides Guava")
|
||||
}
|
||||
add(conf.name, "com.google.code.gson:gson") {
|
||||
version { require("2.8.0") }
|
||||
version { require("2.8.8") }
|
||||
because("Mojang provides Gson")
|
||||
}
|
||||
add(conf.name, "it.unimi.dsi:fastutil") {
|
||||
version { require("8.2.1") }
|
||||
version { require("8.5.6") }
|
||||
because("Mojang provides FastUtil")
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
||||
val disabledLint = listOf(
|
||||
"processing", "path", "fallthrough", "serial"
|
||||
)
|
||||
options.release.set(11)
|
||||
options.release.set(17)
|
||||
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
|
||||
options.isDeprecation = true
|
||||
options.encoding = "UTF-8"
|
||||
@ -32,7 +32,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 16)
|
||||
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
@ -60,13 +60,12 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean
|
||||
options.encoding = "UTF-8"
|
||||
links(
|
||||
"https://javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/",
|
||||
"https://jd.adventure.kyori.net/api/4.9.1/",
|
||||
"https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/2.14.1/",
|
||||
"https://javadoc.io/doc/com.google.guava/guava/21.0/",
|
||||
"https://jd.adventure.kyori.net/api/latest/",
|
||||
"https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/latest/index.html",
|
||||
"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/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
|
||||
)
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import org.gradle.kotlin.dsl.invoke
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
import javax.inject.Inject
|
||||
|
||||
fun Project.applyLibrariesConfiguration() {
|
||||
@ -28,6 +30,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
apply(plugin = "java-base")
|
||||
apply(plugin = "maven-publish")
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
apply(plugin = "signing")
|
||||
|
||||
configurations {
|
||||
create("shade")
|
||||
@ -49,6 +52,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
dependencies {
|
||||
exclude(dependency("com.google.guava:guava"))
|
||||
exclude(dependency("com.google.code.gson:gson"))
|
||||
exclude(dependency("com.google.errorprone:error_prone_annotations"))
|
||||
exclude(dependency("org.checkerframework:checker-qual"))
|
||||
exclude(dependency("org.apache.logging.log4j:log4j-api"))
|
||||
exclude(dependency("com.google.code.findbugs:jsr305"))
|
||||
@ -94,8 +98,14 @@ fun Project.applyLibrariesConfiguration() {
|
||||
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 {
|
||||
dependsOn("jar", "sourcesJar")
|
||||
dependsOn("jar", "sourcesJar", "javadocJar")
|
||||
}
|
||||
|
||||
project.apply<LibsConfigPluginHack>()
|
||||
@ -112,7 +122,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11)
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
|
||||
}
|
||||
outgoing.artifact(tasks.named("jar"))
|
||||
}
|
||||
@ -127,7 +137,7 @@ fun Project.applyLibrariesConfiguration() {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11)
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
|
||||
}
|
||||
outgoing.artifact(tasks.named("jar"))
|
||||
}
|
||||
@ -146,6 +156,20 @@ fun Project.applyLibrariesConfiguration() {
|
||||
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()) {
|
||||
mapToMavenScope("compile")
|
||||
}
|
||||
@ -158,6 +182,22 @@ fun Project.applyLibrariesConfiguration() {
|
||||
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> {
|
||||
publications {
|
||||
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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.gradle.kotlin.dsl.named
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
|
||||
fun Project.applyPlatformAndCoreConfiguration() {
|
||||
applyCommonConfiguration()
|
||||
@ -20,6 +21,7 @@ fun Project.applyPlatformAndCoreConfiguration() {
|
||||
apply(plugin = "idea")
|
||||
apply(plugin = "maven-publish")
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
apply(plugin = "signing")
|
||||
|
||||
applyCommonJavaConfiguration(
|
||||
sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit"),
|
||||
@ -45,6 +47,18 @@ fun Project.applyPlatformAndCoreConfiguration() {
|
||||
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> {
|
||||
publications {
|
||||
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") {
|
||||
|
@ -1,12 +1,12 @@
|
||||
[versions]
|
||||
# Minecraft expectations
|
||||
fastutil = "8.2.1"
|
||||
log4j = "2.17.0"
|
||||
guava = "21.0"
|
||||
gson = "2.8.0"
|
||||
fastutil = "8.5.6"
|
||||
log4j = "2.17.1"
|
||||
guava = "31.0.1-jre"
|
||||
gson = "2.8.8"
|
||||
|
||||
# Platform expectations
|
||||
paper = "1.17.1-R0.1-SNAPSHOT"
|
||||
paper = "1.18.1-R0.1-SNAPSHOT"
|
||||
|
||||
# Plugins
|
||||
vault = "1.7.1"
|
||||
@ -20,15 +20,14 @@ residence = "4.5._13.1"
|
||||
towny = "0.97.5.0"
|
||||
protocollib = "4.7.0"
|
||||
plotsquaredV6 = "6.2.0"
|
||||
plotsquaredV4 = "4.514"
|
||||
redprotect = "1.9.6"
|
||||
|
||||
# Third party
|
||||
flow-math = "1.0.3"
|
||||
paperlib = "1.0.7"
|
||||
paperlib = "1.0.8-SNAPSHOT"
|
||||
bstats = "2.2.1"
|
||||
serverlib = "2.3.1"
|
||||
paster = "1.1.1"
|
||||
paster = "1.1.3"
|
||||
sparsebitset = "1.2"
|
||||
parallelgzip = "1.0.5"
|
||||
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
|
||||
antlr4 = "4.9.3"
|
||||
json-simple = "1.1.1"
|
||||
paranamer = "2.8"
|
||||
jlibnoise = "1.0.0"
|
||||
jchronic = "0.2.4a"
|
||||
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" }
|
||||
plotsquaredV6Bukkit = { group = "com.plotsquared", name = "PlotSquared-Bukkit", 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" }
|
||||
|
||||
# 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" }
|
||||
antlr4Runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" }
|
||||
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" }
|
||||
jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" }
|
||||
lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" }
|
||||
|
@ -10,7 +10,6 @@
|
||||
"mockito-core",
|
||||
"org.antlr",
|
||||
"antlr4-runtime",
|
||||
"paranamer",
|
||||
"fastutil",
|
||||
"it.unimi.dsi:fastutil",
|
||||
"auto-value-annotations",
|
||||
|
@ -4,6 +4,7 @@ include("worldedit-libs")
|
||||
|
||||
include("worldedit-bukkit:adapters:adapter-legacy")
|
||||
include("worldedit-bukkit:adapters:adapter-1_17_1")
|
||||
include("worldedit-bukkit:adapters:adapter-1_18")
|
||||
|
||||
listOf("bukkit", "core", "cli").forEach {
|
||||
include("worldedit-libs:$it")
|
||||
|
@ -1,21 +1,27 @@
|
||||
applyPaperweightAdapterConfiguration()
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
applyPaperweightAdapterConfiguration(
|
||||
"1.17.1-R0.1-20211210.043523-198"
|
||||
)
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "PaperMC"
|
||||
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 {
|
||||
paperDevBundle("1.17.1-R0.1-20211219.175449-201")
|
||||
compileOnly(libs.paperlib)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
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.CacheLoader;
|
||||
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.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.Watchdog;
|
||||
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.util.Direction;
|
||||
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.TranslatableComponent;
|
||||
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> {
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
|
||||
private final Logger LOGGER = Logger.getLogger(getClass().getCanonicalName());
|
||||
|
||||
private final Field serverWorldsField;
|
||||
private final Method getChunkFutureMethod;
|
||||
private final Field chunkProviderExecutorField;
|
||||
private final Field worldsField;
|
||||
private final Method getChunkFutureMainThreadMethod;
|
||||
private final Field mainThreadProcessorField;
|
||||
private final Watchdog watchdog;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -188,18 +192,18 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
throw new UnsupportedClassVersionError("Not 1.17.1!");
|
||||
}
|
||||
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
serverWorldsField.setAccessible(true);
|
||||
worldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
worldsField.setAccessible(true);
|
||||
|
||||
getChunkFutureMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread",
|
||||
getChunkFutureMainThreadMethod = ServerChunkCache.class.getDeclaredMethod("getChunkFutureMainThread",
|
||||
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")
|
||||
);
|
||||
chunkProviderExecutorField.setAccessible(true);
|
||||
mainThreadProcessorField.setAccessible(true);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public BaseBlock getBlock(Location location) {
|
||||
checkNotNull(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 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());
|
||||
int x = location.getBlockX();
|
||||
@ -328,19 +354,11 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
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);
|
||||
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
|
||||
BlockEntity te = chunk.getBlockEntity(blockPos);
|
||||
if (te != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
readTileEntityIntoTag(te, tag); // Load data
|
||||
net.minecraft.nbt.CompoundTag tag = te.save(new net.minecraft.nbt.CompoundTag());
|
||||
//FAWE start - BinaryTag
|
||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
||||
//FAWE end
|
||||
@ -418,7 +436,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
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
|
||||
@ -500,7 +523,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
|
||||
property = new IntegerProperty(state.getName(), ImmutableList.copyOf(state.getPossibleValues()));
|
||||
} 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);
|
||||
@ -650,7 +673,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
} finally {
|
||||
try {
|
||||
@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");
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
@ -723,7 +746,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
List<CompletableFuture<ChunkAccess>> chunkLoadings = submitChunkLoadTasks(region, serverWorld);
|
||||
BlockableEventLoop<Runnable> executor;
|
||||
try {
|
||||
executor = (BlockableEventLoop<Runnable>) chunkProviderExecutorField.get(serverWorld.getChunkSource());
|
||||
executor = (BlockableEventLoop<Runnable>) mainThreadProcessorField.get(serverWorld.getChunkSource());
|
||||
} catch (IllegalAccessException 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());
|
||||
ChunkAccess chunk = chunks.get(new ChunkPos(pos));
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(pos);
|
||||
int internalId = Block.getId(blockData);
|
||||
BlockStateHolder<?> state = BlockStateIdAccess.getBlockStateById(internalId);
|
||||
BlockStateHolder<?> state = ((PaperweightFaweAdapter) WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter()).adapt(blockData);
|
||||
Objects.requireNonNull(state);
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(pos);
|
||||
if (blockEntity != null) {
|
||||
@ -783,7 +807,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
//noinspection unchecked
|
||||
chunkLoadings.add(
|
||||
((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))
|
||||
);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
@ -875,7 +899,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
try {
|
||||
return toNativeList((net.minecraft.nbt.ListTag) foreign);
|
||||
} catch (Throwable e) {
|
||||
logger.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||
LOGGER.log(Level.WARNING, "Failed to convert net.minecraft.nbt.ListTag", e);
|
||||
return ListBinaryTag.empty();
|
||||
}
|
||||
} else if (foreign instanceof net.minecraft.nbt.LongTag) {
|
||||
@ -994,7 +1018,7 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
|
||||
WatchdogThread.tick();
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.WARNING, "Failed to tick watchdog", e);
|
||||
LOGGER.log(Level.WARNING, "Failed to tick watchdog", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@ 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.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
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.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;
|
||||
@ -230,9 +231,29 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
@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);
|
||||
|
||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
||||
@ -240,19 +261,22 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
|
||||
final ServerLevel serverLevel = craftWorld.getHandle();
|
||||
LevelChunk levelChunk = serverLevel.getChunk(x >> 4, z >> 4);
|
||||
final ServerLevel handle = craftWorld.getHandle();
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
||||
BlockState state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
||||
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 = levelChunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
if (blockEntity != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||
blockEntity.save(tag); // readTileEntityIntoTag - load data
|
||||
return state.toBaseBlock((CompoundTag) toNative(tag));
|
||||
net.minecraft.nbt.CompoundTag tag = blockEntity.save(new net.minecraft.nbt.CompoundTag());
|
||||
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +308,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
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) {
|
||||
level.setBlock(blockPos, blockState, 0);
|
||||
// remove tile
|
||||
@ -293,7 +317,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
// 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) fromNative(compoundTag);
|
||||
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));
|
||||
@ -337,14 +361,15 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
|
||||
if (id != null) {
|
||||
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();
|
||||
readEntityIntoTag(mcEntity, minecraftTag);
|
||||
//add Id for AbstractChangeSet to work
|
||||
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
|
||||
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
|
||||
tags.put("Id", new StringTag(id));
|
||||
return new CompoundTag(tags);
|
||||
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 {
|
||||
@ -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!",
|
||||
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);
|
||||
}
|
||||
try {
|
||||
FaweCache.IMP.CHUNK_FLAG.get().set(true);
|
||||
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
|
||||
entityPlayer.connection.send(nmsPacket);
|
||||
} 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())),
|
||||
baseItemStack.getAmount()
|
||||
);
|
||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
|
||||
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt())));
|
||||
return CraftItemStack.asCraftMirror(stack);
|
||||
}
|
||||
|
||||
@ -579,7 +604,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
||||
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
|
||||
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
|
||||
weStack.setNbtData(((CompoundTag) toNative(nmsStack.getTag())));
|
||||
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
|
||||
return weStack;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -269,27 +269,17 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
if (Fawe.isMainThread()) {
|
||||
runnableVal.run();
|
||||
} else {
|
||||
TaskManager.IMP.sync(runnableVal);
|
||||
TaskManager.taskManager().sync(runnableVal);
|
||||
}
|
||||
cachedChanges.clear();
|
||||
cachedChunksToSend.clear();
|
||||
}
|
||||
|
||||
private static final class CachedChange {
|
||||
|
||||
private final LevelChunk levelChunk;
|
||||
private final BlockPos blockPos;
|
||||
private final net.minecraft.world.level.block.state.BlockState blockState;
|
||||
|
||||
private CachedChange(
|
||||
LevelChunk levelChunk,
|
||||
BlockPos blockPos,
|
||||
net.minecraft.world.level.block.state.BlockState blockState
|
||||
) {
|
||||
this.levelChunk = levelChunk;
|
||||
this.blockPos = blockPos;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
private record CachedChange(
|
||||
LevelChunk levelChunk,
|
||||
BlockPos blockPos,
|
||||
net.minecraft.world.level.block.state.BlockState blockState
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import io.papermc.paper.event.block.BeaconDeactivatedEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@ -151,7 +151,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition);
|
||||
fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -419,7 +419,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
try {
|
||||
ServerLevel nmsWorld = serverLevel;
|
||||
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
|
||||
Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities());
|
||||
@ -546,25 +546,30 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
}
|
||||
|
||||
// Biomes
|
||||
BiomeType[] biomes = set.getBiomes();
|
||||
BiomeType[][] biomes = set.getBiomes();
|
||||
if (biomes != null) {
|
||||
// set biomes
|
||||
ChunkBiomeContainer currentBiomes = nmsChunk.getBiomes();
|
||||
if (createCopy) {
|
||||
copy.storeBiomes(currentBiomes);
|
||||
}
|
||||
for (int y = 0, i = 0; y < 64; y++) {
|
||||
for (int z = 0; z < 4; z++) {
|
||||
for (int x = 0; x < 4; x++, i++) {
|
||||
final BiomeType biome = biomes[i];
|
||||
if (biome != null) {
|
||||
Biome nmsBiome =
|
||||
nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get(
|
||||
ResourceLocation.tryParse(biome.getId()));
|
||||
if (nmsBiome == null) {
|
||||
throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId());
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (biomes[layer] == null) {
|
||||
continue;
|
||||
}
|
||||
for (int y = 0, i = 0; y < 4; y++) {
|
||||
for (int z = 0; z < 4; z++) {
|
||||
for (int x = 0; x < 4; x++, i++) {
|
||||
final BiomeType biome = biomes[layer][i];
|
||||
if (biome != null) {
|
||||
Biome nmsBiome =
|
||||
nmsWorld.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).get(
|
||||
ResourceLocation.tryParse(biome.getId()));
|
||||
if (nmsBiome == null) {
|
||||
throw new NullPointerException("BiomeBase null for BiomeType " + biome.getId());
|
||||
}
|
||||
currentBiomes.setBiome(x, (layer << 2) + y, z, nmsBiome);
|
||||
}
|
||||
currentBiomes.setBiome(x, y, z, nmsBiome);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -722,7 +727,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markUnsaved();
|
||||
// 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);
|
||||
}
|
||||
if (finalizer != null) {
|
||||
@ -731,7 +736,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
};
|
||||
}
|
||||
if (syncTasks != null) {
|
||||
QueueHandler queueHandler = Fawe.get().getQueueHandler();
|
||||
QueueHandler queueHandler = Fawe.instance().getQueueHandler();
|
||||
Runnable[] finalSyncTasks = syncTasks;
|
||||
|
||||
// Chain the sync tasks and the callback
|
||||
@ -756,6 +761,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
//noinspection unchecked - required at compile time
|
||||
return (T) (Future) queueHandler.sync(chain);
|
||||
} else {
|
||||
if (callback == null) {
|
||||
@ -840,16 +846,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
data = new char[4096];
|
||||
Arrays.fill(data, (char) 1);
|
||||
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
||||
return data;
|
||||
}
|
||||
if (data != null && data.length != 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];
|
||||
Arrays.fill(data, (char) 1);
|
||||
Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR);
|
||||
}
|
||||
DelegateSemaphore lock = PaperweightPlatformAdapter.applyLock(section);
|
||||
synchronized (lock) {
|
||||
@ -874,13 +880,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char paletteVal = data[i];
|
||||
char ordinal = adapter.ibdIDToOrdinal(paletteVal);
|
||||
// Don't read "empty".
|
||||
data[i] = ordinal == 0 ? 1 : ordinal;
|
||||
data[i] = ordinal;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
char[] paletteToOrdinal = FaweCache.IMP.PALETTE_TO_BLOCK_CHAR.get();
|
||||
char[] paletteToOrdinal = FaweCache.INSTANCE.PALETTE_TO_BLOCK_CHAR.get();
|
||||
try {
|
||||
if (num_palette != 1) {
|
||||
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);
|
||||
paletteToOrdinal[i] = val;
|
||||
}
|
||||
// Don't read "empty".
|
||||
if (val == 0) {
|
||||
val = 1;
|
||||
}
|
||||
data[i] = val;
|
||||
}
|
||||
} else {
|
||||
char ordinal = ordinal(palette.valueFor(0), adapter);
|
||||
// Don't read "empty".
|
||||
if (ordinal == 0) {
|
||||
ordinal = 1;
|
||||
}
|
||||
Arrays.fill(data, ordinal);
|
||||
}
|
||||
} 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) {
|
||||
if (ibd == null) {
|
||||
return BlockTypes.AIR.getDefaultState().getOrdinalChar();
|
||||
return BlockTypesCache.ReservedIDs.AIR;
|
||||
} else {
|
||||
return adapter.adaptToChar(ibd);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
private static final long fieldLockOffset;
|
||||
|
||||
private static final Field fieldGameEventDispatcherSections;
|
||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||
private static final MethodHandle methodremoveBlockEntityTicker;
|
||||
|
||||
private static final Field fieldRemove;
|
||||
|
||||
@ -133,7 +133,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
), BlockPos.class
|
||||
);
|
||||
removeBlockEntityTicker.setAccessible(true);
|
||||
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
|
||||
methodremoveBlockEntityTicker = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
|
||||
|
||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||
fieldRemove.setAccessible(true);
|
||||
@ -215,7 +215,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
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) {
|
||||
@ -247,7 +247,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
LevelChunk levelChunk = optional.get();
|
||||
TaskManager.IMP.task(() -> {
|
||||
TaskManager.taskManager().task(() -> {
|
||||
ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk);
|
||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket));
|
||||
if (lighting) {
|
||||
@ -283,10 +283,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
if (set == null) {
|
||||
return newChunkSection(layer);
|
||||
}
|
||||
final int[] blockToPalette = FaweCache.IMP.BLOCK_TO_PALETTE.get();
|
||||
final int[] paletteToBlock = FaweCache.IMP.PALETTE_TO_BLOCK.get();
|
||||
final long[] blockStates = FaweCache.IMP.BLOCK_STATES.get();
|
||||
final int[] blocksCopy = FaweCache.IMP.SECTION_BLOCKS.get();
|
||||
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<>();
|
||||
@ -303,7 +303,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
int num_palette = num_palette_buffer[0];
|
||||
// BlockStates
|
||||
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
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos());
|
||||
methodremoveBlockEntityTicker.invoke(levelChunk, beacon.getBlockPos());
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public class PaperweightStarlightRelighter implements Relighter {
|
||||
while (iterator.hasNext()) {
|
||||
coords.add(new ChunkPos(iterator.nextLong()));
|
||||
}
|
||||
TaskManager.IMP.task(() -> {
|
||||
TaskManager.taskManager().task(() -> {
|
||||
// trigger chunk load and apply ticket on main thread
|
||||
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
for (ChunkPos pos : coords) {
|
||||
@ -153,9 +153,9 @@ public class PaperweightStarlightRelighter implements Relighter {
|
||||
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
|
||||
}
|
||||
// post process chunks on main thread
|
||||
TaskManager.IMP.task(() -> postProcessChunks(coords));
|
||||
TaskManager.taskManager().task(() -> postProcessChunks(coords));
|
||||
// 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
|
||||
*/
|
||||
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) {
|
||||
int x = pos.x;
|
||||
int z = pos.z;
|
||||
|
@ -66,8 +66,8 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
||||
|
||||
public double asDouble(String key) {
|
||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||
if (tag instanceof NumericTag) {
|
||||
return ((NumericTag) tag).getAsDouble();
|
||||
if (tag instanceof NumericTag numTag) {
|
||||
return numTag.getAsDouble();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -86,20 +86,19 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
||||
|
||||
public int asInt(String key) {
|
||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||
if (tag instanceof NumericTag) {
|
||||
return ((NumericTag) tag).getAsInt();
|
||||
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) {
|
||||
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
|
||||
ArrayList<Tag> list = new ArrayList<>();
|
||||
net.minecraft.nbt.ListTag nbtList = (net.minecraft.nbt.ListTag) tag;
|
||||
for (net.minecraft.nbt.Tag elem : nbtList) {
|
||||
if (elem instanceof net.minecraft.nbt.CompoundTag) {
|
||||
list.add(new PaperweightLazyCompoundTag((net.minecraft.nbt.CompoundTag) elem));
|
||||
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
|
||||
list.add(new PaperweightLazyCompoundTag(compoundTag));
|
||||
} else {
|
||||
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
|
||||
}
|
||||
@ -137,8 +136,8 @@ public class PaperweightLazyCompoundTag extends LazyCompoundTag {
|
||||
|
||||
public long asLong(String key) {
|
||||
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
|
||||
if (tag instanceof NumericTag) {
|
||||
return ((NumericTag) tag).getAsLong();
|
||||
if (tag instanceof NumericTag numTag) {
|
||||
return numTag.getAsLong();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -90,13 +90,13 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private static final Field serverWorldsField;
|
||||
private static final Field worldPaperConfigField;
|
||||
private static final Field flatBedrockField;
|
||||
private static final Field worldsField;
|
||||
private static final Field paperConfigField;
|
||||
private static final Field generateFlatBedrockField;
|
||||
private static final Field generatorSettingFlatField;
|
||||
private static final Field generatorSettingBaseSupplierField;
|
||||
private static final Field delegateField;
|
||||
private static final Field chunkProviderField;
|
||||
private static final Field chunkSourceField;
|
||||
|
||||
//list of chunk stati in correct order without FULL
|
||||
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
|
||||
|
||||
try {
|
||||
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
serverWorldsField.setAccessible(true);
|
||||
worldsField = CraftServer.class.getDeclaredField("worlds");
|
||||
worldsField.setAccessible(true);
|
||||
|
||||
Field tmpPaperConfigField;
|
||||
Field tmpFlatBedrockField;
|
||||
@ -140,8 +140,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
tmpPaperConfigField = null;
|
||||
tmpFlatBedrockField = null;
|
||||
}
|
||||
worldPaperConfigField = tmpPaperConfigField;
|
||||
flatBedrockField = tmpFlatBedrockField;
|
||||
paperConfigField = tmpPaperConfigField;
|
||||
generateFlatBedrockField = tmpFlatBedrockField;
|
||||
|
||||
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
|
||||
"settings", "g"));
|
||||
@ -153,8 +153,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
|
||||
delegateField.setAccessible(true);
|
||||
|
||||
chunkProviderField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C"));
|
||||
chunkProviderField.setAccessible(true);
|
||||
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C"));
|
||||
chunkSourceField.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -187,9 +187,9 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
}
|
||||
|
||||
//flat bedrock? (only on paper)
|
||||
if (worldPaperConfigField != null) {
|
||||
if (paperConfigField != null) {
|
||||
try {
|
||||
generateFlatBedrock = flatBedrockField.getBoolean(worldPaperConfigField.get(originalServerWorld));
|
||||
generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
@ -210,7 +210,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
|
||||
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
|
||||
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
|
||||
session = levelStorageSource.createAccess("worldeditregentempworld", levelStemResourceKey);
|
||||
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
|
||||
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
|
||||
|
||||
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
|
||||
@ -221,7 +221,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
? PaperweightAdapter.replaceSeed(originalServerWorld, seed, originalOpts)
|
||||
: originalOpts;
|
||||
LevelSettings newWorldSettings = new LevelSettings(
|
||||
"worldeditregentempworld",
|
||||
"faweregentempworld",
|
||||
originalWorldData.settings.gameType(),
|
||||
originalWorldData.settings.hardcore(),
|
||||
originalWorldData.settings.difficulty(),
|
||||
@ -232,7 +232,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
|
||||
|
||||
//init world
|
||||
freshWorld = Fawe.get().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
|
||||
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
|
||||
server,
|
||||
server.executor,
|
||||
session,
|
||||
@ -270,8 +270,8 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
freshWorld.noSave = true;
|
||||
removeWorldFromWorldsMap();
|
||||
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
|
||||
if (worldPaperConfigField != null) {
|
||||
worldPaperConfigField.set(freshWorld, originalServerWorld.paperConfig);
|
||||
if (paperConfigField != null) {
|
||||
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
|
||||
}
|
||||
|
||||
//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
|
||||
structureManager = server.getStructureManager();
|
||||
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
||||
@ -336,7 +336,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
//shutdown chunk provider
|
||||
try {
|
||||
Fawe.get().getQueueHandler().sync(() -> {
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
try {
|
||||
freshChunkProvider.close(false);
|
||||
} catch (IOException e) {
|
||||
@ -348,7 +348,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
//remove world from server
|
||||
try {
|
||||
Fawe.get().getQueueHandler().sync(this::removeWorldFromWorldsMap);
|
||||
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
@Override
|
||||
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
||||
// BlockPopulator#populate has to be called synchronously for TileEntity access
|
||||
TaskManager.IMP.task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
|
||||
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -403,10 +403,10 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
||||
|
||||
//util
|
||||
private void removeWorldFromWorldsMap() {
|
||||
Fawe.get().getQueueHandler().sync(() -> {
|
||||
Fawe.instance().getQueueHandler().sync(() -> {
|
||||
try {
|
||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
|
||||
map.remove("worldeditregentempworld");
|
||||
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) worldsField.get(Bukkit.getServer());
|
||||
map.remove("faweregentempworld");
|
||||
} catch (IllegalAccessException 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) {
|
||||
switch (env) {
|
||||
case NETHER:
|
||||
return LevelStem.NETHER;
|
||||
case THE_END:
|
||||
return LevelStem.END;
|
||||
case NORMAL:
|
||||
default:
|
||||
return LevelStem.OVERWORLD;
|
||||
}
|
||||
return switch (env) {
|
||||
case NETHER -> LevelStem.NETHER;
|
||||
case THE_END -> LevelStem.END;
|
||||
default -> LevelStem.OVERWORLD;
|
||||
};
|
||||
}
|
||||
|
||||
private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception {
|
||||
|
17
worldedit-bukkit/adapters/adapter-1_18/build.gradle.kts
Normale Datei
17
worldedit-bukkit/adapters/adapter-1_18/build.gradle.kts
Normale Datei
@ -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)
|
||||
}
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -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) {
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
}
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Binäre Datei nicht angezeigt.
@ -42,12 +42,6 @@ repositories {
|
||||
flatDir { dir(File("src/main/resources")) }
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force("com.google.guava:guava:21.0")
|
||||
}
|
||||
}
|
||||
|
||||
val localImplementation = configurations.create("localImplementation") {
|
||||
description = "Dependencies used locally, but provided by the runtime Bukkit implementation"
|
||||
isCanBeConsumed = false
|
||||
@ -108,7 +102,6 @@ dependencies {
|
||||
compileOnly(libs.protocollib) { isTransitive = false }
|
||||
compileOnly(libs.plotsquaredV6Bukkit) { isTransitive = false }
|
||||
compileOnly(libs.plotsquaredV6Core) { isTransitive = false }
|
||||
compileOnly(libs.plotsquaredV4) { isTransitive = false }
|
||||
|
||||
// Third party
|
||||
compileOnly(libs.flowmath) {
|
||||
@ -187,7 +180,7 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.1"))
|
||||
}
|
||||
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") {
|
||||
include(dependency("org.lz4:lz4-java:1.8.0"))
|
||||
|
@ -68,7 +68,6 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
public FaweBukkit(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
Settings.IMP.TICK_LIMITER.ENABLED = !Bukkit.hasWhitelist();
|
||||
Fawe.set(this);
|
||||
Fawe.setupInjector();
|
||||
try {
|
||||
@ -76,7 +75,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
} catch (Throwable 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);
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
@ -84,17 +83,19 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
Bukkit.getServer().shutdown();
|
||||
}
|
||||
|
||||
chunksStretched = new MinecraftVersion().isEqualOrHigher(MinecraftVersion.NETHER);
|
||||
MinecraftVersion version = new MinecraftVersion();
|
||||
|
||||
chunksStretched = version.isEqualOrHigherThan(MinecraftVersion.NETHER);
|
||||
|
||||
platformAdapter = new NMSAdapter();
|
||||
|
||||
//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
|
||||
TaskManager.IMP.task(() -> {
|
||||
TaskManager.taskManager().task(() -> {
|
||||
// Fix for ProtocolSupport
|
||||
Settings.IMP.PROTOCOL_SUPPORT_FIX =
|
||||
Settings.settings().PROTOCOL_SUPPORT_FIX =
|
||||
Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
|
||||
|
||||
// This class
|
||||
@ -103,6 +104,11 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
// The tick limiter
|
||||
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
|
||||
@ -141,7 +147,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
try {
|
||||
this.itemUtil = tmp = new ItemUtil();
|
||||
} catch (Throwable e) {
|
||||
Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES = false;
|
||||
Settings.settings().EXPERIMENTAL.PERSISTENT_BRUSHES = false;
|
||||
LOGGER.error("Persistent Brushes Failed", e);
|
||||
}
|
||||
}
|
||||
@ -310,14 +316,12 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
if (plotSquared == null) {
|
||||
return;
|
||||
}
|
||||
if (plotSquared.getClass().getPackage().toString().contains("intellectualsites")) {
|
||||
WEManager.IMP.addManager(new com.fastasyncworldedit.bukkit.regions.plotsquaredv4.PlotSquaredFeature());
|
||||
LOGGER.info("Plugin 'PlotSquared' 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.");
|
||||
if (PlotSquared.get().getVersion().version[0] == 6) {
|
||||
WEManager.weManager().addManager(new com.fastasyncworldedit.bukkit.regions.plotsquared.PlotSquaredFeature());
|
||||
LOGGER.info("Plugin 'PlotSquared' v6 found. Using it now.");
|
||||
} else {
|
||||
LOGGER.error("Incompatible version of PlotSquared found. Please use PlotSquared v6.");
|
||||
LOGGER.info("https://www.spigotmc.org/resources/77506/");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ public interface IBukkitAdapter {
|
||||
* @return list of {@link org.bukkit.entity.Entity}
|
||||
*/
|
||||
default List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
|
||||
return TaskManager.IMP.sync(world::getEntities);
|
||||
return TaskManager.taskManager().sync(world::getEntities);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public interface IDelegateBukkitImplAdapter<T> extends BukkitImplAdapter<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
default BaseBlock getBlock(Location location) {
|
||||
default BlockState getBlock(Location location) {
|
||||
return getParent().getBlock(location);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.fastasyncworldedit.core.FAWEPlatformAdapterImpl;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.util.MathMan;
|
||||
import com.fastasyncworldedit.core.world.block.BlockID;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
@ -24,8 +23,8 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
int num_palette = 0;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char ordinal = set[i];
|
||||
if (ordinal == BlockID.__RESERVED__) {
|
||||
ordinal = BlockID.AIR;
|
||||
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
||||
ordinal = BlockTypesCache.ReservedIDs.AIR;
|
||||
}
|
||||
int palette = blockToPalette[ordinal];
|
||||
if (palette == Integer.MAX_VALUE) {
|
||||
@ -43,17 +42,15 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
}
|
||||
System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length);
|
||||
}
|
||||
char lastOrdinal = BlockID.__RESERVED__;
|
||||
char lastOrdinal = 0;
|
||||
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++) {
|
||||
char ordinal = set[i];
|
||||
switch (ordinal) {
|
||||
case BlockID.__RESERVED__:
|
||||
ordinal = BlockID.AIR;
|
||||
case BlockID.AIR:
|
||||
case BlockID.CAVE_AIR:
|
||||
case BlockID.VOID_AIR:
|
||||
case BlockTypesCache.ReservedIDs.__RESERVED__:
|
||||
ordinal = BlockTypesCache.ReservedIDs.AIR;
|
||||
case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR:
|
||||
air++;
|
||||
break;
|
||||
default:
|
||||
@ -95,13 +92,13 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
char[] getArr = null;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char ordinal = set[i];
|
||||
if (ordinal == BlockID.__RESERVED__) {
|
||||
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
||||
if (getArr == null) {
|
||||
getArr = get.apply(layer);
|
||||
}
|
||||
ordinal = getArr[i];
|
||||
if (ordinal == BlockID.__RESERVED__) {
|
||||
ordinal = BlockID.AIR;
|
||||
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
||||
ordinal = BlockTypesCache.ReservedIDs.AIR;
|
||||
}
|
||||
}
|
||||
int palette = blockToPalette[ordinal];
|
||||
@ -120,26 +117,23 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
}
|
||||
System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length);
|
||||
}
|
||||
char lastOrdinal = BlockID.__RESERVED__;
|
||||
char lastOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
|
||||
boolean lastticking = false;
|
||||
boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED;
|
||||
boolean tick_existing = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_EXISTING;
|
||||
boolean tick_placed = Settings.settings().EXPERIMENTAL.ALLOW_TICK_PLACED;
|
||||
boolean tick_existing = Settings.settings().EXPERIMENTAL.ALLOW_TICK_EXISTING;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char ordinal = set[i];
|
||||
switch (ordinal) {
|
||||
case BlockID.__RESERVED__: {
|
||||
case BlockTypesCache.ReservedIDs.__RESERVED__ -> {
|
||||
if (getArr == null) {
|
||||
getArr = get.apply(layer);
|
||||
}
|
||||
ordinal = getArr[i];
|
||||
switch (ordinal) {
|
||||
case BlockID.__RESERVED__:
|
||||
ordinal = BlockID.AIR;
|
||||
case BlockID.AIR:
|
||||
case BlockID.CAVE_AIR:
|
||||
case BlockID.VOID_AIR:
|
||||
set[i] = switch (ordinal = getArr[i]) {
|
||||
case BlockTypesCache.ReservedIDs.__RESERVED__:
|
||||
ordinal = BlockTypesCache.ReservedIDs.AIR;
|
||||
case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR:
|
||||
air++;
|
||||
break;
|
||||
yield ordinal;
|
||||
default:
|
||||
if (!fastmode && !tick_placed && tick_existing) {
|
||||
boolean ticking;
|
||||
@ -152,23 +146,19 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
}
|
||||
if (ticking) {
|
||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
||||
ticking_blocks
|
||||
.put(
|
||||
BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15),
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter()
|
||||
.getInternalBlockStateId(state).orElse(0)
|
||||
);
|
||||
ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15),
|
||||
WorldEditPlugin
|
||||
.getInstance()
|
||||
.getBukkitImplAdapter()
|
||||
.getInternalBlockStateId(state)
|
||||
.orElse(0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
set[i] = ordinal;
|
||||
break;
|
||||
yield ordinal;
|
||||
};
|
||||
}
|
||||
case BlockID.AIR:
|
||||
case BlockID.CAVE_AIR:
|
||||
case BlockID.VOID_AIR:
|
||||
air++;
|
||||
break;
|
||||
case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR -> air++;
|
||||
}
|
||||
if (!fastmode && tick_placed) {
|
||||
boolean ticking;
|
||||
|
@ -18,7 +18,7 @@ public class NMSRelighterFactory implements RelighterFactory {
|
||||
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
|
||||
return new NMSRelighter(
|
||||
queue,
|
||||
relightMode != null ? relightMode : RelightMode.valueOf(Settings.IMP.LIGHTING.MODE)
|
||||
relightMode != null ? relightMode : RelightMode.valueOf(Settings.settings().LIGHTING.MODE)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,10 @@ import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
|
||||
import com.fastasyncworldedit.core.util.MathMan;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -32,6 +35,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -151,7 +155,10 @@ public abstract class Regenerator<IChunkAccess, ProtoChunk extends IChunkAccess,
|
||||
private boolean generate() throws Exception {
|
||||
if (generateConcurrent) {
|
||||
//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
|
||||
|
||||
//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() {
|
||||
//Setting Blocks
|
||||
long start = System.currentTimeMillis();
|
||||
boolean genbiomes = options.shouldRegenBiomes();
|
||||
boolean hasBiome = options.hasBiomeType();
|
||||
BiomeType biome = options.getBiomeType();
|
||||
for (BlockVector3 vec : region) {
|
||||
BaseBlock block = source.getFullBlock(vec);
|
||||
target.setBlock(vec, block);
|
||||
if (hasBiome) {
|
||||
target.setBiome(vec, biome);
|
||||
} else if (genbiomes) {
|
||||
target.setBiome(vec, source.getBiome(vec));
|
||||
}
|
||||
if (!genbiomes && !hasBiome) {
|
||||
target.setBlocks(region, new PlacementPattern());
|
||||
}
|
||||
if (hasBiome) {
|
||||
target.setBlocks(region, new WithBiomePlacementPattern(ignored -> biome));
|
||||
} else if (genbiomes) {
|
||||
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
|
||||
|
@ -45,20 +45,25 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
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 {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
protected int rateLimit = 0;
|
||||
protected Location lastCancelPos;
|
||||
private final int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS_MS,
|
||||
Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS};
|
||||
private final int[] badLimit = new int[]{Settings.settings().TICK_LIMITER.PHYSICS_MS,
|
||||
Settings.settings().TICK_LIMITER.FALLING, Settings.settings().TICK_LIMITER.ITEMS};
|
||||
|
||||
public ChunkListener() {
|
||||
if (Settings.IMP.TICK_LIMITER.ENABLED) {
|
||||
if (Settings.settings().TICK_LIMITER.ENABLED) {
|
||||
PluginManager plm = Bukkit.getPluginManager();
|
||||
Plugin plugin = Fawe.<FaweBukkit>imp().getPlugin();
|
||||
Plugin plugin = Fawe.<FaweBukkit>platform().getPlugin();
|
||||
plm.registerEvents(this, plugin);
|
||||
TaskManager.IMP.repeat(() -> {
|
||||
TaskManager.taskManager().repeat(() -> {
|
||||
Location tmpLoc = lastCancelPos;
|
||||
if (tmpLoc != null) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
/**
|
||||
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener} for an explanation of the deprecation
|
||||
*/
|
||||
@Deprecated(since = "2.0.0")
|
||||
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;
|
||||
|
||||
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[] 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) {
|
||||
if (lastX == cx && lastZ == cz) {
|
||||
return lastCount;
|
||||
@ -112,6 +129,10 @@ public abstract class ChunkListener implements Listener {
|
||||
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) {
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (entity.getType() == EntityType.DROPPED_ITEM) {
|
||||
@ -128,6 +149,10 @@ public abstract class ChunkListener implements Listener {
|
||||
protected long physStart;
|
||||
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() {
|
||||
physSkip = 0;
|
||||
physStart = System.currentTimeMillis();
|
||||
@ -241,13 +266,13 @@ public abstract class ChunkListener implements Listener {
|
||||
if ((++physSkip & 1023) != 0) {
|
||||
return;
|
||||
}
|
||||
FaweTimer timer = Fawe.get().getTimer();
|
||||
FaweTimer timer = Fawe.instance().getTimer();
|
||||
if (timer.getTick() != physTick) {
|
||||
physTick = timer.getTick();
|
||||
physStart = System.currentTimeMillis();
|
||||
return;
|
||||
} else if (System.currentTimeMillis() - physStart
|
||||
< Settings.IMP.TICK_LIMITER.PHYSICS_MS) {
|
||||
< Settings.settings().TICK_LIMITER.PHYSICS_MS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -324,15 +349,15 @@ public abstract class ChunkListener implements Listener {
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int[] count = getCount(cx, cz);
|
||||
if (count[1] >= Settings.IMP.TICK_LIMITER.FALLING) {
|
||||
if (count[1] >= Settings.settings().TICK_LIMITER.FALLING) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
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
|
||||
if (Fawe.get().getTimer().getTPS() < 18) {
|
||||
if (Fawe.instance().getTimer().getTPS() < 18) {
|
||||
cancelNearby(cx, cz);
|
||||
if (rateLimit <= 0) {
|
||||
rateLimit = 20;
|
||||
@ -351,7 +376,7 @@ public abstract class ChunkListener implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
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();
|
||||
Entity[] entities = chunk.getEntities();
|
||||
World world = chunk.getWorld();
|
||||
@ -377,8 +402,8 @@ public abstract class ChunkListener implements Listener {
|
||||
if (Math.abs(velocity.getX()) > vertical
|
||||
|| Math.abs(velocity.getZ()) > vertical) {
|
||||
LOGGER.warn(
|
||||
"[FAWE `tick-limiter`] Detected and cancelled rogue FireWork at "
|
||||
+ ent.getLocation());
|
||||
"[FAWE `tick-limiter`] Detected and cancelled rogue FireWork at {}",
|
||||
ent.getLocation());
|
||||
ent.remove();
|
||||
}
|
||||
}
|
||||
@ -398,17 +423,17 @@ public abstract class ChunkListener implements Listener {
|
||||
int cx = loc.getBlockX() >> 4;
|
||||
int cz = loc.getBlockZ() >> 4;
|
||||
int[] count = getCount(cx, cz);
|
||||
if (count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) {
|
||||
if (count[2] >= Settings.settings().TICK_LIMITER.ITEMS) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (++count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) {
|
||||
if (++count[2] >= Settings.settings().TICK_LIMITER.ITEMS) {
|
||||
cleanup(loc.getChunk());
|
||||
cancelNearby(cx, cz);
|
||||
if (rateLimit <= 0) {
|
||||
rateLimit = 20;
|
||||
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);
|
||||
}
|
||||
|
@ -9,11 +9,20 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
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 {
|
||||
|
||||
private Exception exception;
|
||||
private StackTraceElement[] elements;
|
||||
|
||||
/**
|
||||
* @deprecated see {@link com.fastasyncworldedit.bukkit.listener.ChunkListener9} for an explanation of the deprecation
|
||||
*/
|
||||
@Deprecated(since = "2.0.0")
|
||||
public ChunkListener9() {
|
||||
super();
|
||||
}
|
||||
@ -37,13 +46,13 @@ public class ChunkListener9 extends ChunkListener {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() - physStart > Settings.IMP.TICK_LIMITER.PHYSICS_MS) {
|
||||
if (System.currentTimeMillis() - physStart > Settings.settings().TICK_LIMITER.PHYSICS_MS) {
|
||||
physCancelPair = pair;
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FaweTimer timer = Fawe.get().getTimer();
|
||||
FaweTimer timer = Fawe.instance().getTimer();
|
||||
if (timer.getTick() != physTick) {
|
||||
physTick = timer.getTick();
|
||||
physStart = System.currentTimeMillis();
|
||||
@ -52,7 +61,7 @@ public class ChunkListener9 extends ChunkListener {
|
||||
return;
|
||||
}
|
||||
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();
|
||||
int cx = block.getX() >> 4;
|
||||
int cz = block.getZ() >> 4;
|
||||
|
@ -28,7 +28,7 @@ public class RenderListener implements Listener {
|
||||
|
||||
public RenderListener(Plugin plugin) {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
TaskManager.IMP.repeat(new Runnable() {
|
||||
TaskManager.taskManager().repeat(new Runnable() {
|
||||
private long last = 0;
|
||||
|
||||
@Override
|
||||
@ -38,7 +38,7 @@ public class RenderListener implements Listener {
|
||||
}
|
||||
|
||||
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;
|
||||
last = now;
|
||||
if (diff > 75) {
|
||||
@ -56,7 +56,7 @@ public class RenderListener implements Listener {
|
||||
if (entrySet == null || !entrySet.hasNext()) {
|
||||
entrySet = views.entrySet().iterator();
|
||||
}
|
||||
int nowTick = (int) (Fawe.get().getTimer().getTick());
|
||||
int nowTick = (int) (Fawe.instance().getTimer().getTick());
|
||||
while (entrySet.hasNext()) {
|
||||
Map.Entry<UUID, int[]> entry = entrySet.next();
|
||||
Player player = Bukkit.getPlayer(entry.getKey());
|
||||
@ -81,17 +81,17 @@ public class RenderListener implements Listener {
|
||||
|
||||
private void setViewDistance(Player player, int value) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
if (value == Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING) {
|
||||
if (value == Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING) {
|
||||
views.remove(uuid);
|
||||
} else {
|
||||
int[] val = views.get(uuid);
|
||||
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();
|
||||
views.put(uid, val);
|
||||
} else {
|
||||
if (value <= val[0]) {
|
||||
val[1] = (int) Fawe.get().getTimer().getTick();
|
||||
val[1] = (int) Fawe.instance().getTimer().getTick();
|
||||
}
|
||||
if (val[0] == value) {
|
||||
return;
|
||||
@ -105,7 +105,7 @@ public class RenderListener implements Listener {
|
||||
|
||||
private int getViewDistance(Player player) {
|
||||
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)
|
||||
|
@ -32,7 +32,7 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener
|
||||
}
|
||||
|
||||
@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 Location loc = player.getLocation();
|
||||
final Vector3i vector = Vector3i.from(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
|
@ -1,7 +1,9 @@
|
||||
package com.fastasyncworldedit.bukkit.regions;
|
||||
|
||||
import com.fastasyncworldedit.core.regions.FaweMask;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
@ -30,7 +32,7 @@ public class GriefPreventionFeature extends BukkitMaskManager implements Listene
|
||||
}
|
||||
|
||||
@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 Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, null);
|
||||
if (claim != null) {
|
||||
@ -38,12 +40,12 @@ public class GriefPreventionFeature extends BukkitMaskManager implements Listene
|
||||
claim.getGreaterBoundaryCorner().getBlockX();
|
||||
final BlockVector3 pos1 = BlockVector3.at(
|
||||
claim.getLesserBoundaryCorner().getBlockX(),
|
||||
0,
|
||||
player.getWorld().getMinHeight(),
|
||||
claim.getLesserBoundaryCorner().getBlockZ()
|
||||
);
|
||||
final BlockVector3 pos2 = BlockVector3.at(
|
||||
claim.getGreaterBoundaryCorner().getBlockX(),
|
||||
256,
|
||||
player.getWorld().getMaxHeight(),
|
||||
claim.getGreaterBoundaryCorner().getBlockZ()
|
||||
);
|
||||
return new FaweMask(new CuboidRegion(pos1, pos2)) {
|
||||
|
@ -33,13 +33,13 @@ public class ResidenceFeature extends BukkitMaskManager implements Listener {
|
||||
return residence != null &&
|
||||
(residence.getOwner().equals(player.getName()) ||
|
||||
residence.getOwner().equals(player.getUniqueId().toString()) ||
|
||||
type == MaskType.MEMBER && TaskManager.IMP.sync(() -> residence
|
||||
type == MaskType.MEMBER && TaskManager.taskManager().sync(() -> residence
|
||||
.getPermissions()
|
||||
.playerHas(player, "build", false)));
|
||||
}
|
||||
|
||||
@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 Location location = player.getLocation();
|
||||
ClaimedResidence residence = Residence.getInstance().getResidenceManager().getByLoc(location);
|
||||
|
@ -66,7 +66,7 @@ public class TownyFeature extends BukkitMaskManager implements Listener {
|
||||
}
|
||||
|
||||
@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 Location location = player.getLocation();
|
||||
try {
|
||||
|
@ -53,7 +53,7 @@ public class FaweDelegateRegionManager {
|
||||
int maxY,
|
||||
Runnable whenDone
|
||||
) {
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
World world = BukkitAdapter.adapt(getWorld(area.getWorldName()));
|
||||
EditSession session = WorldEdit.getInstance().newEditSessionBuilder().world(world).checkMemory(false).
|
||||
@ -67,14 +67,14 @@ public class FaweDelegateRegionManager {
|
||||
session.flushQueue();
|
||||
for (CuboidRegion region : regions) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (whenDone != null) {
|
||||
TaskManager.IMP.task(whenDone);
|
||||
TaskManager.taskManager().task(whenDone);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +92,7 @@ public class FaweDelegateRegionManager {
|
||||
@Nullable Runnable whenDone,
|
||||
@Nonnull PlotManager manager
|
||||
) {
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
final HybridPlotWorld hybridPlotWorld = ((HybridPlotManager) manager).getHybridPlotWorld();
|
||||
World world = BukkitAdapter.adapt(getWorld(hybridPlotWorld.getWorldName()));
|
||||
@ -176,10 +176,10 @@ public class FaweDelegateRegionManager {
|
||||
world,
|
||||
new CuboidRegion(plot.getBottomAbs().getBlockVector3(), plot.getTopAbs().getBlockVector3()),
|
||||
null,
|
||||
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE)
|
||||
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
|
||||
);
|
||||
if (whenDone != null) {
|
||||
TaskManager.IMP.task(whenDone);
|
||||
TaskManager.taskManager().task(whenDone);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -192,7 +192,7 @@ public class FaweDelegateRegionManager {
|
||||
Location swapPos,
|
||||
final Runnable whenDone
|
||||
) {
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
//todo because of the following code this should proably be in the Bukkit module
|
||||
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
|
||||
@ -220,18 +220,22 @@ public class FaweDelegateRegionManager {
|
||||
Clipboard clipB = Clipboard.create(regionB, UUID.randomUUID());
|
||||
ForwardExtentCopy copyA = new ForwardExtentCopy(sessionA, regionA, clipA, clipA.getMinimumPoint());
|
||||
ForwardExtentCopy copyB = new ForwardExtentCopy(sessionB, regionB, clipB, clipB.getMinimumPoint());
|
||||
copyA.setCopyingBiomes(true);
|
||||
copyB.setCopyingBiomes(true);
|
||||
try {
|
||||
Operations.completeLegacy(copyA);
|
||||
Operations.completeLegacy(copyB);
|
||||
clipA.paste(sessionB, swapPos.getBlockVector3(), true);
|
||||
clipB.paste(sessionA, pos1.getBlockVector3(), true);
|
||||
sessionA.flushQueue();
|
||||
sessionB.flushQueue();
|
||||
clipA.flush();
|
||||
clipB.flush();
|
||||
clipA.paste(sessionB, swapPos.getBlockVector3(), true, true, true);
|
||||
clipB.paste(sessionA, pos1.getBlockVector3(), true, true, true);
|
||||
sessionA.close();
|
||||
sessionB.close();
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
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(
|
||||
swapPos.getBlockVector3(),
|
||||
@ -241,10 +245,10 @@ public class FaweDelegateRegionManager {
|
||||
swapPos.getZ() + pos2.getZ() - pos1.getZ()
|
||||
)
|
||||
), null,
|
||||
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.IMP.LIGHTING.MODE)
|
||||
RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE)
|
||||
);
|
||||
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) {
|
||||
region.expand(BlockVector3.at(extendBiome, 0, extendBiome));
|
||||
region.expand(BlockVector3.at(-extendBiome, 0, -extendBiome));
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
EditSession editSession = WorldEdit
|
||||
.getInstance()
|
||||
@ -273,7 +277,7 @@ public class FaweDelegateRegionManager {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (whenDone != null) {
|
||||
TaskManager.IMP.task(whenDone);
|
||||
TaskManager.taskManager().task(whenDone);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -285,7 +289,7 @@ public class FaweDelegateRegionManager {
|
||||
final @NonNull Location pos3,
|
||||
final @NonNull Runnable whenDone
|
||||
) {
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
|
||||
World pos3World = BukkitAdapter.adapt(getWorld(pos3.getWorldName()));
|
||||
@ -319,21 +323,21 @@ public class FaweDelegateRegionManager {
|
||||
pos3.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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (whenDone != null) {
|
||||
TaskManager.IMP.task(whenDone);
|
||||
TaskManager.taskManager().task(whenDone);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean regenerateRegion(final Location pos1, final Location pos2, boolean ignore, final Runnable whenDone) {
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
synchronized (FaweDelegateRegionManager.class) {
|
||||
World pos1World = BukkitAdapter.adapt(getWorld(pos1.getWorldName()));
|
||||
try (EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder().world(pos1World)
|
||||
@ -350,7 +354,7 @@ public class FaweDelegateRegionManager {
|
||||
editSession.flushQueue();
|
||||
}
|
||||
if (whenDone != null) {
|
||||
TaskManager.IMP.task(whenDone);
|
||||
TaskManager.taskManager().task(whenDone);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -132,7 +132,7 @@ public class FaweDelegateSchematicHandler {
|
||||
}
|
||||
};
|
||||
if (Fawe.isMainThread()) {
|
||||
com.fastasyncworldedit.core.util.TaskManager.IMP.async(r);
|
||||
com.fastasyncworldedit.core.util.TaskManager.taskManager().async(r);
|
||||
} else {
|
||||
r.run();
|
||||
}
|
||||
@ -186,7 +186,7 @@ public class FaweDelegateSchematicHandler {
|
||||
}
|
||||
return;
|
||||
}
|
||||
final CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag);
|
||||
final CompoundTag weTag = (CompoundTag) FaweCache.INSTANCE.asTag(tag);
|
||||
SchematicHandler.upload(uuid, file, "schem", new RunnableVal<>() {
|
||||
@Override
|
||||
public void run(OutputStream output) {
|
||||
@ -235,10 +235,8 @@ public class FaweDelegateSchematicHandler {
|
||||
Clipboard clip = schematicReader.read();
|
||||
return new Schematic(clip);
|
||||
} catch (IOException e3) {
|
||||
LOGGER.warn("{} | {} : {}", is, is.getClass().getCanonicalName(), e.getMessage());
|
||||
e.printStackTrace();
|
||||
LOGGER.warn(
|
||||
is + " | " + is.getClass().getCanonicalName() + " is not in GZIP format : " + e
|
||||
.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ public class FaweQueueCoordinator extends QueueCoordinator {
|
||||
public FaweQueueCoordinator(World world) {
|
||||
super(world);
|
||||
this.world = world;
|
||||
instance = Fawe.get().getQueueHandler().getQueue(world);
|
||||
Fawe.get().getQueueHandler().unCache();
|
||||
instance = Fawe.instance().getQueueHandler().getQueue(world);
|
||||
Fawe.instance().getQueueHandler().unCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -194,7 +194,7 @@ public class FaweQueueCoordinator extends QueueCoordinator {
|
||||
|
||||
@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));
|
||||
instance.setTile(x, y, z, (com.sk89q.jnbt.CompoundTag) FaweCache.INSTANCE.asTag(tag));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class FaweTrim extends SubCommand {
|
||||
return false;
|
||||
}
|
||||
ran = true;
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
try {
|
||||
// TODO NOT IMPLEMENTED
|
||||
//PlotTrim trim = new PlotTrim(plotPlayer, plotPlayer.getPlotAreaAbs(), strings[0], Boolean.parseBoolean(strings[1]));
|
||||
|
@ -89,7 +89,7 @@ public class PlotSetBiome extends Command {
|
||||
return;
|
||||
}
|
||||
plot.addRunning();
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
EditSession session =
|
||||
WorldEdit
|
||||
.getInstance()
|
||||
|
@ -4,9 +4,6 @@ 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.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.database.DBFunc;
|
||||
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) {
|
||||
if (plot == null) {
|
||||
return false;
|
||||
@ -121,7 +127,7 @@ public class PlotSquaredFeature extends FaweMaskManager {
|
||||
}
|
||||
|
||||
@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));
|
||||
if (pp == null) {
|
||||
return null;
|
||||
|
@ -46,9 +46,9 @@ public class ReplaceAll extends Command {
|
||||
plot.addRunning();
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player.getName());
|
||||
Captions.TASK_START.send(player);
|
||||
TaskManager.IMP.async(() -> fp.runAction(() -> {
|
||||
TaskManager.taskManager().async(() -> fp.runAction(() -> {
|
||||
String worldName = plot.getWorldName();
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
TaskManager.taskManager().sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
SetupUtils.manager.unload(worldName, true);
|
||||
@ -58,7 +58,7 @@ public class ReplaceAll extends Command {
|
||||
String cmd = "/replaceallpattern " + worldName + " " + StringMan.join(args, " ");
|
||||
CommandEvent event = new CommandEvent(actor, cmd);
|
||||
PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event);
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
TaskManager.taskManager().sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
plot.teleportPlayer(player);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -34,7 +34,7 @@ public class BukkitItemStack extends BaseItemStack {
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getNativeItem() {
|
||||
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil();
|
||||
ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
|
||||
if (util != null && nativeItem == null) {
|
||||
return nativeItem = util.getNMSItem(stack);
|
||||
}
|
||||
@ -58,7 +58,7 @@ public class BukkitItemStack extends BaseItemStack {
|
||||
public CompoundTag getNbtData() {
|
||||
if (!loadedNBT) {
|
||||
loadedNBT = true;
|
||||
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil();
|
||||
ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
|
||||
if (util != null) {
|
||||
super.setNbtData(util.getNBT(stack));
|
||||
}
|
||||
@ -68,7 +68,7 @@ public class BukkitItemStack extends BaseItemStack {
|
||||
|
||||
@Override
|
||||
public void setNbtData(@Nullable CompoundTag nbtData) {
|
||||
ItemUtil util = Fawe.<FaweBukkit>imp().getItemUtil();
|
||||
ItemUtil util = Fawe.<FaweBukkit>platform().getItemUtil();
|
||||
if (util != null) {
|
||||
stack = util.setNBT(stack, nbtData);
|
||||
nativeItem = null;
|
||||
|
@ -12,6 +12,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
|
||||
public static final MinecraftVersion NETHER = new MinecraftVersion(1, 16);
|
||||
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 minor;
|
||||
@ -68,7 +69,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
* @param other The other version to compare against.
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -76,7 +77,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
* @param other The other version to compare against.
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -84,7 +85,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
* @param other The other version to compare against.
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -92,7 +93,7 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
* @param other The other version to compare against.
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -139,6 +140,11 @@ public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
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},
|
||||
* where v1_16_R3 is the resolved version.
|
||||
|
@ -107,7 +107,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
this.player = player;
|
||||
//FAWE start
|
||||
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);
|
||||
if (cached == null) {
|
||||
loadClipboardFromDisk();
|
||||
@ -169,7 +169,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
player.getInventory().setItemInMainHand(newItem);
|
||||
HashMap<Integer, ItemStack> overflow = inv.addItem(item);
|
||||
if (!overflow.isEmpty()) {
|
||||
TaskManager.IMP.sync(new RunnableVal<>() {
|
||||
TaskManager.taskManager().sync(new RunnableVal<>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
for (Map.Entry<Integer, ItemStack> entry : overflow.entrySet()) {
|
||||
@ -243,7 +243,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
}
|
||||
org.bukkit.World finalWorld = world;
|
||||
//FAWE end
|
||||
return TaskManager.IMP.sync(() -> player.teleport(new Location(
|
||||
return TaskManager.taskManager().sync(() -> player.teleport(new Location(
|
||||
finalWorld,
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
|
||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.bukkit.util.CommandInfo;
|
||||
@ -274,9 +275,19 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser
|
||||
RelighterFactory getRelighterFactory() {
|
||||
if (this.relighterFactory == null) {
|
||||
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;
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
@ -301,10 +301,10 @@ public class BukkitWorld extends AbstractWorld {
|
||||
if (treeTypeMapping.get(type) == null) {
|
||||
LOGGER.error("No TreeType mapping for TreeGenerator.TreeType." + type);
|
||||
//FAWE start
|
||||
LOGGER.info("The above message is displayed because your FAWE version is newer than " + Bukkit.getVersion() +
|
||||
" and contains features of future minecraft versions which do not exist in "
|
||||
+ Bukkit.getVersion() + ", hence the tree type " + type + " is not available. This is not an error. " +
|
||||
"This version will work on your version of Minecraft. This is an informative message only");
|
||||
LOGGER.info("The above message is displayed because your FAWE version is newer than {}" +
|
||||
" and contains features of future minecraft versions which do not exist in {} hence the tree type" +
|
||||
"{} is not available. This is not an error. This version will work on your version of Minecraft." +
|
||||
"This is an informative message only.", Bukkit.getVersion(), Bukkit.getVersion(), type);
|
||||
//FAWE end
|
||||
}
|
||||
}
|
||||
@ -317,7 +317,7 @@ public class BukkitWorld extends AbstractWorld {
|
||||
@Override
|
||||
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) {
|
||||
//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()
|
||||
));
|
||||
//FAWE end
|
||||
@ -520,7 +520,7 @@ public class BukkitWorld extends AbstractWorld {
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
if (adapter != null) {
|
||||
return adapter.getBlock(BukkitAdapter.adapt(getWorld(), position));
|
||||
return adapter.getFullBlock(BukkitAdapter.adapt(getWorld(), position));
|
||||
} else {
|
||||
return getBlock(position).toBaseBlock();
|
||||
}
|
||||
@ -555,7 +555,7 @@ public class BukkitWorld extends AbstractWorld {
|
||||
@Override
|
||||
public boolean fullySupports3DBiomes() {
|
||||
// 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")
|
||||
|
@ -138,12 +138,12 @@ public class WorldEditPlugin extends JavaPlugin {
|
||||
platform = new BukkitServerInterface(this, getServer());
|
||||
worldEdit.getPlatformManager().register(platform);
|
||||
|
||||
//FAWE start - Rename config to config-legacy.yml TODO: Chose a better name in the future
|
||||
createDefaultConfiguration("config-legacy.yml"); // Create the default configuration file for WorldEdit, for us it's 'config-legacy.yml'
|
||||
//FAWE start - Migrate from config-legacy to worldedit-config
|
||||
migrateLegacyConfig();
|
||||
//FAWE end
|
||||
|
||||
//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 start - Setup permission attachments
|
||||
@ -220,8 +220,6 @@ public class WorldEditPlugin extends JavaPlugin {
|
||||
// Enable metrics
|
||||
new Metrics(this, BSTATS_ID);
|
||||
|
||||
// Check whether the server runs on 11 or greater
|
||||
ServerLib.checkJavaLTS();
|
||||
// Check if we are in a safe environment
|
||||
ServerLib.checkUnsafeForks();
|
||||
// Check if a new build is available
|
||||
@ -369,8 +367,8 @@ public class WorldEditPlugin extends JavaPlugin {
|
||||
} else {
|
||||
//FAWE start - Identify as FAWE
|
||||
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() + ") "
|
||||
+ "that handles the world editing.");
|
||||
+ "but it seems that you have another implementation of FastAsyncWorldEdit installed ({}) "
|
||||
+ "that handles the world editing.", platform.getPlatformName());
|
||||
//FAWE end
|
||||
}
|
||||
this.adapter.invalidate();
|
||||
@ -382,7 +380,7 @@ public class WorldEditPlugin extends JavaPlugin {
|
||||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Fawe.get().onDisable();
|
||||
Fawe.instance().onDisable();
|
||||
WorldEdit worldEdit = WorldEdit.getInstance();
|
||||
worldEdit.getSessionManager().unload();
|
||||
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) {
|
||||
try (FileOutputStream output = new FileOutputStream(actual)) {
|
||||
byte[] buf = new byte[8192];
|
||||
|
@ -106,7 +106,15 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
||||
* @param location the location
|
||||
* @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.
|
||||
@ -306,7 +314,7 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
|
||||
|
||||
@Nullable
|
||||
default World createWorld(WorldCreator creator) {
|
||||
return ((FaweBukkit) Fawe.imp()).createWorldUnloaded(creator::createWorld);
|
||||
return ((FaweBukkit) Fawe.platform()).createWorldUnloaded(creator::createWorld);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.bukkit.adapter;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.util.io.Closer;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -39,6 +40,8 @@ public class BukkitImplLoader {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
private final List<String> adapterCandidates = new ArrayList<>();
|
||||
private final String minorMCVersion = String.valueOf(new MinecraftVersion().getMinor());
|
||||
private int zeroth = 0;
|
||||
private String customCandidate;
|
||||
|
||||
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");
|
||||
if (className != null) {
|
||||
customCandidate = className;
|
||||
zeroth = 1;
|
||||
adapterCandidates.add(className);
|
||||
LOGGER.info("-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters");
|
||||
}
|
||||
@ -101,7 +105,11 @@ public class BukkitImplLoader {
|
||||
int beginIndex = 0;
|
||||
int endIndex = className.length() - CLASS_SUFFIX.length();
|
||||
className = className.substring(beginIndex, endIndex);
|
||||
adapterCandidates.add(className);
|
||||
if (className.contains(minorMCVersion)) {
|
||||
adapterCandidates.add(zeroth, className);
|
||||
} else {
|
||||
adapterCandidates.add(className);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closer.close();
|
||||
@ -142,7 +150,11 @@ public class BukkitImplLoader {
|
||||
int beginIndex = 0;
|
||||
int endIndex = resource.length() - CLASS_SUFFIX.length();
|
||||
String className = resource.substring(beginIndex, endIndex);
|
||||
adapterCandidates.add(className);
|
||||
if (className.contains(minorMCVersion)) {
|
||||
adapterCandidates.add(zeroth, className);
|
||||
} else {
|
||||
adapterCandidates.add(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,39 +10,39 @@
|
||||
# in categories, like "max-blocks-changed", are placed in the "limits"
|
||||
# category.
|
||||
# - 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:".
|
||||
# - Lines starting with # are comments, so they are ignored.
|
||||
# - If you want to allow blocks, make sure to change "disallowed-blocks" to []
|
||||
#
|
||||
|
||||
limits :
|
||||
max-blocks-changed :
|
||||
limits:
|
||||
max-blocks-changed:
|
||||
# Ignored, use FAWE config limits
|
||||
default : -1
|
||||
maximum : -1
|
||||
max-polygonal-points :
|
||||
default : -1
|
||||
maximum : 20
|
||||
max-radius : -1
|
||||
max-super-pickaxe-size : 5
|
||||
max-brush-radius : 100
|
||||
butcher-radius :
|
||||
default : -1
|
||||
maximum : -1
|
||||
disallowed-blocks :
|
||||
default: -1
|
||||
maximum: -1
|
||||
max-polygonal-points:
|
||||
default: -1
|
||||
maximum: 20
|
||||
max-radius: -1
|
||||
max-super-pickaxe-size: 5
|
||||
max-brush-radius: 100
|
||||
butcher-radius:
|
||||
default: -1
|
||||
maximum: -1
|
||||
disallowed-blocks:
|
||||
- "minecraft:wheat"
|
||||
- "minecraft:fire"
|
||||
- "minecraft:redstone_wire"
|
||||
|
||||
use-inventory :
|
||||
enable : false
|
||||
allow-override : true
|
||||
creative-mode-overrides : false
|
||||
use-inventory:
|
||||
enable: false
|
||||
allow-override: true
|
||||
creative-mode-overrides: false
|
||||
|
||||
logging :
|
||||
log-commands : false
|
||||
file : worldedit.log
|
||||
logging:
|
||||
log-commands: false
|
||||
file: worldedit.log
|
||||
# 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.
|
||||
# 2$ : source - a string representing the caller, if available; otherwise, the logger's name.
|
||||
@ -53,44 +53,44 @@ logging :
|
||||
# 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/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 :
|
||||
drop-items : true
|
||||
many-drop-items : false
|
||||
super-pickaxe:
|
||||
drop-items: true
|
||||
many-drop-items: false
|
||||
|
||||
snapshots :
|
||||
directory :
|
||||
snapshots:
|
||||
directory:
|
||||
|
||||
navigation-wand :
|
||||
item : minecraft:compass
|
||||
max-distance : 100
|
||||
navigation-wand:
|
||||
item: minecraft:compass
|
||||
max-distance: 100
|
||||
|
||||
scripting :
|
||||
timeout : 3000
|
||||
dir : craftscripts
|
||||
scripting:
|
||||
timeout: 3000
|
||||
dir: craftscripts
|
||||
|
||||
saving :
|
||||
dir : schematics
|
||||
saving:
|
||||
dir: schematics
|
||||
|
||||
files :
|
||||
allow-symbolic-links : false
|
||||
files:
|
||||
allow-symbolic-links: false
|
||||
|
||||
history :
|
||||
size : 15
|
||||
expiration : 10
|
||||
history:
|
||||
size: 15
|
||||
expiration: 10
|
||||
|
||||
calculation :
|
||||
timeout : 100
|
||||
calculation:
|
||||
timeout: 100
|
||||
|
||||
debugging :
|
||||
trace-unflushed-sessions : false
|
||||
debugging:
|
||||
trace-unflushed-sessions: false
|
||||
|
||||
wand-item : minecraft:wooden_axe
|
||||
shell-save-type :
|
||||
no-double-slash : false
|
||||
no-op-permissions : false
|
||||
debug : false
|
||||
show-help-on-first-use : true
|
||||
server-side-cui : true
|
||||
command-block-support : false
|
||||
wand-item: minecraft:wooden_axe
|
||||
shell-save-type:
|
||||
no-double-slash: false
|
||||
no-op-permissions: false
|
||||
debug: false
|
||||
show-help-on-first-use: true
|
||||
server-side-cui: true
|
||||
command-block-support: false
|
@ -20,14 +20,14 @@ public class MinecraftVersionTest {
|
||||
|
||||
@Test
|
||||
public void testEqualOrHigher() {
|
||||
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 3)));
|
||||
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 2)));
|
||||
assertFalse(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16, 4)));
|
||||
assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 3)));
|
||||
assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 2)));
|
||||
assertFalse(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16, 4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualOrHigherWithoutRelease() {
|
||||
assertTrue(latestVersion.isEqualOrHigher(new MinecraftVersion(1, 16)));
|
||||
assertTrue(latestVersion.isEqualOrHigherThan(new MinecraftVersion(1, 16)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -39,15 +39,15 @@ public class MinecraftVersionTest {
|
||||
|
||||
@Test
|
||||
public void testEqualOrLower() {
|
||||
assertTrue(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 3)));
|
||||
assertTrue(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 4)));
|
||||
assertFalse(latestVersion.isEqualOrLower(new MinecraftVersion(1, 16, 2)));
|
||||
assertTrue(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 3)));
|
||||
assertTrue(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 4)));
|
||||
assertFalse(latestVersion.isEqualOrLowerThan(new MinecraftVersion(1, 16, 2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForChunkStretched() {
|
||||
assertTrue(latestVersion.isEqualOrHigher(MinecraftVersion.NETHER));
|
||||
assertFalse(latestVersion.isLower(new MinecraftVersion(1, 14, 2)));
|
||||
assertTrue(latestVersion.isEqualOrHigherThan(MinecraftVersion.NETHER));
|
||||
assertFalse(latestVersion.isLowerThan(new MinecraftVersion(1, 14, 2)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -118,6 +118,11 @@ public class StubServer implements Server {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSimulationDistance() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull
|
||||
String getIp() {
|
||||
@ -150,6 +155,26 @@ public class StubServer implements Server {
|
||||
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
|
||||
public boolean hasWhitelist() {
|
||||
return false;
|
||||
@ -465,6 +490,11 @@ public class StubServer implements Server {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getHideOnlinePlayers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOnlineMode() {
|
||||
return false;
|
||||
|
@ -26,6 +26,7 @@ import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Preference;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.util.SideEffect;
|
||||
import com.sk89q.worldedit.world.DataFixer;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
@ -169,6 +170,16 @@ class CLIPlatform extends AbstractPlatform {
|
||||
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) {
|
||||
worlds.add(world);
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ public class CLIWorldEdit {
|
||||
this.commandSender = new CLICommandSender(this, LOGGER);
|
||||
this.platform = new CLIPlatform(this);
|
||||
//FAWE start - identify as Fawe
|
||||
LOGGER.info("FastAsyncWorldEdit CLI (version " + getInternalVersion() + ") is loaded");
|
||||
LOGGER.info("FastAsyncWorldEdit CLI (version {}) is loaded", getInternalVersion());
|
||||
//FAWE end
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ applyPlatformAndCoreConfiguration()
|
||||
dependencies {
|
||||
constraints {
|
||||
implementation("org.yaml:snakeyaml") {
|
||||
version { strictly("1.28") }
|
||||
version { strictly("1.30") }
|
||||
because("Bukkit provides SnakeYaml")
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,6 @@ dependencies {
|
||||
|
||||
// Plugins
|
||||
compileOnly(libs.redprotect) { isTransitive = false }
|
||||
compileOnly(libs.plotsquaredV4) { isTransitive = false }
|
||||
compileOnly(libs.plotsquaredV6Core) { isTransitive = false }
|
||||
|
||||
// ensure this is on the classpath for the AP
|
||||
|
@ -1,7 +1,7 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.5.0-RC"
|
||||
kotlin("jvm") version "1.5.30"
|
||||
application
|
||||
}
|
||||
|
||||
|
@ -101,17 +101,17 @@ public class Fawe {
|
||||
this.setupConfigs();
|
||||
TaskManager.IMP = this.implementation.getTaskManager();
|
||||
|
||||
TaskManager.IMP.async(() -> {
|
||||
TaskManager.taskManager().async(() -> {
|
||||
MainUtil.deleteOlder(
|
||||
MainUtil.getFile(this.implementation
|
||||
.getDirectory(), Settings.IMP.PATHS.HISTORY),
|
||||
TimeUnit.DAYS.toMillis(Settings.IMP.HISTORY.DELETE_AFTER_DAYS),
|
||||
.getDirectory(), Settings.settings().PATHS.HISTORY),
|
||||
TimeUnit.DAYS.toMillis(Settings.settings().HISTORY.DELETE_AFTER_DAYS),
|
||||
false
|
||||
);
|
||||
MainUtil.deleteOlder(
|
||||
MainUtil.getFile(this.implementation
|
||||
.getDirectory(), Settings.IMP.PATHS.CLIPBOARD),
|
||||
TimeUnit.DAYS.toMillis(Settings.IMP.CLIPBOARD.DELETE_AFTER_DAYS),
|
||||
.getDirectory(), Settings.settings().PATHS.CLIPBOARD),
|
||||
TimeUnit.DAYS.toMillis(Settings.settings().CLIPBOARD.DELETE_AFTER_DAYS),
|
||||
false
|
||||
);
|
||||
});
|
||||
@ -123,28 +123,49 @@ public class Fawe {
|
||||
this.timer = new FaweTimer();
|
||||
|
||||
// Delayed worldedit setup
|
||||
TaskManager.IMP.later(() -> {
|
||||
TaskManager.taskManager().later(() -> {
|
||||
try {
|
||||
WEManager.IMP.addManagers(Fawe.this.implementation.getMaskManagers());
|
||||
WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers());
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}, 0);
|
||||
|
||||
TaskManager.IMP.repeat(timer, 1);
|
||||
TaskManager.taskManager().repeat(timer, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the implementation specific class.
|
||||
* @deprecated use {@link #platform()}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Deprecated(forRemoval = true, since = "2.0.0")
|
||||
public static <T extends IFawe> T imp() {
|
||||
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.
|
||||
*/
|
||||
public static Fawe get() {
|
||||
public static Fawe instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -225,8 +246,8 @@ public class Fawe {
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
if (imp().getPreloader(false) != null) {
|
||||
imp().getPreloader(false).cancel();
|
||||
if (platform().getPreloader(false) != null) {
|
||||
platform().getPreloader(false).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +317,7 @@ public class Fawe {
|
||||
MainUtil.copyFile(MainUtil.getJarFile(), "lang/strings.json", null);
|
||||
// Setting up 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");
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
|
||||
String versionString = br.readLine();
|
||||
@ -304,17 +325,17 @@ public class Fawe {
|
||||
String dateString = br.readLine();
|
||||
br.close();
|
||||
this.version = FaweVersion.tryParse(versionString, commitString, dateString);
|
||||
Settings.IMP.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.IMP.COMMIT = "https://github.com/IntellectualSites/FastAsyncWorldEdit/commit/" + Integer.toHexString(version.hash);
|
||||
Settings.settings().DATE = new Date(100 + version.year, version.month, version.day).toString();
|
||||
Settings.settings().BUILD = "https://ci.athion.net/job/FastAsyncWorldEdit/" + version.build;
|
||||
Settings.settings().COMMIT = "https://github.com/IntellectualSites/FastAsyncWorldEdit/commit/" + Integer.toHexString(version.hash);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
try {
|
||||
Settings.IMP.reload(file);
|
||||
Settings.settings().reload(file);
|
||||
} catch (Throwable 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 {
|
||||
byte[] in = new byte[0];
|
||||
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in);
|
||||
@ -332,14 +353,14 @@ public class Fawe {
|
||||
assert (Zstd.decompress(ob, compressed) == 0);
|
||||
LOGGER.info("ZSTD Compression Binding loaded successfully");
|
||||
} catch (Throwable e) {
|
||||
if (Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL > 6 || Settings.IMP.HISTORY.COMPRESSION_LEVEL > 6) {
|
||||
Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL);
|
||||
Settings.IMP.HISTORY.COMPRESSION_LEVEL = Math.min(6, Settings.IMP.HISTORY.COMPRESSION_LEVEL);
|
||||
if (Settings.settings().CLIPBOARD.COMPRESSION_LEVEL > 6 || Settings.settings().HISTORY.COMPRESSION_LEVEL > 6) {
|
||||
Settings.settings().CLIPBOARD.COMPRESSION_LEVEL = Math.min(6, Settings.settings().CLIPBOARD.COMPRESSION_LEVEL);
|
||||
Settings.settings().HISTORY.COMPRESSION_LEVEL = Math.min(6, Settings.settings().HISTORY.COMPRESSION_LEVEL);
|
||||
LOGGER.error("ZSTD Compression Binding Not Found.\n"
|
||||
+ "FAWE will still work but compression won't work as well.", e);
|
||||
}
|
||||
}
|
||||
Settings.IMP.save(file);
|
||||
Settings.settings().save(file);
|
||||
}
|
||||
|
||||
public WorldEdit getWorldEdit() {
|
||||
@ -347,7 +368,7 @@ public class Fawe {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
try {
|
||||
@ -371,7 +392,7 @@ public class Fawe {
|
||||
if (max < 0) {
|
||||
continue;
|
||||
}
|
||||
final long alert = (max * Settings.IMP.MAX_MEMORY_PERCENT) / 100;
|
||||
final long alert = (max * Settings.settings().MAX_MEMORY_PERCENT) / 100;
|
||||
mp.setUsageThreshold(alert);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||
import com.fastasyncworldedit.core.regions.FaweMaskManager;
|
||||
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
||||
import com.fastasyncworldedit.core.util.EditSessionBuilder;
|
||||
import com.fastasyncworldedit.core.util.MainUtil;
|
||||
import com.fastasyncworldedit.core.util.MemUtil;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
@ -60,24 +59,13 @@ public class FaweAPI {
|
||||
|
||||
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.
|
||||
*
|
||||
* @return TaskManager
|
||||
*/
|
||||
public static TaskManager getTaskManager() {
|
||||
return TaskManager.IMP;
|
||||
return TaskManager.taskManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +81,7 @@ public class FaweAPI {
|
||||
* @return the queue extent
|
||||
*/
|
||||
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) {
|
||||
queue.disableQueue();
|
||||
}
|
||||
@ -139,7 +127,7 @@ public class FaweAPI {
|
||||
* @return Set of FaweMaskManager
|
||||
*/
|
||||
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).
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
try {
|
||||
WEManager.IMP.cancelEdit(extent, new FaweException(reason));
|
||||
WEManager.weManager().cancelEdit(extent, new FaweException(reason));
|
||||
} catch (WorldEditException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
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!");
|
||||
}
|
||||
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) {
|
||||
Extent extent = origin.getExtent();
|
||||
if (!(extent instanceof World)) {
|
||||
if (!(extent instanceof World world)) {
|
||||
throw new IllegalArgumentException("Origin is not a valid world");
|
||||
}
|
||||
World world = (World) extent;
|
||||
File history = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + world.getName());
|
||||
File history = MainUtil.getFile(Fawe.platform().getDirectory(), Settings.settings().PATHS.HISTORY + File.separator + world.getName());
|
||||
if (!history.exists()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
@ -364,12 +351,12 @@ public class FaweAPI {
|
||||
World unwrapped = WorldWrapper.unwrap(world);
|
||||
if (unwrapped instanceof IQueueExtent) {
|
||||
queue = (IQueueExtent) unwrapped;
|
||||
} else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1) {
|
||||
} else if (Settings.settings().QUEUE.PARALLEL_THREADS > 1) {
|
||||
ParallelQueueExtent parallel =
|
||||
new ParallelQueueExtent(Fawe.get().getQueueHandler(), world, true);
|
||||
new ParallelQueueExtent(Fawe.instance().getQueueHandler(), world, true);
|
||||
queue = parallel.getExtent();
|
||||
} 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 (Settings.IMP.LIGHTING.REMOVE_FIRST) {
|
||||
if (Settings.settings().LIGHTING.REMOVE_FIRST) {
|
||||
relighter.removeAndRelight(true);
|
||||
} else {
|
||||
relighter.fixSkyLighting();
|
||||
|
@ -59,7 +59,15 @@ import java.util.function.Supplier;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
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();
|
||||
|
||||
@ -301,7 +309,7 @@ public enum FaweCache implements Trimable {
|
||||
|
||||
// BlockStates
|
||||
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
|
||||
} else {
|
||||
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
|
||||
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
|
||||
} else {
|
||||
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
|
||||
*/
|
||||
public ThreadPoolExecutor newBlockingExecutor() {
|
||||
int nThreads = Settings.IMP.QUEUE.PARALLEL_THREADS;
|
||||
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
|
||||
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true);
|
||||
return new ThreadPoolExecutor(nThreads, nThreads,
|
||||
0L, TimeUnit.MILLISECONDS, queue,
|
||||
@ -609,7 +617,7 @@ public enum FaweCache implements Trimable {
|
||||
lastException = hash;
|
||||
LOGGER.catching(throwable);
|
||||
count = 0;
|
||||
} else if (count < Settings.IMP.QUEUE.PARALLEL_THREADS) {
|
||||
} else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) {
|
||||
LOGGER.warn(throwable.getMessage());
|
||||
count++;
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
package com.fastasyncworldedit.core;
|
||||
|
||||
import com.fastasyncworldedit.core.util.StringMan;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An internal FAWE class not meant for public use.
|
||||
**/
|
||||
@ -10,28 +14,35 @@ public class FaweVersion {
|
||||
public final int day;
|
||||
public final int hash;
|
||||
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.month = month;
|
||||
this.day = day;
|
||||
this.hash = hash;
|
||||
this.build = build;
|
||||
this.semver = semver;
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
public FaweVersion(String version, String commit, String date) {
|
||||
String[] split = version.substring(version.indexOf('=') + 1).split("-");
|
||||
int build = 0;
|
||||
try {
|
||||
build = Integer.parseInt(split[1]);
|
||||
} catch (NumberFormatException ignored) {
|
||||
String[] split1 = split[0].split("\\.");
|
||||
int[] ver = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
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);
|
||||
String[] split1 = date.substring(date.indexOf('=') + 1).split("\\.");
|
||||
this.year = Integer.parseInt(split1[0]);
|
||||
this.month = Integer.parseInt(split1[1]);
|
||||
this.day = Integer.parseInt(split1[2]);
|
||||
String[] split2 = date.substring(date.indexOf('=') + 1).split("\\.");
|
||||
this.year = Integer.parseInt(split2[0]);
|
||||
this.month = Integer.parseInt(split2[1]);
|
||||
this.day = Integer.parseInt(split2[2]);
|
||||
}
|
||||
|
||||
public static FaweVersion tryParse(String version, String commit, String date) {
|
||||
@ -39,28 +50,42 @@ public class FaweVersion {
|
||||
return new FaweVersion(version, commit, date);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return new FaweVersion(0, 0, 0, 0, 0);
|
||||
return new FaweVersion(0, 0, 0, null, true, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (hash == 0 && build == 0) {
|
||||
return getSimpleVersionName() + "-NoVer-SNAPSHOT";
|
||||
if (semver == null) {
|
||||
return "FastAsyncWorldEdit-NoVer-SNAPSHOT";
|
||||
} 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ public class AnvilCommands {
|
||||
// });
|
||||
// if (useData) {
|
||||
// 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 str = String.format("%-7s (%.3f%%) %s #%d:%d",
|
||||
// String.valueOf(c[1]),
|
||||
|
@ -147,7 +147,7 @@
|
||||
// CFISettings settings = getSettings(player).remove();
|
||||
// generator.setPacketViewer(player);
|
||||
// settings.setGenerator(generator).bind();
|
||||
// generator.setImageViewer(Fawe.imp().getImageViewer(player));
|
||||
// generator.setImageViewer(Fawe.platform().getImageViewer(player));
|
||||
// generator.update();
|
||||
// mainMenu(player);
|
||||
// }
|
||||
@ -226,7 +226,7 @@
|
||||
// World world = FaweAPI.getWorld(folder.getName());
|
||||
// if (world != null) {
|
||||
// if (player.getWorld() != world) {
|
||||
// TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
// TaskManager.taskManager().sync(new RunnableVal<Object>() {
|
||||
// @Override
|
||||
// public void run(Object value) {
|
||||
// Location spawn = new Location(world, world.getSpawnPosition().toVector3());
|
||||
@ -425,7 +425,7 @@
|
||||
// switch (argOpt.toLowerCase(Locale.ROOT)) {
|
||||
// case "true":
|
||||
// case "*": {
|
||||
// generator.setTextureUtil(Fawe.get().getTextureUtil());
|
||||
// generator.setTextureUtil(Fawe.instance().getTextureUtil());
|
||||
// return;
|
||||
// }
|
||||
// case "#clipboard": {
|
||||
@ -453,7 +453,7 @@
|
||||
// parserContext.setExtent(extent);
|
||||
// Request.request().setExtent(extent);
|
||||
// Mask mask = worldEdit.getMaskFactory().parseFromInput(argOpt, parserContext);
|
||||
// TextureUtil tu = Fawe.get().getTextureUtil();
|
||||
// TextureUtil tu = Fawe.instance().getTextureUtil();
|
||||
// for (int typeId : tu.getValidBlockIds()) {
|
||||
// BlockType type = BlockTypes.get(typeId);
|
||||
// extent.init(0, 0, 0, type.getDefaultState().toBaseBlock());
|
||||
@ -464,7 +464,7 @@
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// generator.setTextureUtil(new FilteredTextureUtil(Fawe.get().getTextureUtil(), blocks));
|
||||
// generator.setTextureUtil(new FilteredTextureUtil(Fawe.instance().getTextureUtil(), blocks));
|
||||
// coloring(player);
|
||||
// }
|
||||
//
|
||||
@ -493,9 +493,9 @@
|
||||
// public void complexity(Player player, int min, int max) throws FileNotFoundException {
|
||||
// HeightMapMCAGenerator gen = assertSettings(player).getGenerator();
|
||||
// if (min == 0 && max == 100) {
|
||||
// gen.setTextureUtil(Fawe.get().getTextureUtil());
|
||||
// gen.setTextureUtil(Fawe.instance().getTextureUtil());
|
||||
// } else {
|
||||
// gen.setTextureUtil(new CleanTextureUtil(Fawe.get().getTextureUtil(), min, max));
|
||||
// gen.setTextureUtil(new CleanTextureUtil(Fawe.instance().getTextureUtil(), min, max));
|
||||
// }
|
||||
// coloring(player);
|
||||
// }
|
||||
@ -1201,7 +1201,7 @@
|
||||
// whiteOnly = true;
|
||||
// maskArg = null;
|
||||
// imageMaskArg = null;
|
||||
// generator.setTextureUtil(Fawe.get().getTextureUtil());
|
||||
// generator.setTextureUtil(Fawe.instance().getTextureUtil());
|
||||
// }
|
||||
//
|
||||
// public void resetComponent() {
|
||||
|
@ -95,7 +95,7 @@ public class ListFilters {
|
||||
}
|
||||
String firstArg = finalArg.substring(0, finalArg.length() - File.separator.length());
|
||||
if (firstArg.length() > 3 && firstArg.length() <= 16) {
|
||||
UUID fromName = Fawe.imp().getUUID(finalArg);
|
||||
UUID fromName = Fawe.platform().getUUID(finalArg);
|
||||
if (fromName != null) {
|
||||
newRoot = new File(root, finalArg);
|
||||
if (newRoot.exists()) {
|
||||
|
@ -45,7 +45,7 @@
|
||||
// PlotPlayer player = PlotPlayer.get(actor.getName());
|
||||
//
|
||||
// actor.print("Claiming world");
|
||||
// Plot plot = TaskManager.IMP.sync(new RunnableVal<Plot>() {
|
||||
// Plot plot = TaskManager.taskManager().sync(new RunnableVal<Plot>() {
|
||||
// @Override
|
||||
// public void run(Plot o) {
|
||||
// int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount()
|
||||
@ -73,7 +73,7 @@
|
||||
// File folder = CFICommands.getFolder(plot.getWorldName());
|
||||
// Boolean result = createTask.apply(folder);
|
||||
// if (result == Boolean.TRUE) {
|
||||
// TaskManager.IMP.sync(() -> plot.teleportPlayer(player));
|
||||
// TaskManager.taskManager().sync(() -> plot.teleportPlayer(player));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
@ -90,7 +90,7 @@ public class BrushSettings {
|
||||
// }
|
||||
// if (settings.containsKey(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.constructor.put(SettingType.TRANSFORM, transformArgs);
|
||||
// }
|
||||
|
@ -68,7 +68,7 @@ public class InspectBrush extends BrushTool {
|
||||
player.print(Caption.of("fawe.error.no-perm", "worldedit.tool.inspect"));
|
||||
return false;
|
||||
}
|
||||
if (!Settings.IMP.HISTORY.USE_DATABASE) {
|
||||
if (!Settings.settings().HISTORY.USE_DATABASE) {
|
||||
player.print(Caption.of(
|
||||
"fawe.error.setting.disable",
|
||||
"history.use-database (Import with /history import )"
|
||||
@ -81,7 +81,7 @@ public class InspectBrush extends BrushTool {
|
||||
final int y = target.getBlockY();
|
||||
final int z = target.getBlockZ();
|
||||
World world = player.getWorld();
|
||||
RollbackDatabase db = DBHandler.IMP.getDatabase(world);
|
||||
RollbackDatabase db = DBHandler.dbHandler().getDatabase(world);
|
||||
int count = 0;
|
||||
for (Supplier<RollbackOptimizedHistory> supplier : db.getEdits(target, false)) {
|
||||
count++;
|
||||
@ -95,7 +95,7 @@ public class InspectBrush extends BrushTool {
|
||||
int from = change.from;
|
||||
int to = change.to;
|
||||
UUID uuid = edit.getUUID();
|
||||
String name = Fawe.imp().getName(uuid);
|
||||
String name = Fawe.platform().getName(uuid);
|
||||
int index = edit.getIndex();
|
||||
long age = System.currentTimeMillis() - edit.getBDFile().lastModified();
|
||||
String ageFormatted = MainUtil.secToTime(age / 1000);
|
||||
|
@ -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.
|
||||
*/
|
||||
private <T> T get(String key, Class root) {
|
||||
private <T> T get(String key, Class<?> root) {
|
||||
String[] split = key.split("\\.");
|
||||
Object instance = getInstance(split, root);
|
||||
if (instance != null) {
|
||||
@ -57,7 +57,7 @@ public class Config {
|
||||
* @param key config node
|
||||
* @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("\\.");
|
||||
Object instance = getInstance(split, root);
|
||||
if (instance != null) {
|
||||
@ -201,7 +201,7 @@ public class Config {
|
||||
/**
|
||||
* 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<>();
|
||||
for (Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
@ -223,12 +223,11 @@ public class Config {
|
||||
}
|
||||
StringBuilder m = new StringBuilder();
|
||||
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();
|
||||
}
|
||||
if (value instanceof String) {
|
||||
String stringValue = (String) value;
|
||||
if (value instanceof String stringValue) {
|
||||
if (stringValue.isEmpty()) {
|
||||
return "''";
|
||||
}
|
||||
@ -237,11 +236,11 @@ public class Config {
|
||||
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 {
|
||||
String CTRF = System.lineSeparator();
|
||||
String spacing = StringMan.repeat(" ", indent);
|
||||
HashMap<Class, Object> instances = new HashMap<>();
|
||||
HashMap<Class<?>, Object> instances = new HashMap<>();
|
||||
for (Field field : clazz.getFields()) {
|
||||
if (field.getAnnotation(Ignore.class) != null) {
|
||||
continue;
|
||||
@ -272,7 +271,7 @@ public class Config {
|
||||
configBlock = new ConfigBlock();
|
||||
field.set(instance, configBlock);
|
||||
for (String blockName : blockNames.value()) {
|
||||
configBlock.put(blockName, current.newInstance());
|
||||
configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
}
|
||||
// Save each instance
|
||||
@ -299,11 +298,10 @@ public class Config {
|
||||
}
|
||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||
if (value == null) {
|
||||
field.set(instance, value = current.newInstance());
|
||||
field.set(instance, value = current.getDeclaredConstructor().newInstance());
|
||||
instances.put(current, value);
|
||||
}
|
||||
save(writer, current, value, indent + 2);
|
||||
continue;
|
||||
} else {
|
||||
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
|
||||
field.get(instance),
|
||||
@ -321,7 +319,7 @@ public class Config {
|
||||
*
|
||||
* @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);
|
||||
if (instance == null) {
|
||||
return null;
|
||||
@ -352,74 +350,64 @@ 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.
|
||||
*
|
||||
* @param split the node (split by period)
|
||||
* @return The instance or null
|
||||
*/
|
||||
private Object getInstance(String[] split, Class root) {
|
||||
private Object getInstance(String[] split, Class<?> root) {
|
||||
try {
|
||||
Class<?> clazz = root == null ? MethodHandles.lookup().lookupClass() : root;
|
||||
Object instance = this;
|
||||
while (split.length > 0) {
|
||||
switch (split.length) {
|
||||
case 1:
|
||||
return instance;
|
||||
default:
|
||||
Class found = null;
|
||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||
for (Class current : classes) {
|
||||
if (StringMan.isEqual(current.getSimpleName(), toFieldName(split[0]))) {
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Field instanceField = clazz.getDeclaredField(toFieldName(split[0]));
|
||||
setAccessible(instanceField);
|
||||
if (instanceField.getType() != ConfigBlock.class) {
|
||||
Object value = instanceField.get(instance);
|
||||
if (value == null) {
|
||||
value = found.newInstance();
|
||||
instanceField.set(instance, value);
|
||||
}
|
||||
clazz = found;
|
||||
instance = value;
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
continue;
|
||||
}
|
||||
ConfigBlock value = (ConfigBlock) instanceField.get(instance);
|
||||
if (value == null) {
|
||||
value = new ConfigBlock();
|
||||
instanceField.set(instance, value);
|
||||
}
|
||||
instance = value.get(split[1]);
|
||||
if (instance == null) {
|
||||
instance = found.newInstance();
|
||||
value.put(split[1], instance);
|
||||
}
|
||||
clazz = found;
|
||||
split = Arrays.copyOfRange(split, 2, split.length);
|
||||
continue;
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
if (found != null) {
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
clazz = found;
|
||||
instance = clazz.newInstance();
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
if (split.length == 1) {
|
||||
return instance;
|
||||
}
|
||||
Class<?> found = null;
|
||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||
for (Class<?> current : classes) {
|
||||
if (StringMan.isEqual(current.getSimpleName(), toFieldName(split[0]))) {
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Field instanceField = clazz.getDeclaredField(toFieldName(split[0]));
|
||||
setAccessible(instanceField);
|
||||
if (instanceField.getType() != ConfigBlock.class) {
|
||||
Object value = instanceField.get(instance);
|
||||
if (value == null) {
|
||||
value = found.getDeclaredConstructor().newInstance();
|
||||
instanceField.set(instance, value);
|
||||
}
|
||||
clazz = found;
|
||||
instance = value;
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
continue;
|
||||
}
|
||||
ConfigBlock value = (ConfigBlock) instanceField.get(instance);
|
||||
if (value == null) {
|
||||
value = new ConfigBlock();
|
||||
instanceField.set(instance, value);
|
||||
}
|
||||
instance = value.get(split[1]);
|
||||
if (instance == null) {
|
||||
instance = found.getDeclaredConstructor().newInstance();
|
||||
value.put(split[1], instance);
|
||||
}
|
||||
clazz = found;
|
||||
split = Arrays.copyOfRange(split, 2, split.length);
|
||||
continue;
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
if (found != null) {
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
clazz = found;
|
||||
instance = clazz.getDeclaredConstructor().newInstance();
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -9,12 +9,28 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
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();
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
private static DBHandler INSTANCE;
|
||||
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) {
|
||||
RollbackDatabase database = databases.get(world);
|
||||
if (database != null) {
|
||||
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren