/*
* Copyright (c) 2015 NOVA, All rights reserved.
* This library is free software, licensed under GNU Lesser General Public License version 3
*
* This file is part of NOVA.
*
* NOVA 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.
*
* NOVA 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 NOVA. If not, see <http://www.gnu.org/licenses/>.
*/
package nova.core.item;
import nova.core.component.ComponentMap;
import nova.core.component.ComponentProvider;
import nova.core.component.misc.FactoryProvider;
import nova.core.entity.Entity;
import nova.core.event.bus.Event;
import nova.core.language.LanguageManager;
import nova.core.language.Translatable;
import nova.core.render.Color;
import nova.core.retention.Storable;
import nova.core.util.Direction;
import nova.core.util.Identifiable;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import java.util.List;
import java.util.Optional;
//TODO: This Storable implementation is flawed and not based on ID.
public class Item extends ComponentProvider<ComponentMap> implements Identifiable, Storable, Cloneable, Translatable {
/**
* The amount of this item that is present.
*/
private int count = 1;
/**
* Called to get the ItemFactory that refers to this Block class.
* @return The {@link nova.core.item.ItemFactory} that refers to this Block class.
*/
public final ItemFactory getFactory() {
return (ItemFactory) components.get(FactoryProvider.class).factory;
}
@Override
public final String getID() {
return getFactory().getID();
}
@Override
public String getUnlocalizedName() {
return getFactory().getUnlocalizedName();
}
@Override
public String getLocalizedName() {
return LanguageManager.instance().translate(getUnlocalizedName() + ".name", this.getReplacements());
}
public int getMaxCount() {
return 64;
}
/**
* @return Size of this stack size
*/
public int count() {
return count;
}
/**
* Sets new size of this ItemStack
* @param size New size
*/
public Item setCount(int size) {
count = Math.max(Math.min(getMaxCount(), size), 0);
return this;
}
/**
* Adds size to this ItemStack
* @param size Size to add
* @return Size added
*/
public int addCount(int size) {
int original = count();
setCount(original + size);
return count - original;
}
@Override
public Item clone() {
return getFactory().build(getFactory().save(this));
}
/**
* Returns new ItemStack of the same {@link Item} with specified size
* @param amount Size of cloned ItemStack
* @return new ItemStack
*/
public Item withAmount(int amount) {
Item cloned = clone();
cloned.setCount(amount);
return cloned;
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof Item)) {
return false;
}
Item item = (Item) o;
//Makes sure the stored data and stacksize are the same in items.
return sameItemType(item) && getFactory().save(this).equals(item.getFactory().save(item)) && item.count == count;
}
@Override
public int hashCode() {
int hash = 3;
hash = 83 * hash + this.getID().hashCode();
hash = 83 * hash + this.count;
hash = 83 * hash + this.getFactory().save(this).hashCode();
return hash;
}
/**
* Check if this Item is of type of another Item.
* Will compare the {@link Item#getID() item id}.
* @param item The another Item
* @return Result
*/
public boolean sameItemType(Item item) {
return getID().equals(item.getID());
}
/**
* Gets the color multiplier for rendering
* @return The color
*/
//TODO: Convert to component system
@Deprecated
public Color colorMultiplier() {
return Color.white;
}
public static class TooltipEvent extends Event {
public final Optional<Entity> entity;
public final List<String> tooltips;
/**
* Gets a list of tooltips for this item.
* @param entity {@link Entity} with the component Player attached.
* @param tooltips The tooltip list to add to.
*/
public TooltipEvent(Optional<Entity> entity, List<String> tooltips) {
this.entity = entity;
this.tooltips = tooltips;
}
}
public static class UseEvent extends Event {
//The entity that right clicked
public final Entity entity;
public final Vector3D position;
public final Direction side;
public final Vector3D hit;
//Did this event cause an action? True if the player's action cancels out events.
public boolean action = false;
/**
* Called when the entity right clicks the item onto the block.
* @param entity - The entity using the item
* @param position - The position of the block
* @param side - The side the player clicked
* @param hit - The position the player hit on the block
*/
public UseEvent(Entity entity, Vector3D position, Direction side, Vector3D hit) {
this.entity = entity;
this.position = position;
this.side = side;
this.hit = hit;
}
}
public static class RightClickEvent extends Event {
//The entity that right clicked
public final Entity entity;
public RightClickEvent(Entity entity) {
this.entity = entity;
}
}
}