Search in sources :

Example 1 with EntityTrackerHook

use of com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook in project BKCommonLib by bergerhealer.

the class CommonEntity method spawn.

/**
 * Creates a new Entity and spawns it at the Location and using the controllers
 * specified.
 *
 * @param entityType to spawn
 * @param location to spawn at
 * @param controller to assign to the Entity after spawning
 * @param networkController to assign to the Entity after spawning
 * @return True if spawning occurred, False if not
 * @see #spawn(Location)
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public static final CommonEntity spawn(EntityType entityType, Location location, EntityController controller, EntityNetworkController networkController) {
    CommonEntityType type = CommonEntityType.byEntityType(entityType);
    if (type == CommonEntityType.UNKNOWN) {
        throw new IllegalArgumentException("The Entity Type '" + entityType + "' is invalid!");
    }
    // Create the common entity and Entity NMS handle to add to the server
    final CommonEntity<org.bukkit.entity.Entity> entity = type.createNMSHookEntity(location);
    // Set controller before spawning
    controller.bind(entity, false);
    // We do this by temporarily hooking the EntityTracker, cancelling track() for the entity we don't want
    if (networkController != null && !(networkController instanceof DefaultEntityNetworkController)) {
        // Purpur: enable legacy tracking logic when controllers are used
        if (EntityHandle.T.setLegacyTrackingEntity.isAvailable()) {
            EntityHandle.T.setLegacyTrackingEntity.invoker.invoke(entity.getHandle(), Boolean.TRUE);
        }
        // Hook the entity tracker to cancel track() on this Entity
        Object nmsWorldHandle = HandleConversion.toWorldHandle(location.getWorld());
        EntityTrackerHook hook = hookWorldEntityTracker(nmsWorldHandle);
        hook.ignoredEntities.add(entity.getHandle());
        try {
            // Spawn the entity. This will not create an entity tracker entry.
            EntityUtil.addEntity(entity.getEntity());
            // This is why we use bind(entity, false)!
            // Fire onAttached after having added the Entity to the world
            entity.getController().onAttached();
            // Set the network controller
            entity.setNetworkController(networkController);
        // entity.getNetworkController().onAttached(); // Not needed, the setNetworkController() above does this
        } finally {
            // Remove the entity from the ignore list, restore Entity Tracker entry if last entity
            hook.ignoredEntities.remove(entity.getHandle());
            unhookWorldEntityTracker(nmsWorldHandle, hook);
        }
    } else {
        // Simply spawn. No special things to do here.
        EntityUtil.addEntity(entity.getEntity());
        // This is why we use bind(entity, false)!
        // Fire onAttached after having added the Entity to the world
        entity.getController().onAttached();
    }
    return entity;
}
Also used : CommonLivingEntity(com.bergerkiller.bukkit.common.entity.type.CommonLivingEntity) ExtendedEntity(com.bergerkiller.bukkit.common.bases.ExtendedEntity) EntityTrackerHook(com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook)

Example 2 with EntityTrackerHook

use of com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook in project BKCommonLib by bergerhealer.

the class CommonEntity method hookWorldEntityTracker.

/*
     * Hooks the world's EntityTracker temporarily for the sole purpose of blocking calls to track()
     */
private static EntityTrackerHook hookWorldEntityTracker(Object nmsWorldHandle) {
    Object nmsEntityTrackerHandle = WorldServerHandle.T.getEntityTrackerHandle.invoke(nmsWorldHandle);
    EntityTrackerHook hook = EntityTrackerHook.get(nmsEntityTrackerHandle, EntityTrackerHook.class);
    if (hook == null) {
        hook = new EntityTrackerHook(nmsEntityTrackerHandle);
        WorldServerHandle.T.setEntityTrackerHandle.invoke(nmsWorldHandle, hook.hook(nmsEntityTrackerHandle));
    }
    return hook;
}
Also used : EntityTrackerHook(com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook)

Example 3 with EntityTrackerHook

use of com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook in project BKCommonLib by bergerhealer.

the class CommonEntity method teleport.

@Override
public boolean teleport(Location location, TeleportCause cause) {
    if (isRemoved()) {
        return false;
    }
    // Preparations prior to teleportation
    final Location oldLocation = entity.getLocation();
    final List<org.bukkit.entity.Entity> passengers = getPassengers();
    final WorldHandle newworld = WorldHandle.fromBukkit(location.getWorld());
    final boolean isWorldChange = !this.handle.getWorld().equals(newworld);
    final EntityNetworkController<?> oldNetworkController = getNetworkController();
    final boolean hasNetworkController = !(oldNetworkController instanceof DefaultEntityNetworkController);
    WorldUtil.loadChunks(location, 3);
    // If in a vehicle, make sure we eject first
    if (isInsideVehicle()) {
        ExtendedEntity<Entity> extVeh = new ExtendedEntity<Entity>(getVehicle());
        if (!extVeh.removePassenger(entity)) {
            return false;
        }
    }
    // If vehicle, eject the passenger first
    if (hasPassenger()) {
        this.setPassengersSilent(Collections.<org.bukkit.entity.Entity>emptyList());
    }
    // Perform actual teleportation
    final boolean succ;
    if (entity instanceof Player) {
        // No special logic here. Just teleport.
        succ = entity.teleport(location, cause);
    } else if (!isWorldChange) {
        // First: stop tracking the entity
        final EntityTracker tracker = WorldUtil.getTracker(getWorld());
        tracker.stopTracking(entity);
        // Destroy packets are queued: Make sure to send them RIGHT NOW
        for (Player bukkitPlayer : WorldUtil.getPlayers(getWorld())) {
            CommonPlayer player = get(bukkitPlayer);
            if (player != null) {
                player.flushEntityRemoveQueue();
            }
        }
        // Teleport the non-player entity
        succ = entity.teleport(location, cause);
        // Start tracking the entity again
        if (!hasNetworkController && !isWorldChange) {
            tracker.startTracking(entity);
        }
    } else {
        // Remove from one world and add to the other
        this.handle.getWorldServer().removeEntityWithoutDeath(this.handle);
        this.handle.setDestroyed(false);
        this.handle.setWorld(newworld);
        this.handle.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        if (hasNetworkController) {
            // Hook the entity tracker to cancel track() on this Entity
            Object nmsWorldHandle = HandleConversion.toWorldHandle(location.getWorld());
            EntityTrackerHook hook = hookWorldEntityTracker(nmsWorldHandle);
            hook.ignoredEntities.add(this.handle.getRaw());
            try {
                // Spawn the entity. This will not create an entity tracker entry.
                EntityUtil.addEntity(entity);
            } finally {
                // Remove the entity from the ignore list, restore Entity Tracker entry if last entity
                hook.ignoredEntities.remove(this.handle.getRaw());
                unhookWorldEntityTracker(nmsWorldHandle, hook);
            }
        } else {
            // Simply add the entity, which will register a (default) network controller
            EntityUtil.addEntity(entity);
        }
        succ = true;
    }
    // If there was a passenger, teleport it and let passenger enter again
    if (succ && !passengers.isEmpty()) {
        // Teleport the passenger, but ignore the chunk send check so vehicle is properly spawned to all players
        List<org.bukkit.entity.Entity> teleportedPassengers = new ArrayList<org.bukkit.entity.Entity>();
        this.handle.setIgnoreChunkCheck(true);
        float yawChange = location.getYaw() - oldLocation.getYaw();
        float pitchChange = location.getPitch() - oldLocation.getPitch();
        for (org.bukkit.entity.Entity passenger : passengers) {
            // Figure out a suitable location yaw and pitch based on what it was before
            // We must make sure that when players are mounted, they still face the same way relatively
            Location passengerOld = passenger.getLocation();
            Location passengerLoc = location.clone();
            passengerLoc.setYaw(passengerOld.getYaw() + yawChange);
            passengerLoc.setPitch(passengerOld.getPitch() + pitchChange);
            if (get(passenger).teleport(passengerLoc, cause)) {
                teleportedPassengers.add(passenger);
            }
        }
        ;
        this.handle.setIgnoreChunkCheck(false);
        if (!teleportedPassengers.isEmpty()) {
            if (hasNetworkController) {
                // network controller is used; simply set the passengers of the entity handle
                List<EntityHandle> passengerHandles = new ArrayList<EntityHandle>(teleportedPassengers.size());
                for (org.bukkit.entity.Entity passenger : teleportedPassengers) {
                    EntityHandle phandle = EntityHandle.fromBukkit(passenger);
                    passengerHandles.add(phandle);
                    phandle.setVehicle(this.handle);
                }
                this.handle.setPassengers(passengerHandles);
            } else {
                setPassengersSilent(teleportedPassengers);
            }
        }
    }
    // Set network controller last, to make sure passenger mounting packets are sent properly
    if (hasNetworkController) {
        setNetworkController(oldNetworkController);
    }
    return succ;
}
Also used : CommonLivingEntity(com.bergerkiller.bukkit.common.entity.type.CommonLivingEntity) ExtendedEntity(com.bergerkiller.bukkit.common.bases.ExtendedEntity) ExtendedEntity(com.bergerkiller.bukkit.common.bases.ExtendedEntity) CommonPlayer(com.bergerkiller.bukkit.common.entity.type.CommonPlayer) WorldHandle(com.bergerkiller.generated.net.minecraft.world.level.WorldHandle) EntityTracker(com.bergerkiller.bukkit.common.wrappers.EntityTracker) ArrayList(java.util.ArrayList) EntityHandle(com.bergerkiller.generated.net.minecraft.world.entity.EntityHandle) CraftEntityHandle(com.bergerkiller.generated.org.bukkit.craftbukkit.entity.CraftEntityHandle) CommonPlayer(com.bergerkiller.bukkit.common.entity.type.CommonPlayer) EntityTrackerHook(com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook) org.bukkit.entity(org.bukkit.entity) Location(org.bukkit.Location)

Aggregations

EntityTrackerHook (com.bergerkiller.bukkit.common.internal.hooks.EntityTrackerHook)3 ExtendedEntity (com.bergerkiller.bukkit.common.bases.ExtendedEntity)2 CommonLivingEntity (com.bergerkiller.bukkit.common.entity.type.CommonLivingEntity)2 CommonPlayer (com.bergerkiller.bukkit.common.entity.type.CommonPlayer)1 EntityTracker (com.bergerkiller.bukkit.common.wrappers.EntityTracker)1 EntityHandle (com.bergerkiller.generated.net.minecraft.world.entity.EntityHandle)1 WorldHandle (com.bergerkiller.generated.net.minecraft.world.level.WorldHandle)1 CraftEntityHandle (com.bergerkiller.generated.org.bukkit.craftbukkit.entity.CraftEntityHandle)1 ArrayList (java.util.ArrayList)1 Location (org.bukkit.Location)1 org.bukkit.entity (org.bukkit.entity)1