SimpleMultipart/src/main/java/net/shadowfacts/simplemultipart/item/MultipartItem.java

128 lines
4.5 KiB
Java

package net.shadowfacts.simplemultipart.item;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockHitResult;
import net.shadowfacts.simplemultipart.SimpleMultipart;
import net.shadowfacts.simplemultipart.container.AbstractContainerBlockEntity;
import net.shadowfacts.simplemultipart.container.MultipartContainer;
import net.shadowfacts.simplemultipart.multipart.Multipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.util.MultipartPlacementContext;
/**
* An {@link Item} implementation that handles placing multiparts.
*
* Analogous to {@link net.minecraft.item.block.BlockItem}.
*
* @author shadowfacts
* @since 0.1.1
*/
public class MultipartItem extends Item {
protected Multipart part;
/**
* Creates a Multipart Item for the given part with.
*
* @param part The multipart.
*/
public MultipartItem(Multipart part) {
this(part, new Settings());
}
/**
* Creates a Multipart Item for the given part with the given item settings.
*
* @param part The multipart.
* @param settings The settings for this item.
* @since 0.1.2
*/
public MultipartItem(Multipart part, Settings settings) {
super(settings);
this.part = part;
}
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
return tryPlace(context);
}
/**
* Attempts to place this item's multipart in the given context.
*
* If the player clicked an existing multipart container, it will attempt to insert into that one, falling back on
* creating a new container.
* Which container the placement is being attempted in can be determined from {@link MultipartPlacementContext#isOffset()}.
*
* @param context The item usage context.
* @return The result of the placement.
*/
protected ActionResult tryPlace(ItemUsageContext context) {
// If a multipart inside an existing container was clicked, try inserting into that
MultipartContainer hitContainer = getContainer(context);
if (hitContainer != null && tryPlace(new MultipartPlacementContext(hitContainer, false, context))) {
return ActionResult.SUCCESS;
}
// Otherwise, get or create a new container and try inserting into that
BlockHitResult offsetHitResult = new BlockHitResult(context.method_17698(), context.getFacing(), context.getPos().offset(context.getFacing()), context.method_17699());
ItemUsageContext offsetContext = new ItemUsageContext(context.getPlayer(), context.getItemStack(), offsetHitResult);
MultipartContainer offsetContainer = getOrCreateContainer(offsetContext);
if (offsetContainer != null) {
if (tryPlace(new MultipartPlacementContext(offsetContainer, true, offsetContext))) {
return ActionResult.SUCCESS;
} else {
// if the a new container was created, and no part was inserted, remove the empty container
if (!offsetContainer.hasParts()) {
context.getWorld().setBlockState(offsetContext.getPos(), Blocks.AIR.getDefaultState());
}
}
}
return ActionResult.FAILURE;
}
protected MultipartContainer getContainer(ItemUsageContext context) {
BlockState state = context.getWorld().getBlockState(context.getPos());
if (state.getBlock() == SimpleMultipart.containerBlock) {
return (MultipartContainer)context.getWorld().getBlockEntity(context.getPos());
} else {
return null;
}
}
protected MultipartContainer getOrCreateContainer(ItemUsageContext context) {
MultipartContainer container = getContainer(context);
if (container == null) {
BlockState existing = context.getWorld().getBlockState(context.getPos());
if (existing.isAir()) { // TODO: should check is replaceable (might not be mapped?)
context.getWorld().setBlockState(context.getPos(), SimpleMultipart.containerBlock.getDefaultState());
container = (MultipartContainer)context.getWorld().getBlockEntity(context.getPos());
}
}
return container;
}
/**
* Attempts to insert this item's multipart into the container specified by the given context.
*
* @param context The multipart placement context.
* @return If the placement succeeded.
*/
protected boolean tryPlace(MultipartPlacementContext context) {
MultipartState placementState = part.getPlacementState(context);
if (context.getContainer().canInsert(placementState)) {
context.getContainer().insert(placementState);
context.getItemStack().subtractAmount(1);
return true;
}
return false;
}
}