package com.hypixel.hytale.builtin.deployables;
import com.hypixel.hytale.builtin.deployables.component.DeployableComponent;
import com.hypixel.hytale.builtin.deployables.component.DeployableOwnerComponent;
import com.hypixel.hytale.builtin.deployables.config.DeployableConfig;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.protocol.AnimationSlot;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.protocol.SoundCategory;
import com.hypixel.hytale.protocol.packets.entities.PlayAnimation;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.modules.entity.DespawnComponent;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.server.core.modules.entity.component.AudioComponent;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.Invulnerable;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.hitboxcollision.HitboxCollision;
import com.hypixel.hytale.server.core.modules.entity.hitboxcollision.HitboxCollisionConfig;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
import com.hypixel.hytale.server.core.modules.entitystats.modifier.Modifier;
import com.hypixel.hytale.server.core.modules.entitystats.modifier.StaticModifier;
import com.hypixel.hytale.server.core.modules.entityui.UIComponentList;
import com.hypixel.hytale.server.core.modules.time.TimeResource;
import com.hypixel.hytale.server.core.universe.world.PlayerUtil;
import com.hypixel.hytale.server.core.universe.world.SoundUtil;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class DeployablesUtils {
private static final String DEPLOYABLE_MAX_STAT_MODIFIER = "DEPLOYABLE_MAX";
public DeployablesUtils() {
}
@Nonnull
public static Ref<EntityStore> spawnDeployable(@Nonnull CommandBuffer<EntityStore> commandBuffer, @Nonnull Store<EntityStore> store, @Nonnull DeployableConfig config, @Nonnull Ref<EntityStore> deployerRef, @Nonnull Vector3f position, @Nonnull Vector3f rotation, @Nonnull String spawnFace) {
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
Vector3d spawnPos = new Vector3d((double)position.x, (double)position.y, (double)position.z);
Model model = config.getModel();
AudioComponent audioComponent = new AudioComponent();
if (config.getAmbientSoundEventIndex() != 0) {
audioComponent.addSound(config.getAmbientSoundEventIndex());
}
holder.addComponent(DeployableComponent.getComponentType(), new DeployableComponent());
holder.addComponent(TransformComponent.getComponentType(), new TransformComponent());
holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(Vector3f.FORWARD));
holder.addComponent(UUIDComponent.getComponentType(), new UUIDComponent(UUID.randomUUID()));
holder.addComponent(EntityStatMap.getComponentType(), new EntityStatMap());
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
holder.addComponent(BoundingBox.getComponentType(), new BoundingBox(model.getBoundingBox()));
holder.addComponent(AudioComponent.getComponentType(), audioComponent);
holder.addComponent(NetworkId.getComponentType(), new NetworkId(((EntityStore)store.getExternalData()).takeNextNetworkId()));
holder.ensureComponent(DeployableComponent.getComponentType());
holder.ensureComponent(EntityModule.get().getVisibleComponentType());
holder.ensureComponent(EntityStore.REGISTRY.getNonSerializedComponentType());
UIComponentList uiCompList = (UIComponentList)holder.ensureAndGetComponent(UIComponentList.getComponentType());
uiCompList.update();
if (config.getInvulnerable()) {
holder.ensureComponent(Invulnerable.getComponentType());
}
int hitboxCollisionConfigIndex = config.getHitboxCollisionConfigIndex();
if (hitboxCollisionConfigIndex != -1) {
HitboxCollisionConfig hitboxCollisionAsset = (HitboxCollisionConfig)HitboxCollisionConfig.getAssetMap().getAsset(hitboxCollisionConfigIndex);
holder.addComponent(HitboxCollision.getComponentType(), new HitboxCollision(hitboxCollisionAsset));
}
long liveDuration = config.getLiveDurationInMillis();
if (liveDuration > 0L) {
holder.addComponent(DespawnComponent.getComponentType(), new DespawnComponent(((TimeResource)store.getResource(TimeResource.getResourceType())).getNow().plus(Duration.ofMillis(liveDuration))));
}
EntityStatMap entityStatMapComponent = (EntityStatMap)holder.ensureAndGetComponent(EntityStatMap.getComponentType());
entityStatMapComponent.update();
populateStats(config, entityStatMapComponent);
DeployableComponent deployableComponent = (DeployableComponent)holder.ensureAndGetComponent(DeployableComponent.getComponentType());
deployableComponent.init(deployerRef, store, config, ((TimeResource)store.getResource(TimeResource.getResourceType())).getNow(), spawnFace);
TransformComponent transformComponent = (TransformComponent)holder.ensureAndGetComponent(TransformComponent.getComponentType());
transformComponent.setRotation(rotation);
transformComponent.setPosition(new Vector3d(spawnPos));
HeadRotation headRotationComponent = (HeadRotation)holder.ensureAndGetComponent(HeadRotation.getComponentType());
headRotationComponent.setRotation(rotation);
commandBuffer.ensureComponent(deployerRef, DeployableOwnerComponent.getComponentType());
return commandBuffer.addEntity(holder, AddReason.SPAWN);
}
static void populateStats(@Nonnull DeployableConfig config, @Nonnull EntityStatMap entityStatMapComponent) {
Map<String, DeployableConfig.StatConfig> stats = config.getStatValues();
if (stats != null) {
for(Map.Entry<String, DeployableConfig.StatConfig> statEntry : stats.entrySet()) {
DeployableConfig.StatConfig statConfig = (DeployableConfig.StatConfig)statEntry.getValue();
int statIndex = EntityStatType.getAssetMap().getIndex((String)statEntry.getKey());
EntityStatValue stat = entityStatMapComponent.get(statIndex);
if (stat != null) {
EntityStatType asset = (EntityStatType)EntityStatType.getAssetMap().getAsset(statIndex);
StaticModifier modifier = new StaticModifier(Modifier.ModifierTarget.MAX, StaticModifier.CalculationType.ADDITIVE, statConfig.getMax() - asset.getMax());
entityStatMapComponent.putModifier(statIndex, "DEPLOYABLE_MAX", modifier);
float initialValue = statConfig.getInitial();
if (initialValue == 3.4028235E38F) {
entityStatMapComponent.maximizeStatValue(statIndex);
} else {
entityStatMapComponent.setStatValue(statIndex, initialValue);
}
}
}
}
}
public static void playAnimation(@Nonnull Store<EntityStore> store, int networkId, @Nonnull Ref<EntityStore> ref, @Nonnull DeployableConfig config, @Nonnull AnimationSlot animationSlot, @Nullable String itemAnimationsId, @Nonnull String animationId) {
Model model = config.getModel();
if (animationSlot == AnimationSlot.Action || model == null || model.getAnimationSetMap().containsKey(animationId)) {
PlayAnimation animationPacket = new PlayAnimation(networkId, itemAnimationsId, animationId, animationSlot);
PlayerUtil.forEachPlayerThatCanSeeEntity(ref, (playerRef, playerRefComponent, ca) -> playerRefComponent.getPacketHandler().write((Packet)animationPacket), store);
}
}
public static void stopAnimation(@Nonnull Store<EntityStore> store, int networkId, @Nonnull Ref<EntityStore> ref, @Nonnull AnimationSlot animationSlot) {
PlayAnimation animationPacket = new PlayAnimation(networkId, (String)null, (String)null, animationSlot);
PlayerUtil.forEachPlayerThatCanSeeEntity(ref, (playerRef, playerRefComponent, ca) -> playerRefComponent.getPacketHandler().write((Packet)animationPacket), store);
}
public static void playSoundEventsAtEntity(@Nonnull Ref<EntityStore> ref, @Nonnull ComponentAccessor<EntityStore> componentAccessor, int localIndex, int worldIndex, @Nonnull Vector3d pos) {
Player targetPlayerComponent = (Player)componentAccessor.getComponent(ref, Player.getComponentType());
if (localIndex != 0 && targetPlayerComponent != null) {
SoundUtil.playSoundEvent2d(ref, localIndex, SoundCategory.SFX, componentAccessor);
}
if (worldIndex != 0) {
SoundUtil.playSoundEvent3d(worldIndex, SoundCategory.SFX, pos, componentAccessor);
}
}
}