Added a few new things using block states.

* `//set ##*tag` sets all states in the tag (not just default state per type)
* `//set ^type` is a pattern changing block type but copying all valid existing states
* `//set ^[prop=val,...]` sets the property `prop` to `val` wherever the existing block has that property
* `//set ^type[prop=val,...]` does both of the above
Those work anywhere a pattern is taken, of course.

* The mask syntax `^[prop=val]` matches blocks with the property `prop` set to `val`, or blocks that don't have the property at all.
* The mask syntax `^=[prop=val]` only matches blocks that have the property.
Those work anywhere a mask is taken, of course. (`//mask`, `//gmask`, `//replace`, etc)

The `//drain` command now takes `-w` flag that removes the waterlogged state from blocks (in addition to removing water, as before).
This commit is contained in:
wizjany
2019-02-12 16:39:09 -05:00
parent 1ae0e88b63
commit 88014b18a3
19 changed files with 711 additions and 49 deletions

View File

@ -0,0 +1,60 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockStateMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.NoiseFilter;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.noise.RandomNoise;
import com.sk89q.worldedit.session.request.Request;
import java.util.Arrays;
import java.util.stream.Collectors;
public class BlockStateMaskParser extends InputParser<Mask> {
public BlockStateMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
if (!(input.startsWith("^[") || input.startsWith("^=[")) || !input.endsWith("]")) {
return null;
}
Extent extent = Request.request().getEditSession();
boolean strict = input.charAt(1) == '=';
String states = input.substring(2 + (strict ? 1 : 0), input.length() - 1);
try {
return new BlockStateMask(extent,
Splitter.on(',').omitEmptyStrings().trimResults().withKeyValueSeparator('=').split(states),
strict);
} catch (Exception e) {
throw new InputParseException("Invalid states.", e);
}
}
}

View File

@ -28,9 +28,11 @@ import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class BlockCategoryPatternParser extends InputParser<Pattern> {
@ -46,17 +48,34 @@ public class BlockCategoryPatternParser extends InputParser<Pattern> {
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
if(!input.startsWith("##")) {
if (!input.startsWith("##")) {
return null;
}
BlockCategory category = BlockCategories.get(input.substring(2).toLowerCase());
String tag = input.substring(2).toLowerCase();
boolean anyState = false;
if (tag.startsWith("*")) {
tag = tag.substring(1);
anyState = true;
}
BlockCategory category = BlockCategories.get(tag);
if (category == null) {
throw new InputParseException("Unknown block tag: " + input.substring(2));
throw new InputParseException("Unknown block tag: " + tag);
}
RandomPattern randomPattern = new RandomPattern();
for (BlockType blockType : category.getAll()) {
randomPattern.add(new BlockPattern(blockType.getDefaultState()), 1.0 / category.getAll().size());
Set<BlockType> blocks = category.getAll();
if (blocks.isEmpty()) {
throw new InputParseException("Block tag " + category.getId() + " had no blocks!");
}
if (anyState) {
blocks.stream().flatMap(blockType -> blockType.getAllStates().stream()).forEach(state ->
randomPattern.add(new BlockPattern(state), 1.0));
} else {
for (BlockType blockType : blocks) {
randomPattern.add(new BlockPattern(blockType.getDefaultState()), 1.0);
}
}
return randomPattern;

View File

@ -21,14 +21,13 @@ package com.sk89q.worldedit.extension.factory.parser.pattern;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.factory.BlockFactory;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.List;
public class RandomPatternParser extends InputParser<Pattern> {
@ -38,14 +37,16 @@ public class RandomPatternParser extends InputParser<Pattern> {
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
BlockFactory blockRegistry = worldEdit.getBlockFactory();
RandomPattern randomPattern = new RandomPattern();
String[] splits = input.split(",");
for (String token : StringUtil.parseListInQuotes(splits, ',', '[', ']')) {
BaseBlock block;
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', '[', ']');
if (patterns.size() == 1) {
return null; // let a 'single'-pattern parser handle it
}
for (String token : patterns) {
double chance;
Pattern innerPattern;
// Parse special percentage syntax
if (token.matches("[0-9]+(\\.[0-9]*)?%.*")) {
@ -55,14 +56,14 @@ public class RandomPatternParser extends InputParser<Pattern> {
throw new InputParseException("Missing the type after the % symbol for '" + input + "'");
} else {
chance = Double.parseDouble(p[0]);
block = blockRegistry.parseFromInput(p[1], context);
innerPattern = worldEdit.getPatternFactory().parseFromInput(p[1], context);
}
} else {
chance = 1;
block = blockRegistry.parseFromInput(token, context);
innerPattern = worldEdit.getPatternFactory().parseFromInput(token, context);
}
randomPattern.add(new BlockPattern(block), chance);
randomPattern.add(innerPattern, chance);
}
return randomPattern;

View File

@ -0,0 +1,79 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.pattern;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.buffer.ExtentBuffer;
import com.sk89q.worldedit.function.pattern.ExtentBufferedCompositePattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.StateApplyingPattern;
import com.sk89q.worldedit.function.pattern.TypeApplyingPattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.world.block.BlockState;
import java.util.Map;
import java.util.Set;
public class TypeOrStateApplyingPatternParser extends InputParser<Pattern> {
public TypeOrStateApplyingPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
if (!input.startsWith("^")) {
return null;
}
Extent extent = context.requireExtent();
input = input.substring(1);
String[] parts = input.split("\\[", 2);
String type = parts[0];
if (parts.length == 1) {
return new TypeApplyingPattern(extent,
worldEdit.getBlockFactory().parseFromInput(type, context).getBlockType().getDefaultState());
} else {
// states given
if (!parts[1].endsWith("]")) throw new InputParseException("Invalid state format.");
Map<String, String> statesToSet = Splitter.on(',')
.omitEmptyStrings().trimResults().withKeyValueSeparator('=')
.split(parts[1].substring(0, parts[1].length() - 1));
if (type.isEmpty()) {
return new StateApplyingPattern(extent, statesToSet);
} else {
Extent buffer = new ExtentBuffer(extent);
Pattern typeApplier = new TypeApplyingPattern(buffer,
worldEdit.getBlockFactory().parseFromInput(type, context).getBlockType().getDefaultState());
Pattern stateApplier = new StateApplyingPattern(buffer, statesToSet);
return new ExtentBufferedCompositePattern(buffer, typeApplier, stateApplier);
}
}
}
}