package com.lyndir.omicron.api;
import static com.lyndir.omicron.api.Security.currentPlayer;
import com.google.common.base.*;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.*;
import com.lyndir.lhunath.opal.system.util.*;
import java.util.*;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* <i>10 15, 2012</i>
*
* @author lhunath
*/
public class Player extends MetaObject implements IPlayer {
private static final String[] firstNames = { "Jack", "Daniel", "Derrick", "Yasmin", "Catherin", "Mary" };
private static final String[] lastNames = { "Taylor", "Smith", "Brown", "Wilson", "Jones", "Lee" };
private static final Random random = new Random();
@ObjectMeta(ignoreFor = ObjectMeta.For.all)
private final PlayerController controller = new PlayerController( this );
private final long playerID;
@ObjectMeta(ignoreFor = ObjectMeta.For.all)
private final PlayerKey key;
private final String name;
@ObjectMeta(ignoreFor = ObjectMeta.For.toString)
private final Color primaryColor;
@ObjectMeta(ignoreFor = ObjectMeta.For.toString)
private final Color secondaryColor;
@ObjectMeta(ignoreFor = ObjectMeta.For.all)
private final Map<Long, GameObject> objects = Collections.synchronizedMap( new HashMap<>() );
@ObjectMeta(ignoreFor = ObjectMeta.For.all)
private int score;
@ObjectMeta(ignoreFor = ObjectMeta.For.all)
private int nextObjectSeed;
public Player(final long playerID, @Nullable final PlayerKey key, final String name, final Color primaryColor,
final Color secondaryColor) {
this.playerID = playerID;
this.key = key;
this.name = name;
this.primaryColor = primaryColor;
this.secondaryColor = secondaryColor;
}
@Override
public int hashCode() {
return Objects.hashCode( playerID );
}
@Override
public boolean equals(@Nullable final Object obj) {
return obj instanceof IPlayer && playerID == ((IPlayer) obj).getPlayerID();
}
@Override
@Nonnull
public PlayerController getController() {
return controller;
}
@Override
public long getPlayerID() {
return playerID;
}
boolean hasKey(@Nonnull final PlayerKey playerKey) {
return playerKey.equals( key );
}
boolean isKeyLess() {
return key == null;
}
@Override
public boolean isCurrentPlayer() {
return equals( currentPlayer() );
}
@Override
public String getName() {
return name;
}
@Override
public Color getPrimaryColor() {
return primaryColor;
}
@Override
public Color getSecondaryColor() {
return secondaryColor;
}
ImmutableSet<GameObject> getObjects() {
return ImmutableSet.copyOf( objects.values() );
}
public static String randomName() {
return Joiner.on( ' ' ).join( firstNames[random.nextInt( firstNames.length )], lastNames[random.nextInt( lastNames.length )] );
}
@Override
public int getScore() {
return score;
}
void setScore(final int score) {
ChangeInt.From scoreChange = ChangeInt.from( this.score );
this.score = score;
getController().getGameController().fire().onPlayerScore( this, scoreChange.to( this.score ) );
}
long nextObjectID() {
return Hashing.murmur3_128().newHasher().putLong( playerID ).putInt( nextObjectSeed++ ).hash().asLong();
}
@Nonnull
Optional<GameObject> getObject(final long objectId) {
return Optional.ofNullable( objects.get( objectId ) );
}
void removeObject(final IGameObject gameObject) {
IGameObject lostObject = objects.remove( gameObject.getObjectID() );
Preconditions.checkState( lostObject == null || lostObject == gameObject );
if (lostObject != null)
getController().getGameController()
.fireIfPlayer( this::equals )
.onPlayerLostObject( this, lostObject );
}
void addObjects(final GameObject gameObject) {
GameObject previousObject = objects.put( gameObject.getObjectID(), gameObject );
Preconditions.checkState( previousObject == null || previousObject == gameObject );
if (previousObject == null)
getController().getGameController()
.fireIfPlayer( this::equals )
.onPlayerGainedObject( this, gameObject );
}
void addObjects(final IGameObject... gameObjects) {
for (final IGameObject gameObject : gameObjects)
addObjects( gameObject );
}
@Override
public ImmutableMap<Long, IGameObject> getObjectsByID() {
return ImmutableMap.copyOf( objects );
}
static Player cast(final IPlayer player) {
return (Player) player;
}
}