package nova.microblock.common;
import nova.core.block.Block;
import nova.core.block.BlockFactory;
import nova.core.component.inventory.InventoryException;
import nova.core.entity.Entity;
import nova.core.item.ItemBlock;
import nova.core.network.NetworkTarget;
import nova.core.util.Direction;
import nova.core.util.RayTracer;
import nova.core.util.math.Vector3DUtil;
import nova.core.world.World;
import nova.microblock.NovaMicroblock;
import nova.microblock.micro.Microblock;
import nova.microblock.micro.MicroblockContainer;
import nova.microblock.multi.Multiblock;
import nova.microblock.multi.MultiblockContainer;
import nova.microblock.operation.ContainerPlace;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import java.util.Optional;
/**
* ItemBlocks for microblocks and multiblocks
* @author Calclavia
*/
public class ItemBlockContainer extends ItemBlock {
public ItemBlockContainer(BlockFactory blockFactory) {
super(blockFactory);
events.on(RightClickEvent.class).bind(
evt -> {
if (NetworkTarget.Side.get().isServer()) {
//Do ray trace to find which block it hit
RayTracer rayTracer = new RayTracer(evt.entity).setDistance(7);
Optional<RayTracer.RayTraceBlockResult> hit = rayTracer.rayTraceBlocks(evt.entity.world()).findFirst();
if (hit.isPresent()) {
RayTracer.RayTraceBlockResult result = hit.get();
Vector3D placePos = result.block.position().add(result.side.toVector());
Optional<Block> opBlock = evt.entity.world().getBlock(placePos);
opBlock.ifPresent(
block ->
{
if (block.components.has(MicroblockContainer.class) || block.components.has(MultiblockContainer.class)) {
placeContainer(evt.entity, evt.entity.world(), result.block.position(), result.side, Vector3DUtil.floor(result.hit.subtract(result.block.position())));
}
}
);
}
}
}
);
}
@Override
protected void onUse(UseEvent evt) {
evt.action = placeContainer(evt.entity, evt.entity.world(), evt.position, evt.side, evt.hit);
}
public boolean placeContainer(Entity entity, World world, Vector3D position, Direction side, Vector3D hit) {
if (NetworkTarget.Side.get().isServer()) {
Vector3D placePos = position.add(side.toVector());
Optional<Block> checkBlock = world.getBlock(placePos);
if (checkBlock.isPresent()) {
NovaMicroblock.MicroblockInjectFactory injectFactory = (NovaMicroblock.MicroblockInjectFactory) this.blockFactory;
BlockFactory containedFactory = injectFactory.containedFactory;
//TODO: Dummies are bad
Block dummy = containedFactory.build();
if (dummy.components.has(Microblock.class)) {
//Ask the microblock about how it would like to be placed.
Block.PlaceEvent evt = new Block.PlaceEvent(entity, side, hit, this);
boolean b = new ContainerPlace(world, injectFactory, placePos, evt).operate();
System.out.println("Attempt to place microblock: " + b);
return b;
} else if (dummy.components.has(Multiblock.class)) {
return new ContainerPlace(world, injectFactory, placePos).operate();
} else {
throw new InventoryException("Invalid blockFactory contained in ItemBlockContainer: " + containedFactory);
}
}
}
return false;
}
}