mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
Add configurable disallowed states for limits, global disallowed blocks (#1312)
This commit is contained in:
parent
d641e21dfc
commit
6839fa5567
@ -1,13 +1,21 @@
|
|||||||
package com.fastasyncworldedit.core.configuration;
|
package com.fastasyncworldedit.core.configuration;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
|
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Settings extends Config {
|
public class Settings extends Config {
|
||||||
|
|
||||||
@ -192,7 +200,32 @@ public class Settings extends Config {
|
|||||||
"List of nbt tags to strip from blocks, e.g. Items",
|
"List of nbt tags to strip from blocks, e.g. Items",
|
||||||
})
|
})
|
||||||
public List<String> STRIP_NBT = new ArrayList<>();
|
public List<String> STRIP_NBT = new ArrayList<>();
|
||||||
|
@Comment({
|
||||||
|
"If the disallowed blocks listed in config-legacy.yml should be disallowed in all edits,",
|
||||||
|
"not just where blocks patterns are used.",
|
||||||
|
" - Can prevent blocks being pasted from clipboards, etc.",
|
||||||
|
" - If fast-placement is disabled, this may cause edits to be slower."
|
||||||
|
})
|
||||||
|
public boolean UNIVERSAL_DISALLOWED_BLOCKS = true;
|
||||||
|
@Comment({
|
||||||
|
"List of blocks to deny use of. Can be either an entire block type or a block with a specific property value.",
|
||||||
|
"Where block properties are specified, any blockstate with the property will be disallowed (i.g. all directions",
|
||||||
|
"of a waterlogged fence). For blocking/remapping of all occurence of a property like waterlogged, see",
|
||||||
|
"remap-properties below.",
|
||||||
|
"Example block property blocking:",
|
||||||
|
" - \"minecraft:conduit[waterlogged=true]\"",
|
||||||
|
" - \"minecraft:piston[extended=false,facing=west]\"",
|
||||||
|
" - \"minecraft:wheat[age=7]\""
|
||||||
|
})
|
||||||
|
public List<String> DISALLOWED_BLOCKS = Arrays.asList("\"minecraft:wheat\"", "\"minecraft:fire\"", "\"minecraft:redstone_wire\"");
|
||||||
|
@Comment({
|
||||||
|
"List of block properties that should be remapped if used in an edit. Entries should take the form",
|
||||||
|
"\"property_name[value1_old:value1_new,value2_old:value2_new]\". For example:",
|
||||||
|
" - \"waterlogged[true:false]\"",
|
||||||
|
" - \"age[7:4,6:4,5:4]\"",
|
||||||
|
" - \"extended[true:false]\""
|
||||||
|
})
|
||||||
|
public List<String> REMAP_PROPERTIES = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HISTORY {
|
public static class HISTORY {
|
||||||
@ -399,7 +432,7 @@ public class Settings extends Config {
|
|||||||
|
|
||||||
@Comment({
|
@Comment({
|
||||||
"[SAFE] Keep entities that are positioned in non-air blocks when editing an area",
|
"[SAFE] Keep entities that are positioned in non-air blocks when editing an area",
|
||||||
"Might cause client-side FPS lagg in some situations"
|
"Might cause client-side FPS lag in some situations"
|
||||||
})
|
})
|
||||||
public boolean KEEP_ENTITIES_IN_BLOCKS = false;
|
public boolean KEEP_ENTITIES_IN_BLOCKS = false;
|
||||||
|
|
||||||
@ -607,6 +640,84 @@ public class Settings extends Config {
|
|||||||
limit.STRIP_NBT = Collections.emptySet();
|
limit.STRIP_NBT = Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
limit.UNIVERSAL_DISALLOWED_BLOCKS &= newLimit.UNIVERSAL_DISALLOWED_BLOCKS;
|
||||||
|
|
||||||
|
if (limit.DISALLOWED_BLOCKS == null) {
|
||||||
|
limit.DISALLOWED_BLOCKS = newLimit.DISALLOWED_BLOCKS.isEmpty() ? Collections.emptySet() : new HashSet<>(
|
||||||
|
newLimit.DISALLOWED_BLOCKS);
|
||||||
|
} else if (limit.DISALLOWED_BLOCKS.isEmpty() || newLimit.DISALLOWED_BLOCKS.isEmpty()) {
|
||||||
|
limit.DISALLOWED_BLOCKS = Collections.emptySet();
|
||||||
|
} else {
|
||||||
|
limit.DISALLOWED_BLOCKS = new HashSet<>(limit.DISALLOWED_BLOCKS);
|
||||||
|
limit.DISALLOWED_BLOCKS.retainAll(newLimit.DISALLOWED_BLOCKS
|
||||||
|
.stream()
|
||||||
|
.map(s -> s.contains(":") ? s.toLowerCase(Locale.ROOT) : ("minecraft:" + s).toLowerCase(Locale.ROOT))
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
if (limit.DISALLOWED_BLOCKS.isEmpty()) {
|
||||||
|
limit.DISALLOWED_BLOCKS = Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit.REMAP_PROPERTIES == null) {
|
||||||
|
limit.REMAP_PROPERTIES = newLimit.REMAP_PROPERTIES.isEmpty() ? Collections.emptySet() :
|
||||||
|
newLimit.REMAP_PROPERTIES.stream().flatMap(s -> {
|
||||||
|
String propertyStr = s.substring(0, s.indexOf('['));
|
||||||
|
List<Property<?>> properties =
|
||||||
|
BlockTypesCache.getAllProperties().get(propertyStr.toLowerCase(Locale.ROOT));
|
||||||
|
if (properties == null || properties.isEmpty()) {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
String[] mappings = s.substring(s.indexOf('[') + 1, s.indexOf(']')).split(",");
|
||||||
|
Set<PropertyRemap<?>> remaps = new HashSet<>();
|
||||||
|
for (Property<?> property : properties) {
|
||||||
|
for (String mapping : mappings) {
|
||||||
|
try {
|
||||||
|
String[] fromTo = mapping.split(":");
|
||||||
|
remaps.add(property.getRemap(
|
||||||
|
property.getValueFor(fromTo[0]),
|
||||||
|
property.getValueFor(fromTo[1])
|
||||||
|
));
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
// This property is unlikely to be the one being targeted.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaps.stream();
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
} else if (limit.REMAP_PROPERTIES.isEmpty() || newLimit.REMAP_PROPERTIES.isEmpty()) {
|
||||||
|
limit.REMAP_PROPERTIES = Collections.emptySet();
|
||||||
|
} else {
|
||||||
|
limit.REMAP_PROPERTIES = new HashSet<>(limit.REMAP_PROPERTIES);
|
||||||
|
limit.REMAP_PROPERTIES.retainAll(newLimit.REMAP_PROPERTIES.stream().flatMap(s -> {
|
||||||
|
String propertyStr = s.substring(0, s.indexOf('['));
|
||||||
|
List<Property<?>> properties =
|
||||||
|
BlockTypesCache.getAllProperties().get(propertyStr.toLowerCase(Locale.ROOT));
|
||||||
|
if (properties == null || properties.isEmpty()) {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
String[] mappings = s.substring(s.indexOf('[') + 1, s.indexOf(']')).split(",");
|
||||||
|
Set<PropertyRemap<?>> remaps = new HashSet<>();
|
||||||
|
for (Property<?> property : properties) {
|
||||||
|
for (String mapping : mappings) {
|
||||||
|
try {
|
||||||
|
String[] fromTo = mapping.split(":");
|
||||||
|
remaps.add(property.getRemap(
|
||||||
|
property.getValueFor(fromTo[0]),
|
||||||
|
property.getValueFor(fromTo[1])
|
||||||
|
));
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
// This property is unlikely to be the one being targeted.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaps.stream();
|
||||||
|
}).collect(Collectors.toSet()));
|
||||||
|
if (limit.REMAP_PROPERTIES.isEmpty()) {
|
||||||
|
limit.REMAP_PROPERTIES = Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return limit;
|
return limit;
|
||||||
|
@ -0,0 +1,188 @@
|
|||||||
|
package com.fastasyncworldedit.core.extent;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
|
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||||
|
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.util.ExtentTraverser;
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser;
|
||||||
|
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
import com.sk89q.worldedit.world.block.FuzzyBlockState;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.sk89q.worldedit.world.block.BlockTypesCache.states;
|
||||||
|
|
||||||
|
public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor {
|
||||||
|
|
||||||
|
private static final BlockState RESERVED = BlockTypes.__RESERVED__.getDefaultState();
|
||||||
|
private final Set<PropertyRemap<?>> remaps;
|
||||||
|
private Set<FuzzyBlockState> blockedStates = null;
|
||||||
|
private Set<String> blockedBlocks = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param extent the extent
|
||||||
|
* @param blockedBlocks block types to disallow
|
||||||
|
* @param remaps property remaps to apply, e.g. waterlogged true -> false
|
||||||
|
*/
|
||||||
|
public DisallowedBlocksExtent(Extent extent, Set<String> blockedBlocks, Set<PropertyRemap<?>> remaps) {
|
||||||
|
super(extent);
|
||||||
|
this.remaps = remaps;
|
||||||
|
if (blockedBlocks != null && !blockedBlocks.isEmpty()) {
|
||||||
|
blockedBlocks = blockedBlocks.stream()
|
||||||
|
.map(s -> s.contains(":") ? s.toLowerCase(Locale.ROOT) : ("minecraft:" + s).toLowerCase(Locale.ROOT))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
this.blockedBlocks = new HashSet<>();
|
||||||
|
for (String block : blockedBlocks) {
|
||||||
|
if (block.indexOf('[') == -1 || block.indexOf(']') == -1) {
|
||||||
|
blockedBlocks.add(block);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] properties = block.substring(block.indexOf('[') + 1, block.indexOf(']')).split(",");
|
||||||
|
if (properties.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BlockType type = BlockTypes.get(block.substring(0, block.indexOf('[')));
|
||||||
|
Map<Property<?>, Object> values =
|
||||||
|
DefaultBlockParser.parseProperties(type, properties, null, true);
|
||||||
|
if (values == null || values.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (blockedStates == null) {
|
||||||
|
blockedStates = new HashSet<>();
|
||||||
|
}
|
||||||
|
blockedStates.add(new FuzzyBlockState(type.getDefaultState(), values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||||
|
if (block instanceof BaseBlock || block instanceof BlockState) {
|
||||||
|
B newBlock = checkBlock(block);
|
||||||
|
if (newBlock.getBlockType() == BlockTypes.__RESERVED__) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.setBlock(location, newBlock);
|
||||||
|
}
|
||||||
|
return super.setBlock(location, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException {
|
||||||
|
if (block instanceof BaseBlock || block instanceof BlockState) {
|
||||||
|
B newBlock = checkBlock(block);
|
||||||
|
if (newBlock.getBlockType() == BlockTypes.__RESERVED__) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.setBlock(x, y, z, newBlock);
|
||||||
|
}
|
||||||
|
return super.setBlock(x, y, z, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <B extends BlockStateHolder<B>> B checkBlock(B block) {
|
||||||
|
if (blockedBlocks != null) {
|
||||||
|
if (blockedBlocks.contains(block.getBlockType().getId())) {
|
||||||
|
return (B) (block instanceof BlockState ? RESERVED : RESERVED.toBaseBlock()); // set to reserved/empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockedStates == null) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
for (FuzzyBlockState state : blockedStates) {
|
||||||
|
if (state.equalsFuzzy(block)) {
|
||||||
|
return (B) (block instanceof BlockState ? RESERVED : RESERVED.toBaseBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remaps == null || remaps.isEmpty()) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
for (PropertyRemap<?> remap : remaps) {
|
||||||
|
block = remap.apply(block);
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
||||||
|
if (blockedStates == null && blockedBlocks == null) { // Shouldn't be possible, but make sure
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
for (int layer = set.getMinSectionPosition(); layer <= set.getMaxSectionPosition(); layer++) {
|
||||||
|
if (!set.hasSection(layer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] blocks = Objects.requireNonNull(set.loadIfPresent(layer));
|
||||||
|
it:
|
||||||
|
for (int i = 0; i < blocks.length; i++) {
|
||||||
|
char block = blocks[i];
|
||||||
|
BlockState state = states[block];
|
||||||
|
if (blockedBlocks != null) {
|
||||||
|
if (blockedBlocks.contains(state.getBlockType().getId())) {
|
||||||
|
blocks[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockedStates == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (FuzzyBlockState fuzzy : blockedStates) {
|
||||||
|
if (fuzzy.equalsFuzzy(state)) {
|
||||||
|
blocks[i] = 0;
|
||||||
|
continue it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remaps == null || remaps.isEmpty()) {
|
||||||
|
blocks[i] = block;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (PropertyRemap<?> remap : remaps) {
|
||||||
|
state = remap.apply(state);
|
||||||
|
}
|
||||||
|
blocks[i] = state.getOrdinalChar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<IChunkSet> postProcessSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
||||||
|
return CompletableFuture.completedFuture(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Extent construct(final Extent child) {
|
||||||
|
if (getExtent() != child) {
|
||||||
|
new ExtentTraverser<Extent>(this).setNext(child);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorScope getScope() {
|
||||||
|
return ProcessorScope.CHANGING_BLOCKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extent;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||||
import com.fastasyncworldedit.core.util.WEManager;
|
import com.fastasyncworldedit.core.util.WEManager;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.fastasyncworldedit.core.extent;
|
package com.fastasyncworldedit.core.extent;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
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;
|
||||||
|
@ -4,7 +4,7 @@ import com.fastasyncworldedit.core.extent.filter.block.ExtentFilterBlock;
|
|||||||
import com.fastasyncworldedit.core.function.generator.GenBase;
|
import com.fastasyncworldedit.core.function.generator.GenBase;
|
||||||
import com.fastasyncworldedit.core.function.generator.Resource;
|
import com.fastasyncworldedit.core.function.generator.Resource;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.Filter;
|
import com.fastasyncworldedit.core.queue.Filter;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.fastasyncworldedit.core.extent;
|
package com.fastasyncworldedit.core.extent;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
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;
|
||||||
|
@ -5,7 +5,7 @@ import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
|||||||
import com.fastasyncworldedit.core.function.generator.GenBase;
|
import com.fastasyncworldedit.core.function.generator.GenBase;
|
||||||
import com.fastasyncworldedit.core.function.generator.Resource;
|
import com.fastasyncworldedit.core.function.generator.Resource;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
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;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.fastasyncworldedit.core.extent;
|
package com.fastasyncworldedit.core.extent;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.WEManager;
|
import com.fastasyncworldedit.core.util.WEManager;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.fastasyncworldedit.core.extent;
|
package com.fastasyncworldedit.core.extent;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
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;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.fastasyncworldedit.core.object;
|
package com.fastasyncworldedit.core.limit;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
|
|
||||||
@ -21,6 +21,9 @@ public class FaweLimit {
|
|||||||
public boolean CONFIRM_LARGE = true;
|
public boolean CONFIRM_LARGE = true;
|
||||||
public boolean RESTRICT_HISTORY_TO_REGIONS = true;
|
public boolean RESTRICT_HISTORY_TO_REGIONS = true;
|
||||||
public Set<String> STRIP_NBT = null;
|
public Set<String> STRIP_NBT = null;
|
||||||
|
public boolean UNIVERSAL_DISALLOWED_BLOCKS = true;
|
||||||
|
public Set<String> DISALLOWED_BLOCKS = null;
|
||||||
|
public Set<PropertyRemap<?>> REMAP_PROPERTIES = null;
|
||||||
|
|
||||||
public static FaweLimit MAX;
|
public static FaweLimit MAX;
|
||||||
|
|
||||||
@ -112,6 +115,9 @@ public class FaweLimit {
|
|||||||
MAX.CONFIRM_LARGE = true;
|
MAX.CONFIRM_LARGE = true;
|
||||||
MAX.RESTRICT_HISTORY_TO_REGIONS = false;
|
MAX.RESTRICT_HISTORY_TO_REGIONS = false;
|
||||||
MAX.STRIP_NBT = null;
|
MAX.STRIP_NBT = null;
|
||||||
|
MAX.UNIVERSAL_DISALLOWED_BLOCKS = false;
|
||||||
|
MAX.DISALLOWED_BLOCKS = null;
|
||||||
|
MAX.REMAP_PROPERTIES = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean MAX_CHANGES() {
|
public boolean MAX_CHANGES() {
|
||||||
@ -234,7 +240,10 @@ public class FaweLimit {
|
|||||||
&& SPEED_REDUCTION == 0
|
&& SPEED_REDUCTION == 0
|
||||||
&& FAST_PLACEMENT
|
&& FAST_PLACEMENT
|
||||||
&& !RESTRICT_HISTORY_TO_REGIONS
|
&& !RESTRICT_HISTORY_TO_REGIONS
|
||||||
&& (STRIP_NBT == null || STRIP_NBT.isEmpty());
|
&& (STRIP_NBT == null || STRIP_NBT.isEmpty())
|
||||||
|
&& !UNIVERSAL_DISALLOWED_BLOCKS
|
||||||
|
&& (DISALLOWED_BLOCKS == null || DISALLOWED_BLOCKS.isEmpty())
|
||||||
|
&& (REMAP_PROPERTIES == null || REMAP_PROPERTIES.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(FaweLimit limit) {
|
public void set(FaweLimit limit) {
|
||||||
@ -252,6 +261,9 @@ public class FaweLimit {
|
|||||||
CONFIRM_LARGE = limit.CONFIRM_LARGE;
|
CONFIRM_LARGE = limit.CONFIRM_LARGE;
|
||||||
RESTRICT_HISTORY_TO_REGIONS = limit.RESTRICT_HISTORY_TO_REGIONS;
|
RESTRICT_HISTORY_TO_REGIONS = limit.RESTRICT_HISTORY_TO_REGIONS;
|
||||||
STRIP_NBT = limit.STRIP_NBT;
|
STRIP_NBT = limit.STRIP_NBT;
|
||||||
|
UNIVERSAL_DISALLOWED_BLOCKS = limit.UNIVERSAL_DISALLOWED_BLOCKS;
|
||||||
|
DISALLOWED_BLOCKS = limit.DISALLOWED_BLOCKS;
|
||||||
|
REMAP_PROPERTIES = limit.REMAP_PROPERTIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FaweLimit copy() {
|
public FaweLimit copy() {
|
||||||
@ -270,6 +282,9 @@ public class FaweLimit {
|
|||||||
limit.CONFIRM_LARGE = CONFIRM_LARGE;
|
limit.CONFIRM_LARGE = CONFIRM_LARGE;
|
||||||
limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS;
|
limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS;
|
||||||
limit.STRIP_NBT = STRIP_NBT;
|
limit.STRIP_NBT = STRIP_NBT;
|
||||||
|
limit.UNIVERSAL_DISALLOWED_BLOCKS = UNIVERSAL_DISALLOWED_BLOCKS;
|
||||||
|
limit.DISALLOWED_BLOCKS = DISALLOWED_BLOCKS;
|
||||||
|
limit.REMAP_PROPERTIES = REMAP_PROPERTIES;
|
||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.fastasyncworldedit.core.limit;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
|
|
||||||
|
public class PropertyRemap<T> {
|
||||||
|
|
||||||
|
private final Property<T> property;
|
||||||
|
private final T oldValue;
|
||||||
|
private final T newValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New instance
|
||||||
|
*
|
||||||
|
* @param property property to remap values for
|
||||||
|
* @param oldValue value to remap from
|
||||||
|
* @param newValue value to remap to
|
||||||
|
*/
|
||||||
|
public PropertyRemap(Property<T> property, T oldValue, T newValue) {
|
||||||
|
this.property = property;
|
||||||
|
this.oldValue = oldValue;
|
||||||
|
this.newValue = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply remapping to a state. Will return original state if property is not present.
|
||||||
|
*
|
||||||
|
* @param state Block to apply remapping to
|
||||||
|
* @return new state
|
||||||
|
*/
|
||||||
|
public <B extends BlockStateHolder<B>> B apply(B state) {
|
||||||
|
if (!state.getBlockType().hasProperty(property.getKey())) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
T current = state.getState(property);
|
||||||
|
if (current == oldValue) {
|
||||||
|
state = state.with(property.getKey(), newValue);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply remapping to a given value if the given block type has the property associated with this remap instance.
|
||||||
|
*
|
||||||
|
* @param type block type to check
|
||||||
|
* @param value value to remap
|
||||||
|
* @return new value
|
||||||
|
*/
|
||||||
|
public T apply(BlockType type, T value) {
|
||||||
|
if (type.hasProperty(property.getKey())) {
|
||||||
|
return value == oldValue ? newValue : value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,7 +23,7 @@ import com.fastasyncworldedit.core.history.RollbackOptimizedHistory;
|
|||||||
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
|
||||||
import com.fastasyncworldedit.core.history.changeset.BlockBagChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.BlockBagChangeSet;
|
||||||
import com.fastasyncworldedit.core.history.changeset.NullChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.NullChangeSet;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||||
|
@ -50,7 +50,7 @@ import com.fastasyncworldedit.core.math.MutableBlockVector2;
|
|||||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||||
import com.fastasyncworldedit.core.math.MutableVector3;
|
import com.fastasyncworldedit.core.math.MutableVector3;
|
||||||
import com.fastasyncworldedit.core.math.random.SimplexNoise;
|
import com.fastasyncworldedit.core.math.random.SimplexNoise;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.preloader.Preloader;
|
import com.fastasyncworldedit.core.queue.implementation.preloader.Preloader;
|
||||||
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
||||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||||
|
@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.Fawe;
|
|||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
import com.fastasyncworldedit.core.extent.DisallowedBlocksExtent;
|
||||||
import com.fastasyncworldedit.core.extent.FaweRegionExtent;
|
import com.fastasyncworldedit.core.extent.FaweRegionExtent;
|
||||||
import com.fastasyncworldedit.core.extent.HistoryExtent;
|
import com.fastasyncworldedit.core.extent.HistoryExtent;
|
||||||
import com.fastasyncworldedit.core.extent.LimitExtent;
|
import com.fastasyncworldedit.core.extent.LimitExtent;
|
||||||
@ -42,7 +43,8 @@ import com.fastasyncworldedit.core.history.RollbackOptimizedHistory;
|
|||||||
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
|
||||||
import com.fastasyncworldedit.core.history.changeset.BlockBagChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.BlockBagChangeSet;
|
||||||
import com.fastasyncworldedit.core.history.changeset.NullChangeSet;
|
import com.fastasyncworldedit.core.history.changeset.NullChangeSet;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
|
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||||
@ -68,7 +70,9 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -551,6 +555,23 @@ public final class EditSessionBuilder {
|
|||||||
this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
|
this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.limit != null && !this.limit.isUnlimited()) {
|
||||||
|
Set<String> limitBlocks = new HashSet<>();
|
||||||
|
if ((getActor() == null || getActor().hasPermission("worldedit.anyblock") && this.limit.UNIVERSAL_DISALLOWED_BLOCKS)) {
|
||||||
|
limitBlocks.addAll(WorldEdit.getInstance().getConfiguration().disallowedBlocks);
|
||||||
|
}
|
||||||
|
if (this.limit.DISALLOWED_BLOCKS != null && !this.limit.DISALLOWED_BLOCKS.isEmpty()) {
|
||||||
|
limitBlocks.addAll(this.limit.DISALLOWED_BLOCKS);
|
||||||
|
}
|
||||||
|
Set<PropertyRemap<?>> remaps = this.limit.REMAP_PROPERTIES;
|
||||||
|
if (!limitBlocks.isEmpty() || (remaps != null && !remaps.isEmpty())) {
|
||||||
|
if (placeChunks) {
|
||||||
|
extent.addProcessor(new DisallowedBlocksExtent(this.extent, limitBlocks, remaps));
|
||||||
|
} else {
|
||||||
|
this.extent = new DisallowedBlocksExtent(this.extent, limitBlocks, remaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY);
|
this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -27,7 +27,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
|||||||
import com.fastasyncworldedit.core.history.DiskStorageHistory;
|
import com.fastasyncworldedit.core.history.DiskStorageHistory;
|
||||||
import com.fastasyncworldedit.core.internal.io.FaweInputStream;
|
import com.fastasyncworldedit.core.internal.io.FaweInputStream;
|
||||||
import com.fastasyncworldedit.core.internal.io.FaweOutputStream;
|
import com.fastasyncworldedit.core.internal.io.FaweOutputStream;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.BrushCache;
|
import com.fastasyncworldedit.core.util.BrushCache;
|
||||||
import com.fastasyncworldedit.core.util.MainUtil;
|
import com.fastasyncworldedit.core.util.MainUtil;
|
||||||
import com.fastasyncworldedit.core.util.StringMan;
|
import com.fastasyncworldedit.core.util.StringMan;
|
||||||
|
@ -54,7 +54,7 @@ import com.fastasyncworldedit.core.function.mask.IdMask;
|
|||||||
import com.fastasyncworldedit.core.function.mask.SingleBlockTypeMask;
|
import com.fastasyncworldedit.core.function.mask.SingleBlockTypeMask;
|
||||||
import com.fastasyncworldedit.core.math.heightmap.ScalableHeightMap;
|
import com.fastasyncworldedit.core.math.heightmap.ScalableHeightMap;
|
||||||
import com.fastasyncworldedit.core.math.heightmap.ScalableHeightMap.Shape;
|
import com.fastasyncworldedit.core.math.heightmap.ScalableHeightMap.Shape;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.MainUtil;
|
import com.fastasyncworldedit.core.util.MainUtil;
|
||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.fastasyncworldedit.core.util.StringMan;
|
import com.fastasyncworldedit.core.util.StringMan;
|
||||||
|
@ -29,7 +29,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
|||||||
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
|
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
||||||
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
|
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.ImgurUtility;
|
import com.fastasyncworldedit.core.util.ImgurUtility;
|
||||||
import com.fastasyncworldedit.core.util.MainUtil;
|
import com.fastasyncworldedit.core.util.MainUtil;
|
||||||
import com.fastasyncworldedit.core.util.MaskTraverser;
|
import com.fastasyncworldedit.core.util.MaskTraverser;
|
||||||
@ -45,7 +45,6 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
|||||||
import com.sk89q.worldedit.command.util.Logging;
|
import com.sk89q.worldedit.command.util.Logging;
|
||||||
import com.sk89q.worldedit.command.util.annotation.Confirm;
|
import com.sk89q.worldedit.command.util.annotation.Confirm;
|
||||||
import com.sk89q.worldedit.command.util.annotation.Preload;
|
import com.sk89q.worldedit.command.util.annotation.Preload;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
|
@ -23,7 +23,7 @@ import com.fastasyncworldedit.core.FaweAPI;
|
|||||||
import com.fastasyncworldedit.core.FaweCache;
|
import com.fastasyncworldedit.core.FaweCache;
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.MaskTraverser;
|
import com.fastasyncworldedit.core.util.MaskTraverser;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
@ -23,6 +23,8 @@ import com.fastasyncworldedit.core.configuration.Caption;
|
|||||||
import com.fastasyncworldedit.core.extent.inventory.SlottableBlockBag;
|
import com.fastasyncworldedit.core.extent.inventory.SlottableBlockBag;
|
||||||
import com.fastasyncworldedit.core.jnbt.JSON2NBT;
|
import com.fastasyncworldedit.core.jnbt.JSON2NBT;
|
||||||
import com.fastasyncworldedit.core.jnbt.NBTException;
|
import com.fastasyncworldedit.core.jnbt.NBTException;
|
||||||
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
|
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.fastasyncworldedit.core.util.StringMan;
|
import com.fastasyncworldedit.core.util.StringMan;
|
||||||
import com.fastasyncworldedit.core.world.block.BlanketBaseBlock;
|
import com.fastasyncworldedit.core.world.block.BlanketBaseBlock;
|
||||||
@ -66,6 +68,8 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,19 +175,57 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<Property<?>, Object> parseProperties(
|
//FAWE start - make public
|
||||||
|
public static Map<Property<?>, Object> parseProperties(
|
||||||
|
//FAWE end
|
||||||
BlockType type,
|
BlockType type,
|
||||||
String[] stateProperties,
|
String[] stateProperties,
|
||||||
ParserContext context
|
ParserContext context,
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
boolean nullNotError
|
||||||
|
//FAWE end
|
||||||
) throws NoMatchException {
|
) throws NoMatchException {
|
||||||
Map<Property<?>, Object> blockStates = new HashMap<>();
|
Map<Property<?>, Object> blockStates = new HashMap<>();
|
||||||
|
|
||||||
|
//FAWE start - disallowed states
|
||||||
|
if (context != null && context.getActor() != null && !context.getActor().getLimit().isUnlimited()) {
|
||||||
|
for (String input : context.getActor().getLimit().DISALLOWED_BLOCKS) {
|
||||||
|
if (input.indexOf('[') == -1 && input.indexOf(']') == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!type.getId().equalsIgnoreCase(input.substring(0, input.indexOf('[')))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] properties = input.substring(input.indexOf('[') + 1, input.indexOf(']')).split(",");
|
||||||
|
Set<String> blocked = Arrays.stream(properties).filter(s -> {
|
||||||
|
for (String in : stateProperties) {
|
||||||
|
if (in.equalsIgnoreCase(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).collect(Collectors.toSet());
|
||||||
|
if (!blocked.isEmpty()) {
|
||||||
|
throw new DisallowedUsageException(Caption.of(
|
||||||
|
"fawe.error.limit.disallowed-block",
|
||||||
|
TextComponent.of(input)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
if (stateProperties.length > 0) { // Block data not yet detected
|
if (stateProperties.length > 0) { // Block data not yet detected
|
||||||
// Parse the block data (optional)
|
// Parse the block data (optional)
|
||||||
for (String parseableData : stateProperties) {
|
for (String parseableData : stateProperties) {
|
||||||
try {
|
try {
|
||||||
String[] parts = parseableData.split("=");
|
String[] parts = parseableData.split("=");
|
||||||
if (parts.length != 2) {
|
if (parts.length != 2) {
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
if (nullNotError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
throw new InputParseException(
|
throw new InputParseException(
|
||||||
Caption.of(
|
Caption.of(
|
||||||
"worldedit.error.parser.bad-state-format",
|
"worldedit.error.parser.bad-state-format",
|
||||||
@ -195,7 +237,14 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Property<Object> propertyKey = (Property<Object>) type.getPropertyMap().get(parts[0]);
|
Property<Object> propertyKey = (Property<Object>) type.getPropertyMap().get(parts[0]);
|
||||||
if (propertyKey == null) {
|
if (propertyKey == null) {
|
||||||
if (context.getActor() != null) {
|
//FAWE start - nullable context
|
||||||
|
if (context != null && context.getActor() != null) {
|
||||||
|
//FAWE end
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
if (nullNotError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
throw new NoMatchException(Caption.of(
|
throw new NoMatchException(Caption.of(
|
||||||
"worldedit.error.parser.unknown-property",
|
"worldedit.error.parser.unknown-property",
|
||||||
TextComponent.of(parts[0]),
|
TextComponent.of(parts[0]),
|
||||||
@ -207,6 +256,11 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
return Maps.newHashMap();
|
return Maps.newHashMap();
|
||||||
}
|
}
|
||||||
if (blockStates.containsKey(propertyKey)) {
|
if (blockStates.containsKey(propertyKey)) {
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
if (nullNotError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
throw new InputParseException(Caption.of(
|
throw new InputParseException(Caption.of(
|
||||||
"worldedit.error.parser.duplicate-property",
|
"worldedit.error.parser.duplicate-property",
|
||||||
TextComponent.of(parts[0])
|
TextComponent.of(parts[0])
|
||||||
@ -216,6 +270,11 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
try {
|
try {
|
||||||
value = propertyKey.getValueFor(parts[1]);
|
value = propertyKey.getValueFor(parts[1]);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
if (nullNotError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
throw new NoMatchException(Caption.of(
|
throw new NoMatchException(Caption.of(
|
||||||
"worldedit.error.parser.unknown-value",
|
"worldedit.error.parser.unknown-value",
|
||||||
TextComponent.of(parts[1]),
|
TextComponent.of(parts[1]),
|
||||||
@ -223,10 +282,30 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start - blocked states
|
||||||
|
if (context != null && context.getActor() != null && !context.getActor().getLimit().isUnlimited()) {
|
||||||
|
if (context.getActor().getLimit().REMAP_PROPERTIES != null
|
||||||
|
&& !context.getActor().getLimit().REMAP_PROPERTIES.isEmpty()) {
|
||||||
|
for (PropertyRemap remap : context.getActor().getLimit().REMAP_PROPERTIES) {
|
||||||
|
Object newValue = remap.apply(type, value);
|
||||||
|
if (newValue != value) {
|
||||||
|
value = newValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
blockStates.put(propertyKey, value);
|
blockStates.put(propertyKey, value);
|
||||||
} catch (NoMatchException e) {
|
} catch (NoMatchException | DisallowedUsageException e) {
|
||||||
throw e; // Pass-through
|
throw e; // Pass-through
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
//FAWE start - if null should be returned instead of throwing an error
|
||||||
|
if (nullNotError) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
throw new InputParseException(Caption.of(
|
throw new InputParseException(Caption.of(
|
||||||
"worldedit.error.parser.bad-state-format",
|
"worldedit.error.parser.bad-state-format",
|
||||||
TextComponent.of(parseableData)
|
TextComponent.of(parseableData)
|
||||||
@ -387,7 +466,9 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
blockStates.putAll(parseProperties(state.getBlockType(), stateProperties, context));
|
//FAWE start - Not null if nullNotError false.
|
||||||
|
blockStates.putAll(parseProperties(state.getBlockType(), stateProperties, context, false));
|
||||||
|
//FAWE end
|
||||||
if (context.isPreferringWildcard()) {
|
if (context.isPreferringWildcard()) {
|
||||||
if (stateString == null || stateString.isEmpty()) {
|
if (stateString == null || stateString.isEmpty()) {
|
||||||
state = new FuzzyBlockState(state);
|
state = new FuzzyBlockState(state);
|
||||||
@ -428,10 +509,23 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
|||||||
|
|
||||||
if (context.isRestricted()) {
|
if (context.isRestricted()) {
|
||||||
Actor actor = context.requireActor();
|
Actor actor = context.requireActor();
|
||||||
if (actor != null && !actor.hasPermission("worldedit.anyblock")
|
//FAWE start - per-limit disallowed blocks
|
||||||
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) {
|
if (actor != null) {
|
||||||
throw new DisallowedUsageException(Caption.of("worldedit.error.disallowed-block", TextComponent.of(input)));
|
if (!actor.hasPermission("worldedit.anyblock")
|
||||||
|
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId().toLowerCase(Locale.ROOT))) {
|
||||||
|
throw new DisallowedUsageException(Caption.of("worldedit.error.disallowed-block", TextComponent.of(blockType.getId())));
|
||||||
|
}
|
||||||
|
FaweLimit limit = actor.getLimit();
|
||||||
|
if (!limit.isUnlimited()) {
|
||||||
|
// No need to account for blocked states/properties as it will simply return false in the equality check
|
||||||
|
// during contains.
|
||||||
|
if (limit.DISALLOWED_BLOCKS.contains(blockType.getId().toLowerCase(Locale.ROOT))) {
|
||||||
|
throw new DisallowedUsageException(Caption.of("fawe.error.limit.disallowed-block",
|
||||||
|
TextComponent.of(blockType.getId())));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
|
@ -22,7 +22,7 @@ package com.sk89q.worldedit.extension.platform;
|
|||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
import com.fastasyncworldedit.core.entity.MapMetadatable;
|
import com.fastasyncworldedit.core.entity.MapMetadatable;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.task.InterruptableCondition;
|
import com.fastasyncworldedit.core.util.task.InterruptableCondition;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
|
@ -22,7 +22,7 @@ package com.sk89q.worldedit.regions;
|
|||||||
import com.fastasyncworldedit.core.extent.SingleRegionExtent;
|
import com.fastasyncworldedit.core.extent.SingleRegionExtent;
|
||||||
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
import com.fastasyncworldedit.core.object.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.queue.Filter;
|
import com.fastasyncworldedit.core.queue.Filter;
|
||||||
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
import com.fastasyncworldedit.core.queue.IBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.queue.IChunk;
|
import com.fastasyncworldedit.core.queue.IChunk;
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.registry.state;
|
package com.sk89q.worldedit.registry.state;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||||
import com.fastasyncworldedit.core.registry.state.PropertyKey;
|
import com.fastasyncworldedit.core.registry.state.PropertyKey;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a state property of a block.
|
* Describes a state property of a block.
|
||||||
@ -57,16 +59,45 @@ public interface Property<T> {
|
|||||||
T getValueFor(String string) throws IllegalArgumentException;
|
T getValueFor(String string) throws IllegalArgumentException;
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of the given value in the list of values
|
||||||
|
*
|
||||||
|
* @param value value to get index for
|
||||||
|
* @throws IllegalArgumentException if value not applicable to this property
|
||||||
|
*/
|
||||||
default int getIndex(T value) {
|
default int getIndex(T value) {
|
||||||
return getValues().indexOf(value);
|
return getValues().indexOf(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
default int getIndexFor(CharSequence string) throws IllegalArgumentException {
|
/**
|
||||||
return getIndex(getValueFor(string.toString()));
|
* Get the index of the given value in the list of values
|
||||||
|
*
|
||||||
|
* @param value value to get index for
|
||||||
|
* @throws IllegalArgumentException if value not applicable to this property
|
||||||
|
*/
|
||||||
|
default int getIndexFor(CharSequence value) throws IllegalArgumentException {
|
||||||
|
return getIndex(getValueFor(value.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link PropertyKey} associated with this property.
|
||||||
|
*/
|
||||||
default PropertyKey getKey() {
|
default PropertyKey getKey() {
|
||||||
return PropertyKey.getOrCreate(getName());
|
return PropertyKey.getOrCreate(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a {@link PropertyRemap} instance for this property with the given remap.
|
||||||
|
*
|
||||||
|
* @param from value to remap from
|
||||||
|
* @param to value to remap to
|
||||||
|
* @return new {@link PropertyRemap} instance
|
||||||
|
*/
|
||||||
|
default PropertyRemap<T> getRemap(Object from, Object to) {
|
||||||
|
Objects.requireNonNull(from);
|
||||||
|
Objects.requireNonNull(to);
|
||||||
|
return new PropertyRemap<T>(this, (T) from, (T) to);
|
||||||
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple LocalConfiguration that loads settings using
|
* Simple LocalConfiguration that loads settings using
|
||||||
@ -92,7 +93,10 @@ public class PropertiesConfiguration extends LocalConfiguration {
|
|||||||
|
|
||||||
profile = getBool("profile", profile);
|
profile = getBool("profile", profile);
|
||||||
traceUnflushedSessions = getBool("trace-unflushed-sessions", traceUnflushedSessions);
|
traceUnflushedSessions = getBool("trace-unflushed-sessions", traceUnflushedSessions);
|
||||||
disallowedBlocks = getStringSet("disallowed-blocks", getDefaultDisallowedBlocks());
|
disallowedBlocks = getStringSet("disallowed-blocks", getDefaultDisallowedBlocks())
|
||||||
|
.stream()
|
||||||
|
.map(s -> s.contains(":") ? s.toLowerCase(Locale.ROOT) : ("minecraft:" + s).toLowerCase(Locale.ROOT))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit);
|
defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit);
|
||||||
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
||||||
defaultVerticalHeight = getInt("default-vertical-height", defaultVerticalHeight);
|
defaultVerticalHeight = getInt("default-vertical-height", defaultVerticalHeight);
|
||||||
|
@ -30,6 +30,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A less simple implementation of {@link LocalConfiguration}
|
* A less simple implementation of {@link LocalConfiguration}
|
||||||
@ -94,10 +95,10 @@ public class YAMLConfiguration extends LocalConfiguration {
|
|||||||
butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius));
|
butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius));
|
||||||
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
||||||
|
|
||||||
disallowedBlocks = new HashSet<>(config.getStringList(
|
disallowedBlocks = config.getStringList("limits.disallowed-blocks", Lists.newArrayList(getDefaultDisallowedBlocks()))
|
||||||
"limits.disallowed-blocks",
|
.stream()
|
||||||
Lists.newArrayList(getDefaultDisallowedBlocks())
|
.map(s -> s.contains(":") ? s.toLowerCase(Locale.ROOT) : ("minecraft:" + s).toLowerCase(Locale.ROOT))
|
||||||
));
|
.collect(Collectors.toSet());
|
||||||
allowedDataCycleBlocks = new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null));
|
allowedDataCycleBlocks = new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null));
|
||||||
|
|
||||||
registerHelp = config.getBoolean("register-help", true);
|
registerHelp = config.getBoolean("register-help", true);
|
||||||
|
@ -152,8 +152,8 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
String input = key.toString();
|
String input = key.toString();
|
||||||
throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(
|
throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(
|
||||||
BlockTypesCache.values)
|
BlockTypesCache.values)
|
||||||
.filter(b -> StringMan.blockStateMatches(input, b.getId()))
|
|
||||||
.map(BlockType::getId)
|
.map(BlockType::getId)
|
||||||
|
.filter(id -> StringMan.blockStateMatches(input, id))
|
||||||
.sorted(StringMan.blockStateComparator(input))
|
.sorted(StringMan.blockStateComparator(input))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
@ -163,7 +163,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
return type.getDefaultState();
|
return type.getDefaultState();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends Property> propList = type.getProperties();
|
List<? extends Property<?>> propList = type.getProperties();
|
||||||
|
|
||||||
if (state.charAt(state.length() - 1) != ']') {
|
if (state.charAt(state.length() - 1) != ']') {
|
||||||
state = state + "]";
|
state = state + "]";
|
||||||
@ -172,7 +172,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
charSequence.setString(state);
|
charSequence.setString(state);
|
||||||
|
|
||||||
if (propList.size() == 1) {
|
if (propList.size() == 1) {
|
||||||
AbstractProperty property = (AbstractProperty) propList.get(0);
|
AbstractProperty<?> property = (AbstractProperty<?>) propList.get(0);
|
||||||
String name = property.getName();
|
String name = property.getName();
|
||||||
|
|
||||||
charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1);
|
charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1);
|
||||||
@ -188,7 +188,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
stateId = type.getDefaultState().getInternalId();
|
stateId = type.getDefaultState().getInternalId();
|
||||||
}
|
}
|
||||||
int length = state.length();
|
int length = state.length();
|
||||||
AbstractProperty property = null;
|
AbstractProperty<?> property = null;
|
||||||
|
|
||||||
int last = propStrStart + 1;
|
int last = propStrStart + 1;
|
||||||
for (int i = last; i < length; i++) {
|
for (int i = last; i < length; i++) {
|
||||||
@ -200,7 +200,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
if (property != null) {
|
if (property != null) {
|
||||||
int index = property.getIndexFor(charSequence);
|
int index = property.getIndexFor(charSequence);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
throw SuggestInputParseException.of(charSequence.toString(), property.getValues());
|
throw SuggestInputParseException.of(charSequence.toString(), (List<Object>) property.getValues());
|
||||||
}
|
}
|
||||||
stateId = property.modifyIndex(stateId, index);
|
stateId = property.modifyIndex(stateId, index);
|
||||||
} else {
|
} else {
|
||||||
@ -288,7 +288,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
public <V> BlockState with(final Property<V> property, final V value) {
|
public <V> BlockState with(final Property<V> property, final V value) {
|
||||||
try {
|
try {
|
||||||
BlockType type = getBlockType();
|
BlockType type = getBlockType();
|
||||||
int newState = ((AbstractProperty) property).modify(this.getInternalId(), value);
|
int newState = ((AbstractProperty<V>) property).modify(this.getInternalId(), value);
|
||||||
return newState != this.getInternalId() ? type.withStateId(newState) : this;
|
return newState != this.getInternalId() ? type.withStateId(newState) : this;
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new IllegalArgumentException("Property not found: " + property);
|
throw new IllegalArgumentException("Property not found: " + property);
|
||||||
@ -298,7 +298,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
@Override
|
@Override
|
||||||
public <V> V getState(final Property<V> property) {
|
public <V> V getState(final Property<V> property) {
|
||||||
try {
|
try {
|
||||||
AbstractProperty ap = (AbstractProperty) property;
|
AbstractProperty<V> ap = (AbstractProperty<V>) property;
|
||||||
return (V) ap.getValue(this.getInternalId());
|
return (V) ap.getValue(this.getInternalId());
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new IllegalArgumentException("Property not found: " + property);
|
throw new IllegalArgumentException("Property not found: " + property);
|
||||||
@ -309,7 +309,11 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
public <V> BlockState with(final PropertyKey property, final V value) {
|
public <V> BlockState with(final PropertyKey property, final V value) {
|
||||||
try {
|
try {
|
||||||
BlockType type = getBlockType();
|
BlockType type = getBlockType();
|
||||||
int newState = ((AbstractProperty) type.getProperty(property)).modify(this.getInternalId(), value);
|
AbstractProperty<V> abstractProperty = ((AbstractProperty<V>) type.getProperty(property));
|
||||||
|
if (abstractProperty == null) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
int newState = abstractProperty.modify(this.getInternalId(), value);
|
||||||
return newState != this.getInternalId() ? type.withStateId(newState) : this;
|
return newState != this.getInternalId() ? type.withStateId(newState) : this;
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new IllegalArgumentException("Property not found: " + property);
|
throw new IllegalArgumentException("Property not found: " + property);
|
||||||
@ -340,7 +344,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
|||||||
//FAWE end
|
//FAWE end
|
||||||
BlockType type = this.getBlockType();
|
BlockType type = this.getBlockType();
|
||||||
// Lazily initialize the map
|
// Lazily initialize the map
|
||||||
Map<? extends Property, Object> map = Maps.asMap(type.getPropertiesSet(), (Function<Property, Object>) this::getState);
|
Map<? extends Property<?>, Object> map = Maps.asMap(type.getPropertiesSet(), (Function<Property<?>, Object>) this::getState);
|
||||||
//noinspection RedundantCast - This is required for compilation, etc.
|
//noinspection RedundantCast - This is required for compilation, etc.
|
||||||
return Collections.unmodifiableMap((Map<Property<?>, Object>) map);
|
return Collections.unmodifiableMap((Map<Property<?>, Object>) map);
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
@ -52,8 +52,8 @@ public class FuzzyBlockState extends BlockState {
|
|||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
private FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) {
|
//FAWE start - use internal ids, public constructor
|
||||||
//FAWE start - use internal ids
|
public FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) {
|
||||||
super(state.getBlockType(), state.getInternalId(), state.getOrdinal());
|
super(state.getBlockType(), state.getInternalId(), state.getOrdinal());
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
props = Collections.emptyMap();
|
props = Collections.emptyMap();
|
||||||
|
@ -148,6 +148,8 @@
|
|||||||
"fawe.error.clipboard.invalid.info": "File: {0} (len: {1})",
|
"fawe.error.clipboard.invalid.info": "File: {0} (len: {1})",
|
||||||
"fawe.error.clipboard.load.failure": "Could not load clipboard. Possible that the clipboard is still being written to from another server?!",
|
"fawe.error.clipboard.load.failure": "Could not load clipboard. Possible that the clipboard is still being written to from another server?!",
|
||||||
"fawe.error.clipboard.on.disk.version.mismatch": "Clipboard version mismatch. Please delete your clipboards folder and restart the server.",
|
"fawe.error.clipboard.on.disk.version.mismatch": "Clipboard version mismatch. Please delete your clipboards folder and restart the server.",
|
||||||
|
"fawe.error.limit.disallowed-block": "Your limit disallows use of block '{0}'",
|
||||||
|
"fawe.error.limit.disallowed-property": "Your limit disallows use of property '{0}'",
|
||||||
|
|
||||||
"fawe.cancel.count": "Cancelled {0} edits.",
|
"fawe.cancel.count": "Cancelled {0} edits.",
|
||||||
"fawe.cancel.reason.confirm": "Use //confirm to execute {0}",
|
"fawe.cancel.reason.confirm": "Use //confirm to execute {0}",
|
||||||
|
Loading…
Reference in New Issue
Block a user