Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-24 18:10:08 +01:00
Ursprung
74a2f02003
Commit
b4d7562b87
@ -1,11 +1,13 @@
|
||||
package com.boydti.fawe.bukkit;
|
||||
|
||||
import com.boydti.fawe.FAWEPlatformAdapterImpl;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.beta.implementation.cache.preloader.AsyncPreloader;
|
||||
import com.boydti.fawe.beta.implementation.cache.preloader.Preloader;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitQueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
||||
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
|
||||
import com.boydti.fawe.bukkit.listener.CFIPacketListener;
|
||||
@ -58,6 +60,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
private BukkitImageListener imageListener;
|
||||
private CFIPacketListener packetListener;
|
||||
private final boolean chunksStretched;
|
||||
private final FAWEPlatformAdapterImpl platformAdapter;
|
||||
|
||||
public FaweBukkit(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@ -81,6 +84,8 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
chunksStretched =
|
||||
Integer.parseInt(Bukkit.getBukkitVersion().split("-")[0].split("\\.")[1]) >= 16;
|
||||
|
||||
platformAdapter = new NMSAdapter();
|
||||
|
||||
//PlotSquared support is limited to Spigot/Paper as of 02/20/2020
|
||||
TaskManager.IMP.later(this::setupPlotSquared, 0);
|
||||
|
||||
@ -294,6 +299,11 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return chunksStretched;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FAWEPlatformAdapterImpl getPlatformAdapter() {
|
||||
return platformAdapter;
|
||||
}
|
||||
|
||||
private void setupPlotSquared() {
|
||||
Plugin plotSquared = this.plugin.getServer().getPluginManager().getPlugin("PlotSquared");
|
||||
if (plotSquared == null) {
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.boydti.fawe.bukkit.adapter;
|
||||
|
||||
public interface BukkitGetBlocks {
|
||||
|
||||
void send(int mask, boolean lighting);
|
||||
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.boydti.fawe.bukkit.adapter;
|
||||
|
||||
import com.boydti.fawe.FAWEPlatformAdapterImpl;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.implementation.chunk.ChunkHolder;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -10,7 +13,7 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NMSAdapter {
|
||||
public class NMSAdapter implements FAWEPlatformAdapterImpl {
|
||||
public static int createPalette(int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy,
|
||||
int[] num_palette_buffer, char[] set, Map<BlockVector3, Integer> ticking_blocks, boolean fastmode) {
|
||||
int air = 0;
|
||||
@ -182,4 +185,12 @@ public class NMSAdapter {
|
||||
num_palette_buffer[0] = num_palette;
|
||||
return air;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(IChunkGet chunk, int mask, boolean lighting) {
|
||||
if (!(chunk instanceof BukkitGetBlocks)) {
|
||||
throw new IllegalArgumentException("(IChunkGet) chunk not of type BukkitGetBlocks");
|
||||
}
|
||||
((BukkitGetBlocks) chunk).send(mask, lighting);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitGetBlocks;
|
||||
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;
|
||||
@ -74,7 +75,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_15_2.class);
|
||||
|
||||
@ -90,6 +91,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_15_2_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
private boolean lightUpdate = false;
|
||||
|
||||
public BukkitGetBlocks_1_15_2(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -120,6 +122,37 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
BitArray bitArray = new BitArray(9, 256);
|
||||
bitArray.fromRaw(data);
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
@ -141,6 +174,34 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibble) {
|
||||
byte[] bytes = nibble.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sky) {
|
||||
SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibbleSky) {
|
||||
byte[] bytes = nibbleSky.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
TileEntity tileEntity = getChunk().getTileEntity(new BlockPosition((x & 15) + (
|
||||
@ -436,33 +497,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
|
||||
Map<HeightMapType, int[]> heightMaps = set.getHeightMaps();
|
||||
for (Map.Entry<HeightMapType, int[]> entry : heightMaps.entrySet()) {
|
||||
BitArray bitArray = new BitArray(9, 256);
|
||||
bitArray.fromRaw(entry.getValue());
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(entry.getKey().name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
boolean lightUpdate = false;
|
||||
|
||||
// Lighting
|
||||
char[][] light = set.getLight();
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
char[][] skyLight = set.getSkyLight();
|
||||
if (skyLight != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(skyLight, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
BukkitGetBlocks_1_15_2.this.setHeightmapToGet(entry.getKey(), entry.getValue());
|
||||
}
|
||||
BukkitGetBlocks_1_15_2.this.setLightingToGet(set.getLight());
|
||||
BukkitGetBlocks_1_15_2.this.setSkyLightingToGet(set.getSkyLight());
|
||||
|
||||
Runnable[] syncTasks = null;
|
||||
|
||||
@ -584,7 +622,9 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markDirty();
|
||||
// send to player
|
||||
BukkitAdapter_1_15_2.sendChunk(nmsWorld, chunkX, chunkZ, finalMask, finalLightUpdate);
|
||||
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
|
||||
this.send(finalMask, finalLightUpdate);
|
||||
}
|
||||
if (finalizer != null) {
|
||||
finalizer.run();
|
||||
}
|
||||
@ -636,6 +676,11 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void send(int mask, boolean lighting) {
|
||||
BukkitAdapter_1_15_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
|
@ -104,6 +104,15 @@ public class BukkitGetBlocks_1_15_2_Copy implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_15_2.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -122,6 +131,9 @@ public class BukkitGetBlocks_1_15_2_Copy implements IChunkGet {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitGetBlocks;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -74,7 +75,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_16_1.class);
|
||||
|
||||
@ -90,6 +91,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_1_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
private boolean lightUpdate = false;
|
||||
|
||||
public BukkitGetBlocks_1_16_1(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -121,6 +123,37 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(data);
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
@ -142,6 +175,34 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibble) {
|
||||
byte[] bytes = nibble.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sky) {
|
||||
SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibbleSky) {
|
||||
byte[] bytes = nibbleSky.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
TileEntity tileEntity = getChunk().getTileEntity(new BlockPosition((x & 15) + (
|
||||
@ -438,33 +499,10 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
|
||||
Map<HeightMapType, int[]> heightMaps = set.getHeightMaps();
|
||||
for (Map.Entry<HeightMapType, int[]> entry : heightMaps.entrySet()) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(entry.getValue());
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(entry.getKey().name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
boolean lightUpdate = false;
|
||||
|
||||
// Lighting
|
||||
char[][] light = set.getLight();
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
char[][] skyLight = set.getSkyLight();
|
||||
if (skyLight != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(skyLight, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
BukkitGetBlocks_1_16_1.this.setHeightmapToGet(entry.getKey(), entry.getValue());
|
||||
}
|
||||
BukkitGetBlocks_1_16_1.this.setLightingToGet(set.getLight());
|
||||
BukkitGetBlocks_1_16_1.this.setSkyLightingToGet(set.getSkyLight());
|
||||
|
||||
Runnable[] syncTasks = null;
|
||||
|
||||
@ -586,7 +624,9 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markDirty();
|
||||
// send to player
|
||||
BukkitAdapter_1_16_1.sendChunk(nmsWorld, chunkX, chunkZ, finalMask, finalLightUpdate);
|
||||
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
|
||||
this.send(finalMask, finalLightUpdate);
|
||||
}
|
||||
if (finalizer != null) {
|
||||
finalizer.run();
|
||||
}
|
||||
@ -638,6 +678,11 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void send(int mask, boolean lighting) {
|
||||
BukkitAdapter_1_16_1.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
|
@ -104,6 +104,15 @@ public class BukkitGetBlocks_1_16_1_Copy implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_16_1.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -122,6 +131,9 @@ public class BukkitGetBlocks_1_16_1_Copy implements IChunkGet {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitGetBlocks;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_2.nbt.LazyCompoundTag_1_16_2;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -75,7 +76,7 @@ import java.util.function.Function;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_16_2.class);
|
||||
|
||||
@ -91,6 +92,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_2_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
private boolean lightUpdate = false;
|
||||
|
||||
public BukkitGetBlocks_1_16_2(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -121,6 +123,37 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(data);
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
@ -142,6 +175,34 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibble) {
|
||||
byte[] bytes = nibble.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sky) {
|
||||
SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibbleSky) {
|
||||
byte[] bytes = nibbleSky.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
TileEntity tileEntity = getChunk().getTileEntity(new BlockPosition((x & 15) + (
|
||||
@ -441,33 +502,10 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
|
||||
Map<HeightMapType, int[]> heightMaps = set.getHeightMaps();
|
||||
for (Map.Entry<HeightMapType, int[]> entry : heightMaps.entrySet()) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(entry.getValue());
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(entry.getKey().name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
boolean lightUpdate = false;
|
||||
|
||||
// Lighting
|
||||
char[][] light = set.getLight();
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
char[][] skyLight = set.getSkyLight();
|
||||
if (skyLight != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(skyLight, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
BukkitGetBlocks_1_16_2.this.setHeightmapToGet(entry.getKey(), entry.getValue());
|
||||
}
|
||||
BukkitGetBlocks_1_16_2.this.setLightingToGet(set.getLight());
|
||||
BukkitGetBlocks_1_16_2.this.setSkyLightingToGet(set.getSkyLight());
|
||||
|
||||
Runnable[] syncTasks = null;
|
||||
|
||||
@ -589,7 +627,9 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markDirty();
|
||||
// send to player
|
||||
BukkitAdapter_1_16_2.sendChunk(nmsWorld, chunkX, chunkZ, finalMask, finalLightUpdate);
|
||||
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
|
||||
this.send(finalMask, finalLightUpdate);
|
||||
}
|
||||
if (finalizer != null) {
|
||||
finalizer.run();
|
||||
}
|
||||
@ -641,6 +681,11 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void send(int mask, boolean lighting) {
|
||||
BukkitAdapter_1_16_2.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
|
@ -105,6 +105,15 @@ public class BukkitGetBlocks_1_16_2_Copy implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_2.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -123,6 +132,9 @@ public class BukkitGetBlocks_1_16_2_Copy implements IChunkGet {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitGetBlocks;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -75,7 +76,7 @@ import java.util.function.Function;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBlocks {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_16_4.class);
|
||||
|
||||
@ -91,6 +92,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_4_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
private boolean lightUpdate = false;
|
||||
|
||||
public BukkitGetBlocks_1_16_4(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -121,6 +123,37 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] light) {
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(data);
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
@ -142,6 +175,34 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibble) {
|
||||
byte[] bytes = nibble.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sky) {
|
||||
SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer);
|
||||
NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky);
|
||||
if (nibble != null) {
|
||||
lightUpdate = true;
|
||||
synchronized (nibbleSky) {
|
||||
byte[] bytes = nibbleSky.getCloneIfSet();
|
||||
if (bytes != NibbleArray.EMPTY_NIBBLE) {
|
||||
Arrays.fill(bytes, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
TileEntity tileEntity = getChunk().getTileEntity(new BlockPosition((x & 15) + (
|
||||
@ -441,33 +502,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
|
||||
Map<HeightMapType, int[]> heightMaps = set.getHeightMaps();
|
||||
for (Map.Entry<HeightMapType, int[]> entry : heightMaps.entrySet()) {
|
||||
BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256);
|
||||
bitArray.fromRaw(entry.getValue());
|
||||
nmsChunk.heightMap.get(HeightMap.Type.valueOf(entry.getKey().name())).a(bitArray.getData());
|
||||
}
|
||||
|
||||
boolean lightUpdate = false;
|
||||
|
||||
// Lighting
|
||||
char[][] light = set.getLight();
|
||||
if (light != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(light, EnumSkyBlock.BLOCK);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
char[][] skyLight = set.getSkyLight();
|
||||
if (skyLight != null) {
|
||||
lightUpdate = true;
|
||||
try {
|
||||
fillLightNibble(skyLight, EnumSkyBlock.SKY);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
BukkitGetBlocks_1_16_4.this.setHeightmapToGet(entry.getKey(), entry.getValue());
|
||||
}
|
||||
BukkitGetBlocks_1_16_4.this.setLightingToGet(set.getLight());
|
||||
BukkitGetBlocks_1_16_4.this.setSkyLightingToGet(set.getSkyLight());
|
||||
|
||||
Runnable[] syncTasks = null;
|
||||
|
||||
@ -589,7 +627,9 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
nmsChunk.mustNotSave = false;
|
||||
nmsChunk.markDirty();
|
||||
// send to player
|
||||
BukkitAdapter_1_16_4.sendChunk(nmsWorld, chunkX, chunkZ, finalMask, finalLightUpdate);
|
||||
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
|
||||
this.send(finalMask, finalLightUpdate);
|
||||
}
|
||||
if (finalizer != null) {
|
||||
finalizer.run();
|
||||
}
|
||||
@ -641,6 +681,11 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void send(int mask, boolean lighting) {
|
||||
BukkitAdapter_1_16_4.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
|
@ -105,6 +105,15 @@ public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_4.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -123,6 +132,9 @@ public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
|
||||
public interface FAWEPlatformAdapterImpl {
|
||||
|
||||
void sendChunk(IChunkGet chunk, int mask, boolean lighting);
|
||||
|
||||
}
|
@ -361,7 +361,7 @@ public class FaweAPI {
|
||||
} else {
|
||||
relighter.removeLighting();
|
||||
}
|
||||
relighter.sendChunks();
|
||||
relighter.flush();
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -43,4 +43,6 @@ public interface IFawe {
|
||||
return true;
|
||||
}
|
||||
|
||||
FAWEPlatformAdapterImpl getPlatformAdapter();
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,12 @@ public class CombinedBlocks implements IBlocks {
|
||||
return bitMask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
primary.removeSectionLighting(layer, sky);
|
||||
secondary.removeSectionLighting(layer, sky);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return primary.hasSection(layer) || secondary.hasSection(layer);
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.beta;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.implementation.processors.EmptyBatchProcessor;
|
||||
import com.boydti.fawe.beta.implementation.processors.MultiBatchProcessor;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -126,4 +127,11 @@ public interface IBatchProcessor {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default to CUSTOM ProcessorScope as we want custom processors people add to be before we write history, but after FAWE does it's own stuff.
|
||||
*/
|
||||
default ProcessorScope getScope() {
|
||||
return ProcessorScope.CUSTOM;
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ public interface IBlocks extends Trimable {
|
||||
.map(layer -> (1 << layer)).sum();
|
||||
}
|
||||
|
||||
void removeSectionLighting(int layer, boolean sky);
|
||||
|
||||
boolean trim(boolean aggressive, int layer);
|
||||
|
||||
IBlocks reset();
|
||||
|
@ -56,4 +56,10 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
|
||||
default IChunkGet getCopy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void setLightingToGet(char[][] lighting);
|
||||
|
||||
void setSkyLightingToGet(char[][] lighting);
|
||||
|
||||
void setHeightmapToGet(HeightMapType type, int[] data);
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
|
||||
void setSkyLightLayer(int layer, char[] toSet);
|
||||
|
||||
void removeSectionLighting(int layer, boolean sky);
|
||||
|
||||
void setFullBright(int layer);
|
||||
|
||||
void setEntity(CompoundTag tag);
|
||||
|
@ -44,6 +44,11 @@ public class FallbackChunkGet implements IChunkGet {
|
||||
return extent.getBiomeType(bx + x, y, bz + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return extent.getBlock(bx + x, y, bz + z);
|
||||
@ -106,6 +111,21 @@ public class FallbackChunkGet implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return true;
|
||||
|
@ -38,6 +38,9 @@ public final class NullChunkGet implements IChunkGet {
|
||||
return BiomeTypes.FOREST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(int layer, boolean sky) {}
|
||||
|
||||
@NotNull
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
@ -69,6 +72,15 @@ public final class NullChunkGet implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
public boolean trim(boolean aggressive) {
|
||||
return true;
|
||||
}
|
||||
|
@ -151,6 +151,25 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
return createCopy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {
|
||||
delegate.setLightingToGet(this, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {
|
||||
delegate.setSkyLightingToGet(this, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||
delegate.setHeightmapToGet(this, type, data);
|
||||
}
|
||||
|
||||
public void flushLightToGet(boolean heightmaps) {
|
||||
delegate.flushLightToGet(this, heightmaps);
|
||||
}
|
||||
|
||||
private static final IBlockDelegate BOTH = new IBlockDelegate() {
|
||||
@Override
|
||||
public IChunkGet get(ChunkHolder chunk) {
|
||||
@ -187,6 +206,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
@Override
|
||||
public void removeSectionLighting(ChunkHolder chunk, int layer, boolean sky) {
|
||||
chunk.chunkSet.removeSectionLighting(layer, sky);
|
||||
chunk.chunkExisting.removeSectionLighting(layer, sky);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -264,6 +284,27 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
@Override public int[] getHeightMap(ChunkHolder chunk, HeightMapType type) {
|
||||
return chunk.chunkExisting.getHeightMap(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushLightToGet(ChunkHolder chunk, boolean heightmaps) {
|
||||
chunk.chunkExisting.setLightingToGet(chunk.chunkSet.getLight());
|
||||
chunk.chunkExisting.setSkyLightingToGet(chunk.chunkSet.getSkyLight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.chunkExisting.setLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.chunkExisting.setSkyLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(ChunkHolder chunk, HeightMapType type, int[] data) {
|
||||
chunk.chunkExisting.setHeightmapToGet(type, data);
|
||||
}
|
||||
};
|
||||
|
||||
private static final IBlockDelegate GET = new IBlockDelegate() {
|
||||
@ -382,6 +423,26 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
@Override public int[] getHeightMap(ChunkHolder chunk, HeightMapType type) {
|
||||
return chunk.chunkExisting.getHeightMap(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushLightToGet(ChunkHolder chunk, boolean heightmaps) {
|
||||
// Do nothing as no lighting to flush to GET
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.chunkExisting.setLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.chunkExisting.setSkyLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(ChunkHolder chunk, HeightMapType type, int[] data) {
|
||||
chunk.chunkExisting.setHeightmapToGet(type, data);
|
||||
}
|
||||
};
|
||||
|
||||
private static final IBlockDelegate SET = new IBlockDelegate() {
|
||||
@ -421,7 +482,9 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(ChunkHolder chunk, int layer, boolean sky) {
|
||||
chunk.chunkSet.removeSectionLighting(layer, sky);
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = BOTH;
|
||||
chunk.removeSectionLighting(layer, sky);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -524,6 +587,39 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
chunk.chunkExisting.trim(false);
|
||||
return chunk.getHeightMap(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushLightToGet(ChunkHolder chunk, boolean heightmaps) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = BOTH;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.chunkExisting.setLightingToGet(chunk.chunkSet.getLight());
|
||||
chunk.chunkExisting.setSkyLightingToGet(chunk.chunkSet.getSkyLight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = BOTH;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.chunkExisting.setLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = BOTH;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.chunkExisting.setSkyLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(ChunkHolder chunk, HeightMapType type, int[] data) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = BOTH;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.chunkExisting.setHeightmapToGet(type, data);
|
||||
}
|
||||
};
|
||||
|
||||
private static final IBlockDelegate NULL = new IBlockDelegate() {
|
||||
@ -597,8 +693,9 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
|
||||
@Override
|
||||
public void removeSectionLighting(ChunkHolder chunk, int layer, boolean sky) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.getOrCreateSet();
|
||||
chunk.delegate = SET;
|
||||
chunk.delegate = BOTH;
|
||||
chunk.removeSectionLighting(layer, sky);
|
||||
}
|
||||
|
||||
@ -667,6 +764,35 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
chunk.chunkExisting.trim(false);
|
||||
return chunk.getHeightMap(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushLightToGet(ChunkHolder chunk, boolean heightmaps) {
|
||||
// Do nothing as no light to flush
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = GET;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.setLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(ChunkHolder chunk, char[][] lighting) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = GET;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.setSkyLightingToGet(lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(ChunkHolder chunk, HeightMapType type, int[] data) {
|
||||
chunk.getOrCreateGet();
|
||||
chunk.delegate = GET;
|
||||
chunk.chunkExisting.trim(false);
|
||||
chunk.setHeightmapToGet(type, data);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@ -947,5 +1073,13 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||
int getOpacity(ChunkHolder chunk, int x, int y, int z);
|
||||
|
||||
int[] getHeightMap(ChunkHolder chunk, HeightMapType type);
|
||||
|
||||
void flushLightToGet(ChunkHolder chunk, boolean heightmaps);
|
||||
|
||||
void setLightingToGet(ChunkHolder chunk, char[][] lighting);
|
||||
|
||||
void setSkyLightingToGet(ChunkHolder chunk, char[][] lighting);
|
||||
|
||||
void setHeightmapToGet(ChunkHolder chunk, HeightMapType type, int[] data);
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +177,15 @@ public final class NullChunk implements IQueueChunk {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
@Nullable
|
||||
public <T extends Future<T>> T call(@Nullable IChunkSet set, @Nullable Runnable finalize) {
|
||||
return null;
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.boydti.fawe.beta.implementation.lighting;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.IQueueChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.chunk.ChunkHolder;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.RelightMode;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
@ -34,6 +36,7 @@ import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NMSRelighter implements Relighter {
|
||||
@ -64,11 +67,17 @@ public class NMSRelighter implements Relighter {
|
||||
private final Map<Long, long[][][] /* z y x */> lightQueue;
|
||||
private final AtomicBoolean lightLock = new AtomicBoolean(false);
|
||||
private final ConcurrentHashMap<Long, long[][][]> concurrentLightQueue;
|
||||
private final RelightMode relightMode;
|
||||
private final int maxY;
|
||||
private final boolean calculateHeightMaps;
|
||||
private final ReentrantLock lightingLock;
|
||||
private boolean removeFirst;
|
||||
|
||||
public NMSRelighter(IQueueExtent<IQueueChunk> queue, boolean calculateHeightMaps) {
|
||||
this(queue, calculateHeightMaps, null);
|
||||
}
|
||||
|
||||
public NMSRelighter(IQueueExtent<IQueueChunk> queue, boolean calculateHeightMaps, RelightMode relightMode) {
|
||||
this.queue = queue;
|
||||
this.skyToRelight = new Long2ObjectOpenHashMap<>(12);
|
||||
this.lightQueue = new Long2ObjectOpenHashMap<>(12);
|
||||
@ -77,12 +86,19 @@ public class NMSRelighter implements Relighter {
|
||||
this.heightMaps = new Long2ObjectOpenHashMap<>(12);
|
||||
this.maxY = queue.getMaxY();
|
||||
this.calculateHeightMaps = calculateHeightMaps;
|
||||
this.relightMode = relightMode != null ? relightMode : RelightMode.valueOf(Settings.IMP.LIGHTING.MODE);
|
||||
this.lightingLock = new ReentrantLock();
|
||||
}
|
||||
|
||||
@Override public boolean isEmpty() {
|
||||
return skyToRelight.isEmpty() && lightQueue.isEmpty() && extentdSkyToRelight.isEmpty() && concurrentLightQueue.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ReentrantLock getLock() {
|
||||
return lightingLock;
|
||||
}
|
||||
|
||||
@Override public synchronized void removeAndRelight(boolean sky) {
|
||||
removeFirst = true;
|
||||
fixLightingSafe(sky);
|
||||
@ -778,6 +794,7 @@ public class NMSRelighter implements Relighter {
|
||||
}
|
||||
}
|
||||
fixBlockLighting();
|
||||
sendChunks();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -786,7 +803,11 @@ public class NMSRelighter implements Relighter {
|
||||
public void fixBlockLighting() {
|
||||
synchronized (lightQueue) {
|
||||
while (!lightLock.compareAndSet(false, true)) {
|
||||
;
|
||||
try {
|
||||
lightLock.wait(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
updateBlockLight(this.lightQueue);
|
||||
@ -796,7 +817,7 @@ public class NMSRelighter implements Relighter {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendChunks() {
|
||||
public synchronized void flush() {
|
||||
Iterator<Map.Entry<Long, Integer>> iter = chunksToSend.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Long, Integer> entry = iter.next();
|
||||
@ -827,6 +848,40 @@ public class NMSRelighter implements Relighter {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendChunks() {
|
||||
RunnableVal<Object> runnable = new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
Iterator<Map.Entry<Long, Integer>> iter = chunksToSend.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Long, Integer> entry = iter.next();
|
||||
long pair = entry.getKey();
|
||||
int bitMask = entry.getValue();
|
||||
int x = MathMan.unpairIntX(pair);
|
||||
int z = MathMan.unpairIntY(pair);
|
||||
ChunkHolder<?> chunk = (ChunkHolder<?>) queue.getOrCreateChunk(x, z);
|
||||
chunk.setBitMask(bitMask);
|
||||
if (calculateHeightMaps && heightMaps != null) {
|
||||
Map<HeightMapType, int[]> heightMapList = heightMaps.get(pair);
|
||||
if (heightMapList != null) {
|
||||
for (Map.Entry<HeightMapType, int[]> heightMapEntry : heightMapList.entrySet()) {
|
||||
chunk.setHeightMap(heightMapEntry.getKey(), heightMapEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
chunk.flushLightToGet(true);
|
||||
Fawe.imp().getPlatformAdapter().sendChunk(chunk.getOrCreateGet(), bitMask, true);
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (Settings.IMP.LIGHTING.ASYNC) {
|
||||
runnable.run();
|
||||
} else {
|
||||
TaskManager.IMP.sync(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void fixSkyLighting() {
|
||||
// Order chunks
|
||||
Map<Long, RelightSkyEntry> map = getSkyMap();
|
||||
@ -913,7 +968,7 @@ public class NMSRelighter implements Relighter {
|
||||
for (RelightSkyEntry chunk : chunks) { // Propagate skylight
|
||||
int layer = y >> 4;
|
||||
byte[] mask = chunk.mask;
|
||||
if ((y & 15) == 15 && chunk.fix[layer] != SkipReason.NONE) {
|
||||
if (chunk.fix[layer] != SkipReason.NONE) {
|
||||
if ((y & 15) == 0 && layer != 0 && chunk.fix[layer - 1] == SkipReason.NONE) {
|
||||
fill(mask, chunk.x, y, chunk.z, chunk.fix[layer]);
|
||||
}
|
||||
@ -945,7 +1000,7 @@ public class NMSRelighter implements Relighter {
|
||||
BlockMaterial material = state.getMaterial();
|
||||
int opacity = material.getLightOpacity();
|
||||
int brightness = material.getLightValue();
|
||||
if (brightness > 1) {
|
||||
if (brightness != iChunk.getEmmittedLight(x, y, z)) {
|
||||
addLightUpdate(bx + x, y, bz + z);
|
||||
}
|
||||
|
||||
@ -957,25 +1012,26 @@ public class NMSRelighter implements Relighter {
|
||||
if (heightMapList.get(HeightMapType.OCEAN_FLOOR)[j] == 0 && material.isSolid()) {
|
||||
heightMapList.get(HeightMapType.OCEAN_FLOOR)[j] = y + 1;
|
||||
}
|
||||
Map<Property<?>, Object> states = state.getStates();
|
||||
try {
|
||||
if (heightMapList.get(HeightMapType.MOTION_BLOCKING)[j] == 0 && (material.isSolid() || material.isLiquid() || (
|
||||
state.getStates().containsKey(waterLogged) && state.getState(waterLogged)))) {
|
||||
states.containsKey(waterLogged) && state.getState(waterLogged)))) {
|
||||
heightMapList.get(HeightMapType.MOTION_BLOCKING)[j] = y + 1;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
log.debug("Error calculating waterlogged state for BlockState: " + state.getBlockType().getId() + ". States:");
|
||||
log.debug(state.getStates().entrySet().stream().map(e -> e.getKey() + "=" + e.getValue())
|
||||
log.debug(states.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue())
|
||||
.collect(Collectors.joining(", ", "{", "}")));
|
||||
}
|
||||
try {
|
||||
if (heightMapList.get(HeightMapType.MOTION_BLOCKING_NO_LEAVES)[j] == 0 && (material.isSolid() || material.isLiquid() || (
|
||||
state.getStates().containsKey(waterLogged) && state.getState(waterLogged))) && !state.getBlockType().getId()
|
||||
states.containsKey(waterLogged) && state.getState(waterLogged))) && !state.getBlockType().getId()
|
||||
.toLowerCase().contains("leaves")) {
|
||||
heightMapList.get(HeightMapType.MOTION_BLOCKING_NO_LEAVES)[j] = y + 1;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
log.debug("Error calculating waterlogged state for BlockState: " + state.getBlockType().getId() + ". States:");
|
||||
log.debug(state.getStates().entrySet().stream().map(e -> e.getKey() + "=" + e.getValue())
|
||||
log.debug(states.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue())
|
||||
.collect(Collectors.joining(", ", "{", "}")));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.boydti.fawe.beta.implementation.lighting;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class NullRelighter implements Relighter {
|
||||
|
||||
public static NullRelighter INSTANCE = new NullRelighter();
|
||||
@ -46,4 +48,9 @@ public class NullRelighter implements Relighter {
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReentrantLock getLock() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.boydti.fawe.beta.implementation.lighting;
|
||||
|
||||
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.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class RelightProcessor implements IBatchProcessor {
|
||||
|
||||
private final Relighter relighter;
|
||||
|
||||
public RelightProcessor(Relighter relighter) {
|
||||
if (relighter instanceof NullRelighter) {
|
||||
throw new IllegalArgumentException("NullRelighter cannot be used for a RelightProcessor");
|
||||
}
|
||||
this.relighter = relighter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
if (Settings.IMP.LIGHTING.MODE == 2) {
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
|
||||
} else if (Settings.IMP.LIGHTING.MODE == 1) {
|
||||
byte[] fix = new byte[16];
|
||||
boolean relight = false;
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
if (!set.hasSection(i)) {
|
||||
fix[i] = Relighter.SkipReason.AIR;
|
||||
continue;
|
||||
}
|
||||
relight = true;
|
||||
break;
|
||||
}
|
||||
if (relight) {
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<IChunkSet> postProcessSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
return CompletableFuture.completedFuture(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Extent construct(Extent child) {
|
||||
throw new UnsupportedOperationException("Processing only");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.boydti.fawe.beta.implementation.lighting;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public interface Relighter {
|
||||
|
||||
/**
|
||||
@ -66,6 +68,8 @@ public interface Relighter {
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
ReentrantLock getLock();
|
||||
|
||||
class SkipReason {
|
||||
public static final byte NONE = 0;
|
||||
public static final byte AIR = 1;
|
||||
|
@ -51,4 +51,9 @@ public class BatchProcessorHolder implements IBatchProcessorHolder {
|
||||
IBatchProcessor tmp = getProcessor();
|
||||
return super.toString() + "{" + (tmp == this ? "" : getProcessor()) + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return getProcessor().getScope();
|
||||
}
|
||||
}
|
||||
|
@ -81,4 +81,9 @@ public class ChunkSendProcessor implements IBatchProcessor {
|
||||
public Extent construct(Extent child) {
|
||||
throw new UnsupportedOperationException("Processing only");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -49,4 +49,9 @@ public final class EmptyBatchProcessor implements IBatchProcessor {
|
||||
private EmptyBatchProcessor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.ADDING_BLOCKS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,21 +9,30 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MultiBatchProcessor implements IBatchProcessor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MultiBatchProcessor.class);
|
||||
|
||||
private IBatchProcessor[] processors;
|
||||
private final LoadingCache<Class<?>, Map<Long, Filter>> classToThreadIdToFilter =
|
||||
FaweCache.IMP.createCache((Supplier<Map<Long, Filter>>) ConcurrentHashMap::new);
|
||||
|
||||
public MultiBatchProcessor(IBatchProcessor... processors) {
|
||||
this.processors = processors;
|
||||
}
|
||||
@ -65,20 +74,33 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
Map<Integer, Set<IBatchProcessor>> ordered = new HashMap<>();
|
||||
try {
|
||||
IChunkSet chunkSet = set;
|
||||
for (int i = processors.length - 1; i >= 0; i--) {
|
||||
IBatchProcessor processor = processors[i];
|
||||
if (processor instanceof Filter) {
|
||||
chunkSet = ((IBatchProcessor) classToThreadIdToFilter.getUnchecked(processor.getClass())
|
||||
.computeIfAbsent(Thread.currentThread().getId(), k -> ((Filter) processor).fork())).processSet(chunk, get, chunkSet);
|
||||
} else {
|
||||
chunkSet = processor.processSet(chunk, get, chunkSet);
|
||||
for (IBatchProcessor processor : processors) {
|
||||
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
|
||||
ordered.merge(processor.getScope().intValue(), new HashSet<>(Collections.singleton(processor)), (existing, theNew) -> {
|
||||
existing.add(processor);
|
||||
return existing;
|
||||
});
|
||||
continue;
|
||||
}
|
||||
chunkSet = processSet(processor, chunk, get, chunkSet);
|
||||
}
|
||||
if (ordered.size() > 0) {
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
Set<IBatchProcessor> processors = ordered.get(i);
|
||||
if (processors == null) {
|
||||
continue;
|
||||
}
|
||||
for (IBatchProcessor processor : processors) {
|
||||
chunkSet = processSet(processor,chunk, get, chunkSet);
|
||||
if (chunkSet == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return chunkSet;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
@ -86,11 +108,25 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private IChunkSet processSet(IBatchProcessor processor, IChunk chunk, IChunkGet get, IChunkSet chunkSet) {
|
||||
if (processor instanceof Filter) {
|
||||
chunkSet = ((IBatchProcessor) classToThreadIdToFilter.getUnchecked(processor.getClass())
|
||||
.computeIfAbsent(Thread.currentThread().getId(), k -> ((Filter) processor).fork())).processSet(chunk, get, chunkSet);
|
||||
} else {
|
||||
chunkSet = processor.processSet(chunk, get, chunkSet);
|
||||
}
|
||||
return chunkSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<IChunkSet> postProcessSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
try {
|
||||
for (int i = processors.length - 1 ; i >= 0; i--) {
|
||||
IBatchProcessor processor = processors[i];
|
||||
for (IBatchProcessor processor : processors) {
|
||||
// We do NOT want to edit blocks in post processing
|
||||
if (processor.getScope() != ProcessorScope.READING_SET_BLOCKS) {
|
||||
continue;
|
||||
}
|
||||
set = processor.postProcessSet(chunk, get, set).get();
|
||||
if (set == null) {
|
||||
return null;
|
||||
@ -163,4 +199,13 @@ public class MultiBatchProcessor implements IBatchProcessor {
|
||||
public String toString() {
|
||||
return super.toString() + "{" + StringMan.join(processors, ",") + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
int scope = 0;
|
||||
for (IBatchProcessor processor : processors) {
|
||||
scope = Math.max(scope, processor.getScope().intValue());
|
||||
}
|
||||
return ProcessorScope.valueOf(0);
|
||||
}
|
||||
}
|
||||
|
@ -36,4 +36,9 @@ public final class NullProcessor implements IBatchProcessor {
|
||||
private NullProcessor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.ADDING_BLOCKS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package com.boydti.fawe.beta.implementation.processors;
|
||||
|
||||
/**
|
||||
* The scope of a processor.
|
||||
* Order in which processors are executed:
|
||||
* - ADDING_BLOCKS (processors that strictly ADD blocks to an edit ONLY)
|
||||
* - CHANGING_BLOCKS (processors that strictly ADD or CHANGE blocks being set)
|
||||
* - REMOVING_BLOCKS (processors that string ADD, CHANGE or REMOVE blocks being set)
|
||||
* - CUSTOM (processors that do not specify a SCOPE)
|
||||
* - READING_SET_BLOCKS (processors that do not alter blocks at all, and read the blocks that are actually going to set, e.g. history processors)
|
||||
*/
|
||||
public enum ProcessorScope {
|
||||
ADDING_BLOCKS(0), CHANGING_BLOCKS(1), REMOVING_BLOCKS(2), CUSTOM(3), READING_SET_BLOCKS(4);
|
||||
|
||||
private final int value;
|
||||
|
||||
ProcessorScope(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static ProcessorScope valueOf(int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
return ProcessorScope.ADDING_BLOCKS;
|
||||
case 1:
|
||||
return ProcessorScope.CHANGING_BLOCKS;
|
||||
case 2:
|
||||
return ProcessorScope.REMOVING_BLOCKS;
|
||||
case 4:
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
case 3:
|
||||
default:
|
||||
return ProcessorScope.CUSTOM;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.processors.EmptyBatchProcessor;
|
||||
import com.boydti.fawe.beta.implementation.processors.ExtentBatchProcessorHolder;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
@ -352,4 +353,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
||||
public ChunkFilterBlock initFilterBlock() {
|
||||
return new CharFilterBlock(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.ADDING_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -623,6 +623,15 @@ public class MCAChunk implements IChunk {
|
||||
return createCopy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setSkyLightingToGet(char[][] lighting) {}
|
||||
|
||||
@Override
|
||||
public void setHeightmapToGet(HeightMapType type, int[] data) {}
|
||||
|
||||
@Override
|
||||
public Future call(IChunkSet set, Runnable finalize) {
|
||||
return null;
|
||||
|
@ -6,6 +6,7 @@ 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.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.object.HistoryExtent;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
@ -212,6 +213,11 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
|
||||
return (Future<IChunkSet>) addWriteTask(() -> processSet(chunk, get, set));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
}
|
||||
|
||||
public abstract void addTileCreate(CompoundTag tag);
|
||||
|
||||
public abstract void addTileRemove(CompoundTag tag);
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.extent;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.util.ExtentTraverser;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
@ -147,4 +148,9 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
||||
}
|
||||
return super.createEntity(location, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -355,4 +356,9 @@ public class NullExtent extends FaweRegionExtent implements IBatchProcessor {
|
||||
public Extent construct(Extent child) {
|
||||
throw reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.ADDING_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.regions;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.regions.IDelegateRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -24,4 +25,9 @@ public class FaweMask implements IDelegateRegion {
|
||||
public Region clone() {
|
||||
throw new UnsupportedOperationException("Clone not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.REMOVING_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IQueueChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.lighting.NMSRelighter;
|
||||
import com.boydti.fawe.beta.implementation.lighting.NullRelighter;
|
||||
import com.boydti.fawe.beta.implementation.lighting.RelightProcessor;
|
||||
import com.boydti.fawe.beta.implementation.lighting.Relighter;
|
||||
import com.boydti.fawe.beta.implementation.processors.LimitExtent;
|
||||
import com.boydti.fawe.beta.implementation.queue.ParallelQueueExtent;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -67,6 +71,7 @@ public class EditSessionBuilder {
|
||||
private EditSessionEvent event;
|
||||
private String command;
|
||||
private RelightMode relightMode;
|
||||
private Relighter relighter;
|
||||
private Boolean wnaMode;
|
||||
|
||||
/**
|
||||
@ -396,6 +401,14 @@ public class EditSessionBuilder {
|
||||
allowedRegions = new Region[]{RegionWrapper.GLOBAL()};
|
||||
// this.extent = new HeightBoundExtent(this.extent, this.limit, 0, world.getMaxY());
|
||||
}
|
||||
// There's no need to do lighting (and it'll also just be a pain to implement) if we're not placing chunks
|
||||
if (placeChunks && ((relightMode != null && relightMode != RelightMode.NONE) || (relightMode == null && Settings.IMP.LIGHTING.MODE > 0))) {
|
||||
relighter = new NMSRelighter(queue, Settings.IMP.LIGHTING.DO_HEIGHTMAPS,
|
||||
relightMode != null ? relightMode : RelightMode.valueOf(Settings.IMP.LIGHTING.MODE));
|
||||
extent.addProcessor(new RelightProcessor(relighter));
|
||||
} else {
|
||||
relighter = NullRelighter.INSTANCE;
|
||||
}
|
||||
if (limit != null && !limit.isUnlimited() && regionExtent != null) {
|
||||
this.extent = new LimitExtent(regionExtent, limit);
|
||||
} else if (limit != null && !limit.isUnlimited()) {
|
||||
@ -454,6 +467,10 @@ public class EditSessionBuilder {
|
||||
return blockBag;
|
||||
}
|
||||
|
||||
public Relighter getRelighter() {
|
||||
return relighter;
|
||||
}
|
||||
|
||||
public boolean isWNAMode() {
|
||||
return wnaMode;
|
||||
}
|
||||
@ -462,5 +479,4 @@ public class EditSessionBuilder {
|
||||
public Region[] getAllowedRegions() {
|
||||
return allowedRegions;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.implementation.lighting.NullRelighter;
|
||||
import com.boydti.fawe.beta.implementation.lighting.Relighter;
|
||||
import com.boydti.fawe.config.Caption;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
@ -224,12 +226,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
private final int maxY;
|
||||
private final List<WatchdogTickingExtent> watchdogExtents = new ArrayList<>(2);
|
||||
|
||||
private final Relighter relighter;
|
||||
private final boolean wnaMode;
|
||||
|
||||
@Nullable
|
||||
private final Region[] allowedRegions;
|
||||
|
||||
|
||||
@Deprecated
|
||||
public EditSession(@NotNull EventBus bus, World world, @Nullable Player player,
|
||||
@Nullable FaweLimit limit, @Nullable AbstractChangeSet changeSet,
|
||||
@ -264,6 +266,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
this.maxY = world.getMaxY();
|
||||
this.blockBag = builder.getBlockBag();
|
||||
this.history = changeSet != null;
|
||||
this.relighter = builder.getRelighter();
|
||||
this.wnaMode = builder.isWNAMode();
|
||||
this.allowedRegions = builder.getAllowedRegions() != null ? builder.getAllowedRegions().clone() : null;
|
||||
}
|
||||
@ -1093,6 +1096,25 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
}
|
||||
// Reset limit
|
||||
limit.set(originalLimit);
|
||||
try {
|
||||
if (relighter != null && !(relighter instanceof NullRelighter)) {
|
||||
// Only relight once!
|
||||
if (!relighter.getLock().tryLock()) {
|
||||
relighter.getLock().lock();
|
||||
relighter.getLock().unlock();
|
||||
} else {
|
||||
if (Settings.IMP.LIGHTING.REMOVE_FIRST) {
|
||||
relighter.removeAndRelight(true);
|
||||
} else {
|
||||
relighter.fixSkyLighting();
|
||||
relighter.fixBlockLighting();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
player.printError(TranslatableComponent.of("fawe.error.lighting"));
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Enqueue it
|
||||
if (getChangeSet() != null) {
|
||||
if (Settings.IMP.HISTORY.COMBINE_STAGES) {
|
||||
|
@ -23,6 +23,7 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ExtentFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.changeset.AbstractChangeSet;
|
||||
import com.boydti.fawe.object.clipboard.WorldCopyClipboard;
|
||||
@ -707,6 +708,9 @@ public interface Extent extends InputExtent, OutputExtent {
|
||||
}
|
||||
|
||||
default Extent addPostProcessor(IBatchProcessor processor) {
|
||||
if (processor.getScope() == ProcessorScope.READING_SET_BLOCKS) {
|
||||
throw new IllegalArgumentException("You cannot alter blocks in a PostProcessor");
|
||||
}
|
||||
return processor.construct(this);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.FilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
@ -128,4 +129,9 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce
|
||||
public Filter fork() {
|
||||
return new MaskingExtent(getExtent(), this.mask.copy(), this.threadIdToFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.REMOVING_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
@ -774,5 +775,4 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.object.extent.SingleRegionExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
@ -365,4 +366,9 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
}
|
||||
return new SingleRegionExtent(child, FaweLimit.MAX, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ProcessorScope getScope() {
|
||||
return ProcessorScope.REMOVING_BLOCKS;
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@
|
||||
"fawe.error.worldedit.some.fails.blockbag": "Missing blocks: {0}",
|
||||
"fawe.error.mask.angle": "Cannot combine degree with block-step",
|
||||
"fawe.error.invalid-flag": "The flag {0} is not applicable here",
|
||||
"fawe.error.lighting": "Error when attempting lighting. You may need to reload the chunks to see the edit.",
|
||||
|
||||
"fawe.cancel.worldedit.cancel.count": "Cancelled {0} edits.",
|
||||
"fawe.cancel.worldedit.cancel.reason.confirm": "Use //confirm to execute {2}",
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren