Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-09-06 16:12:51 +02:00
Merge branch '1.15' of https://github.com/IntellectualSites/FastAsyncWorldEdit-1.13 into 1.15
Dieser Commit ist enthalten in:
Commit
34d40cb856
@ -12,6 +12,7 @@ FAWE is a fork of WorldEdit that has huge speed and memory improvements and cons
|
||||
* [Discord](https://discord.gg/KxkjDVg)
|
||||
* [Wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit-1.13/wiki)
|
||||
* [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit-1.13/issues)
|
||||
* [Crowdin](https://intellectualsites.crowdin.com/fastasyncworldedit)
|
||||
|
||||
## Downloads
|
||||
### 1.13+
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binäre Datei nicht angezeigt.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
29
gradlew
vendored
29
gradlew
vendored
@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@ -175,14 +175,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
3
gradlew.bat
vendored
3
gradlew.bat
vendored
@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
|
@ -1,18 +1,23 @@
|
||||
package com.boydti.fawe.bukkit.adapter;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NMSAdapter {
|
||||
public static int createPalette(int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy,
|
||||
int[] num_palette_buffer, char[] set, Map<BlockVector3, Integer> ticking_blocks) {
|
||||
int[] num_palette_buffer, char[] set, Map<BlockVector3, Integer> ticking_blocks, boolean fastmode) {
|
||||
int air = 0;
|
||||
int num_palette = 0;
|
||||
char lastOrdinal = BlockID.__RESERVED__;
|
||||
boolean lastticking = false;
|
||||
boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char ordinal = set[i];
|
||||
switch (ordinal) {
|
||||
@ -24,11 +29,22 @@ public class NMSAdapter {
|
||||
air++;
|
||||
break;
|
||||
default:
|
||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
||||
if (state.getMaterial().isTicksRandomly()) {
|
||||
ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15),
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter()
|
||||
.getInternalBlockStateId(state).orElse(0));
|
||||
if (!fastmode && !tick_placed) {
|
||||
boolean ticking;
|
||||
if (ordinal != lastOrdinal) {
|
||||
ticking = BlockTypesCache.ticking[ordinal];
|
||||
lastOrdinal = ordinal;
|
||||
lastticking = ticking;
|
||||
} else {
|
||||
ticking = lastticking;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
int palette = blockToPalette[ordinal];
|
||||
@ -45,10 +61,14 @@ public class NMSAdapter {
|
||||
|
||||
public static int createPalette(int layer, int[] blockToPalette, int[] paletteToBlock,
|
||||
int[] blocksCopy, int[] num_palette_buffer, Function<Integer, char[]> get, char[] set,
|
||||
Map<BlockVector3, Integer> ticking_blocks) {
|
||||
Map<BlockVector3, Integer> ticking_blocks, boolean fastmode) {
|
||||
int air = 0;
|
||||
int num_palette = 0;
|
||||
char[] getArr = null;
|
||||
char lastOrdinal = BlockID.__RESERVED__;
|
||||
boolean lastticking = false;
|
||||
boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED;
|
||||
boolean tick_existing = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_EXISTING;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char ordinal = set[i];
|
||||
switch (ordinal) {
|
||||
@ -65,6 +85,24 @@ public class NMSAdapter {
|
||||
case BlockID.VOID_AIR:
|
||||
air++;
|
||||
break;
|
||||
default:
|
||||
if (!fastmode && !tick_placed && tick_existing) {
|
||||
boolean ticking;
|
||||
if (ordinal != lastOrdinal) {
|
||||
ticking = BlockTypesCache.ticking[ordinal];
|
||||
lastOrdinal = ordinal;
|
||||
lastticking = ticking;
|
||||
} else {
|
||||
ticking = lastticking;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
set[i] = ordinal;
|
||||
break;
|
||||
@ -75,11 +113,21 @@ public class NMSAdapter {
|
||||
air++;
|
||||
break;
|
||||
}
|
||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
||||
if (state.getMaterial().isTicksRandomly()) {
|
||||
ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15),
|
||||
WorldEditPlugin.getInstance().getBukkitImplAdapter()
|
||||
.getInternalBlockStateId(state).orElse(0));
|
||||
if (!fastmode && tick_placed) {
|
||||
boolean ticking;
|
||||
if (ordinal != lastOrdinal) {
|
||||
ticking = BlockTypesCache.ticking[ordinal];
|
||||
lastOrdinal = ordinal;
|
||||
lastticking = ticking;
|
||||
} else {
|
||||
ticking = lastticking;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
int palette = blockToPalette[ordinal];
|
||||
if (palette == Integer.MAX_VALUE) {
|
||||
|
@ -199,11 +199,11 @@ public final class BukkitAdapter_1_14 extends NMSAdapter {
|
||||
/*
|
||||
NMS conversion
|
||||
*/
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks) {
|
||||
return newChunkSection(layer, null, blocks);
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) {
|
||||
return newChunkSection(layer, null, blocks, fastmode);
|
||||
}
|
||||
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set) {
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set, boolean fastmode) {
|
||||
if (set == null) {
|
||||
return newChunkSection(layer);
|
||||
}
|
||||
@ -216,9 +216,9 @@ public final class BukkitAdapter_1_14 extends NMSAdapter {
|
||||
Map<BlockVector3, Integer> ticking_blocks = new HashMap<>();
|
||||
int air;
|
||||
if (get == null) {
|
||||
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks);
|
||||
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks, fastmode);
|
||||
} else {
|
||||
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks);
|
||||
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks, fastmode);
|
||||
}
|
||||
int num_palette = num_palette_buffer[0];
|
||||
// BlockStates
|
||||
|
@ -5,10 +5,12 @@ import static org.slf4j.LoggerFactory.getLogger;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.nbt.LazyCompoundTag_1_14;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.AdaptedMap;
|
||||
import com.boydti.fawe.object.collection.BitArray;
|
||||
import com.google.common.base.Suppliers;
|
||||
@ -227,6 +229,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z);
|
||||
boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE;
|
||||
|
||||
// Remove existing tiles
|
||||
{
|
||||
@ -262,7 +265,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr);
|
||||
newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr, fastmode);
|
||||
if (BukkitAdapter_1_14.setSectionAtomic(sections, null, newSection, layer)) {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
continue;
|
||||
@ -274,6 +277,10 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ensure that the server doesn't try to tick the chunksection while we're editing it.
|
||||
BukkitAdapter_1_14.fieldTickingBlockCount.set(existingSection, (short) 0);
|
||||
|
||||
DelegateLock lock = BukkitAdapter_1_14.applyLock(existingSection);
|
||||
synchronized (this) {
|
||||
synchronized (lock) {
|
||||
@ -290,7 +297,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
} else if (lock.isModified()) {
|
||||
this.reset(layer);
|
||||
}
|
||||
newSection = BukkitAdapter_1_14.newChunkSection(layer, this::load, setArr);
|
||||
newSection = BukkitAdapter_1_14.newChunkSection(layer, this::load, setArr, fastmode);
|
||||
if (!BukkitAdapter_1_14.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
||||
continue;
|
||||
@ -620,7 +627,37 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
if (aggressive) {
|
||||
sections = null;
|
||||
nmsChunk = null;
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
final DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitAdapter_1_14.fieldPalette.get(blocksExisting);
|
||||
int paletteSize;
|
||||
|
||||
if (palette instanceof DataPaletteLinear) {
|
||||
paletteSize = ((DataPaletteLinear<IBlockData>) palette).b();
|
||||
} else if (palette instanceof DataPaletteHash) {
|
||||
paletteSize = ((DataPaletteHash<IBlockData>) palette).b();
|
||||
} else {
|
||||
super.trim(false, i);
|
||||
continue;
|
||||
}
|
||||
if (paletteSize == 1) {
|
||||
//If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks.
|
||||
continue;
|
||||
}
|
||||
super.trim(false, i);
|
||||
} catch (IllegalAccessException ignored) {
|
||||
super.trim(false, i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.trim(aggressive);
|
||||
}
|
||||
}
|
||||
|
@ -186,11 +186,11 @@ public final class BukkitAdapter_1_15 extends NMSAdapter {
|
||||
/*
|
||||
NMS conversion
|
||||
*/
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks) {
|
||||
return newChunkSection(layer, null, blocks);
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) {
|
||||
return newChunkSection(layer, null, blocks, fastmode);
|
||||
}
|
||||
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set) {
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set, boolean fastmode) {
|
||||
if (set == null) {
|
||||
return newChunkSection(layer);
|
||||
}
|
||||
@ -203,9 +203,9 @@ public final class BukkitAdapter_1_15 extends NMSAdapter {
|
||||
Map<BlockVector3, Integer> ticking_blocks = new HashMap<>();
|
||||
int air;
|
||||
if (get == null) {
|
||||
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks);
|
||||
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks, fastmode);
|
||||
} else {
|
||||
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks);
|
||||
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks, fastmode);
|
||||
}
|
||||
int num_palette = num_palette_buffer[0];
|
||||
// BlockStates
|
||||
|
@ -5,10 +5,12 @@ import static org.slf4j.LoggerFactory.getLogger;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15.nbt.LazyCompoundTag_1_15;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.AdaptedMap;
|
||||
import com.boydti.fawe.object.collection.BitArray;
|
||||
import com.google.common.base.Suppliers;
|
||||
@ -235,6 +237,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks {
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z);
|
||||
boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE;
|
||||
|
||||
// Remove existing tiles
|
||||
{
|
||||
@ -270,7 +273,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks {
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr);
|
||||
newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr, fastmode);
|
||||
if (BukkitAdapter_1_15.setSectionAtomic(sections, null, newSection, layer)) {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
continue;
|
||||
@ -282,6 +285,10 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ensure that the server doesn't try to tick the chunksection while we're editing it.
|
||||
BukkitAdapter_1_15.fieldTickingBlockCount.set(existingSection, (short) 0);
|
||||
|
||||
DelegateLock lock = BukkitAdapter_1_15.applyLock(existingSection);
|
||||
synchronized (this) {
|
||||
synchronized (lock) {
|
||||
@ -298,7 +305,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks {
|
||||
} else if (lock.isModified()) {
|
||||
this.reset(layer);
|
||||
}
|
||||
newSection = BukkitAdapter_1_15.newChunkSection(layer, this::load, setArr);
|
||||
newSection = BukkitAdapter_1_15.newChunkSection(layer, this::load, setArr, fastmode);
|
||||
if (!BukkitAdapter_1_15.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
||||
continue;
|
||||
@ -640,7 +647,37 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks {
|
||||
if (aggressive) {
|
||||
sections = null;
|
||||
nmsChunk = null;
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
final DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitAdapter_1_15.fieldPalette.get(blocksExisting);
|
||||
int paletteSize;
|
||||
|
||||
if (palette instanceof DataPaletteLinear) {
|
||||
paletteSize = ((DataPaletteLinear<IBlockData>) palette).b();
|
||||
} else if (palette instanceof DataPaletteHash) {
|
||||
paletteSize = ((DataPaletteHash<IBlockData>) palette).b();
|
||||
} else {
|
||||
super.trim(false, i);
|
||||
continue;
|
||||
}
|
||||
if (paletteSize == 1) {
|
||||
//If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks.
|
||||
continue;
|
||||
}
|
||||
super.trim(false, i);
|
||||
} catch (IllegalAccessException ignored) {
|
||||
super.trim(false, i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.trim(aggressive);
|
||||
}
|
||||
}
|
||||
|
@ -187,11 +187,11 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
/*
|
||||
NMS conversion
|
||||
*/
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks) {
|
||||
return newChunkSection(layer, null, blocks);
|
||||
public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) {
|
||||
return newChunkSection(layer, null, blocks, fastmode);
|
||||
}
|
||||
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set) {
|
||||
public static ChunkSection newChunkSection(final int layer, final Function<Integer, char[]> get, char[] set, boolean fastmode) {
|
||||
if (set == null) {
|
||||
return newChunkSection(layer);
|
||||
}
|
||||
@ -205,10 +205,10 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
int air;
|
||||
if (get == null) {
|
||||
air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer,
|
||||
set, ticking_blocks);
|
||||
set, ticking_blocks, fastmode);
|
||||
} else {
|
||||
air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy,
|
||||
num_palette_buffer, get, set, ticking_blocks);
|
||||
num_palette_buffer, get, set, ticking_blocks, fastmode);
|
||||
}
|
||||
int num_palette = num_palette_buffer[0];
|
||||
// BlockStates
|
||||
@ -251,10 +251,11 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
fieldPalette.set(dataPaletteBlocks, palette);
|
||||
fieldSize.set(dataPaletteBlocks, bitsPerEntry);
|
||||
setCount(ticking_blocks.size(), 4096 - air, section);
|
||||
ticking_blocks.forEach((pos, ordinal) -> {
|
||||
section.setType(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(),
|
||||
Block.getByCombinedId(ordinal));
|
||||
});
|
||||
if (!fastmode) {
|
||||
ticking_blocks.forEach((pos, ordinal) -> section
|
||||
.setType(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(),
|
||||
Block.getByCombinedId(ordinal)));
|
||||
}
|
||||
} catch (final IllegalAccessException | NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package com.boydti.fawe.bukkit.adapter.mc1_15_2;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.AdaptedMap;
|
||||
import com.boydti.fawe.object.collection.BitArray;
|
||||
import com.google.common.base.Suppliers;
|
||||
@ -242,6 +244,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z);
|
||||
boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE;
|
||||
|
||||
// Remove existing tiles
|
||||
{
|
||||
@ -282,7 +285,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr);
|
||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr, fastmode);
|
||||
if (BukkitAdapter_1_15_2.setSectionAtomic(sections, null, newSection, layer)) {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
continue;
|
||||
@ -294,7 +297,11 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
}
|
||||
BukkitAdapter_1_15_2.fieldTickingBlockCount.set(existingSection, (short) 0);
|
||||
|
||||
//ensure that the server doesn't try to tick the chunksection while we're editing it.
|
||||
DelegateLock lock = BukkitAdapter_1_15_2.applyLock(existingSection);
|
||||
|
||||
synchronized (this) {
|
||||
synchronized (lock) {
|
||||
lock.untilFree();
|
||||
@ -310,7 +317,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
} else if (lock.isModified()) {
|
||||
this.reset(layer);
|
||||
}
|
||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr);
|
||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode);
|
||||
if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
||||
continue;
|
||||
@ -644,7 +651,37 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
if (aggressive) {
|
||||
sections = null;
|
||||
nmsChunk = null;
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
final DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitAdapter_1_15_2.fieldPalette.get(blocksExisting);
|
||||
int paletteSize;
|
||||
|
||||
if (palette instanceof DataPaletteLinear) {
|
||||
paletteSize = ((DataPaletteLinear<IBlockData>) palette).b();
|
||||
} else if (palette instanceof DataPaletteHash) {
|
||||
paletteSize = ((DataPaletteHash<IBlockData>) palette).b();
|
||||
} else {
|
||||
super.trim(false, i);
|
||||
continue;
|
||||
}
|
||||
if (paletteSize == 1) {
|
||||
//If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks.
|
||||
continue;
|
||||
}
|
||||
super.trim(false, i);
|
||||
} catch (IllegalAccessException ignored) {
|
||||
super.trim(false, i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.trim(aggressive);
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LightningStrike;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -649,6 +650,11 @@ public class AsyncWorld extends PassthroughExtent implements World {
|
||||
return TaskManager.IMP.sync(() -> parent.spawn(location, clazz, function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Entity> @NotNull T spawn(@NotNull Location location, @NotNull Class<T> clazz, @Nullable Consumer<T> function, CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FallingBlock spawnFallingBlock(Location location, MaterialData data) throws IllegalArgumentException {
|
||||
return TaskManager.IMP.sync(() -> parent.spawnFallingBlock(location, data));
|
||||
@ -1053,6 +1059,21 @@ public class AsyncWorld extends PassthroughExtent implements World {
|
||||
return parent.getViewDistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViewDistance(int viewDistance) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNoTickViewDistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNoTickViewDistance(int viewDistance) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTrace(Location arg0, Vector arg1, double arg2, FluidCollisionMode arg3, boolean arg4,
|
||||
double arg5, Predicate<Entity> arg6) {
|
||||
@ -1174,6 +1195,11 @@ public class AsyncWorld extends PassthroughExtent implements World {
|
||||
return parent.getChunkAtAsync(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<Chunk> getChunkAtAsync(int x, int z, boolean gen, boolean urgent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDayTime() {
|
||||
return parent.isDayTime();
|
||||
|
@ -145,4 +145,9 @@ public class CombinedBlocks implements IBlocks {
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ public interface IBlocks extends Trimable {
|
||||
.map(layer -> (1 << layer)).sum();
|
||||
}
|
||||
|
||||
boolean trim(boolean aggressive, int layer);
|
||||
|
||||
IBlocks reset();
|
||||
|
||||
default byte[] toByteArray(boolean full) {
|
||||
|
@ -3,14 +3,12 @@ package com.boydti.fawe.beta;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.extent.OutputExtent;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for setting blocks
|
||||
@ -42,6 +40,13 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
return getBiomes() != null;
|
||||
}
|
||||
|
||||
default boolean isFastMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
//default to avoid tricky child classes. We only need it in a few cases anyway.
|
||||
default void setFastMode(boolean fastMode){}
|
||||
|
||||
@Override
|
||||
IChunkSet reset();
|
||||
|
||||
|
@ -82,6 +82,10 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
||||
return BlockVector3.at(30000000, FaweCache.IMP.WORLD_MAX_Y, 30000000);
|
||||
}
|
||||
|
||||
void setFastMode(boolean fastMode);
|
||||
|
||||
boolean isFastMode();
|
||||
|
||||
/**
|
||||
* Create a new root IChunk object<br> - Full chunks will be reused, so a more optimized chunk
|
||||
* can be returned in that case<br> - Don't wrap the chunk, that should be done in {@link
|
||||
@ -143,6 +147,7 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
||||
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
|
||||
// Initialize
|
||||
chunk.init(this, chunkX, chunkZ);
|
||||
chunk.setFastMode(isFastMode());
|
||||
|
||||
T newChunk = filter.applyChunk(chunk, region);
|
||||
if (newChunk != null) {
|
||||
|
@ -153,4 +153,9 @@ public class BitSetBlocks implements IChunkSet {
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,17 @@ public abstract class CharBlocks implements IBlocks {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
boolean result = true;
|
||||
if (sections[layer] == EMPTY && blocks[layer] != null) {
|
||||
blocks[layer] = null;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet reset() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
|
@ -25,6 +25,13 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
sections[layer] = EMPTY;
|
||||
blocks[layer] = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet reset() {
|
||||
super.reset();
|
||||
|
@ -34,6 +34,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
public BlockVector3ChunkMap<CompoundTag> tiles;
|
||||
public HashSet<CompoundTag> entities;
|
||||
public HashSet<UUID> entityRemoves;
|
||||
private boolean fastMode = false;
|
||||
|
||||
private CharSetBlocks() {}
|
||||
|
||||
@ -131,6 +132,16 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
entityRemoves.add(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFastMode(boolean fastMode) {
|
||||
this.fastMode = fastMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFastMode() {
|
||||
return fastMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (biomes != null) {
|
||||
|
@ -85,6 +85,11 @@ public class FallbackChunkGet implements IChunkGet {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
|
@ -50,6 +50,10 @@ object NullChunkGet : IChunkGet {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun trim(aggressive: Boolean, layer: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun <T : Future<T>> call(set: IChunkSet, finalize: Runnable): T? {
|
||||
return null
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
private IQueueExtent<? extends IChunk> extent; // the parent queue extent which has this chunk
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
private boolean fastmode;
|
||||
|
||||
private ChunkHolder() {
|
||||
this.delegate = NULL;
|
||||
@ -100,6 +101,16 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
return getOrCreateGet().load(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFastMode() {
|
||||
return fastmode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFastMode(boolean fastmode) {
|
||||
this.fastmode = fastmode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getEntity(UUID uuid) {
|
||||
return delegate.get(this).getEntity(uuid);
|
||||
@ -313,6 +324,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
public void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
|
||||
final IChunkGet get = getOrCreateGet();
|
||||
final IChunkSet set = getOrCreateSet();
|
||||
set.setFastMode(fastmode);
|
||||
try {
|
||||
block.filter(this, get, set, filter, region, full);
|
||||
} finally {
|
||||
@ -344,6 +356,11 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return this.trim(aggressive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return chunkSet == null || chunkSet.isEmpty();
|
||||
|
@ -117,5 +117,9 @@ object NullChunk : IQueueChunk<Nothing> {
|
||||
override fun trim(aggressive: Boolean): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun trim(aggressive: Boolean, layer: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
public class BatchProcessorHolder implements IBatchProcessorHolder {
|
||||
private IBatchProcessor processor = EmptyBatchProcessor.INSTANCE;
|
||||
|
@ -44,12 +44,14 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
private final QueueHandler handler;
|
||||
private final BatchProcessorHolder processor;
|
||||
private int changes;
|
||||
private final boolean fastmode;
|
||||
|
||||
public ParallelQueueExtent(QueueHandler handler, World world) {
|
||||
public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode) {
|
||||
super(handler.getQueue(world, new BatchProcessorHolder()));
|
||||
this.world = world;
|
||||
this.handler = handler;
|
||||
this.processor = (BatchProcessorHolder) getExtent().getProcessor();
|
||||
this.fastmode = fastmode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -94,6 +96,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
final Filter newFilter = filter.fork();
|
||||
// Create a chunk that we will reuse/reset for each operation
|
||||
final IQueueExtent<IQueueChunk> queue = getNewQueue();
|
||||
queue.setFastMode(fastmode);
|
||||
synchronized (queue) {
|
||||
ChunkFilterBlock block = null;
|
||||
|
||||
@ -162,7 +165,8 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
@Override
|
||||
public int replaceBlocks(Region region, Mask mask, Pattern pattern)
|
||||
throws MaxChangedBlocksException {
|
||||
return this.changes = apply(region, mask.toFilter(pattern), false).getBlocksApplied();
|
||||
boolean full = mask.replacesAir();
|
||||
return this.changes = apply(region, mask.toFilter(pattern), full).getBlocksApplied();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,6 +49,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
||||
|
||||
private boolean enabledQueue = true;
|
||||
|
||||
private boolean fastmode = false;
|
||||
|
||||
/**
|
||||
* Safety check to ensure that the thread being used matches the one being initialized on. - Can
|
||||
* be removed later
|
||||
@ -80,6 +82,16 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
||||
return cacheSet.get(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFastMode(boolean fastmode) {
|
||||
this.fastmode = fastmode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFastMode() {
|
||||
return fastmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the queue.
|
||||
*/
|
||||
|
@ -309,6 +309,11 @@ public class Settings extends Config {
|
||||
})
|
||||
public int DISCARD_AFTER_MS = 60000;
|
||||
|
||||
@Comment({
|
||||
"When using fastmode also do not bother to fix existing ticking blocks"
|
||||
})
|
||||
public boolean NO_TICK_FASTMODE = true;
|
||||
|
||||
public static class PROGRESS {
|
||||
@Comment({"Display constant titles about the progress of a user's edit",
|
||||
" - false = disabled",
|
||||
@ -369,6 +374,18 @@ public class Settings extends Config {
|
||||
"Other experimental features"
|
||||
})
|
||||
public boolean OTHER = false;
|
||||
|
||||
@Comment({
|
||||
"Allow blocks placed by WorldEdit to tick. This could cause the big lags.",
|
||||
"This has no effect on existing blocks one way or the other."
|
||||
})
|
||||
public boolean ALLOW_TICK_PLACED = false;
|
||||
|
||||
@Comment({
|
||||
"Force re-ticking of existing blocks not edited by FAWE.",
|
||||
"This will increase time taken slightly."
|
||||
})
|
||||
public boolean ALLOW_TICK_EXISTING = true;
|
||||
}
|
||||
|
||||
public static class WEB {
|
||||
|
@ -549,6 +549,11 @@ public class MCAChunk implements IChunk {
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return hasSection(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getEntity(UUID uuid) {
|
||||
return this.entities.get(uuid);
|
||||
|
@ -184,7 +184,11 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(int index, B block) {
|
||||
states[index] = block.getOrdinalChar();
|
||||
char ordinal = block.getOrdinalChar();
|
||||
if (ordinal == 0) {
|
||||
ordinal = 1;
|
||||
}
|
||||
states[index] = ordinal;
|
||||
boolean hasNbt = block instanceof BaseBlock && block.hasNbtData();
|
||||
if (hasNbt) {
|
||||
setTile(index, block.getNbtData());
|
||||
|
@ -388,6 +388,9 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable
|
||||
try {
|
||||
int index = HEADER_SIZE + (getIndex(x, y, z) << 1);
|
||||
char ordinal = block.getOrdinalChar();
|
||||
if (ordinal == 0) {
|
||||
ordinal = 1;
|
||||
}
|
||||
byteBuffer.putChar(index, ordinal);
|
||||
boolean hasNbt = block instanceof BaseBlock && block.hasNbtData();
|
||||
if (hasNbt) {
|
||||
|
@ -263,6 +263,9 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(int index, B block) {
|
||||
int ordinal = block.getOrdinal();
|
||||
if (ordinal == 0) {
|
||||
ordinal = 1;
|
||||
}
|
||||
setOrdinal(index, ordinal);
|
||||
boolean hasNbt = block instanceof BaseBlock && block.hasNbtData();
|
||||
if (hasNbt) {
|
||||
|
@ -296,7 +296,7 @@ public class EditSessionBuilder {
|
||||
if (unwrapped instanceof IQueueExtent) {
|
||||
extent = queue = (IQueueExtent) unwrapped;
|
||||
} else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1 && threaded) {
|
||||
ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world);
|
||||
ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world, fastmode);
|
||||
queue = parallel.getExtent();
|
||||
extent = parallel;
|
||||
} else {
|
||||
|
@ -72,6 +72,7 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
@ -366,7 +367,7 @@ public class ClipboardCommands {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
player.print(Caption.of("fawe.web.download.link" , urlText));
|
||||
player.print(Caption.of("fawe.web.download.link" , urlText).clickEvent(ClickEvent.openUrl(urlText)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,8 +134,8 @@ public class GenerationCommands {
|
||||
@Arg(desc = "TODO", def = "100") int threshold, @Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException {
|
||||
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
|
||||
URL url = new URL(argStr);
|
||||
if (!url.getHost().equalsIgnoreCase("i.imgur.com") && !url.getHost().equalsIgnoreCase("empcraft.com")) {
|
||||
throw new IOException("Only i.imgur.com or empcraft.com/ui links are allowed!");
|
||||
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
|
||||
throw new IOException("Only i.imgur.com links are allowed!");
|
||||
}
|
||||
BufferedImage image = MainUtil.readImage(url);
|
||||
if (dimensions != null) {
|
||||
|
@ -212,6 +212,7 @@ public class SchematicCommands {
|
||||
}
|
||||
UUID uuid = UUID.fromString(filename.substring(4));
|
||||
URL webUrl = new URL(Settings.IMP.WEB.URL);
|
||||
format = ClipboardFormats.findByAlias(formatName);
|
||||
URL url = new URL(webUrl, "uploads/" + uuid + "." + format.getPrimaryFileExtension());
|
||||
ReadableByteChannel byteChannel = Channels.newChannel(url.openStream());
|
||||
in = Channels.newInputStream(byteChannel);
|
||||
|
@ -364,6 +364,12 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
}
|
||||
state = fuzzyBuilder.build();
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<Property<?>, Object> blockState : blockStates.entrySet()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Object> objProp = (Property<Object>) blockState.getKey();
|
||||
state = state.with(objProp, blockState.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
// this should be impossible but IntelliJ isn't that smart
|
||||
|
@ -223,11 +223,13 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
int volume = width * height * length;
|
||||
if (palette.length < 128) {
|
||||
for (int index = 0; index < volume; index++) {
|
||||
linear.setBlock(index, getBlockState(fis.read()));
|
||||
int ordinal = fis.read();
|
||||
linear.setBlock(index, getBlockState(ordinal));
|
||||
}
|
||||
} else {
|
||||
for (int index = 0; index < volume; index++) {
|
||||
linear.setBlock(index, getBlockState(fis.readVarInt()));
|
||||
int ordinal = fis.readVarInt();
|
||||
linear.setBlock(index, getBlockState(ordinal));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -235,7 +237,8 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
clipboard.setBlock(x, y, z, getBlockState(fis.read()));
|
||||
int ordinal = fis.read();
|
||||
clipboard.setBlock(x, y, z, getBlockState(ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,7 +246,8 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int z = 0; z < length; z++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
clipboard.setBlock(x, y, z, getBlockState(fis.readVarInt()));
|
||||
int ordinal = fis.readVarInt();
|
||||
clipboard.setBlock(x, y, z, getBlockState(ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
||||
import com.boydti.fawe.util.IOUtil;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -45,7 +44,6 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
@ -181,6 +179,9 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
}
|
||||
|
||||
int ordinal = block.getOrdinal();
|
||||
if (ordinal == 0) {
|
||||
ordinal = 1;
|
||||
}
|
||||
char value = palette[ordinal];
|
||||
if (value == Character.MAX_VALUE) {
|
||||
int size = paletteMax++;
|
||||
@ -338,4 +339,4 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
public void close() throws IOException {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +189,15 @@ public class BlockMask extends ABlockMask {
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return ordinals[vector.getOrdinal(extent)];
|
||||
int test = vector.getOrdinal(extent);
|
||||
return ordinals[test] || replacesAir() && test == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return ordinals[BlockTypes.AIR.getDefaultState().getOrdinal()]
|
||||
|| ordinals[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()]
|
||||
|| ordinals[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,6 +26,8 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -65,6 +67,11 @@ public class BlockStateMask extends AbstractExtentMask {
|
||||
.allMatch(entry -> block.getState(entry.getKey()) == entry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return test(BlockTypes.AIR.getDefaultState()) || test(BlockTypes.CAVE_AIR.getDefaultState()) || test(BlockTypes.VOID_AIR.getDefaultState());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
|
@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class BlockTypeMask extends AbstractExtentMask {
|
||||
|
||||
private final boolean[] types;
|
||||
private boolean hasAir;
|
||||
|
||||
/**
|
||||
* Create a new block mask.
|
||||
@ -63,7 +64,9 @@ public class BlockTypeMask extends AbstractExtentMask {
|
||||
public BlockTypeMask(Extent extent, @NotNull BlockType... block) {
|
||||
super(extent);
|
||||
this.types = new boolean[BlockTypes.size()];
|
||||
for (BlockType type : block) this.types[type.getInternalId()] = true;
|
||||
for (BlockType type : block) {
|
||||
add(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,9 +79,6 @@ public class BlockTypeMask extends AbstractExtentMask {
|
||||
for (BlockType type : blocks) {
|
||||
add(type);
|
||||
}
|
||||
for (BlockType type : blocks) {
|
||||
this.types[type.getInternalId()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +88,9 @@ public class BlockTypeMask extends AbstractExtentMask {
|
||||
*/
|
||||
public void add(@NotNull BlockType... block) {
|
||||
for (BlockType type : block) {
|
||||
if (!hasAir && (type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR)) {
|
||||
hasAir = true;
|
||||
}
|
||||
this.types[type.getInternalId()] = true;
|
||||
}
|
||||
}
|
||||
@ -110,6 +113,11 @@ public class BlockTypeMask extends AbstractExtentMask {
|
||||
return test(vector.getBlock(extent).getBlockType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return hasAir;
|
||||
}
|
||||
|
||||
public boolean test(BlockType block) {
|
||||
return types[block.getInternalId()];
|
||||
}
|
||||
|
@ -123,4 +123,8 @@ public interface Mask {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
default boolean replacesAir() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,11 @@ public class OffsetMask extends AbstractMask {
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 pos) {
|
||||
return getMask().test(extent, pos);
|
||||
BlockVector3 testPos = pos.add(offset);
|
||||
if (testPos.getBlockY() < 0 || testPos.getBlockY() > 255) {
|
||||
return false;
|
||||
}
|
||||
return getMask().test(extent, pos.add(offset));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -1,13 +1,12 @@
|
||||
package com.sk89q.worldedit.function.mask;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
public class SingleBlockStateMask extends ABlockMask {
|
||||
private final char ordinal;
|
||||
private final boolean isAir;
|
||||
|
||||
public BlockState getBlockState() {
|
||||
return BlockState.getFromOrdinal(ordinal);
|
||||
@ -15,12 +14,14 @@ public class SingleBlockStateMask extends ABlockMask {
|
||||
|
||||
public SingleBlockStateMask(Extent extent, BlockState state) {
|
||||
super(extent);
|
||||
isAir = state.isAir();
|
||||
this.ordinal = state.getOrdinalChar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return ordinal == vector.getOrdinal(extent);
|
||||
int test = vector.getOrdinal(extent);
|
||||
return ordinal == test || isAir && test == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -33,6 +34,11 @@ public class SingleBlockStateMask extends ABlockMask {
|
||||
return new InverseSingleBlockStateMask(getExtent(), BlockState.getFromOrdinal(ordinal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return isAir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask tryCombine(Mask mask) {
|
||||
if (mask instanceof ABlockMask) {
|
||||
|
@ -8,10 +8,12 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
|
||||
public class SingleBlockTypeMask extends ABlockMask {
|
||||
private final int internalId;
|
||||
private final boolean isAir;
|
||||
|
||||
public SingleBlockTypeMask(Extent extent, BlockType type) {
|
||||
super(extent);
|
||||
this.internalId = type.getInternalId();
|
||||
isAir = type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR;
|
||||
this.internalId = type.getInternalId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -27,4 +29,9 @@ public class SingleBlockTypeMask extends ABlockMask {
|
||||
public BlockType getBlockType() {
|
||||
return BlockTypes.get(internalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return isAir;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.sk89q.worldedit.world.block;
|
||||
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.google.common.primitives.Booleans;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
@ -166,12 +167,14 @@ public class BlockTypesCache {
|
||||
|
||||
public static final BlockType[] values;
|
||||
public static final BlockState[] states;
|
||||
public static final boolean[] ticking;
|
||||
|
||||
protected static final Set<String> $NAMESPACES = new LinkedHashSet<>();
|
||||
|
||||
static {
|
||||
try {
|
||||
ArrayList<BlockState> stateList = new ArrayList<>();
|
||||
ArrayList<Boolean> tickList = new ArrayList<>();
|
||||
|
||||
Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS);
|
||||
Registries registries = platform.getRegistries();
|
||||
@ -202,7 +205,7 @@ public class BlockTypesCache {
|
||||
if (values[internalId] != null) {
|
||||
throw new IllegalStateException("Invalid duplicate id for " + field.getName());
|
||||
}
|
||||
BlockType type = register(defaultState, internalId, stateList);
|
||||
BlockType type = register(defaultState, internalId, stateList, tickList);
|
||||
// Note: Throws IndexOutOfBoundsError if nothing is registered and blocksMap is empty
|
||||
values[internalId] = type;
|
||||
}
|
||||
@ -214,7 +217,7 @@ public class BlockTypesCache {
|
||||
String defaultState = entry.getValue();
|
||||
// Skip already registered ids
|
||||
for (; values[internalId] != null; internalId++);
|
||||
BlockType type = register(defaultState, internalId, stateList);
|
||||
BlockType type = register(defaultState, internalId, stateList, tickList);
|
||||
values[internalId] = type;
|
||||
}
|
||||
}
|
||||
@ -223,7 +226,7 @@ public class BlockTypesCache {
|
||||
}
|
||||
|
||||
states = stateList.toArray(new BlockState[stateList.size()]);
|
||||
|
||||
ticking = Booleans.toArray(tickList);
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
@ -231,12 +234,14 @@ public class BlockTypesCache {
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockType register(final String id, int internalId, List<BlockState> states) {
|
||||
private static BlockType register(final String id, int internalId, List<BlockState> states, List<Boolean> tickList) {
|
||||
// Get the enum name (remove namespace if minecraft:)
|
||||
int propStart = id.indexOf('[');
|
||||
String typeName = id.substring(0, propStart == -1 ? id.length() : propStart);
|
||||
String enumName = (typeName.startsWith("minecraft:") ? typeName.substring(10) : typeName).toUpperCase(Locale.ROOT);
|
||||
int oldsize = states.size();
|
||||
BlockType existing = new BlockType(id, internalId, states);
|
||||
tickList.addAll(Collections.nCopies(states.size() - oldsize, existing.getMaterial().isTicksRandomly()));
|
||||
// register states
|
||||
BlockType.REGISTRY.register(typeName, existing);
|
||||
String nameSpace = typeName.substring(0, typeName.indexOf(':'));
|
||||
|
@ -72,10 +72,10 @@
|
||||
"fawe.worldedit.history.command.history.clear": "History cleared",
|
||||
"fawe.worldedit.history.command.redo.error": "Nothing left to redo. (See also `/inspect` and `/frb`)",
|
||||
"fawe.worldedit.history.command.history.other.error": "Unable to find session for {0}.",
|
||||
"fawe.worldedit.history.command.redo.success": "Redo successful{0}.",
|
||||
"fawe.worldedit.history.command.redo.success": "Redo successful {0}.",
|
||||
"fawe.worldedit.history.command.undo.error": "Nothing left to undo. (See also `/inspect` and `/frb`)",
|
||||
"fawe.worldedit.history.command.undo.disabled": "Undo disabled, use: //fast",
|
||||
"fawe.worldedit.history.command.undo.success": "Undo successful{0}.",
|
||||
"fawe.worldedit.history.command.undo.success": "Undo successful {0}.",
|
||||
|
||||
"fawe.worldedit.operation.operation": "Operation queued ({0})",
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
"fawe.worldedit.selection.selection.shift": "Region shifted",
|
||||
"fawe.worldedit.selection.selection.cleared": "Selection cleared",
|
||||
|
||||
"fawe.worldedit.anvil.world.is.loaded": "The world shouldn't be in use when executing. Unload the world, or use use -f to override (save first)",
|
||||
"fawe.worldedit.anvil.world.is.loaded": "The world shouldn't be in use when executing. Unload the world, or use -f to override (save first)",
|
||||
|
||||
"fawe.worldedit.brush.brush.reset": "Reset your brush. (SHIFT + Click)",
|
||||
"fawe.worldedit.brush.brush.none": "You aren't holding a brush!",
|
||||
@ -238,7 +238,7 @@
|
||||
|
||||
"fawe.error.command.syntax": "Usage: {0}",
|
||||
"fawe.error.no-perm": "You are lacking the permission node: {0}",
|
||||
"fawe.error.block.not.allowed": "You are not allowed to use",
|
||||
"fawe.error.block.not.allowed": "You are not allowed to use: {0}",
|
||||
"fawe.error.setting.disable": "Lacking setting: {0}",
|
||||
"fawe.error.brush.not.found": "Available brushes: {0}",
|
||||
"fawe.error.brush.incompatible": "Brush not compatible with this version",
|
||||
@ -373,7 +373,7 @@
|
||||
"worldedit.limit.set": "Block change limit set to {0}.",
|
||||
"worldedit.limit.return-to-default": "(Use //limit to go back to the default.)",
|
||||
"worldedit.timeout.too-high": "Your maximum allowable timeout is {0}ms.",
|
||||
"worldedit.timeout.set": "Timeout time set to {0} ms.",
|
||||
"worldedit.timeout.set": "Timeout time set to {0}ms.",
|
||||
"worldedit.timeout.return-to-default": " (Use //timeout to go back to the default.)",
|
||||
"worldedit.fast.disabled": "Fast mode disabled.",
|
||||
"worldedit.fast.enabled": "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.",
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren