Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-25 10:30:04 +01:00
Add configurable disallowed states for limits, global disallowed blocks (#1312)
Dieser Commit ist enthalten in:
Ursprung
d641e21dfc
Commit
6839fa5567
@ -1,13 +1,21 @@
|
||||
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.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
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 {
|
||||
|
||||
@ -192,7 +200,32 @@ public class Settings extends Config {
|
||||
"List of nbt tags to strip from blocks, e.g. Items",
|
||||
})
|
||||
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 {
|
||||
@ -399,7 +432,7 @@ public class Settings extends Config {
|
||||
|
||||
@Comment({
|
||||
"[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;
|
||||
|
||||
@ -607,6 +640,84 @@ public class Settings extends Config {
|
||||
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;
|
||||
|
@ -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.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.util.ExtentTraverser;
|
||||
import com.fastasyncworldedit.core.util.WEManager;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.IChunkGet;
|
||||
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.Resource;
|
||||
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.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.IChunkGet;
|
||||
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.Resource;
|
||||
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.IChunk;
|
||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.fastasyncworldedit.core.extent;
|
||||
|
||||
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.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.IChunkGet;
|
||||
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;
|
||||
|
||||
@ -21,6 +21,9 @@ public class FaweLimit {
|
||||
public boolean CONFIRM_LARGE = true;
|
||||
public boolean RESTRICT_HISTORY_TO_REGIONS = true;
|
||||
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;
|
||||
|
||||
@ -112,6 +115,9 @@ public class FaweLimit {
|
||||
MAX.CONFIRM_LARGE = true;
|
||||
MAX.RESTRICT_HISTORY_TO_REGIONS = false;
|
||||
MAX.STRIP_NBT = null;
|
||||
MAX.UNIVERSAL_DISALLOWED_BLOCKS = false;
|
||||
MAX.DISALLOWED_BLOCKS = null;
|
||||
MAX.REMAP_PROPERTIES = null;
|
||||
}
|
||||
|
||||
public boolean MAX_CHANGES() {
|
||||
@ -234,7 +240,10 @@ public class FaweLimit {
|
||||
&& SPEED_REDUCTION == 0
|
||||
&& FAST_PLACEMENT
|
||||
&& !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) {
|
||||
@ -252,6 +261,9 @@ public class FaweLimit {
|
||||
CONFIRM_LARGE = limit.CONFIRM_LARGE;
|
||||
RESTRICT_HISTORY_TO_REGIONS = limit.RESTRICT_HISTORY_TO_REGIONS;
|
||||
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() {
|
||||
@ -270,6 +282,9 @@ public class FaweLimit {
|
||||
limit.CONFIRM_LARGE = CONFIRM_LARGE;
|
||||
limit.RESTRICT_HISTORY_TO_REGIONS = RESTRICT_HISTORY_TO_REGIONS;
|
||||
limit.STRIP_NBT = STRIP_NBT;
|
||||
limit.UNIVERSAL_DISALLOWED_BLOCKS = UNIVERSAL_DISALLOWED_BLOCKS;
|
||||
limit.DISALLOWED_BLOCKS = DISALLOWED_BLOCKS;
|
||||
limit.REMAP_PROPERTIES = REMAP_PROPERTIES;
|
||||
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.BlockBagChangeSet;
|
||||
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.IQueueExtent;
|
||||
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.MutableVector3;
|
||||
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.regions.RegionWrapper;
|
||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||
|
@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.extent.DisallowedBlocksExtent;
|
||||
import com.fastasyncworldedit.core.extent.FaweRegionExtent;
|
||||
import com.fastasyncworldedit.core.extent.HistoryExtent;
|
||||
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.BlockBagChangeSet;
|
||||
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.IQueueExtent;
|
||||
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||
@ -68,7 +70,9 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -551,6 +555,23 @@ public final class EditSessionBuilder {
|
||||
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);
|
||||
}
|
||||
return this;
|
||||
|
@ -27,7 +27,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
||||
import com.fastasyncworldedit.core.history.DiskStorageHistory;
|
||||
import com.fastasyncworldedit.core.internal.io.FaweInputStream;
|
||||
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.MainUtil;
|
||||
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.math.heightmap.ScalableHeightMap;
|
||||
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.MathMan;
|
||||
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.URIClipboardHolder;
|
||||
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.MainUtil;
|
||||
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.annotation.Confirm;
|
||||
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.extent.clipboard.BlockArrayClipboard;
|
||||
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.configuration.Caption;
|
||||
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.sk89q.jnbt.CompoundTag;
|
||||
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.jnbt.JSON2NBT;
|
||||
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.StringMan;
|
||||
import com.fastasyncworldedit.core.world.block.BlanketBaseBlock;
|
||||
@ -66,6 +68,8 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
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,
|
||||
String[] stateProperties,
|
||||
ParserContext context
|
||||
ParserContext context,
|
||||
//FAWE start - if null should be returned instead of throwing an error
|
||||
boolean nullNotError
|
||||
//FAWE end
|
||||
) throws NoMatchException {
|
||||
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
|
||||
// Parse the block data (optional)
|
||||
for (String parseableData : stateProperties) {
|
||||
try {
|
||||
String[] parts = parseableData.split("=");
|
||||
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(
|
||||
Caption.of(
|
||||
"worldedit.error.parser.bad-state-format",
|
||||
@ -195,7 +237,14 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Object> propertyKey = (Property<Object>) type.getPropertyMap().get(parts[0]);
|
||||
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(
|
||||
"worldedit.error.parser.unknown-property",
|
||||
TextComponent.of(parts[0]),
|
||||
@ -207,6 +256,11 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
return Maps.newHashMap();
|
||||
}
|
||||
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(
|
||||
"worldedit.error.parser.duplicate-property",
|
||||
TextComponent.of(parts[0])
|
||||
@ -216,6 +270,11 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
try {
|
||||
value = propertyKey.getValueFor(parts[1]);
|
||||
} 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(
|
||||
"worldedit.error.parser.unknown-value",
|
||||
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);
|
||||
} catch (NoMatchException e) {
|
||||
} catch (NoMatchException | DisallowedUsageException e) {
|
||||
throw e; // Pass-through
|
||||
} 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(
|
||||
"worldedit.error.parser.bad-state-format",
|
||||
TextComponent.of(parseableData)
|
||||
@ -387,7 +466,9 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
}
|
||||
//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 (stateString == null || stateString.isEmpty()) {
|
||||
state = new FuzzyBlockState(state);
|
||||
@ -428,10 +509,23 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
|
||||
if (context.isRestricted()) {
|
||||
Actor actor = context.requireActor();
|
||||
if (actor != null && !actor.hasPermission("worldedit.anyblock")
|
||||
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) {
|
||||
throw new DisallowedUsageException(Caption.of("worldedit.error.disallowed-block", TextComponent.of(input)));
|
||||
//FAWE start - per-limit disallowed blocks
|
||||
if (actor != null) {
|
||||
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) {
|
||||
|
@ -22,7 +22,7 @@ package com.sk89q.worldedit.extension.platform;
|
||||
import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
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.sk89q.worldedit.EditSession;
|
||||
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.filter.block.ChunkFilterBlock;
|
||||
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.IBatchProcessor;
|
||||
import com.fastasyncworldedit.core.queue.IChunk;
|
||||
|
@ -19,10 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.registry.state;
|
||||
|
||||
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||
import com.fastasyncworldedit.core.registry.state.PropertyKey;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Describes a state property of a block.
|
||||
@ -57,16 +59,45 @@ public interface Property<T> {
|
||||
T getValueFor(String string) throws IllegalArgumentException;
|
||||
|
||||
//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) {
|
||||
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() {
|
||||
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
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Simple LocalConfiguration that loads settings using
|
||||
@ -92,7 +93,10 @@ public class PropertiesConfiguration extends LocalConfiguration {
|
||||
|
||||
profile = getBool("profile", profile);
|
||||
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);
|
||||
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
||||
defaultVerticalHeight = getInt("default-vertical-height", defaultVerticalHeight);
|
||||
|
@ -30,6 +30,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
||||
|
||||
disallowedBlocks = new HashSet<>(config.getStringList(
|
||||
"limits.disallowed-blocks",
|
||||
Lists.newArrayList(getDefaultDisallowedBlocks())
|
||||
));
|
||||
disallowedBlocks = config.getStringList("limits.disallowed-blocks", Lists.newArrayList(getDefaultDisallowedBlocks()))
|
||||
.stream()
|
||||
.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));
|
||||
|
||||
registerHelp = config.getBoolean("register-help", true);
|
||||
|
@ -152,8 +152,8 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
String input = key.toString();
|
||||
throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(
|
||||
BlockTypesCache.values)
|
||||
.filter(b -> StringMan.blockStateMatches(input, b.getId()))
|
||||
.map(BlockType::getId)
|
||||
.filter(id -> StringMan.blockStateMatches(input, id))
|
||||
.sorted(StringMan.blockStateComparator(input))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
@ -163,7 +163,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
return type.getDefaultState();
|
||||
}
|
||||
|
||||
List<? extends Property> propList = type.getProperties();
|
||||
List<? extends Property<?>> propList = type.getProperties();
|
||||
|
||||
if (state.charAt(state.length() - 1) != ']') {
|
||||
state = state + "]";
|
||||
@ -172,7 +172,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
charSequence.setString(state);
|
||||
|
||||
if (propList.size() == 1) {
|
||||
AbstractProperty property = (AbstractProperty) propList.get(0);
|
||||
AbstractProperty<?> property = (AbstractProperty<?>) propList.get(0);
|
||||
String name = property.getName();
|
||||
|
||||
charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1);
|
||||
@ -188,7 +188,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
stateId = type.getDefaultState().getInternalId();
|
||||
}
|
||||
int length = state.length();
|
||||
AbstractProperty property = null;
|
||||
AbstractProperty<?> property = null;
|
||||
|
||||
int last = propStrStart + 1;
|
||||
for (int i = last; i < length; i++) {
|
||||
@ -200,7 +200,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
if (property != null) {
|
||||
int index = property.getIndexFor(charSequence);
|
||||
if (index == -1) {
|
||||
throw SuggestInputParseException.of(charSequence.toString(), property.getValues());
|
||||
throw SuggestInputParseException.of(charSequence.toString(), (List<Object>) property.getValues());
|
||||
}
|
||||
stateId = property.modifyIndex(stateId, index);
|
||||
} else {
|
||||
@ -288,7 +288,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
public <V> BlockState with(final Property<V> property, final V value) {
|
||||
try {
|
||||
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;
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalArgumentException("Property not found: " + property);
|
||||
@ -298,7 +298,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
@Override
|
||||
public <V> V getState(final Property<V> property) {
|
||||
try {
|
||||
AbstractProperty ap = (AbstractProperty) property;
|
||||
AbstractProperty<V> ap = (AbstractProperty<V>) property;
|
||||
return (V) ap.getValue(this.getInternalId());
|
||||
} catch (ClassCastException e) {
|
||||
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) {
|
||||
try {
|
||||
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;
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalArgumentException("Property not found: " + property);
|
||||
@ -340,7 +344,7 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
|
||||
//FAWE end
|
||||
BlockType type = this.getBlockType();
|
||||
// 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.
|
||||
return Collections.unmodifiableMap((Map<Property<?>, Object>) map);
|
||||
//FAWE end
|
||||
|
@ -52,8 +52,8 @@ public class FuzzyBlockState extends BlockState {
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
private FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) {
|
||||
//FAWE start - use internal ids
|
||||
//FAWE start - use internal ids, public constructor
|
||||
public FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) {
|
||||
super(state.getBlockType(), state.getInternalId(), state.getOrdinal());
|
||||
if (values == null || values.isEmpty()) {
|
||||
props = Collections.emptyMap();
|
||||
|
@ -148,6 +148,8 @@
|
||||
"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.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.reason.confirm": "Use //confirm to execute {0}",
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren