package com.lyndir.omicron.cli.command;
import com.google.common.base.Throwables;
import com.google.common.collect.*;
import com.lyndir.lhunath.opal.math.*;
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
import com.lyndir.omicron.api.*;
import com.lyndir.omicron.api.util.Maybe;
import com.lyndir.omicron.cli.OmicronCLI;
import java.util.Iterator;
import java.util.Optional;
import java.util.stream.Stream;
/**
* <i>10 07, 2012</i>
*
* @author lhunath
*/
@CommandGroup(name = "move", abbr = "mv", desc = "Move game objects around in the level.")
public class MoveCommand extends Command {
public MoveCommand(final OmicronCLI omicron) {
super( omicron );
}
@Override
public void evaluate(final Iterator<String> tokens) {
Optional<IPlayer> localPlayerOptional = getOmicron().getLocalPlayer();
if (!localPlayerOptional.isPresent()) {
err( "No local player in the game." );
return;
}
IPlayer localPlayer = localPlayerOptional.get();
String objectIDArgument = Iterators.getNext( tokens, null );
if (objectIDArgument == null) {
err( "Missing objectID. Syntax: objectID side/level" );
return;
}
if ("help".equals( objectIDArgument )) {
inf( "Usage: objectID side/level" );
inf( " objectID: The ID of the object to move (see list objects)." );
inf( " side/level: The side of the object's current tile or level to move to." );
return;
}
int objectId = ConversionUtils.toIntegerNN( objectIDArgument );
String sideArgument = Iterators.getNext( tokens, null );
if (sideArgument == null) {
err( "Missing side/level. Syntax: objectID side/level" );
return;
}
Optional<Side> side = Side.forName( sideArgument );
if (!side.isPresent()) {
err( "No such side/level: %s. Valid sides are: %s, valid levels are: %s", side, //
Stream.of( Side.values() ).map( Side::name ), //
Stream.of( LevelType.values() ).map( LevelType::name )
);
return;
}
// Find the game object for the given ID.
Maybe<? extends IGameObject> maybeObject = localPlayer.getController().getObject( objectId );
if (maybeObject.presence() != Maybe.Presence.PRESENT) {
err( "No observable object with ID: %s", objectId );
return;
}
IGameObject gameObject = maybeObject.get();
// Check to see if it's mobile by finding its mobility module.
Optional<IMobilityModule> optionalMobility = gameObject.getModule( PublicModuleType.MOBILITY, 0 );
if (!optionalMobility.isPresent()) {
err( "Object is not mobile: %s", gameObject );
return;
}
IMobilityModule mobilityModule = optionalMobility.get();
Maybe<? extends ITile> maybeLocation = mobilityModule.getGameObject().getLocation();
if (maybeLocation.presence() != Maybe.Presence.PRESENT) {
err( "Object's location is not known: %s", gameObject );
return;
}
ITile location = maybeLocation.get();
Vec2 targetPosition = location.getPosition().translate( side.get().getDelta() );
Optional<? extends ITile> targetLocation = location.getLevel().getTile( targetPosition );
if (!targetLocation.isPresent()) {
err( "No tile at that side for position: %s.", targetPosition );
return;
}
// Move the object.
IMobilityModuleController.IMovement movement = mobilityModule.getController().movement( targetLocation.get() );
if (!movement.isPossible()) {
err( "This movement is not possible: %s.", movement );
return;
}
try {
movement.execute();
inf( "Object is now at: %s", gameObject.getLocation() );
}
catch (IModule.ImpossibleException | IModule.InvalidatedException e) {
throw Throwables.propagate( e );
}
}
}