package ring.commands;
import java.util.Collection;
import java.util.List;
import ring.entities.Entity;
import ring.items.Item;
import ring.mobiles.Mobile;
import ring.mobiles.backbone.Inventory;
import ring.movement.Room;
import ring.world.WorldObject;
/**
* This class is responsible for transforming parameters received into objects for the
* MUD to use. In effect, it is the bridge between what the user types in at the terminal
* and the internals of the object-oriented MUD system.
* @author projectmoon
*
*/
public final class CommandParameters {
//TODO rework logic for most of this. It has the following problems:
//1. Will not work for any CommandSender except Mobiles. (BIG limitation)
//2. Ghetto transformation logic. i.e.: since everything is transformed
// individually, the results may not be what is desired.
/**
* An enum representing different types of Command parameters. The type tells
* the CommandParameters objects how to translate the strings it has into
* actual MUD objects.
*/
public enum CommandType {
TEXT,
SPELL,
INVENTORY,
EQUIPMENT,
FROM_ROOM
}
private Object[] objParameters;
private String[] initParameters;
private CommandSender sender;
private CommandType cmdType;
/**
* Creates a new CommandParameters object for the specified parameter string
* and {@link CommandSender}.
* @param params
* @param sender
*/
public CommandParameters(String[] params, CommandSender sender) {
this.sender = sender;
initParameters = params;
}
/**
* Initializes the command parameters to support a particular {@link CommandType}.
* Different command types are initialized in different ways. For example, a text
* command applies no transformations to its parameters. However, a command that
* operates on a Room (i.e. CommandType.FROM_ROOM) would transform its parameters
* into {@link WorldObject}s.
* @param cmdType
*/
public void init(CommandType cmdType) {
this.cmdType = cmdType;
objParameters = getParameters(initParameters, cmdType);
}
/**
* Gets the {@link CommandType} that these parameters were
* initialized to support.
* @return
*/
public CommandType getType() {
return cmdType;
}
/**
* Returns the amount of parameters in this object.
* @return The number of parameters.
*/
public int length() {
return initParameters.length;
}
/**
* Gets the original parameter string, as split at the starting index.
* @param fromIndex
* @return
*/
public String getTextParameters(int fromIndex) {
String res = "";
for (int c = fromIndex; c < length(); c++) {
res += initParameters[c] + " ";
}
return res.trim();
}
/**
* Gets the object parameter at the specified index.
* @param index
* @return The parameter as an object, or null if there are no parameters.
*/
public Object getParameter(int index) {
if (objParameters == null)
return null;
if (index >= objParameters.length)
return null;
return objParameters[index];
}
/**
* Gets the text parameter at the specified index.
* @param index
* @return The parameter as a String, or null if there are no parameters.
*/
public String getParameterAsText(int index) {
if (objParameters == null)
return null;
else
return initParameters[index];
}
/**
* Convenience method for returning the last parameter in object form.
* @return
*/
public Object lastParameter() {
return objParameters[objParameters.length - 1];
}
/**
* Convenience method for creating spell names.
* @return
* @throws ClassCastException
*/
public String constructSpellName() throws ClassCastException {
String text = "";
for (int c = 0; c < objParameters.length - 1; c++) {
System.out.println("examining: " + objParameters[c]);
if (!(objParameters[c] instanceof String))
throw (new ClassCastException("Object must be string!"));
else
text += (String) objParameters[c] + " ";
}
return text.trim();
}
/**
* This gets the parameter string for the command, which everything
* that comes after the initial command verb.
* @return The parameter string, or null if there are no parameters.
*/
public String paramString() {
if (objParameters == null)
return null;
String res = "";
for (int c = 0; c < objParameters.length; c++) {
if (objParameters[c] == null)
res += "[null]";
else
res += objParameters[c].toString();
res += " ";
}
res = res.trim();
return res;
}
/**
* This method transforms parameters from string names into objects.
* @param params
* @param cmdType
* @return
*/
private Object[] getParameters(String[] params, CommandType cmdType) {
// Handle a command that has no parameters.
if ((params == null) || (params.length == 0) || (params[0] == null))
return null;
switch (cmdType) {
case TEXT:
return initializeForText(params);
case SPELL:
return initializeForSpell(params);
case INVENTORY:
return initializeForInventory(params);
case EQUIPMENT:
return initializeForEquipment(params);
case FROM_ROOM:
return initializeForFromRoom(params);
default:
throw new IllegalArgumentException("Unrecognized CommandType.");
}
}
/**
* Initializes the parameters for a text command. There are no transformations
* done to the parameters.
* @param params
* @return An Object array with the modified parameters.
*/
private Object[] initializeForText(String[] params) {
return params;
}
/**
* Initializes the parameters for a spell command. Leaves everything up to the
* last word as text, but transforms the last word into a target from the room.
* @param params
* @return An Object array with the modified parameters.
*/
private Object[] initializeForSpell(String[] params) {
Object[] parameters = new Object[params.length];
for (int c = 0; c < params.length - 1; c++) {
parameters[c] = params[c];
}
String name = params[params.length - 1].toString();
parameters[params.length - 1] = getWorldObjectFromRoomByName(name);
return parameters;
}
/**
* Initializes the parameters for a command that pulls from the current room.
* Every parameter is transformed into a world object from the room.
* @param params
* @return An Object array with the modified parameters.
*/
private Object[] initializeForFromRoom(String[] params) {
Object[] parameters = new Object[params.length];
for (int x = 0; x < parameters.length; x++) {
// First, let's check to see if the parameter is something in
// the room. This is the most common
// Parameter.
WorldObject o = getWorldObjectFromRoomByName(params[x]);
parameters[x] = o;
}
return parameters;
}
/**
* Initializes the parameters for a command that pulls form the
* sender's equipment. Parameters are transformed into world objects
* from the sender's equipment.
* @param params
* @return An Object array with the modified parameters.
*/
private Object[] initializeForEquipment(String[] params) {
Object[] parameters = new Object[params.length];
for (int x = 0; x < params.length; x++) {
// First, let's check to see if the parameter is something in
// the room. This is the most common
// Parameter.
WorldObject o = getWorldObjectFromEquipmentByName(params[x]);
if (o != null) {
parameters[x] = o;
}
// it must be something else. For now, pass it along.
else {
parameters[x] = params[x];
}
}
return parameters;
}
/**
* Initializes the parameters for a command that targets the sender's
* inventory. Parameters are transformed into world objects from the sender's
* inventory.
* @param params
* @return An Object array with the modified parameters.
*/
private Object[] initializeForInventory(String[] params) {
Object[] parameters = new Object[params.length];
for (int x = 0; x < params.length; x++) {
// First, let's check to see if the parameter is something in
// the room. This is the most common
// Parameter.
WorldObject o = getWorldObjectFromInventoryByName(params[x]);
if (o != null) {
parameters[x] = o;
}
// it must be something else. For now, return null.
else {
parameters[x] = null;
}
}
return parameters;
}
/**
* This method returns the most relevant {@link WorldObject} found in the sender's
* inventory.
* @param name
* @return The most relevant WorldObject, or null if nothing was found.
*/
@SuppressWarnings("unchecked")
private WorldObject getWorldObjectFromInventoryByName(String name) {
Mobile mob = (Mobile)sender;
Inventory inventory = mob.getDynamicModel().getInventory();
return search(name, inventory.getItems());
}
/**
* This method returns the most relevant WorldObject found in the
* sender's equipment.
* @param name The name of the item to search for in the equipment.
* @return The most relevant WorldObject, or null if nothing was found.
*/
@SuppressWarnings("unchecked")
private WorldObject getWorldObjectFromEquipmentByName(String name) {
Mobile mob = (Mobile) sender;
Collection<Item> items = mob.getDynamicModel().getEquipment().getItems();
return search(name, items);
}
/**
* This method returns the most relevant {@link WorldObject} found in the sender's
* current Room.
* @param name The name of the WorldObject to search for in the room.
* @return The most relevant WorldObject, or null if nothing was found.
*/
@SuppressWarnings("unchecked")
private WorldObject getWorldObjectFromRoomByName(String name) {
//Too short to search on.
if (name.length() < 2) {
return null;
}
//
Mobile senderMob = (Mobile)this.sender;
Room room = senderMob.getLocation();
//Get all world objects in this room to search against.
List<Mobile> mobs = room.getMobiles();
List<Item> items = room.getItems();
List<Entity> entities = room.getEntities();
return search(name, mobs, items, entities);
}
/**
* This method delegates to {@link ring.commands.WorldObjectSearch} in order
* to search collections of world objects from generic data sources. It returns
* the most relevant world object found amongst all presented collections. The
* text searched for is case-insensitive.
* @param name The name to search for.
* @param worldObjectLists {@link java.util.Collection}s of {@link WorldObject}s.
* @return The most relevant world object, or null if nothing was found.
*/
private WorldObject search(String name, Collection<? extends WorldObject> ... worldObjectLists) {
WorldObjectSearch search = new WorldObjectSearch();
for (Collection<? extends WorldObject> list : worldObjectLists) {
search.addSearchList(list);
}
List<WorldObject> results = search.search(name);
if (results.size() > 0) {
return results.get(0);
}
else {
return null;
}
}
public String[] getParameterArray() {
return initParameters;
}
}