Add `slot#` pattern

This commit is contained in:
Jesse Boyd 2017-09-06 18:18:58 +10:00
parent e27b1d5421
commit 398943b9b0
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
5 changed files with 324 additions and 75 deletions

View File

@ -19,16 +19,23 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.bukkit.util.ItemUtil;
import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.WorldVector;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.sk89q.worldedit.extent.inventory.*;
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.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.ItemType; import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagException;
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
import com.sk89q.worldedit.extent.inventory.SlottableBlockBag;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class BukkitPlayerBlockBag extends BlockBag { public class BukkitPlayerBlockBag extends BlockBag implements SlottableBlockBag {
private Player player; private Player player;
private ItemStack[] items; private ItemStack[] items;
@ -60,6 +67,59 @@ public class BukkitPlayerBlockBag extends BlockBag {
return player; return player;
} }
@Override
public BaseItem getItem(int slot) {
loadInventory();
return toBaseItem(items[slot]);
}
@Override
public void setItem(int slot, BaseItem block) {
loadInventory();
items[slot] = toItemStack(block);
}
@Override
public int getSelectedSlot() {
return player.getInventory().getHeldItemSlot();
}
private BaseItem toBaseItem(ItemStack item) {
if (item == null) return new BaseItemStack(0, 0);
int id = item.getTypeId();
short data;
if (id < 256) {
data = item.getData().getData();
} else {
data = item.getDurability();
}
BaseItemStack baseItem = new BaseItemStack(id, item.getAmount(), data);
ItemUtil itemUtil = Fawe.<FaweBukkit>imp().getItemUtil();
if (itemUtil != null && item.hasItemMeta()) {
baseItem.setNbtData(itemUtil.getNBT(item));
}
return baseItem;
}
private ItemStack toItemStack(BaseItem item) {
if (item == null) return null;
final int id = item.getType();
final int damage = item.getData();
int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1;
ItemStack bukkitItem;
if (id < 256) {
bukkitItem = new ItemStack(id, amount, (short) 0, (byte) damage);
} else {
bukkitItem = new ItemStack(id, amount, (short) damage);
}
ItemUtil itemUtil = Fawe.<FaweBukkit>imp().getItemUtil();
if (itemUtil != null && item.hasNBTData()) {
bukkitItem = itemUtil.setNBT(bukkitItem, item.getNbtData());
}
return bukkitItem;
}
@Override @Override
public void fetchItem(BaseItem item) throws BlockBagException { public void fetchItem(BaseItem item) throws BlockBagException {
final int id = item.getType(); final int id = item.getType();

View File

@ -31,6 +31,7 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BlockData; import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands; import com.sk89q.worldedit.command.BrushCommands;
@ -573,6 +574,7 @@ public class Fawe {
Vector2D.inject(); // Optimizations Vector2D.inject(); // Optimizations
// Block // Block
BaseBlock.inject(); // Optimizations BaseBlock.inject(); // Optimizations
BaseItem.inject();
// Biome // Biome
BaseBiome.inject(); // Features BaseBiome.inject(); // Features
// Pattern // Pattern

View File

@ -0,0 +1,140 @@
/*
* 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;
import com.sk89q.jnbt.CompoundTag;
import java.util.HashMap;
import java.util.Map;
/**
* Represents an item, without an amount value. See {@link BaseItemStack}
* for an instance with stack amount information.
*
* <p>This class may be removed in the future.</p>
*/
public class BaseItem {
private int id;
private short data;
private CompoundTag nbt;
private final Map<Integer, Integer> enchantments = new HashMap<Integer, Integer>();
/**
* Construct the object.
*
* @param id ID of the item
*/
public BaseItem(int id) {
this.id = id;
this.data = 0;
}
/**
* Construct the object.
*
* @param id ID of the item
* @param data data value of the item
*/
public BaseItem(int id, short data) {
this.id = id;
this.data = data;
}
/**
* Get the type of item.
*
* @return the id
*/
public int getType() {
return id;
}
/**
* Get the type of item.
*
* @param id the id to set
*/
public void setType(int id) {
this.id = id;
}
/**
* Get the damage value.
*
* @return the damage
*/
@Deprecated
public short getDamage() {
return data;
}
/**
* Get the data value.
*
* @return the data
*/
public short getData() {
return data;
}
/**
* Set the data value.
*
* @param data the damage to set
*/
@Deprecated
public void setDamage(short data) {
this.data = data;
}
/**
* Set the data value.
*
* @param data the damage to set
*/
public void setData(short data) {
this.data = data;
}
public boolean hasNBTData() {
return nbt != null;
}
public CompoundTag getNbtData() {
return nbt;
}
public void setNbtData(CompoundTag nbt) {
this.nbt = nbt;
}
/**
* Get the map of enchantments.
*
* @return map of enchantments
*/
public Map<Integer, Integer> getEnchantments() {
return enchantments;
}
public static Class<?> inject() {
return BaseItem.class;
}
}

View File

@ -31,6 +31,7 @@ import com.sk89q.worldedit.NotABlockException;
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.BaseItem;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.ClothColor; import com.sk89q.worldedit.blocks.ClothColor;
import com.sk89q.worldedit.blocks.MobSpawnerBlock; import com.sk89q.worldedit.blocks.MobSpawnerBlock;
@ -44,6 +45,8 @@ import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext; 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.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.SlottableBlockBag;
import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
@ -132,93 +135,120 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
CompoundTag nbt = null; CompoundTag nbt = null;
boolean parseDataValue = true; boolean parseDataValue = true;
switch (testId.substring(0, Math.min(testId.length(), 4))) {
if ("hand".equalsIgnoreCase(testId)) { case "pos1": {
// Get the block type from the item in the user's hand. // Get the block type from the "primary position"
final BaseBlock blockInHand = getBlockInHand(context.requireActor()); final World world = context.requireWorld();
blockId = blockInHand.getId(); final BlockVector primaryPosition;
blockType = BlockType.fromID(blockId); try {
data = blockInHand.getData(); primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition();
nbt = blockInHand.getNbtData(); } catch (IncompleteRegionException e) {
} else if ("pos1".equalsIgnoreCase(testId)) { throw new InputParseException("Your selection is not complete.");
// Get the block type from the "primary position" }
final World world = context.requireWorld(); final BaseBlock block = world.getBlock(primaryPosition);
final BlockVector primaryPosition; blockId = block.getId();
try {
primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition();
} catch (IncompleteRegionException e) {
throw new InputParseException("Your selection is not complete.");
}
final BaseBlock blockInHand = world.getBlock(primaryPosition);
blockId = blockInHand.getId();
blockType = BlockType.fromID(blockId);
data = blockInHand.getData();
nbt = blockInHand.getNbtData();
} else {
// Attempt to parse the item ID or otherwise resolve an item/block
// name to its numeric ID
if (MathMan.isInteger(testId)) {
blockId = Integer.parseInt(testId);
blockType = BlockType.fromID(blockId); blockType = BlockType.fromID(blockId);
} else { data = block.getData();
BundledBlockData.BlockEntry block = BundledBlockData.getInstance().findById(testId); nbt = block.getNbtData();
if (block == null) { break;
BaseBlock baseBlock = BundledBlockData.getInstance().findByState(testId); }
if (baseBlock == null) { case "hand": {
blockType = BlockType.lookup(testId); BaseBlock blockInHand = getBlockInHand(context.requireActor());
if (blockType == null) { blockId = blockInHand.getId();
int t = worldEdit.getServer().resolveItem(testId); blockType = BlockType.fromID(blockId);
if (t == 0 && !testId.contains("air")) { data = blockInHand.getData();
throw new NoMatchException("Invalid block '" + input + "'."); nbt = blockInHand.getNbtData();
} break;
if (t >= 0) { }
blockType = BlockType.fromID(t); // Could be null case "slot": {
blockId = t; try {
} else if (blockLocator.length == 2) { // Block IDs in MC 1.7 and above use mod:name int slot = Integer.parseInt(testId.substring(4)) - 1;
t = worldEdit.getServer().resolveItem(blockAndExtraData[0]); Actor actor = context.requireActor();
if (!(actor instanceof Player)) {
throw new InputParseException("The user is not a player!");
}
Player player = (Player) actor;
BlockBag bag = player.getInventoryBlockBag();
if (bag == null || !(bag instanceof SlottableBlockBag)) {
throw new InputParseException("Unsupported!");
}
SlottableBlockBag slottable = (SlottableBlockBag) bag;
BaseItem item = slottable.getItem(slot);
blockId = item.getType();
if (!player.getWorld().isValidBlockType(blockId)) {
throw new InputParseException("You're not holding a block!");
}
blockType = BlockType.fromID(blockId);
data = item.getData();
nbt = item.getNbtData();
break;
} catch (NumberFormatException ignore) {}
}
default: {
// Attempt to parse the item ID or otherwise resolve an item/block
// name to its numeric ID
if (MathMan.isInteger(testId)) {
blockId = Integer.parseInt(testId);
blockType = BlockType.fromID(blockId);
} else {
BundledBlockData.BlockEntry block = BundledBlockData.getInstance().findById(testId);
if (block == null) {
BaseBlock baseBlock = BundledBlockData.getInstance().findByState(testId);
if (baseBlock == null) {
blockType = BlockType.lookup(testId);
if (blockType == null) {
int t = worldEdit.getServer().resolveItem(testId);
if (t == 0 && !testId.contains("air")) {
throw new NoMatchException("Invalid block '" + input + "'.");
}
if (t >= 0) { if (t >= 0) {
blockType = BlockType.fromID(t); // Could be null blockType = BlockType.fromID(t); // Could be null
blockId = t; blockId = t;
typeAndData = new String[]{blockAndExtraData[0]}; } else if (blockLocator.length == 2) { // Block IDs in MC 1.7 and above use mod:name
testId = blockAndExtraData[0]; t = worldEdit.getServer().resolveItem(blockAndExtraData[0]);
if (t >= 0) {
blockType = BlockType.fromID(t); // Could be null
blockId = t;
typeAndData = new String[]{blockAndExtraData[0]};
testId = blockAndExtraData[0];
}
} }
} }
} else {
blockId = baseBlock.getId();
blockType = BlockType.fromID(blockId);
data = baseBlock.getData();
} }
} else { } else {
blockId = baseBlock.getId(); blockId = block.legacyId;
blockType = BlockType.fromID(blockId); blockType = BlockType.fromID(blockId);
data = baseBlock.getData();
} }
} else {
blockId = block.legacyId;
blockType = BlockType.fromID(blockId);
} }
} if (blockId == -1 && blockType == null) {
if (blockId == -1 && blockType == null) { // Maybe it's a cloth
// Maybe it's a cloth ClothColor col = ClothColor.lookup(testId);
ClothColor col = ClothColor.lookup(testId); if (col == null) {
if (col == null) { throw new NoMatchException("Can't figure out what block '" + input + "' refers to");
throw new NoMatchException("Can't figure out what block '" + input + "' refers to"); }
blockType = BlockType.CLOTH;
data = col.getID();
// Prevent overriding the data value
parseDataValue = false;
} }
blockType = BlockType.CLOTH; // Read block ID
data = col.getID(); if (blockId == -1) {
blockId = blockType.getID();
}
// Prevent overriding the data value if (!context.requireWorld().isValidBlockType(blockId)) {
parseDataValue = false; throw new NoMatchException("Does not match a valid block type: '" + input + "'");
} }
// Read block ID
if (blockId == -1) {
blockId = blockType.getID();
}
if (!context.requireWorld().isValidBlockType(blockId)) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
} }
} }
if (!context.isPreferringWildcard() && data == -1) { if (!context.isPreferringWildcard() && data == -1) {
// No wildcards allowed => eliminate them. // No wildcards allowed => eliminate them.
data = 0; data = 0;

View File

@ -0,0 +1,17 @@
package com.sk89q.worldedit.extent.inventory;
import com.sk89q.worldedit.blocks.BaseItem;
public interface SlottableBlockBag {
BaseItem getItem(int slot);
void setItem(int slot, BaseItem block);
default int size() {
return 36;
}
default int getSelectedSlot() {
return -1;
}
}