3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-11-17 00:20:09 +01:00

feat: do not wait for chunk loads when calling

Dieser Commit ist enthalten in:
dordsor21 2024-09-14 18:32:37 +01:00
Ursprung b4635e85c9
Commit e161abea56
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 1E53E88969FFCF0B
20 geänderte Dateien mit 185 neuen und 79 gelöschten Zeilen

Datei anzeigen

@ -9,8 +9,10 @@ import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.math.BitArrayUnstretched; import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
@ -423,7 +425,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { public synchronized <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) { if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
} }

Datei anzeigen

@ -3,8 +3,10 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -254,7 +256,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
} }
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize) {
return null; return null;
} }

Datei anzeigen

@ -9,8 +9,10 @@ import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.math.BitArrayUnstretched; import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
@ -423,7 +425,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { public synchronized <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) { if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
} }

Datei anzeigen

@ -3,8 +3,10 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -254,7 +256,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
} }
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize) {
return null; return null;
} }

Datei anzeigen

@ -9,8 +9,10 @@ import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.math.BitArrayUnstretched; import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
@ -424,7 +426,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { public synchronized <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) { if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
} }

Datei anzeigen

@ -3,8 +3,10 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -257,7 +259,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
} }
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize) {
return null; return null;
} }

Datei anzeigen

@ -6,11 +6,14 @@ import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.math.BitArrayUnstretched; import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
@ -21,6 +24,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -82,7 +86,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
@ -191,7 +197,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
try { try {
fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition); fillLightNibble(light, LightLayer.BLOCK, minSectionPosition, maxSectionPosition);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Error setting lighting to get", e);
} }
} }
} }
@ -203,7 +209,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
try { try {
fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition); fillLightNibble(light, LightLayer.SKY, minSectionPosition, maxSectionPosition);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Error setting sky lighting to get", e);
} }
} }
} }
@ -419,18 +425,35 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
entity.discard(); entity.discard();
} }
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) { public CompletableFuture<LevelChunk> ensureLoaded(ServerLevel nmsWorld, int chunkX, int chunkZ) {
return PaperweightPlatformAdapter.ensureLoaded(nmsWorld, chunkX, chunkZ); return PaperweightPlatformAdapter.ensureLoaded(nmsWorld, chunkX, chunkZ);
} }
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { public synchronized <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalizer) {
if (!callLock.isHeldByCurrentThread()) { if (!callLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked.");
} }
forceLoadSections = false; forceLoadSections = false;
LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); final ServerLevel nmsWorld = serverLevel;
CompletableFuture<LevelChunk> nmsChunkFuture = ensureLoaded(nmsWorld, chunkX, chunkZ);
LevelChunk chunk = nmsChunkFuture.getNow(null);
// Run immediately if possible
if (chunk != null) {
return internalCall(set, finalizer, chunk, nmsWorld);
}
nmsChunkFuture.thenApply(nmsChunk -> owner.submitTaskUnchecked(() -> (T) internalCall(
set,
finalizer,
nmsChunk,
nmsWorld
)));
return (T) (Future) CompletableFuture.completedFuture(null);
}
private <T extends Future<T>> T internalCall(IChunkSet set, Runnable finalizer, LevelChunk nmsChunk, ServerLevel nmsWorld) {
try {
PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null;
if (createCopy) { if (createCopy) {
if (copies.containsKey(copyKey)) { if (copies.containsKey(copyKey)) {
@ -438,7 +461,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
copies.put(copyKey, copy); copies.put(copyKey, copy);
} }
try {
// Remove existing tiles. Create a copy so that we can remove blocks // Remove existing tiles. Create a copy so that we can remove blocks
Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); Map<BlockPos, BlockEntity> chunkTiles = new HashMap<>(nmsChunk.getBlockEntities());
List<BlockEntity> beacons = null; List<BlockEntity> beacons = null;
@ -510,7 +532,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
biomeData biomeData
); );
if (PaperweightPlatformAdapter.setSectionAtomic( if (PaperweightPlatformAdapter.setSectionAtomic(
serverLevel.getWorld().getName(), nmsWorld.getWorld().getName(),
chunkPos, chunkPos,
levelChunkSections, levelChunkSections,
null, null,
@ -586,7 +608,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
biomeData biomeData
); );
if (PaperweightPlatformAdapter.setSectionAtomic( if (PaperweightPlatformAdapter.setSectionAtomic(
serverLevel.getWorld().getName(), nmsWorld.getWorld().getName(),
chunkPos, chunkPos,
levelChunkSections, levelChunkSections,
null, null,
@ -650,7 +672,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes() biomeData != null ? biomeData : (PalettedContainer<Holder<Biome>>) existingSection.getBiomes()
); );
if (!PaperweightPlatformAdapter.setSectionAtomic( if (!PaperweightPlatformAdapter.setSectionAtomic(
serverLevel.getWorld().getName(), nmsWorld.getWorld().getName(),
chunkPos, chunkPos,
levelChunkSections, levelChunkSections,
existingSection, existingSection,
@ -725,7 +747,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
for (UUID uuid : entityRemoves) { for (UUID uuid : entityRemoves) {
Entity entity = serverLevel.getEntities().get(uuid); Entity entity = nmsWorld.getEntities().get(uuid);
if (entity != null) { if (entity != null) {
removeEntity(entity); removeEntity(entity);
} }
@ -764,7 +786,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
EntityType<?> type = EntityType.byString(id).orElse(null); EntityType<?> type = EntityType.byString(id).orElse(null);
if (type != null) { if (type != null) {
Entity entity = type.create(serverLevel); Entity entity = type.create(nmsWorld);
if (entity != null) { if (entity != null) {
final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag);
for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
@ -773,11 +795,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
entity.load(tag); entity.load(tag);
entity.absMoveTo(x, y, z, yaw, pitch); entity.absMoveTo(x, y, z, yaw, pitch);
entity.setUUID(NbtUtils.uuid(nativeTag)); entity.setUUID(NbtUtils.uuid(nativeTag));
if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
LOGGER.warn( LOGGER.warn(
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`", "Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
id, id,
serverLevel.getWorld().getName(), nmsWorld.getWorld().getName(),
x, x,
y, y,
z z
@ -807,11 +829,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
final int z = blockHash.z() + bz; final int z = blockHash.z() + bz;
final BlockPos pos = new BlockPos(x, y, z); final BlockPos pos = new BlockPos(x, y, z);
synchronized (serverLevel) { synchronized (nmsWorld) {
BlockEntity tileEntity = serverLevel.getBlockEntity(pos); BlockEntity tileEntity = nmsWorld.getBlockEntity(pos);
if (tileEntity == null || tileEntity.isRemoved()) { if (tileEntity == null || tileEntity.isRemoved()) {
serverLevel.removeBlockEntity(pos); nmsWorld.removeBlockEntity(pos);
tileEntity = serverLevel.getBlockEntity(pos); tileEntity = nmsWorld.getBlockEntity(pos);
} }
if (tileEntity != null) { if (tileEntity != null) {
final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag());
@ -866,7 +888,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
return queueHandler.async(callback, null); return queueHandler.async(callback, null);
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Error performing final chunk calling at {},{}", chunkX, chunkZ, e);
throw e; throw e;
} }
}; };
@ -884,7 +906,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
return null; return null;
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); LOGGER.error("Error calling chunk at {},{}", chunkX, chunkZ, e);
return null; return null;
} finally { } finally {
forceLoadSections = true; forceLoadSections = true;
@ -1029,7 +1051,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
} }
return data; return data;
} catch (IllegalAccessException | InterruptedException e) { } catch (IllegalAccessException | InterruptedException e) {
e.printStackTrace(); LOGGER.error("Could not read block data from palette", e);
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {
lock.release(); lock.release();
@ -1071,7 +1093,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
synchronized (this) { synchronized (this) {
levelChunk = this.levelChunk; levelChunk = this.levelChunk;
if (levelChunk == null) { if (levelChunk == null) {
this.levelChunk = levelChunk = ensureLoaded(this.serverLevel, chunkX, chunkZ); try {
this.levelChunk = levelChunk = ensureLoaded(this.serverLevel, chunkX, chunkZ).get();
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Could not get chunk at {},{}", chunkX, chunkZ, e);
throw new FaweException(
TextComponent.of("Could not get chunk at " + chunkX + "," + chunkZ + ": " + e.getMessage()),
FaweException.Type.OTHER,
false
);
}
} }
} }
} }

Datei anzeigen

@ -3,8 +3,10 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -257,7 +259,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
} }
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize) {
return null; return null;
} }

Datei anzeigen

@ -78,6 +78,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -265,7 +267,43 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
} }
public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) { public static CompletableFuture<LevelChunk> ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) {
LevelChunk levelChunk = getChunkImmediatelyAsync(serverLevel, chunkX, chunkZ);
if (levelChunk != null) {
return CompletableFuture.completedFuture(levelChunk);
}
if (PaperLib.isPaper()) {
CompletableFuture<LevelChunk> future = serverLevel
.getWorld()
.getChunkAtAsync(chunkX, chunkZ, true, true)
.thenApply(chunk -> {
addTicket(serverLevel, chunkX, chunkZ);
try {
return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk);
} catch (Throwable e) {
LOGGER.error("Could not asynchronously load chunk at {},{}", chunkX, chunkZ, e);
return null;
}
});
try {
if (!future.isCompletedExceptionally() || (future.isDone() && future.get() != null)) {
return future;
}
Throwable t = future.exceptionNow();
LOGGER.error("Asynchronous chunk load at {},{} exceptionally completed immediately", chunkX, chunkZ, t);
} catch (InterruptedException | ExecutionException e) {
LOGGER.error(
"Unexpected error when getting completed future at chunk {},{}. Returning to default.",
chunkX,
chunkZ,
e
);
}
}
return CompletableFuture.supplyAsync(() -> TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)));
}
public static @Nullable LevelChunk getChunkImmediatelyAsync(ServerLevel serverLevel, int chunkX, int chunkZ) {
if (!PaperLib.isPaper()) { if (!PaperLib.isPaper()) {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false); LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false);
if (nmsChunk != null) { if (nmsChunk != null) {
@ -274,6 +312,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
if (Fawe.isMainThread()) { if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ); return serverLevel.getChunk(chunkX, chunkZ);
} }
return null;
} else { } else {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ);
if (nmsChunk != null) { if (nmsChunk != null) {
@ -289,31 +328,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
if (Fawe.isMainThread()) { if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ); return serverLevel.getChunk(chunkX, chunkZ);
} }
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); return null;
try {
CraftChunk chunk;
try {
chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
String world = serverLevel.getWorld().getName();
// We've already taken 10 seconds we can afford to wait a little here.
boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null);
if (loaded) {
LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world);
// Retry chunk load
chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get();
} else {
throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!");
} }
} }
addTicket(serverLevel, chunkX, chunkZ);
return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk);
} catch (Throwable e) {
e.printStackTrace();
}
}
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
}
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
// Ensure chunk is definitely loaded before applying a ticket // Ensure chunk is definitely loaded before applying a ticket

Datei anzeigen

@ -50,6 +50,7 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -645,7 +646,7 @@ public enum FaweCache implements Trimable {
*/ */
public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) { public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) {
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS; int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true); LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
return new ThreadPoolExecutor(nThreads, nThreads, return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, queue, 0L, TimeUnit.MILLISECONDS, queue,
new ThreadFactoryBuilder().setNameFormat(name).build(), new ThreadFactoryBuilder().setNameFormat(name).build(),

Datei anzeigen

@ -10,6 +10,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -127,9 +128,7 @@ public interface IBatchProcessor {
char[] arr = set.loadIfPresent(layer); char[] arr = set.loadIfPresent(layer);
if (arr != null) { if (arr != null) {
int index = (minY & 15) << 8; int index = (minY & 15) << 8;
for (int i = index; i < 4096; i++) { Arrays.fill(arr, index, 4096, (char) BlockTypesCache.ReservedIDs.__RESERVED__);
arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
}
} }
set.setBlocks(layer, arr); set.setBlocks(layer, arr);
} else if (layer == maxLayer) { } else if (layer == maxLayer) {

Datei anzeigen

@ -45,7 +45,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
} }
<T extends Future<T>> T call(IChunkSet set, Runnable finalize); <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize);
@Deprecated(forRemoval = true, since = "2.11.2") @Deprecated(forRemoval = true, since = "2.11.2")
default CompoundTag getEntity(UUID uuid) { default CompoundTag getEntity(UUID uuid) {
@ -81,7 +81,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
} }
/** /**
* Lock the {@link IChunkGet#call(IChunkSet, Runnable)} method to the current thread using a reentrant lock. Also locks * Lock the {@link IChunkGet#call(IQueueExtent, IChunkSet, Runnable)} method to the current thread using a reentrant lock. Also locks
* related methods e.g. {@link IChunkGet#setCreateCopy(boolean)} * related methods e.g. {@link IChunkGet#setCreateCopy(boolean)}
* *
* @since 2.8.2 * @since 2.8.2
@ -89,7 +89,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
default void lockCall() {} default void lockCall() {}
/** /**
* Unlock {@link IChunkGet#call(IChunkSet, Runnable)} (and other related methods) to executions from other threads * Unlock {@link IChunkGet#call(IQueueExtent, IChunkSet, Runnable)} (and other related methods) to executions from other threads
* *
* @since 2.8.2 * @since 2.8.2
*/ */

Datei anzeigen

@ -10,10 +10,12 @@ import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import org.jetbrains.annotations.ApiStatus;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.Flushable; import java.io.Flushable;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future; import java.util.concurrent.Future;
/** /**
@ -61,7 +63,7 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
IChunkSet getCachedSet(int chunkX, int chunkZ); IChunkSet getCachedSet(int chunkX, int chunkZ);
/** /**
* Submit the chunk so that it's changes are applied to the world * Submit the chunk so that its changes are applied to the world
* *
* @return Future * @return Future
*/ */
@ -81,6 +83,12 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
boolean isFastMode(); boolean isFastMode();
/**
* Submit a task to the extent to be queued as if it were a chunk
*/
@ApiStatus.Internal
<V extends Future<V>> V submitTaskUnchecked(Callable<V> callable);
/** /**
* Create a new root IChunk object. Full chunks will be reused, so a more optimized chunk can be * Create a new root IChunk object. Full chunks will be reused, so a more optimized chunk can be
* returned in that case. * returned in that case.

Datei anzeigen

@ -149,6 +149,8 @@ public class ParallelQueueExtent extends PassthroughExtent {
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue(); final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
queue.setFastMode(fastmode); queue.setFastMode(fastmode);
queue.setFaweExceptionArray(faweExceptionReasonsUsed); queue.setFaweExceptionArray(faweExceptionReasonsUsed);
int div = ((size + 1) * 3) >> 1; // Allow each thread to use 1.5x TARGET_SIZE / PARALLEL_THREADS
queue.setTargetSize(Settings.settings().QUEUE.TARGET_SIZE / div);
enter(queue); enter(queue);
synchronized (queue) { synchronized (queue) {
try { try {

Datei anzeigen

@ -18,6 +18,7 @@ import com.fastasyncworldedit.core.util.task.FaweForkJoinWorkerThreadFactory;
import com.fastasyncworldedit.core.wrappers.WorldWrapper; import com.fastasyncworldedit.core.wrappers.WorldWrapper;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.jetbrains.annotations.ApiStatus;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap; import java.util.HashMap;
@ -41,14 +42,12 @@ import java.util.function.Supplier;
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
public abstract class QueueHandler implements Trimable, Runnable { public abstract class QueueHandler implements Trimable, Runnable {
private static final int PROCESSORS = Runtime.getRuntime().availableProcessors();
/** /**
* Primary queue should be used for tasks that are unlikely to wait on other tasks, IO, etc. (i.e. spend most of their * Primary queue should be used for tasks that are unlikely to wait on other tasks, IO, etc. (i.e. spend most of their
* time utilising CPU. * time utilising CPU.
*/ */
private final ForkJoinPool forkJoinPoolPrimary = new ForkJoinPool( private final ForkJoinPool forkJoinPoolPrimary = new ForkJoinPool(
PROCESSORS, Settings.settings().QUEUE.PARALLEL_THREADS,
new FaweForkJoinWorkerThreadFactory("FAWE Fork Join Pool Primary - %s"), new FaweForkJoinWorkerThreadFactory("FAWE Fork Join Pool Primary - %s"),
null, null,
false false
@ -59,7 +58,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
* primary queue. They may be IO-bound tasks. * primary queue. They may be IO-bound tasks.
*/ */
private final ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool( private final ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool(
PROCESSORS, Settings.settings().QUEUE.PARALLEL_THREADS,
new FaweForkJoinWorkerThreadFactory("FAWE Fork Join Pool Secondary - %s"), new FaweForkJoinWorkerThreadFactory("FAWE Fork Join Pool Secondary - %s"),
null, null,
false false
@ -93,6 +92,11 @@ public abstract class QueueHandler implements Trimable, Runnable {
TaskManager.taskManager().repeat(this, 1); TaskManager.taskManager().repeat(this, 1);
} }
@ApiStatus.Internal
public ThreadPoolExecutor getBlockingExecutor() {
return blockingExecutor;
}
@Override @Override
public void run() { public void run() {
if (!Fawe.isMainThread()) { if (!Fawe.isMainThread()) {
@ -380,6 +384,11 @@ public abstract class QueueHandler implements Trimable, Runnable {
return (T) blockingExecutor.submit(chunk); return (T) blockingExecutor.submit(chunk);
} }
@ApiStatus.Internal
public <T extends Future<T>> T submitToBlocking(Callable<T> callable) {
return (T) blockingExecutor.submit(callable);
}
/** /**
* Get or create the WorldChunkCache for a world * Get or create the WorldChunkCache for a world
*/ */

Datei anzeigen

@ -31,6 +31,7 @@ import com.sk89q.worldedit.world.World;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -68,6 +69,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
private boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; private boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
private int lastException = Integer.MIN_VALUE; private int lastException = Integer.MIN_VALUE;
private int exceptionCount = 0; private int exceptionCount = 0;
private int targetSize = Settings.settings().QUEUE.TARGET_SIZE;
public SingleThreadQueueExtent() { public SingleThreadQueueExtent() {
} }
@ -120,6 +122,10 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
return maxY; return maxY;
} }
public void setTargetSize(int targetSize) {
this.targetSize = targetSize;
}
/** /**
* Sets the cached boolean array of length {@code FaweException.Type.values().length} that determines if a thrown * Sets the cached boolean array of length {@code FaweException.Type.values().length} that determines if a thrown
* {@link FaweException} of type {@link FaweException.Type} should be output to console, rethrown to attempt to be visible * {@link FaweException} of type {@link FaweException.Type} should be output to console, rethrown to attempt to be visible
@ -154,6 +160,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
this.setPostProcessor(EmptyBatchProcessor.getInstance()); this.setPostProcessor(EmptyBatchProcessor.getInstance());
this.world = null; this.world = null;
this.faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; this.faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
this.targetSize = Settings.settings().QUEUE.TARGET_SIZE;
} }
/** /**
@ -246,6 +253,13 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
return (V) Fawe.instance().getQueueHandler().submit(chunk); return (V) Fawe.instance().getQueueHandler().submit(chunk);
} }
@Override
public <V extends Future<V>> V submitTaskUnchecked(Callable<V> callable) {
V future = (V) Fawe.instance().getQueueHandler().submitToBlocking(callable);
submissions.add(future);
return future;
}
@Override @Override
public synchronized boolean trim(boolean aggressive) { public synchronized boolean trim(boolean aggressive) {
cacheGet.trim(aggressive); cacheGet.trim(aggressive);
@ -308,7 +322,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
// If queueing is enabled AND either of the following // If queueing is enabled AND either of the following
// - memory is low & queue size > num threads + 8 // - memory is low & queue size > num threads + 8
// - queue size > target size and primary queue has less than num threads submissions // - queue size > target size and primary queue has less than num threads submissions
int targetSize = lowMem ? Settings.settings().QUEUE.PARALLEL_THREADS + 8 : Settings.settings().QUEUE.TARGET_SIZE; int targetSize = lowMem ? Settings.settings().QUEUE.PARALLEL_THREADS + 8 : this.targetSize;
if (enabledQueue && size > targetSize && (lowMem || Fawe.instance().getQueueHandler().isUnderutilized())) { if (enabledQueue && size > targetSize && (lowMem || Fawe.instance().getQueueHandler().isUnderutilized())) {
chunk = chunks.removeFirst(); chunk = chunks.removeFirst();
final Future future = submitUnchecked(chunk); final Future future = submitUnchecked(chunk);

Datei anzeigen

@ -9,6 +9,8 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.invoke.VarHandle;
import java.util.Arrays;
public abstract class CharBlocks implements IBlocks { public abstract class CharBlocks implements IBlocks {
@ -20,7 +22,10 @@ public abstract class CharBlocks implements IBlocks {
char[] arr = blocks.blocks[layer]; char[] arr = blocks.blocks[layer];
if (arr == null) { if (arr == null) {
// Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues
return EMPTY.get(blocks, layer, false); synchronized (blocks.sectionLocks[layer]) {
LOGGER.warn("Unexpected null section, please report this occurence alongside a debugpaste.");
return getSkipFull(blocks, layer, false);
}
} }
return arr; return arr;
} }
@ -32,6 +37,7 @@ public abstract class CharBlocks implements IBlocks {
if (arr == null) { if (arr == null) {
// Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues
synchronized (blocks.sectionLocks[layer]) { synchronized (blocks.sectionLocks[layer]) {
LOGGER.warn("Unexpected null section, please report this occurence alongside a debugpaste.");
return getSkipFull(blocks, layer, aggressive); return getSkipFull(blocks, layer, aggressive);
} }
} }
@ -118,6 +124,7 @@ public abstract class CharBlocks implements IBlocks {
public synchronized IChunkSet reset() { public synchronized IChunkSet reset() {
for (int i = 0; i < sectionCount; i++) { for (int i = 0; i < sectionCount; i++) {
sections[i] = EMPTY; sections[i] = EMPTY;
VarHandle.storeStoreFence();
blocks[i] = null; blocks[i] = null;
} }
return null; return null;
@ -134,9 +141,7 @@ public abstract class CharBlocks implements IBlocks {
if (data == null) { if (data == null) {
return new char[4096]; return new char[4096];
} }
for (int i = 0; i < 4096; i++) { Arrays.fill(data, defaultOrdinal());
data[i] = defaultOrdinal();
}
return data; return data;
} }

Datei anzeigen

@ -4,8 +4,10 @@ import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
@ -114,7 +116,7 @@ public final class NullChunkGet implements IChunkGet {
} }
@Nullable @Nullable
public <T extends Future<T>> T call(@Nonnull IChunkSet set, @Nonnull Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, @Nonnull IChunkSet set, @Nonnull Runnable finalize) {
return null; return null;
} }

Datei anzeigen

@ -987,7 +987,8 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
if (chunkSet != null && !chunkSet.isEmpty()) { if (chunkSet != null && !chunkSet.isEmpty()) {
chunkSet.setBitMask(bitMask); chunkSet.setBitMask(bitMask);
IChunkSet copy = chunkSet.createCopy(); IChunkSet copy = chunkSet.createCopy();
return this.call(copy, () -> {
return this.call(extent, copy, () -> {
// Do nothing // Do nothing
}); });
} }
@ -997,8 +998,9 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
/** /**
* This method should never be called from outside ChunkHolder * This method should never be called from outside ChunkHolder
*/ */
@Override @Override
public synchronized T call(IChunkSet set, Runnable finalize) { public <U extends Future<U>> U call(IQueueExtent<? extends IChunk> owner, IChunkSet set, Runnable finalize) {
if (set != null) { if (set != null) {
IChunkGet get = getOrCreateGet(); IChunkGet get = getOrCreateGet();
try { try {
@ -1016,7 +1018,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
} else { } else {
finalizer = finalize; finalizer = finalize;
} }
return get.call(set, finalizer); return get.call(extent, set, finalizer);
} finally { } finally {
get.unlockCall(); get.unlockCall();
untrackExtent(); untrackExtent();

Datei anzeigen

@ -4,8 +4,10 @@ import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
@ -225,7 +227,7 @@ public final class NullChunk implements IQueueChunk {
} }
@Nullable @Nullable
public <T extends Future<T>> T call(@Nullable IChunkSet set, @Nullable Runnable finalize) { public <T extends Future<T>> T call(IQueueExtent<? extends IChunk> owner, @Nullable IChunkSet set, @Nullable Runnable finalize) {
return null; return null;
} }