176 lines
7.3 KiB
Java
176 lines
7.3 KiB
Java
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3;
|
|
|
|
import com.fastasyncworldedit.core.configuration.Settings;
|
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
|
import com.fastasyncworldedit.core.queue.IChunk;
|
|
import com.fastasyncworldedit.core.queue.IChunkGet;
|
|
import com.fastasyncworldedit.core.queue.IChunkSet;
|
|
import com.fastasyncworldedit.core.registry.state.PropertyKey;
|
|
import com.sk89q.worldedit.extent.Extent;
|
|
import com.sk89q.worldedit.world.block.BlockState;
|
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.world.level.material.Fluid;
|
|
import net.minecraft.world.level.material.Fluids;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
public class PaperweightPostProcessor implements IBatchProcessor {
|
|
|
|
@Override
|
|
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
|
return set;
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
@Override
|
|
public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) {
|
|
boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS;
|
|
// The PostProcessor shouldn't be added, but just in case
|
|
if (!tickFluid) {
|
|
return;
|
|
}
|
|
PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet;
|
|
layer:
|
|
for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) {
|
|
char[] set = iChunkSet.loadIfPresent(layer);
|
|
if (set == null) {
|
|
// No edit means no need to process
|
|
continue;
|
|
}
|
|
char[] get = null;
|
|
for (int i = 0; i < 4096; i++) {
|
|
char ordinal = set[i];
|
|
char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
|
|
boolean fromGet = false; // Used for liquids
|
|
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
|
if (get == null) {
|
|
get = getBlocks.load(layer);
|
|
}
|
|
// If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't
|
|
// actually being set
|
|
if (get == null) {
|
|
continue layer;
|
|
}
|
|
fromGet = true;
|
|
ordinal = replacedOrdinal = get[i];
|
|
}
|
|
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
|
|
continue;
|
|
} else if (!fromGet) { // if fromGet, don't do the same again
|
|
if (get == null) {
|
|
get = getBlocks.load(layer);
|
|
}
|
|
replacedOrdinal = get[i];
|
|
}
|
|
boolean ticking = BlockTypesCache.ticking[ordinal];
|
|
boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal];
|
|
boolean replacedWasLiquid = false;
|
|
BlockState replacedState = null;
|
|
if (!ticking) {
|
|
// If the block being replaced was not ticking, it cannot be a liquid
|
|
if (!replacedWasTicking) {
|
|
continue;
|
|
}
|
|
// If the block being replaced is not fluid, we do not need to worry
|
|
if (!(replacedWasLiquid =
|
|
(replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) {
|
|
continue;
|
|
}
|
|
}
|
|
BlockState state = BlockState.getFromOrdinal(ordinal);
|
|
boolean liquid = state.getMaterial().isLiquid();
|
|
int x = i & 15;
|
|
int y = (i >> 8) & 15;
|
|
int z = (i >> 4) & 15;
|
|
BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z);
|
|
if (liquid || replacedWasLiquid) {
|
|
if (liquid) {
|
|
addFluid(getBlocks.serverLevel, state, position);
|
|
continue;
|
|
}
|
|
// If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this
|
|
// may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up
|
|
// being ticked anyway. We only need it to be "hit" once.
|
|
if (!wasAdjacentToWater(get, set, i, x, y, z)) {
|
|
continue;
|
|
}
|
|
addFluid(getBlocks.serverLevel, replacedState, position);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public Extent construct(final Extent child) {
|
|
throw new UnsupportedOperationException("Processing only");
|
|
}
|
|
|
|
@Override
|
|
public ProcessorScope getScope() {
|
|
return ProcessorScope.READING_SET_BLOCKS;
|
|
}
|
|
|
|
private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) {
|
|
if (set == null || get == null) {
|
|
return false;
|
|
}
|
|
char ordinal;
|
|
char reserved = BlockTypesCache.ReservedIDs.__RESERVED__;
|
|
if (x > 0 && set[i - 1] != reserved) {
|
|
if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (x < 15 && set[i + 1] != reserved) {
|
|
if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (z > 0 && set[i - 16] != reserved) {
|
|
if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (z < 15 && set[i + 16] != reserved) {
|
|
if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (y > 0 && set[i - 256] != reserved) {
|
|
if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (y < 15 && set[i + 256] != reserved) {
|
|
return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
private boolean isFluid(char ordinal) {
|
|
return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid();
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) {
|
|
Fluid type;
|
|
if (replacedState.getBlockType() == BlockTypes.LAVA) {
|
|
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA;
|
|
} else {
|
|
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
|
|
}
|
|
serverLevel.scheduleTick(
|
|
position,
|
|
type,
|
|
type.getTickDelay(serverLevel)
|
|
);
|
|
}
|
|
|
|
}
|