package com.lyndir.omicron.api;
import static com.lyndir.omicron.api.Security.*;
import com.google.common.collect.*;
import java.util.*;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.*;
import com.lyndir.omicron.api.util.Maybe;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* <i>10 15, 2012</i>
*
* @author lhunath
*/
public class GameObject extends MetaObject implements IGameObject {
@SuppressWarnings("UnusedDeclaration")
private static final Logger logger = Logger.get( GameObject.class );
private final GameObjectController<? extends GameObject> controller;
private final UnitType unitType;
private final Game game;
private final long objectID;
private final ImmutableListMultimap<PublicModuleType<?>, Module> modules;
@Nullable
private Player owner;
private Tile location;
GameObject(@Nonnull final UnitType unitType, @Nonnull final Game game, @Nonnull final Player owner, final Tile location) {
this( unitType, game, owner, location, owner.nextObjectID() );
}
GameObject(@Nonnull final UnitType unitType, @Nonnull final Game game, @Nullable final Player owner, final Tile location,
final long objectID) {
this.unitType = unitType;
this.game = game;
this.owner = owner;
this.location = location;
this.objectID = objectID;
ImmutableListMultimap.Builder<PublicModuleType<?>, Module> modulesBuilder = ImmutableListMultimap.builder();
for (final Module module : unitType.createModules()) {
modulesBuilder.put( module.getType(), module );
module.setGameObject( this );
}
modules = modulesBuilder.build();
controller = new GameObjectController<>( this );
}
/**
* Register ourselves into the game.
*/
void register() {
location.setContents( this );
if (owner != null)
owner.addObjects( this );
}
@Override
public int hashCode() {
return Objects.hashCode( objectID );
}
@Override
public boolean equals(final Object obj) {
return obj instanceof IGameObject && objectID == ((IGameObject) obj).getObjectID();
}
@Override
@Nonnull
public GameObjectController<? extends GameObject> getController() {
return controller;
}
@Override
@Nonnull
public Optional<Player> getOwner() {
return Optional.ofNullable( owner );
}
void setOwner(@Nullable final Player owner) {
Change.From<IPlayer> ownerChange = Change.<IPlayer>from( this.owner );
this.owner = owner;
getGame().getController().fireIfObservable( this ) //
.onUnitCaptured( this, ownerChange.to( this.owner ) );
}
@Override
public long getObjectID() {
return objectID;
}
@Override
public Game getGame() {
return game;
}
@Override
public Maybe<Tile> getLocation() {
if (!isGod() && !isOwnedByCurrentPlayer())
if (!currentPlayer().canObserve( location ).isTrue())
// Has a location but current player cannot observe it.
return Maybe.unknown();
// We're either god, can be observed by or are owned by the current player.
return Maybe.of( location );
}
void setLocation(@Nonnull final Tile location) {
Change.From<ITile> locationChange = Change.<ITile>from( this.location );
this.location = location;
getGame().getController().fireIfObservable( location ) //
.onUnitMoved( this, locationChange.to( this.location ) );
}
@Override
public UnitType getType() {
return unitType;
}
@Override
public ImmutableMultimap<PublicModuleType<?>, ? extends IModule> getModulesByType() {
assertObservable( this );
return modules;
}
@Nullable
static GameObject castN(@Nullable final IGameObject gameObject) {
return (GameObject) gameObject;
}
static GameObject cast(final IGameObject gameObject) {
return (GameObject) gameObject;
}
}