/* * Copyright (c) 2015 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA 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. * * NOVA 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 NOVA. If not, see <http://www.gnu.org/licenses/>. */ package nova.core.entity; import nova.core.block.Stateful; import nova.core.component.ComponentMap; import nova.core.component.ComponentProvider; import nova.core.component.misc.FactoryProvider; import nova.core.component.transform.EntityTransform; import nova.core.entity.component.Player; import nova.core.util.Identifiable; import nova.core.util.UniqueIdentifiable; import nova.core.world.World; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import java.util.Set; /** * An entity is an object in the world that has a position. */ @SuppressWarnings("rawtypes") public class Entity extends ComponentProvider<ComponentMap> implements UniqueIdentifiable, Identifiable, Stateful { public final EntityTransform transform() { return components.get(EntityTransform.class); } public final World world() { return transform().world(); } public final Vector3D position() { return transform().position(); } public final Vector3D scale() { return transform().scale(); } public final Vector3D pivot() { return transform().pivot(); } public final Rotation rotation() { return transform().rotation(); } public final double x() { return position().getX(); } public final double y() { return position().getY(); } public final double z() { return position().getZ(); } public void setWorld(World world) { transform().setWorld(world); } public void setPosition(Vector3D pos) { transform().setPosition(pos); } public void setScale(Vector3D scale) { transform().setScale(scale); } public void setPivot(Vector3D pivot) { transform().setPivot(pivot); } public void setRotation(Rotation rotation) { transform().setRotation(rotation); } public final EntityFactory getFactory() { return (EntityFactory) components.get(FactoryProvider.class).factory; } @Override public final String getID() { return getFactory().getID(); } @Override public String getUniqueID() { Set<UniqueIdentifiable> ui = components.getSet(UniqueIdentifiable.class); if (ui.size() == 1) { return ui.iterator().next().getUniqueID(); // Just get the first instance. } else if (ui.size() > 1) { return ui.stream() // Stream iterate over the whole set .filter(s -> s instanceof Player).findFirst() // If we have a player component, then prefer that over anything else, .map(UniqueIdentifiable::getUniqueID) // as the player UUID is usually preferable over anything else. .orElseGet(() -> ui.iterator().next().getUniqueID()); // If we don't have a player component, just use the first UUID we can find. } else { return getID(); // As a fallback, if all else fails, just use the generic entity ID. } } }