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;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.bukkit.util.ItemUtil;
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.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID;
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 ItemStack[] items;
@ -60,6 +67,59 @@ public class BukkitPlayerBlockBag extends BlockBag {
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
public void fetchItem(BaseItem item) throws BlockBagException {
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.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands;
@ -573,6 +574,7 @@ public class Fawe {
Vector2D.inject(); // Optimizations
// Block
BaseBlock.inject(); // Optimizations
BaseItem.inject();
// Biome
BaseBiome.inject(); // Features
// 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.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.ClothColor;
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.ParserContext;
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.world.World;
import com.sk89q.worldedit.world.registry.BundledBlockData;
@ -132,93 +135,120 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
CompoundTag nbt = null;
boolean parseDataValue = true;
if ("hand".equalsIgnoreCase(testId)) {
// Get the block type from the item in the user's hand.
final BaseBlock blockInHand = getBlockInHand(context.requireActor());
blockId = blockInHand.getId();
blockType = BlockType.fromID(blockId);
data = blockInHand.getData();
nbt = blockInHand.getNbtData();
} else if ("pos1".equalsIgnoreCase(testId)) {
// Get the block type from the "primary position"
final World world = context.requireWorld();
final BlockVector primaryPosition;
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);
switch (testId.substring(0, Math.min(testId.length(), 4))) {
case "pos1": {
// Get the block type from the "primary position"
final World world = context.requireWorld();
final BlockVector primaryPosition;
try {
primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition();
} catch (IncompleteRegionException e) {
throw new InputParseException("Your selection is not complete.");
}
final BaseBlock block = world.getBlock(primaryPosition);
blockId = block.getId();
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) {
blockType = BlockType.fromID(t); // Could be null
blockId = t;
} else if (blockLocator.length == 2) { // Block IDs in MC 1.7 and above use mod:name
t = worldEdit.getServer().resolveItem(blockAndExtraData[0]);
data = block.getData();
nbt = block.getNbtData();
break;
}
case "hand": {
BaseBlock blockInHand = getBlockInHand(context.requireActor());
blockId = blockInHand.getId();
blockType = BlockType.fromID(blockId);
data = blockInHand.getData();
nbt = blockInHand.getNbtData();
break;
}
case "slot": {
try {
int slot = Integer.parseInt(testId.substring(4)) - 1;
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) {
blockType = BlockType.fromID(t); // Could be null
blockId = t;
typeAndData = new String[]{blockAndExtraData[0]};
testId = blockAndExtraData[0];
} else if (blockLocator.length == 2) { // Block IDs in MC 1.7 and above use mod:name
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 {
blockId = baseBlock.getId();
blockId = block.legacyId;
blockType = BlockType.fromID(blockId);
data = baseBlock.getData();
}
} else {
blockId = block.legacyId;
blockType = BlockType.fromID(blockId);
}
}
if (blockId == -1 && blockType == null) {
// Maybe it's a cloth
ClothColor col = ClothColor.lookup(testId);
if (col == null) {
throw new NoMatchException("Can't figure out what block '" + input + "' refers to");
if (blockId == -1 && blockType == null) {
// Maybe it's a cloth
ClothColor col = ClothColor.lookup(testId);
if (col == null) {
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;
data = col.getID();
// Read block ID
if (blockId == -1) {
blockId = blockType.getID();
}
// Prevent overriding the data value
parseDataValue = false;
}
// 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.requireWorld().isValidBlockType(blockId)) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
}
}
}
if (!context.isPreferringWildcard() && data == -1) {
// No wildcards allowed => eliminate them.
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;
}
}