/* * This file is part of BukkitBridge. * * Copyright (c) 2012 Spout LLC <http://www.spout.org/> * BukkitBridge is licensed under the GNU General Public License. * * BukkitBridge 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. * * BukkitBridge 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.spout.bridge.bukkit.entity; import java.util.List; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.EntityEffect; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import org.spout.api.component.entity.EntityComponent; import org.spout.api.event.entity.EntityTeleportEvent; import org.spout.api.geo.discrete.Point; import org.spout.api.map.DefaultedKey; import org.spout.api.map.DefaultedKeyImpl; import org.spout.math.imaginary.Quaternionf; import org.spout.math.vector.Vector3f; import org.spout.bridge.BukkitUtil; import org.spout.bridge.bukkit.BridgeServer; import org.spout.vanilla.component.entity.misc.Burn; import org.spout.vanilla.component.entity.misc.Health; import org.spout.vanilla.data.VanillaData; public abstract class BridgeEntity implements Entity { protected static final DefaultedKey<Integer> TICKS_LIVED = new DefaultedKeyImpl<Integer>("ticks_lived", 0); private final org.spout.api.entity.Entity handle; private final BridgeComponent component; protected BridgeEntity(org.spout.api.entity.Entity handle) { this.handle = handle; this.component = this.handle.add(BridgeComponent.class); } public org.spout.api.entity.Entity getHandle() { return handle; } public final BridgeComponent getComponent() { return component; } @Override public BridgeServer getServer() { return (BridgeServer) Bukkit.getServer(); } @Override public List<MetadataValue> getMetadata(String key) { throw new UnsupportedOperationException(); } @Override public boolean hasMetadata(String key) { return getHandle().getData().containsKey(key); } @Override public void removeMetadata(String arg0, Plugin arg1) { getHandle().getData().remove(arg0); } @Override public void setMetadata(String arg0, MetadataValue arg1) { throw new UnsupportedOperationException(); } @Override public boolean eject() { throw new UnsupportedOperationException(); } @Override public int getEntityId() { return handle.getId(); } @Override public float getFallDistance() { throw new UnsupportedOperationException(); } @Override public int getFireTicks() { Burn burn = handle.get(Burn.class); if (burn == null) { return 0; } return (int) burn.getFireTick(); } @Override public EntityDamageEvent getLastDamageCause() { throw new UnsupportedOperationException(); } @Override public Location getLocation() { Point pos = handle.getPhysics().getPosition(); World w = getServer().getWorld(handle.getWorld().getUID()); Quaternionf rotation = handle.getPhysics().getRotation(); Vector3f rot = rotation.getAxesAnglesRad(); return new Location(w, pos.getX(), pos.getY(), pos.getZ(), rot.getY(), rot.getZ()); } @Override public int getMaxFireTicks() { throw new UnsupportedOperationException(); } @Override public List<Entity> getNearbyEntities(double arg0, double arg1, double arg2) { throw new UnsupportedOperationException(); } @Override public Entity getPassenger() { throw new UnsupportedOperationException(); } @Override public UUID getUniqueId() { return handle.getUID(); } @Override public Entity getVehicle() { throw new UnsupportedOperationException(); } @Override public Vector getVelocity() { Vector3f velocity = getHandle().getPhysics().getMovementVelocity(); return new Vector(velocity.getX(), velocity.getY(), velocity.getZ()); } @Override public World getWorld() { return getServer().getWorld(handle.getWorld().getUID()); } @Override public boolean isDead() { Health health = getHandle().get(Health.class); return health != null ? health.isDead() : handle.isRemoved(); } @Override public boolean isEmpty() { return getPassenger() == null; } @Override public boolean isInsideVehicle() { return getVehicle() != null; } @Override public boolean isValid() { return !handle.isRemoved() && handle.getId() != -1; } @Override public boolean leaveVehicle() { throw new UnsupportedOperationException(); } @Override public void playEffect(EntityEffect effect) { throw new UnsupportedOperationException(); } @Override public EntityType getType() { return null; } @Override public void remove() { handle.remove(); } @Override public void setFallDistance(float dist) { throw new UnsupportedOperationException(); } @Override public void setFireTicks(int ticks) { Burn burn = handle.get(Burn.class); if (burn != null) { burn.setOnFire(ticks / 20, true); } } @Override public void setLastDamageCause(EntityDamageEvent event) { throw new UnsupportedOperationException(); } @Override public boolean setPassenger(Entity entity) { throw new UnsupportedOperationException(); } @Override public int getTicksLived() { return handle.getData().get(TICKS_LIVED); } @Override public void setTicksLived(int ticks) { handle.getData().put(TICKS_LIVED, ticks); } @Override public void setVelocity(Vector vec) { if (handle.getPhysics().isActivated()) { handle.getPhysics().force(new Vector3f(vec.getX(), vec.getY(), vec.getZ())); } } @Override public boolean teleport(Location loc) { return teleport(loc, TeleportCause.PLUGIN); } @Override public boolean teleport(Entity entity) { return teleport(entity.getLocation()); } @Override public boolean teleport(Location loc, TeleportCause cause) { Location prev = getLocation(); // Call Spout EntityTeleportEvent; later mapped to Bukkit EntityTeleportEvent via the EntityListener EntityTeleportEvent event = new EntityTeleportEvent(handle, BukkitUtil.toPoint(prev), BukkitUtil.toPoint(loc)); handle.getEngine().getEventManager().callEvent(event); if (!event.isCancelled()) { loc = BukkitUtil.fromPoint(event.getTo()); prev = BukkitUtil.fromPoint(event.getFrom()); handle.getPhysics().setPosition(new Point(handle.getWorld(), (float) loc.getX(), (float) loc.getY(), (float) loc.getZ())); handle.getPhysics().setRotation(new Quaternionf(loc.getPitch(), loc.getYaw(), 0, 0)); return true; } return false; } @Override public boolean teleport(Entity loc, TeleportCause cause) { return teleport(loc.getLocation(), cause); } @Override public boolean equals(Object obj) { if (!(obj instanceof BridgeEntity)) { return false; } BridgeEntity other = (BridgeEntity) obj; return other.getEntityId() == this.getEntityId(); } @Override public int hashCode() { return getEntityId(); } @Override public String toString() { return "{ " + getClass().getSimpleName() + " : " + handle.toString() + " }"; } @Override public Location getLocation(Location loc) { if (loc != null) { Point pos = handle.getPhysics().getPosition(); Quaternionf rotation = handle.getPhysics().getRotation(); Vector3f rot = rotation.getAxesAnglesRad(); loc.setWorld(getWorld()); loc.setX(pos.getX()); loc.setY(pos.getY()); loc.setZ(loc.getZ()); loc.setYaw(rot.getY()); loc.setPitch(rot.getZ()); } return loc; } @Override public boolean isOnGround() { return getComponent().getData().get(VanillaData.IS_ON_GROUND); } } class BridgeComponent extends EntityComponent { private final org.spout.api.entity.Entity handle; public BridgeComponent(org.spout.api.entity.Entity entity) { this.handle = entity; } @Override public boolean canTick() { return true; } @Override public void onTick(float dt) { handle.getData().put(BridgeEntity.TICKS_LIVED, handle.getData().get(BridgeEntity.TICKS_LIVED) + 1); } }