blob: e5416e3d965ba805f106e148d242400b32047e01 [file] [log] [blame] [raw]
/*
* Copyright (c) 2010-2011 Graham Edgecombe.
*
* This file is part of Lightstone.
*
* Lightstone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lightstone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Lightstone. If not, see <http://www.gnu.org/licenses/>.
*/
package net.lightstone.model;
import net.lightstone.msg.Message;
import net.lightstone.world.World;
/**
* Represents some entity in the world such as an item on the floor or a player.
* @author Graham Edgecombe
*/
public abstract class Entity {
/**
* The world this entity belongs to.
*/
protected final World world;
/**
* A flag indicating if this entity is currently active.
*/
protected boolean active = true;
/**
* This entity's unique id.
*/
protected int id;
/**
* The current position.
*/
protected Position position = Position.ZERO;
/**
* The position in the last cycle.
*/
protected Position previousPosition = Position.ZERO;
/**
* The current rotation.
*/
protected Rotation rotation = Rotation.ZERO;
/**
* The rotation in the last cycle.
*/
protected Rotation previousRotation = Rotation.ZERO;
/**
* Creates an entity and adds it to the specified world.
* @param world The world.
*/
public Entity(World world) {
this.world = world;
world.getEntities().allocate(this);
}
/**
* Checks if this entity is within the {@link Chunk#VISIBLE_RADIUS} of
* another.
* @param other The other entity.
* @return {@code true} if the entities can see each other, {@code false} if
* not.
*/
public boolean isWithinDistance(Entity other) {
double dx = Math.abs(position.getX() - other.position.getX());
double dz = Math.abs(position.getZ() - other.position.getZ());
return dx <= (Chunk.VISIBLE_RADIUS * Chunk.WIDTH) && dz <= (Chunk.VISIBLE_RADIUS * Chunk.HEIGHT);
}
/**
* Gets the world this entity is in.
* @return The world this entity is in.
*/
public World getWorld() {
return world;
}
/**
* Destroys this entity by removing it from the world and marking it as not
* being active.
*/
public void destroy() {
active = false;
world.getEntities().deallocate(this);
}
/**
* Checks if this entity is active.
* @return {@code true} if so, {@code false} if not.
*/
public boolean isActive() {
return active;
}
/**
* Gets the id of this entity.
* @return The id.
*/
public int getId() {
return id;
}
/**
* Called every game cycle. Subclasses should implement this to implement
* periodic functionality e.g. mob AI.
*/
public void pulse() {
}
/**
* Resets the previous position and rotations of the entity to the current
* position and rotation.
*/
public void reset() {
previousPosition = position;
previousRotation = rotation;
}
/**
* Gets this entity's position.
* @return The position of this entity.
*/
public Position getPosition() {
return position;
}
/**
* Gets the entity's previous position.
* @return The previous position of this entity.
*/
public Position getPreviousPosition() {
return previousPosition;
}
/**
* Sets this entity's position.
* @param position The new position.
*/
public void setPosition(Position position) {
this.position = position;
}
/**
* Gets this entity's rotation.
* @return The rotation of this entity.
*/
public Rotation getRotation() {
return rotation;
}
/**
* Gets the entity's previous rotation.
* @return The previous rotation of this entity.
*/
public Rotation getPreviousRotation() {
return previousRotation;
}
/**
* Sets this entity's rotation.
* @param rotation The new rotation.
*/
public void setRotation(Rotation rotation) {
this.rotation = rotation;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Entity other = (Entity) obj;
if (id != other.id)
return false;
return true;
}
/**
* Creates a {@link Message} which can be sent to a client to spawn this
* entity.
* @return A message which can spawn this entity.
*/
public abstract Message createSpawnMessage();
/**
* Creates a {@link Message} which can be sent to a client to update this
* entity.
* @return A message which can update this entity.
*/
public abstract Message createUpdateMessage();
/**
* Checks if this entity has moved this cycle.
* @return {@code true} if so, {@code false} if not.
*/
public boolean hasMoved() {
return !position.equals(previousPosition);
}
/**
* Checks if this entity has rotated this cycle.
* @return {@code true} if so, {@code false} if not.
*/
public boolean hasRotated() {
return !rotation.equals(previousRotation);
}
}