All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.juliarn.npclib.common.npc.CommonNpc Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of npc-lib, licensed under the MIT License (MIT).
 *
 * Copyright (c) 2022-2023 Julian M., Pasqual K. and contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.github.juliarn.npclib.common.npc;

import com.github.juliarn.npclib.api.Npc;
import com.github.juliarn.npclib.api.NpcTracker;
import com.github.juliarn.npclib.api.Platform;
import com.github.juliarn.npclib.api.Position;
import com.github.juliarn.npclib.api.flag.NpcFlag;
import com.github.juliarn.npclib.api.profile.Profile;
import com.github.juliarn.npclib.api.protocol.NpcSpecificOutboundPacket;
import com.github.juliarn.npclib.api.protocol.enums.EntityAnimation;
import com.github.juliarn.npclib.api.protocol.enums.ItemSlot;
import com.github.juliarn.npclib.api.protocol.enums.PlayerInfoAction;
import com.github.juliarn.npclib.api.protocol.meta.EntityMetadataFactory;
import com.github.juliarn.npclib.api.settings.NpcSettings;
import com.github.juliarn.npclib.api.util.Util;
import com.github.juliarn.npclib.common.event.DefaultHideNpcEvent;
import com.github.juliarn.npclib.common.event.DefaultShowNpcEvent;
import com.github.juliarn.npclib.common.flag.CommonNpcFlaggedObject;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.UnmodifiableView;

public class CommonNpc extends CommonNpcFlaggedObject implements Npc {

  protected final int entityId;
  protected final Profile.Resolved profile;

  protected final W world;
  protected final Position pos;

  protected final Platform platform;
  protected final NpcSettings

npcSettings; protected final Set

trackedPlayers = Collections.synchronizedSet(new HashSet<>()); protected final Set

includedPlayers = Collections.synchronizedSet(new HashSet<>()); public CommonNpc( @NotNull Map, Optional> flags, int entityId, @NotNull Profile.Resolved profile, @NotNull W world, @NotNull Position pos, @NotNull Platform platform, @NotNull NpcSettings

npcSettings ) { super(flags); this.entityId = entityId; this.profile = profile; this.world = world; this.pos = pos; this.platform = platform; this.npcSettings = npcSettings; } @Override public int entityId() { return this.entityId; } @Override public @NotNull Profile.Resolved profile() { return this.profile; } @Override public @NotNull W world() { return this.world; } @Override public @NotNull Position position() { return this.pos; } @Override public @NotNull NpcSettings

settings() { return this.npcSettings; } @Override public @NotNull Platform platform() { return this.platform; } @Override public @NotNull NpcTracker npcTracker() { return this.platform.npcTracker(); } @Override public boolean shouldIncludePlayer(@NotNull P player) { return this.npcSettings.trackingRule().shouldTrack(this, player); } @Override public @UnmodifiableView @NotNull Collection

includedPlayers() { return Collections.unmodifiableSet(this.includedPlayers); } @Override public boolean includesPlayer(@NotNull P player) { return this.includedPlayers.contains(player); } @Override public @NotNull Npc addIncludedPlayer(@NotNull P player) { this.includedPlayers.add(player); return this; } @Override public @NotNull Npc removeIncludedPlayer(@NotNull P player) { this.includedPlayers.remove(player); return this; } @Override @SuppressWarnings("unchecked") public @NotNull Npc unlink() { // remove this npc from the tracked ones, do it first to prevent further player tracking this.npcTracker().stopTrackingNpc(this); // remove this npc for all tracked players Object[] players = this.trackedPlayers.toArray(); for (Object player : players) { this.stopTrackingPlayer((P) player); } // for chaining return this; } @Override public @UnmodifiableView @NotNull Collection

trackedPlayers() { return Collections.unmodifiableSet(this.trackedPlayers); } @Override public boolean tracksPlayer(@NotNull P player) { return this.trackedPlayers.contains(player); } @Override public @NotNull Npc trackPlayer(@NotNull P player) { // check if we should track the player if (this.shouldIncludePlayer(player)) { return this.forceTrackPlayer(player); } // nothing to do return this; } @Override public @NotNull Npc forceTrackPlayer(@NotNull P player) { // check if the player is not already tracked if (!this.trackedPlayers.contains(player)) { // break early if the add is not wanted by plugin if (this.platform.eventManager().post(DefaultShowNpcEvent.pre(this, player)).cancelled()) { return this; } // register the player, prevent duplicate spawns in case the entity was spawned // by a different thread during processing of the pre-track event if (!this.trackedPlayers.add(player)) { return this; } // send the player info packet & schedule the actual add of the // player entity into the target world this.platform.packetFactory().createPlayerInfoPacket(PlayerInfoAction.ADD_PLAYER).schedule(player, this); this.platform.taskManager().scheduleDelayedAsync(() -> { this.platform.packetFactory().createEntitySpawnPacket().schedule(player, this); this.platform.eventManager().post(DefaultShowNpcEvent.post(this, player)); }, 10); } return this; } @Override public @NotNull Npc stopTrackingPlayer(@NotNull P player) { // check if the player was previously tracked if (this.trackedPlayers.contains(player)) { // break early if the removal is not wanted by plugin if (this.platform.eventManager().post(DefaultHideNpcEvent.pre(this, player)).cancelled()) { return this; } // unregister the player, prevent duplicate remove packets in case the entity // was removed by a different thread during processing of the pre-hide event if (!this.trackedPlayers.remove(player)) { return this; } // schedule an entity remove (the player list change is not needed normally, but to make sure that the npc is gone) this.platform.packetFactory().createEntityRemovePacket().schedule(player, this); this.platform.packetFactory().createPlayerInfoPacket(PlayerInfoAction.REMOVE_PLAYER).schedule(player, this); // post the finish of the removal to all plugins this.platform.eventManager().post(DefaultHideNpcEvent.post(this, player)); } // for chaining return this; } @Override public @NotNull NpcSpecificOutboundPacket rotate(float yaw, float pitch) { return this.platform.packetFactory().createRotationPacket(yaw, pitch).toSpecific(this); } @Override public @NotNull NpcSpecificOutboundPacket lookAt(@NotNull Position position) { double diffX = position.x() - this.pos.x(); double diffY = position.y() - this.pos.y(); double diffZ = position.z() - this.pos.z(); double distanceXZ = Math.sqrt(diffX * diffX + diffZ * diffZ); double distanceY = Math.sqrt(distanceXZ * distanceXZ + diffY * diffY); double yaw = Math.toDegrees(Math.acos(diffX / distanceXZ)); double pitch = Math.toDegrees(Math.acos(diffY / distanceY)) - 90; // correct yaw according to difference if (diffZ < 0) { yaw += Math.abs(180 - yaw) * 2; } yaw -= 90; return this.platform.packetFactory().createRotationPacket((float) yaw, (float) pitch).toSpecific(this); } @Override public @NotNull NpcSpecificOutboundPacket playAnimation(@NotNull EntityAnimation animation) { return this.platform.packetFactory().createAnimationPacket(animation).toSpecific(this); } @Override public @NotNull NpcSpecificOutboundPacket changeItem(@NotNull ItemSlot slot, @NotNull I item) { return this.platform.packetFactory().createEquipmentPacket(slot, item).toSpecific(this); } @Override public @NotNull NpcSpecificOutboundPacket changeMetadata( @NotNull EntityMetadataFactory metadata, @NotNull T value ) { return this.platform.packetFactory().createEntityMetaPacket(metadata, value).toSpecific(this); } @Override public int hashCode() { return Integer.hashCode(this.entityId()); } @Override public boolean equals(Object obj) { return Util.equals(Npc.class, this, obj, (orig, comp) -> orig.entityId() == comp.entityId()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy