Start work on the new BaseBlock/BlockState split

This commit is contained in:
Matthew Miller 2018-06-17 15:42:47 +10:00
parent aaaf2d5678
commit c43109bde5
20 changed files with 273 additions and 268 deletions

View File

@ -1,44 +0,0 @@
/*
* 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.util;
public final class ArrayUtil {
private ArrayUtil() {
}
public static String[] removePortionOfArray(String[] array, int from, int to, String replace) {
String[] newArray = new String[from + array.length - to - (replace == null ? 1 : 0)];
System.arraycopy(array, 0, newArray, 0, from);
if (replace != null) newArray[from] = replace;
System.arraycopy(array, to + 1, newArray, from + (replace == null ? 0 : 1),
array.length - to - 1);
return newArray;
}
public static char[] removePortionOfArray(char[] array, int from, int to, Character replace) {
char[] newArray = new char[from + array.length - to - (replace == null ? 1 : 0)];
System.arraycopy(array, 0, newArray, 0, from);
if (replace != null) newArray[from] = replace;
System.arraycopy(array, to + 1, newArray, from + (replace == null ? 0 : 1),
array.length - to - 1);
return newArray;
}
}

View File

@ -599,21 +599,6 @@ public class EditSession implements Extent {
return bypassNone.commit(); return bypassNone.commit();
} }
/**
* Count the number of blocks of a given list of types in a region.
*
* @param region the region
* @param searchIDs a list of IDs to search
* @return the number of found blocks
*/
public int countBlock(Region region, Set<Integer> searchIDs) {
Set<BaseBlock> passOn = new HashSet<>();
for (Integer i : searchIDs) {
passOn.add(new BaseBlock(i, -1));
}
return countBlocks(region, passOn);
}
/** /**
* Count the number of blocks of a list of types in a region. * Count the number of blocks of a list of types in a region.
* *

View File

@ -19,12 +19,14 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import static com.sk89q.worldedit.event.platform.Interaction.HIT;
import static com.sk89q.worldedit.event.platform.Interaction.OPEN;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection; import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.event.platform.BlockInteractEvent; import com.sk89q.worldedit.event.platform.BlockInteractEvent;
import com.sk89q.worldedit.event.platform.InputType; import com.sk89q.worldedit.event.platform.InputType;
import com.sk89q.worldedit.event.platform.PlayerInputEvent; import com.sk89q.worldedit.event.platform.PlayerInputEvent;
@ -32,7 +34,6 @@ import com.sk89q.worldedit.extension.factory.BlockFactory;
import com.sk89q.worldedit.extension.factory.ItemFactory; import com.sk89q.worldedit.extension.factory.ItemFactory;
import com.sk89q.worldedit.extension.factory.MaskFactory; import com.sk89q.worldedit.extension.factory.MaskFactory;
import com.sk89q.worldedit.extension.factory.PatternFactory; import com.sk89q.worldedit.extension.factory.PatternFactory;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.PlatformManager; import com.sk89q.worldedit.extension.platform.PlatformManager;
@ -50,23 +51,19 @@ import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
import com.sk89q.worldedit.util.io.file.InvalidFilenameException; import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler; import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.BundledItemData;
import javax.script.ScriptException;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull; import javax.script.ScriptException;
import static com.sk89q.worldedit.event.platform.Interaction.HIT;
import static com.sk89q.worldedit.event.platform.Interaction.OPEN;
/** /**
* The entry point and container for a working implementation of WorldEdit. * The entry point and container for a working implementation of WorldEdit.
@ -102,6 +99,7 @@ public class WorldEdit {
WorldEditPrefixHandler.register("com.sk89q.worldedit"); WorldEditPrefixHandler.register("com.sk89q.worldedit");
getVersion(); getVersion();
BundledBlockData.getInstance(); // Load block registry BundledBlockData.getInstance(); // Load block registry
BundledItemData.getInstance(); // Load item registry
} }
private WorldEdit() { private WorldEdit() {
@ -191,78 +189,6 @@ public class WorldEdit {
return sessions; return sessions;
} }
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
public BaseBlock getBlock(Player player, String arg, boolean allAllowed) throws WorldEditException {
return getBlock(player, arg, allAllowed, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
public BaseBlock getBlock(Player player, String arg, boolean allAllowed, boolean allowNoData) throws WorldEditException {
ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(getSessionManager().get(player));
context.setRestricted(!allAllowed);
context.setPreferringWildcard(allowNoData);
return getBlockFactory().parseFromInput(arg, context);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
public BaseBlock getBlock(Player player, String id) throws WorldEditException {
return getBlock(player, id, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed, boolean allowNoData) throws WorldEditException {
String[] items = list.split(",");
Set<BaseBlock> blocks = new HashSet<>();
for (String id : items) {
blocks.add(getBlock(player, id, allAllowed, allowNoData));
}
return blocks;
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
*/
@Deprecated
public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed) throws WorldEditException {
return getBlocks(player, list, allAllowed, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
public Set<BaseBlock> getBlocks(Player player, String list) throws WorldEditException {
return getBlocks(player, list, false);
}
/**
* @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
*/
@Deprecated
public Set<Integer> getBlockIDs(Player player, String list, boolean allBlocksAllowed) throws WorldEditException {
String[] items = list.split(",");
Set<Integer> blocks = new HashSet<>();
for (String s : items) {
blocks.add(getBlock(player, s, allBlocksAllowed).getType().getLegacyId());
}
return blocks;
}
/** /**
* Gets the path to a file. This method will check to see if the filename * Gets the path to a file. This method will check to see if the filename
* has valid characters and has an extension. It also prevents directory * has valid characters and has an extension. It also prevents directory
@ -641,7 +567,7 @@ public class WorldEdit {
String filename = f.getPath(); String filename = f.getPath();
int index = filename.lastIndexOf("."); int index = filename.lastIndexOf(".");
String ext = filename.substring(index + 1, filename.length()); String ext = filename.substring(index + 1);
if (!ext.equalsIgnoreCase("js")) { if (!ext.equalsIgnoreCase("js")) {
player.printError("Only .js scripts are currently supported"); player.printError("Only .js scripts are currently supported");
@ -677,7 +603,7 @@ public class WorldEdit {
LocalSession session = getSessionManager().get(player); LocalSession session = getSessionManager().get(player);
CraftScriptContext scriptContext = new CraftScriptContext(this, getServer(), getConfiguration(), session, player, args); CraftScriptContext scriptContext = new CraftScriptContext(this, getServer(), getConfiguration(), session, player, args);
CraftScriptEngine engine = null; CraftScriptEngine engine;
try { try {
engine = new RhinoCraftScriptEngine(); engine = new RhinoCraftScriptEngine();
@ -739,20 +665,6 @@ public class WorldEdit {
return editSessionFactory; return editSessionFactory;
} }
/**
* @deprecated EditSessionFactories are no longer used. Please register an {@link EditSessionEvent} event
* with the event bus in order to override or catch changes to the world
*/
@Deprecated
public void setEditSessionFactory(EditSessionFactory factory) {
checkNotNull(factory);
logger.severe("Got request to set EditSessionFactory of type " +
factory.getClass().getName() + " from " + factory.getClass().getPackage().getName() +
" but EditSessionFactories have been removed in favor of extending EditSession's extents.\n\n" +
"This may mean that any block logger / intercepters addons/plugins/mods that you have installed will not " +
"intercept WorldEdit's changes! Please notify the maintainer of the other addon about this.");
}
/** /**
* Get the version. * Get the version.
* *
@ -782,11 +694,4 @@ public class WorldEdit {
return version; return version;
} }
/**
* @deprecated Declare your platform version with {@link Platform#getPlatformVersion()}
*/
@Deprecated
public static void setVersion(String version) {
}
} }

View File

@ -0,0 +1,114 @@
/*
* 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.blocks.type;
import com.google.common.collect.ArrayTable;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.sk89q.worldedit.world.registry.state.State;
import com.sk89q.worldedit.world.registry.state.value.SimpleStateValue;
import java.util.HashMap;
import java.util.Map;
/**
* An immutable class that represents the state a block can be in.
*/
public class BlockState {
private final BlockType blockType;
private final Map<State<SimpleStateValue>, SimpleStateValue> values;
// Neighbouring state table.
private Table<State<SimpleStateValue>, SimpleStateValue, BlockState> states;
BlockState(BlockType blockType) {
this.blockType = blockType;
this.values = new HashMap<>();
}
public void populate(Map<Map<State<SimpleStateValue>, SimpleStateValue>, BlockState> stateMap) {
final Table<State<SimpleStateValue>, SimpleStateValue, BlockState> states = HashBasedTable.create();
for(final Map.Entry<State<SimpleStateValue>, SimpleStateValue> entry : this.values.entrySet()) {
final State<SimpleStateValue> state = entry.getKey();
state.getValues().forEach(value -> {
if(value != entry.getValue()) {
states.put(state, value, stateMap.get(this.withValue(state, value)));
}
});
}
this.states = states.isEmpty() ? states : ArrayTable.create(states);
}
private Map<State<SimpleStateValue>, SimpleStateValue> withValue(final State<SimpleStateValue> property, final SimpleStateValue value) {
final Map<State<SimpleStateValue>, SimpleStateValue> values = Maps.newHashMap(this.values);
values.put(property, value);
return values;
}
/**
* Get the block type
*
* @return The type
*/
public BlockType getBlockType() {
return this.blockType;
}
/**
* Returns a BlockState with the given state and value applied.
*
* @param state The state
* @param value The value
* @return The modified state, or same if could not be applied
*/
public BlockState with(State<SimpleStateValue> state, SimpleStateValue value) {
BlockState result = states.get(state, value);
return result == null ? this : result;
}
/**
* Gets the value at the given state
*
* @param state The state
* @return The value
*/
public SimpleStateValue getState(State<SimpleStateValue> state) {
return this.values.get(state);
}
/**
* Internal method used for creating the initial BlockState.
*
* Sets a value. DO NOT USE THIS.
*
* @param state The state
* @param value The value
* @return The blockstate, for chaining
*/
BlockState setState(State<SimpleStateValue> state, SimpleStateValue value) {
this.values.put(state, value);
return this;
}
}

View File

@ -21,22 +21,61 @@ package com.sk89q.worldedit.blocks.type;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.function.Function;
public class BlockType { public class BlockType {
private String id; private String id;
private BlockState defaultState;
public BlockType(String id) { public BlockType(String id) {
this(id, null);
}
public BlockType(String id, Function<BlockState, BlockState> values) {
// If it has no namespace, assume minecraft. // If it has no namespace, assume minecraft.
if (!id.contains(":")) { if (!id.contains(":")) {
id = "minecraft:" + id; id = "minecraft:" + id;
} }
this.id = id; this.id = id;
this.defaultState = new BlockState(this);
if (values != null) {
this.defaultState = values.apply(this.defaultState);
}
} }
/**
* Gets the ID of this block.
*
* @return The id
*/
public String getId() { public String getId() {
return this.id; return this.id;
} }
/**
* Gets the name of this block, or the ID if the name cannot be found.
*
* @return The name, or ID
*/
public String getName() {
BundledBlockData.BlockEntry entry = BundledBlockData.getInstance().findById(this.id);
if (entry == null) {
return getId();
} else {
return entry.localizedName;
}
}
/**
* Gets the default state of this block type.
*
* @return The default state
*/
public BlockState getDefaultState() {
return this.defaultState;
}
/** /**
* Gets the legacy ID. Needed for legacy reasons. * Gets the legacy ID. Needed for legacy reasons.
* *

View File

@ -34,8 +34,8 @@ import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -624,26 +624,22 @@ public class SelectionCommands {
aliases = { "/count" }, aliases = { "/count" },
usage = "<block>", usage = "<block>",
desc = "Counts the number of a certain type of block", desc = "Counts the number of a certain type of block",
flags = "d",
min = 1, min = 1,
max = 1 max = 1
) )
@CommandPermissions("worldedit.analysis.count") @CommandPermissions("worldedit.analysis.count")
public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
boolean useData = args.hasFlag('d'); ParserContext context = new ParserContext();
if (args.getString(0).contains(":")) { context.setActor(player);
useData = true; //override d flag, if they specified data they want it context.setExtent(player.getExtent());
} context.setWorld(player.getWorld());
if (useData) { context.setSession(session);
Set<BaseBlock> searchBlocks = we.getBlocks(player, args.getString(0), true); context.setRestricted(false);
int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
player.print("Counted: " + count); Set<BaseBlock> searchBlocks = we.getBlockFactory().parseFromListInput(args.getString(0), context);
} else { int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
Set<Integer> searchIDs = we.getBlockIDs(player, args.getString(0), true); player.print("Counted: " + count);
int count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs);
player.print("Counted: " + count);
}
} }
@Command( @Command(
@ -662,49 +658,32 @@ public class SelectionCommands {
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException { public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
int size; int size;
boolean useData = args.hasFlag('d'); List<Countable<BaseBlock>> distributionData;
List<Countable<Integer>> distribution = null;
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) { if (args.hasFlag('c')) {
// TODO: Update for new clipboard // TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again"); throw new CommandException("Needs to be re-written again");
} else { } else {
if (useData) { distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
} else {
distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld()));
}
size = session.getSelection(player.getWorld()).getArea(); size = session.getSelection(player.getWorld()).getArea();
} }
if ((useData && distributionData.size() <= 0) if (distributionData.size() <= 0) { // *Should* always be false
|| (!useData && distribution.size() <= 0)) { // *Should* always be false
player.printError("No blocks counted."); player.printError("No blocks counted.");
return; return;
} }
player.print("# total blocks: " + size); player.print("# total blocks: " + size);
if (useData) { for (Countable<BaseBlock> c : distributionData) {
for (Countable<BaseBlock> c : distributionData) { String name = c.getID().getType().getName();
String name = BlockType.fromID(c.getID().getId()).getName(); String str = String.format("%-7s (%.3f%%) %s #%s%s",
String str = String.format("%-7s (%.3f%%) %s #%d:%d", String.valueOf(c.getAmount()),
String.valueOf(c.getAmount()), c.getAmount() / (double) size * 100,
c.getAmount() / (double) size * 100, name,
name == null ? "Unknown" : name, c.getID().getType().getId(),
c.getID().getType(), c.getID().getData()); c.getID().getStates());
player.print(str); player.print(str);
}
} else {
for (Countable<Integer> c : distribution) {
BlockType block = BlockType.fromID(c.getID());
String str = String.format("%-7s (%.3f%%) %s #%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
block == null ? "Unknown" : block.getName(), c.getID());
player.print(str);
}
} }
} }

View File

@ -100,7 +100,14 @@ public class ToolCommands {
@CommandPermissions("worldedit.tool.replacer") @CommandPermissions("worldedit.tool.replacer")
public void repl(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void repl(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
BaseBlock targetBlock = we.getBlock(player, args.getString(0)); ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(session);
context.setRestricted(true);
context.setPreferringWildcard(false);
BaseBlock targetBlock = we.getBlockFactory().parseFromInput(args.getString(0), context);
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock)); session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock));
player.print("Block replacer tool bound to " player.print("Block replacer tool bound to "
+ ItemType.toHeldName(player.getItemInHand()) + "."); + ItemType.toHeldName(player.getItemInHand()) + ".");
@ -189,8 +196,16 @@ public class ToolCommands {
@CommandPermissions("worldedit.tool.lrbuild") @CommandPermissions("worldedit.tool.lrbuild")
public void longrangebuildtool(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void longrangebuildtool(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
BaseBlock secondary = we.getBlock(player, args.getString(0)); ParserContext context = new ParserContext();
BaseBlock primary = we.getBlock(player, args.getString(1)); context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(session);
context.setRestricted(true);
context.setPreferringWildcard(false);
BaseBlock secondary = we.getBlockFactory().parseFromInput(args.getString(0), context);
BaseBlock primary = we.getBlockFactory().parseFromInput(args.getString(1), context);
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary)); session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary));
player.print("Long-range building tool bound to " + ItemType.toHeldName(player.getItemInHand()) + "."); player.print("Long-range building tool bound to " + ItemType.toHeldName(player.getItemInHand()) + ".");
player.print("Left-click set to " + ItemType.toName(secondary.getType().getLegacyId()) + "; right-click set to " player.print("Left-click set to " + ItemType.toName(secondary.getType().getLegacyId()) + "; right-click set to "

View File

@ -250,7 +250,14 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
BaseBlock block = we.getBlock(player, args.getString(0), true); ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(session);
context.setRestricted(false);
context.setPreferringWildcard(false);
BaseBlock block = we.getBlockFactory().parseFromInput(args.getString(0), context);
int size = Math.max(1, args.getInteger(1, 50)); int size = Math.max(1, args.getInteger(1, 50));
we.checkMaxRadius(size); we.checkMaxRadius(size);

View File

@ -50,7 +50,7 @@ public class AreaPickaxe implements BlockTool {
int ox = clicked.getBlockX(); int ox = clicked.getBlockX();
int oy = clicked.getBlockY(); int oy = clicked.getBlockY();
int oz = clicked.getBlockZ(); int oz = clicked.getBlockZ();
BlockType initialType = ((World) clicked.getExtent()).getBlock(clicked.toVector()).getType(); BlockType initialType = clicked.getExtent().getBlock(clicked.toVector()).getType();
if (initialType == BlockTypes.AIR) { if (initialType == BlockTypes.AIR) {
return true; return true;
@ -72,7 +72,7 @@ public class AreaPickaxe implements BlockTool {
continue; continue;
} }
((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType.getLegacyId(), clicked.toVector().distanceSq(pos)); ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos));
editSession.setBlock(pos, air); editSession.setBlock(pos, air);
} }

View File

@ -26,7 +26,6 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.world.World;
/** /**
* A mode that replaces one block. * A mode that replaces one block.
@ -66,10 +65,9 @@ public class BlockReplacer implements DoubleActionBlockTool {
@Override @Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
World world = (World) clicked.getExtent();
EditSession editSession = session.createEditSession(player); EditSession editSession = session.createEditSession(player);
targetBlock = (editSession).getBlock(clicked.toVector()); targetBlock = (editSession).getBlock(clicked.toVector());
BlockType type = BlockType.fromID(targetBlock.getType().getLegacyId()); BlockType type = targetBlock.getType().getLegacyType();
if (type != null) { if (type != null) {
player.print("Replacer tool switched to: " + type.getName()); player.print("Replacer tool switched to: " + type.getName());

View File

@ -102,7 +102,7 @@ public class FloatingTreeRemover implements BlockTool {
return true; return true;
} }
Vector[] recurseDirections = { private Vector[] recurseDirections = {
PlayerDirection.NORTH.vector(), PlayerDirection.NORTH.vector(),
PlayerDirection.EAST.vector(), PlayerDirection.EAST.vector(),
PlayerDirection.SOUTH.vector(), PlayerDirection.SOUTH.vector(),

View File

@ -67,8 +67,8 @@ public class FloodFillTool implements BlockTool {
EditSession editSession = session.createEditSession(player); EditSession editSession = session.createEditSession(player);
try { try {
recurse(server, editSession, world, clicked.toVector().toBlockVector(), recurse(editSession, clicked.toVector().toBlockVector(),
clicked.toVector(), range, initialType.getLegacyId(), new HashSet<>()); clicked.toVector(), range, initialType, new HashSet<>());
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached."); player.printError("Max blocks change limit reached.");
} finally { } finally {
@ -78,7 +78,7 @@ public class FloodFillTool implements BlockTool {
return true; return true;
} }
private void recurse(Platform server, EditSession editSession, World world, BlockVector pos, Vector origin, int size, int initialType, private void recurse(EditSession editSession, BlockVector pos, Vector origin, int size, BlockType initialType,
Set<BlockVector> visited) throws MaxChangedBlocksException { Set<BlockVector> visited) throws MaxChangedBlocksException {
if (origin.distance(pos) > size || visited.contains(pos)) { if (origin.distance(pos) > size || visited.contains(pos)) {
@ -87,23 +87,23 @@ public class FloodFillTool implements BlockTool {
visited.add(pos); visited.add(pos);
if (editSession.getBlock(pos).getType().getLegacyId() == initialType) { if (editSession.getBlock(pos).getType() == initialType) {
editSession.setBlock(pos, pattern.apply(pos)); editSession.setBlock(pos, pattern.apply(pos));
} else { } else {
return; return;
} }
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(), recurse(editSession, pos.add(1, 0, 0).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(), recurse(editSession, pos.add(-1, 0, 0).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(), recurse(editSession, pos.add(0, 0, 1).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(), recurse(editSession, pos.add(0, 0, -1).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(), recurse(editSession, pos.add(0, 1, 0).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(), recurse(editSession, pos.add(0, -1, 0).toBlockVector(),
origin, size, initialType, visited); origin, size, initialType, visited);
} }

View File

@ -93,7 +93,7 @@ public class RecursivePickaxe implements BlockTool {
return; return;
} }
world.queueBlockBreakEffect(server, pos, initialType.getLegacyId(), distanceSq); world.queueBlockBreakEffect(server, pos, initialType, distanceSq);
editSession.setBlock(pos, air); editSession.setBlock(pos, air);

View File

@ -24,7 +24,7 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.type.BlockType;
import com.sk89q.worldedit.blocks.type.BlockTypes; import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
@ -44,8 +44,8 @@ public class SinglePickaxe implements BlockTool {
@Override @Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
World world = (World) clicked.getExtent(); World world = (World) clicked.getExtent();
final int blockType = world.getLazyBlock(clicked.toVector()).getId(); final BlockType blockType = world.getLazyBlock(clicked.toVector()).getType();
if (blockType == BlockID.BEDROCK if (blockType == BlockTypes.BEDROCK
&& !player.canDestroyBedrock()) { && !player.canDestroyBedrock()) {
return true; return true;
} }
@ -61,7 +61,7 @@ public class SinglePickaxe implements BlockTool {
editSession.flushQueue(); editSession.flushQueue();
} }
world.playEffect(clicked.toVector(), 2001, blockType); world.playEffect(clicked.toVector(), 2001, blockType.getLegacyId());
return true; return true;
} }

View File

@ -143,7 +143,7 @@ public class CraftScriptContext extends CraftScriptEnvironment {
} }
/** /**
* Get an item ID from an item name or an item ID number. * Get an item from an item name or an item ID number.
* *
* @param input input to parse * @param input input to parse
* @param allAllowed true to ignore blacklists * @param allAllowed true to ignore blacklists
@ -152,7 +152,14 @@ public class CraftScriptContext extends CraftScriptEnvironment {
* @throws DisallowedItemException * @throws DisallowedItemException
*/ */
public BaseBlock getBlock(String input, boolean allAllowed) throws WorldEditException { public BaseBlock getBlock(String input, boolean allAllowed) throws WorldEditException {
return controller.getBlock(player, input, allAllowed); ParserContext context = new ParserContext();
context.setActor(player);
context.setWorld(player.getWorld());
context.setSession(session);
context.setRestricted(!allAllowed);
context.setPreferringWildcard(false);
return controller.getBlockFactory().parseFromListInput(input, context).stream().findFirst().orElse(null);
} }
/** /**
@ -164,7 +171,7 @@ public class CraftScriptContext extends CraftScriptEnvironment {
* @throws DisallowedItemException * @throws DisallowedItemException
*/ */
public BaseBlock getBlock(String id) throws WorldEditException { public BaseBlock getBlock(String id) throws WorldEditException {
return controller.getBlock(player, id, false); return getBlock(id, false);
} }
/** /**
@ -192,27 +199,13 @@ public class CraftScriptContext extends CraftScriptEnvironment {
* @throws UnknownItemException * @throws UnknownItemException
* @throws DisallowedItemException * @throws DisallowedItemException
*/ */
public Set<Integer> getBlockIDs(String list, boolean allBlocksAllowed) throws WorldEditException { public Set<BaseBlock> getBlocks(String list, boolean allBlocksAllowed) throws WorldEditException {
return controller.getBlockIDs(player, list, allBlocksAllowed); ParserContext context = new ParserContext();
} context.setActor(player);
context.setWorld(player.getWorld());
/** context.setSession(session);
* Gets the path to a file. This method will check to see if the filename context.setRestricted(!allBlocksAllowed);
* has valid characters and has an extension. It also prevents directory return controller.getBlockFactory().parseFromListInput(list, context);
* traversal exploits by checking the root directory and the file directory.
* On success, a {@code java.io.File} object will be returned.
*
* <p>Use this method if you need to read a file from a directory.</p>
*
* @param folder sub-directory to look in
* @param filename filename (user-submitted)
* @return a file
* @throws FilenameException
*/
@Deprecated
public File getSafeFile(String folder, String filename) throws FilenameException {
File dir = controller.getWorkingDirectoryFile(folder);
return controller.getSafeOpenFile(player, dir, filename, null, (String[]) null);
} }
/** /**

View File

@ -180,7 +180,7 @@ public abstract class AbstractWorld implements World {
} }
@Override @Override
public boolean queueBlockBreakEffect(Platform server, Vector position, int blockId, double priority) { public boolean queueBlockBreakEffect(Platform server, Vector position, com.sk89q.worldedit.blocks.type.BlockType blockType, double priority) {
if (taskId == -1) { if (taskId == -1) {
taskId = server.schedule(0, 1, () -> { taskId = server.schedule(0, 1, () -> {
int max = Math.max(1, Math.min(30, effectQueue.size() / 3)); int max = Math.max(1, Math.min(30, effectQueue.size() / 3));
@ -196,7 +196,7 @@ public abstract class AbstractWorld implements World {
return false; return false;
} }
effectQueue.offer(new QueuedEffect(position, blockId, priority)); effectQueue.offer(new QueuedEffect(position, blockType, priority));
return true; return true;
} }
@ -218,17 +218,17 @@ public abstract class AbstractWorld implements World {
private class QueuedEffect implements Comparable<QueuedEffect> { private class QueuedEffect implements Comparable<QueuedEffect> {
private final Vector position; private final Vector position;
private final int blockId; private final com.sk89q.worldedit.blocks.type.BlockType blockType;
private final double priority; private final double priority;
private QueuedEffect(Vector position, int blockId, double priority) { private QueuedEffect(Vector position, com.sk89q.worldedit.blocks.type.BlockType blockType, double priority) {
this.position = position; this.position = position;
this.blockId = blockId; this.blockType = blockType;
this.priority = priority; this.priority = priority;
} }
public void play() { public void play() {
playEffect(position, 2001, blockId); playEffect(position, 2001, blockType.getLegacyId());
} }
@Override @Override

View File

@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.type.BlockType;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
@ -262,11 +263,11 @@ public interface World extends Extent {
* *
* @param server the server * @param server the server
* @param position the position * @param position the position
* @param blockId the block ID * @param blockType the block type
* @param priority the priority * @param priority the priority
* @return true if the effect was played * @return true if the effect was played
*/ */
boolean queueBlockBreakEffect(Platform server, Vector position, int blockId, double priority); boolean queueBlockBreakEffect(Platform server, Vector position, BlockType blockType, double priority);
/** /**
* Get the data for blocks and so on for this world. * Get the data for blocks and so on for this world.

View File

@ -98,7 +98,7 @@ public class BundledBlockData {
* @return the entry, or null * @return the entry, or null
*/ */
@Nullable @Nullable
private BlockEntry findById(String id) { public BlockEntry findById(String id) {
// If it has no namespace, assume minecraft. // If it has no namespace, assume minecraft.
if (!id.contains(":")) { if (!id.contains(":")) {
id = "minecraft:" + id; id = "minecraft:" + id;
@ -190,10 +190,11 @@ public class BundledBlockData {
return INSTANCE; return INSTANCE;
} }
private static class BlockEntry { public static class BlockEntry {
private int legacyId; private int legacyId;
private String id; private String id;
private String unlocalizedName; private String unlocalizedName;
public String localizedName;
private List<String> aliases; private List<String> aliases;
private Map<String, SimpleState> states = new HashMap<>(); private Map<String, SimpleState> states = new HashMap<>();
private SimpleBlockMaterial material = new SimpleBlockMaterial(); private SimpleBlockMaterial material = new SimpleBlockMaterial();

View File

@ -21,6 +21,11 @@ package com.sk89q.worldedit.world.registry.state;
import com.sk89q.worldedit.world.registry.state.value.DirectionalStateValue; import com.sk89q.worldedit.world.registry.state.value.DirectionalStateValue;
import java.util.List;
public class DirectionalState extends SimpleState<DirectionalStateValue> { public class DirectionalState extends SimpleState<DirectionalStateValue> {
public DirectionalState(List<DirectionalStateValue> values) {
super(values);
}
} }

View File

@ -21,17 +21,24 @@ package com.sk89q.worldedit.world.registry.state;
import com.sk89q.worldedit.world.registry.state.value.SimpleStateValue; import com.sk89q.worldedit.world.registry.state.value.SimpleStateValue;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class SimpleState<T extends SimpleStateValue> implements State<T> { public class SimpleState<T extends SimpleStateValue> implements State<T> {
private List<T> values = new ArrayList<>(); private List<T> values;
/**
* Creates a state with values
*
* @param values The values
*/
public SimpleState(List<T> values) {
this.values = values;
}
@Override @Override
public List<T> getValues() { public List<T> getValues() {
return Collections.unmodifiableList(values); return Collections.unmodifiableList(values);
} }
} }