package com.hypixel.hytale.server.core.entity;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.math.vector.Transform;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.event.events.ecs.DropItemEvent;
import com.hypixel.hytale.server.core.event.events.ecs.InteractivelyPickupItemEvent;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
import com.hypixel.hytale.server.core.inventory.container.SimpleItemContainer;
import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ItemUtils {
public ItemUtils() {
}
public static void interactivelyPickupItem(@Nonnull Ref<EntityStore> ref, @Nonnull ItemStack itemStack, @Nullable Vector3d origin, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
LivingEntity entity = (LivingEntity)EntityUtils.getEntity(ref, componentAccessor);
InteractivelyPickupItemEvent event = new InteractivelyPickupItemEvent(itemStack);
componentAccessor.invoke(ref, event);
if (event.isCancelled()) {
dropItem(ref, itemStack, componentAccessor);
} else {
Player playerComponent = (Player)componentAccessor.getComponent(ref, Player.getComponentType());
if (playerComponent != null) {
TransformComponent transformComponent = (TransformComponent)componentAccessor.getComponent(ref, TransformComponent.getComponentType());
assert transformComponent != null;
PlayerSettings playerSettingsComponent = (PlayerSettings)componentAccessor.getComponent(ref, PlayerSettings.getComponentType());
if (playerSettingsComponent == null) {
playerSettingsComponent = PlayerSettings.defaults();
}
Holder<EntityStore> pickupItemHolder = null;
Item item = itemStack.getItem();
ItemContainer itemContainer = playerComponent.getInventory().getContainerForItemPickup(item, playerSettingsComponent);
ItemStackTransaction transaction = itemContainer.addItemStack(itemStack);
ItemStack remainder = transaction.getRemainder();
if (remainder != null && !remainder.isEmpty()) {
int quantity = itemStack.getQuantity() - remainder.getQuantity();
if (quantity > 0) {
ItemStack itemStackClone = itemStack.withQuantity(quantity);
playerComponent.notifyPickupItem(ref, itemStackClone, (Vector3d)null, componentAccessor);
if (origin != null) {
pickupItemHolder = ItemComponent.generatePickedUpItem(itemStackClone, origin, componentAccessor, ref);
}
}
dropItem(ref, remainder, componentAccessor);
} else {
playerComponent.notifyPickupItem(ref, itemStack, (Vector3d)null, componentAccessor);
if (origin != null) {
pickupItemHolder = ItemComponent.generatePickedUpItem(itemStack, origin, componentAccessor, ref);
}
}
if (pickupItemHolder != null) {
componentAccessor.addEntity(pickupItemHolder, AddReason.SPAWN);
}
} else {
SimpleItemContainer.addOrDropItemStack(componentAccessor, ref, entity.getInventory().getCombinedHotbarFirst(), itemStack);
}
}
}
@Nullable
public static Ref<EntityStore> throwItem(@Nonnull Ref<EntityStore> ref, @Nonnull ItemStack itemStack, float throwSpeed, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
DropItemEvent.Drop event = new DropItemEvent.Drop(itemStack, throwSpeed);
componentAccessor.invoke(ref, event);
if (event.isCancelled()) {
return null;
} else {
throwSpeed = event.getThrowSpeed();
itemStack = event.getItemStack();
if (!itemStack.isEmpty() && itemStack.isValid()) {
HeadRotation headRotationComponent = (HeadRotation)componentAccessor.getComponent(ref, HeadRotation.getComponentType());
assert headRotationComponent != null;
Vector3f rotation = headRotationComponent.getRotation();
Vector3d direction = Transform.getDirection(rotation.getPitch(), rotation.getYaw());
return throwItem(ref, componentAccessor, itemStack, direction, throwSpeed);
} else {
HytaleLogger.getLogger().at(Level.WARNING).log("Attempted to throw invalid item %s at %s by %s", itemStack, throwSpeed, ref.getIndex());
return null;
}
}
}
@Nullable
public static Ref<EntityStore> throwItem(@Nonnull Ref<EntityStore> ref, @Nonnull ComponentAccessor<EntityStore> store, @Nonnull ItemStack itemStack, @Nonnull Vector3d throwDirection, float throwSpeed) {
TransformComponent transformComponent = (TransformComponent)store.getComponent(ref, TransformComponent.getComponentType());
assert transformComponent != null;
ModelComponent modelComponent = (ModelComponent)store.getComponent(ref, ModelComponent.getComponentType());
assert modelComponent != null;
Vector3d throwPosition = transformComponent.getPosition().clone();
Model model = modelComponent.getModel();
throwPosition.add(0.0, (double)model.getEyeHeight(ref, store), 0.0).add(throwDirection);
Holder<EntityStore> itemEntityHolder = ItemComponent.generateItemDrop(store, itemStack, throwPosition, Vector3f.ZERO, (float)throwDirection.x * throwSpeed, (float)throwDirection.y * throwSpeed, (float)throwDirection.z * throwSpeed);
if (itemEntityHolder == null) {
return null;
} else {
ItemComponent itemComponent = (ItemComponent)itemEntityHolder.getComponent(ItemComponent.getComponentType());
if (itemComponent != null) {
itemComponent.setPickupDelay(1.5F);
}
return store.addEntity(itemEntityHolder, AddReason.SPAWN);
}
}
@Nullable
public static Ref<EntityStore> dropItem(@Nonnull Ref<EntityStore> ref, @Nonnull ItemStack itemStack, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
return throwItem(ref, itemStack, 1.0F, componentAccessor);
}
}