mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 09:17:39 +00:00
Fix NBT stripping and trimming (#2929)
This commit is contained in:
parent
b4635e85c9
commit
3b6e5e83c9
@ -512,8 +512,8 @@ public class LimitExtent extends AbstractDelegateExtent implements IBatchProcess
|
|||||||
if (!processing) {
|
if (!processing) {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
int tiles = set.getTiles().size();
|
int tiles = set.tiles().size();
|
||||||
int ents = set.getEntities().size() + set.getEntityRemoves().size();
|
int ents = set.entities().size() + set.getEntityRemoves().size();
|
||||||
limit.THROW_MAX_CHANGES(tiles + ents);
|
limit.THROW_MAX_CHANGES(tiles + ents);
|
||||||
limit.THROW_MAX_BLOCKSTATES(tiles);
|
limit.THROW_MAX_BLOCKSTATES(tiles);
|
||||||
limit.THROW_MAX_ENTITIES(ents);
|
limit.THROW_MAX_ENTITIES(ents);
|
||||||
|
@ -2,14 +2,12 @@ package com.fastasyncworldedit.core.extent;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
|
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
|
||||||
|
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.queue.IChunk;
|
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.util.ExtentTraverser;
|
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
@ -20,16 +18,17 @@ import com.sk89q.worldedit.util.Location;
|
|||||||
import com.sk89q.worldedit.world.NbtValued;
|
import com.sk89q.worldedit.world.NbtValued;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||||
|
import org.enginehub.linbus.tree.LinTag;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.HashMap;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor {
|
public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor {
|
||||||
@ -75,79 +74,82 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
if (!(block instanceof BaseBlock localBlock)) {
|
if (!(block instanceof BaseBlock localBlock)) {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
if (!localBlock.hasNbtData()) {
|
final LinCompoundTag nbt = localBlock.getNbt();
|
||||||
|
if (nbt == null) {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
CompoundTag nbt = localBlock.getNbtData();
|
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
|
||||||
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
|
|
||||||
for (String key : strip) {
|
for (String key : strip) {
|
||||||
value.remove(key);
|
nbtBuilder.remove(key);
|
||||||
}
|
}
|
||||||
return (B) localBlock.toBaseBlock(new CompoundTag(value));
|
return (B) localBlock.toBaseBlock(nbtBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends NbtValued> T stripEntityNBT(T entity) {
|
public <T extends NbtValued> T stripEntityNBT(T entity) {
|
||||||
if (!entity.hasNbtData()) {
|
LinCompoundTag nbt = entity.getNbt();
|
||||||
|
if (nbt == null) {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
CompoundTag nbt = entity.getNbtData();
|
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
|
||||||
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
|
|
||||||
for (String key : strip) {
|
for (String key : strip) {
|
||||||
value.remove(key);
|
nbtBuilder.remove(key);
|
||||||
}
|
}
|
||||||
entity.setNbtData(new CompoundTag(value));
|
entity.setNbt(nbtBuilder.build());
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
||||||
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
|
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
|
||||||
Set<CompoundTag> entities = set.getEntities();
|
Collection<FaweCompoundTag> entities = set.entities();
|
||||||
if (tiles.isEmpty() && entities.isEmpty()) {
|
if (tiles.isEmpty() && entities.isEmpty()) {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
|
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
|
||||||
for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
|
for (final var entry : tiles.entrySet()) {
|
||||||
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
|
FaweCompoundTag original = entry.getValue();
|
||||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
FaweCompoundTag result = stripNbt(original);
|
||||||
entry.getValue().getValue().forEach((k, v) -> {
|
if (original != result) {
|
||||||
if (strip.contains(k.toLowerCase())) {
|
|
||||||
isStripped.set(true);
|
|
||||||
} else {
|
|
||||||
map.put(k, v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (isStripped.get()) {
|
|
||||||
if (isBv3ChunkMap) {
|
if (isBv3ChunkMap) {
|
||||||
// Replace existing value with stripped value
|
// Replace existing value with stripped value
|
||||||
tiles.put(entry.getKey(), new CompoundTag(map.build()));
|
tiles.put(entry.getKey(), result);
|
||||||
} else {
|
} else {
|
||||||
entry.setValue(new CompoundTag(map.build()));
|
entry.setValue(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Set<CompoundTag> stripped = new HashSet<>();
|
Set<FaweCompoundTag> stripped = new HashSet<>();
|
||||||
Iterator<CompoundTag> iterator = entities.iterator();
|
Iterator<FaweCompoundTag> iterator = entities.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
CompoundTag entity = iterator.next();
|
FaweCompoundTag original = iterator.next();
|
||||||
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
|
FaweCompoundTag result = stripNbt(original);
|
||||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
if (original != result) {
|
||||||
entity.getValue().forEach((k, v) -> {
|
|
||||||
if (strip.contains(k.toUpperCase(Locale.ROOT))) {
|
|
||||||
isStripped.set(true);
|
|
||||||
} else {
|
|
||||||
map.put(k, v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (isStripped.get()) {
|
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
stripped.add(new CompoundTag(map.build()));
|
stripped.add(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set.getEntities().addAll(stripped);
|
// this relies on entities.addAll(...) not throwing an exception if empty+unmodifiable (=> stripped is empty too)
|
||||||
|
entities.addAll(stripped);
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FaweCompoundTag stripNbt(
|
||||||
|
FaweCompoundTag compoundTag
|
||||||
|
) {
|
||||||
|
LinCompoundTag.Builder builder = LinCompoundTag.builder();
|
||||||
|
boolean stripped = false;
|
||||||
|
for (var entry : compoundTag.linTag().value().entrySet()) {
|
||||||
|
String k = entry.getKey();
|
||||||
|
LinTag<?> v = entry.getValue();
|
||||||
|
if (strip.contains(k.toLowerCase(Locale.ROOT))) {
|
||||||
|
stripped = true;
|
||||||
|
} else {
|
||||||
|
builder.put(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stripped ? FaweCompoundTag.of(builder.build()) : compoundTag;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Extent construct(final Extent child) {
|
public Extent construct(final Extent child) {
|
||||||
|
@ -3,15 +3,16 @@ package com.fastasyncworldedit.core.queue;
|
|||||||
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
|
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor;
|
import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
||||||
|
import com.fastasyncworldedit.core.util.NbtUtils;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
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.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -156,11 +157,11 @@ public interface IBatchProcessor {
|
|||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true, since = "2.8.4")
|
@Deprecated(forRemoval = true, since = "2.8.4")
|
||||||
default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) {
|
default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) {
|
||||||
Set<CompoundTag> ents = set.getEntities();
|
Collection<FaweCompoundTag> ents = set.entities();
|
||||||
if (!ents.isEmpty()) {
|
if (!ents.isEmpty()) {
|
||||||
ents.removeIf(ent -> !contains.apply(ent.getEntityPosition().toBlockPoint()));
|
ents.removeIf(ent -> !contains.apply(NbtUtils.entityPosition(ent).toBlockPoint()));
|
||||||
}
|
}
|
||||||
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
|
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
|
||||||
if (!tiles.isEmpty()) {
|
if (!tiles.isEmpty()) {
|
||||||
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !contains
|
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !contains
|
||||||
.apply(blockVector3CompoundTagEntry.getKey()));
|
.apply(blockVector3CompoundTagEntry.getKey()));
|
||||||
@ -177,11 +178,11 @@ public interface IBatchProcessor {
|
|||||||
default boolean trimNBT(
|
default boolean trimNBT(
|
||||||
IChunkSet set, Function<BlockVector3, Boolean> containsEntity, Function<BlockVector3, Boolean> containsTile
|
IChunkSet set, Function<BlockVector3, Boolean> containsEntity, Function<BlockVector3, Boolean> containsTile
|
||||||
) {
|
) {
|
||||||
Set<CompoundTag> ents = set.getEntities();
|
Collection<FaweCompoundTag> ents = set.entities();
|
||||||
if (!ents.isEmpty()) {
|
if (!ents.isEmpty()) {
|
||||||
ents.removeIf(ent -> !containsEntity.apply(ent.getEntityPosition().toBlockPoint()));
|
ents.removeIf(ent -> !containsEntity.apply(NbtUtils.entityPosition(ent).toBlockPoint()));
|
||||||
}
|
}
|
||||||
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
|
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
|
||||||
if (!tiles.isEmpty()) {
|
if (!tiles.isEmpty()) {
|
||||||
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey()));
|
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey()));
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public interface IBlocks extends Trimable {
|
|||||||
|
|
||||||
@Deprecated(forRemoval = true, since = "2.11.2")
|
@Deprecated(forRemoval = true, since = "2.11.2")
|
||||||
default Map<BlockVector3, CompoundTag> getTiles() {
|
default Map<BlockVector3, CompoundTag> getTiles() {
|
||||||
return AdaptedMap.immutable(tiles(), pos -> pos, IBlocks::toCompoundTag);
|
return AdaptedMap.values(tiles(), ct -> FaweCompoundTag.of(ct.toLinTag()), IBlocks::toCompoundTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<BlockVector3, FaweCompoundTag> tiles();
|
Map<BlockVector3, FaweCompoundTag> tiles();
|
||||||
|
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.util;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
||||||
import org.enginehub.linbus.tree.LinByteTag;
|
import org.enginehub.linbus.tree.LinByteTag;
|
||||||
@ -211,4 +212,18 @@ public final class NbtUtils {
|
|||||||
map.put("PersistentIDLSB", LinLongTag.of(uuid.getLeastSignificantBits()));
|
map.put("PersistentIDLSB", LinLongTag.of(uuid.getLeastSignificantBits()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the position data of the given tag}
|
||||||
|
*
|
||||||
|
* @param compoundTag the tag to extract position information from
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public static Vector3 entityPosition(FaweCompoundTag compoundTag) {
|
||||||
|
LinListTag<LinDoubleTag> pos = compoundTag.linTag().getListTag("Pos", LinTagType.doubleTag());
|
||||||
|
double x = pos.get(0).valueAsDouble();
|
||||||
|
double y = pos.get(1).valueAsDouble();
|
||||||
|
double z = pos.get(2).valueAsDouble();
|
||||||
|
return Vector3.at(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user