package net.minecraft.command.selectors;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.SyntaxErrorException;
import net.minecraft.command.arg.ArgWrapper;
import net.minecraft.command.arg.CommandArg;
import net.minecraft.command.arg.TypedWrapper;
import net.minecraft.command.arg.TypedWrapper.Getter;
import net.minecraft.command.collections.TypeIDs;
import net.minecraft.command.construction.SelectorConstructable;
import net.minecraft.command.descriptors.SelectorDescriptorDefault.DefaultParserData;
import net.minecraft.command.parser.Parser;
import net.minecraft.command.type.custom.nbt.TypeNBTArg;
import net.minecraft.command.type.management.TypeID;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.Vec3;
public abstract class SelectorNBT extends CommandArg<NBTBase>
{
public static final SelectorConstructable constructable = new SelectorConstructable()
{
@Override
public ArgWrapper<NBTBase> construct(final DefaultParserData parserData) throws SyntaxErrorException
{
final TypedWrapper<?> nbt = getRequiredParam(0, parserData);
final Getter<String> path = getParam(TypeIDs.String, 1, parserData);
final TypeID<?> type = nbt.type();
if (type == TypeIDs.Entity)
return TypeIDs.NBTBase.wrap(new EntityNBT(path, nbt.get(TypeIDs.Entity)));
if (type == TypeIDs.NBTBase)
return TypeIDs.NBTBase.wrap(new CompoundNBT(path, nbt.get(TypeIDs.NBTBase)));
if (type == TypeIDs.Coordinates)
return TypeIDs.NBTBase.wrap(new BlockNBT(path, nbt.get(TypeIDs.Coordinates)));
return TypeIDs.NBTBase.wrap(new StringNBT(path, nbt.get(TypeIDs.String)));
}
};
private final Getter<String> path;
public SelectorNBT(final Getter<String> path)
{
this.path = path;
}
public NBTBase lookup(NBTBase tag) throws CommandException
{
if (this.path == null)
return tag;
final String path = this.path.get();
final String[] parts = path.split("\\.");
for (final String part : parts)
{
switch (tag.getId())
{
case 10:
tag = ((NBTTagCompound) tag).getTag(part);
break;
case 9:
try
{
tag = ((NBTTagList) tag).get(Integer.parseInt(part));
break;
} catch (final NumberFormatException e)
{
}
default:
tag = null;
}
if (tag == null)
throw new CommandException("Unable to find '" + path + "' in tag");
}
return tag;
}
public static class EntityNBT extends SelectorNBT
{
private final Getter<Entity> entity;
public EntityNBT(final Getter<String> path, final Getter<Entity> getter)
{
super(path);
this.entity = getter;
}
@Override
public NBTBase eval(final ICommandSender sender) throws CommandException
{
final NBTTagCompound tag = new NBTTagCompound();
final Entity e = this.entity.get();
if (!e.writeMountToNBT(tag))
e.writeToNBT(tag);
return this.lookup(tag);
}
}
public static class CompoundNBT extends SelectorNBT
{
private final Getter<NBTBase> tag;
public CompoundNBT(final Getter<String> path, final Getter<NBTBase> tag)
{
super(path);
this.tag = tag;
}
@Override
public NBTBase eval(final ICommandSender sender) throws CommandException
{
return this.lookup(this.tag.get());
}
}
public static class BlockNBT extends SelectorNBT
{
private final Getter<Vec3> coord;
public BlockNBT(final Getter<String> path, final Getter<Vec3> coord)
{
super(path);
this.coord = coord;
}
@Override
public NBTBase eval(final ICommandSender sender) throws CommandException
{
final BlockPos pos = new BlockPos(this.coord.get());
final TileEntity te = sender.getEntityWorld().getTileEntity(pos);
if (te == null)
throw new CommandException("Block at " + pos.toString() + " has no associated NBT-data");
final NBTTagCompound tag = new NBTTagCompound();
te.writeToNBT(tag);
return this.lookup(tag);
}
}
public static class StringNBT extends SelectorNBT
{
private final Getter<String> nbtString;
public StringNBT(final Getter<String> path, final Getter<String> nbtString)
{
super(path);
this.nbtString = nbtString;
}
@Override
public NBTBase eval(final ICommandSender sender) throws CommandException
{
CommandArg<NBTTagCompound> nbt;
try
{
final Parser parser = new Parser(this.nbtString.get());
nbt = TypeNBTArg.parserDefault.parse(parser).arg();
} catch (final Throwable t)
{
throw new CommandException("Unable to parse NBT-Tag", t);
}
return this.lookup(nbt.eval(sender));
}
}
}