/*
* 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.wrapper.mc.forge.v17.wrapper.block.backward;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
import nova.core.block.Block;
import nova.core.block.component.BlockProperty;
import nova.core.block.component.LightEmitter;
import nova.core.component.misc.Collider;
import nova.core.component.renderer.StaticRenderer;
import nova.core.component.transform.BlockTransform;
import nova.core.item.ItemFactory;
import nova.core.render.model.CustomModel;
import nova.core.retention.Data;
import nova.core.retention.Storable;
import nova.core.retention.Store;
import nova.core.sound.Sound;
import nova.core.util.shape.Cuboid;
import nova.core.world.World;
import nova.core.wrapper.mc.forge.v17.util.WrapperEvent;
import nova.core.wrapper.mc.forge.v17.wrapper.block.world.WorldConverter;
import nova.core.wrapper.mc.forge.v17.wrapper.cuboid.CuboidConverter;
import nova.core.wrapper.mc.forge.v17.wrapper.data.DataConverter;
import nova.core.wrapper.mc.forge.v17.wrapper.entity.EntityConverter;
import nova.internal.core.Game;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class BWBlock extends Block implements Storable {
public final net.minecraft.block.Block mcBlock;
@Store
public int metadata;
private TileEntity mcTileEntity;
public BWBlock(net.minecraft.block.Block block) {
this.mcBlock = block;
}
public BWBlock(net.minecraft.block.Block block, World world, Vector3D pos) {
this.mcBlock = block;
components.add(new BWBlockTransform(this, world, pos));
components.add(new BlockProperty.Opacity().setOpacity(mcBlock.getMaterial().isOpaque() ? 1 : 0));
if (mcBlock.isReplaceable(blockAccess(), xi(), yi(), zi()))
components.add(BlockProperty.Replaceable.instance());
BlockProperty.BlockSound blockSound = components.add(new BlockProperty.BlockSound());
blockSound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.PLACE, new Sound("", mcBlock.stepSound.func_150496_b()));
blockSound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.BREAK, new Sound("", mcBlock.stepSound.getBreakSound()));
blockSound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.WALK, new Sound("", mcBlock.stepSound.getStepResourcePath()));
components.add(new LightEmitter()).setEmittedLevel(() -> mcBlock.getLightValue(blockAccess(), xi(), yi(), zi()) / 15.0);
components.add(new Collider(this))
.setBoundingBox(() -> new Cuboid(mcBlock.getBlockBoundsMinX(), mcBlock.getBlockBoundsMinY(), mcBlock.getBlockBoundsMinZ(), mcBlock.getBlockBoundsMaxX(), mcBlock.getBlockBoundsMaxY(), mcBlock.getBlockBoundsMaxZ()))
.setOcclusionBoxes(entity -> {
List<AxisAlignedBB> aabbs = new ArrayList<>();
if (blockAccess() instanceof net.minecraft.world.World)
mcBlock.addCollisionBoxesToList(
(net.minecraft.world.World) blockAccess(),
(int) position().getX(),
(int) position().getY(),
(int) position().getZ(),
CuboidConverter.instance().toNative(entity
.flatMap(e -> e.components.getOp(Collider.class))
.map(c -> c.boundingBox.get())
.orElseGet(() -> Cuboid.ONE.add(pos))),
aabbs,
entity.map(EntityConverter.instance()::toNative).orElse(null)
);
return aabbs.stream()
.map(CuboidConverter.instance()::toNova)
.map(cuboid -> cuboid.subtract(pos))
.collect(Collectors.toSet());
}).setSelectionBoxes(entity -> {
final AxisAlignedBB bb = mcBlock.getSelectedBoundingBoxFromPool(((net.minecraft.world.World) blockAccess()), xi(), yi(), zi());
Cuboid cuboid = CuboidConverter.instance().toNova(bb);
return Collections.singleton(cuboid.subtract(position()));
});
components.add(new StaticRenderer())
.onRender(model -> model.addChild(new CustomModel(self -> RenderBlocks.getInstance().renderStandardBlock(mcBlock, xi(), yi(), zi()))));
WrapperEvent.BWBlockCreate event = new WrapperEvent.BWBlockCreate(world, pos, this, mcBlock);
Game.events().publish(event);
}
@Override
public ItemFactory getItemFactory() {
return Game.natives().toNova(new ItemStack(Item.getItemFromBlock(mcBlock)));
}
public int xi() {
return (int) x();
}
public int yi() {
return (int) y();
}
public int zi() {
return (int) z();
}
public net.minecraft.block.Block block() {
return mcBlock;
}
public IBlockAccess blockAccess() {
return WorldConverter.instance().toNative(world());
}
public int getMetadata() {
return blockAccess().getBlockMetadata(xi(), yi(), zi());
}
public Optional<TileEntity> getTileEntity() {
if (mcTileEntity == null && mcBlock.hasTileEntity(getMetadata())) {
mcTileEntity = blockAccess().getTileEntity(xi(), yi(), zi());
}
return Optional.ofNullable(mcTileEntity);
}
@Override
public boolean canReplace() {
return mcBlock.canPlaceBlockAt((net.minecraft.world.World) blockAccess(), xi(), yi(), zi());
}
@Override
public boolean shouldDisplacePlacement() {
if (mcBlock == Blocks.snow_layer && (blockAccess().getBlockMetadata(xi(), yi(), zi()) & 7) < 1) {
return false;
}
if (mcBlock == Blocks.vine || mcBlock == Blocks.tallgrass || mcBlock == Blocks.deadbush || mcBlock.isReplaceable(blockAccess(), xi(), yi(), zi())) {
return false;
}
return super.shouldDisplacePlacement();
}
@Override
public void save(Data data) {
Storable.super.save(data);
getTileEntity().ifPresent(tile -> {
NBTTagCompound nbt = new NBTTagCompound();
tile.writeToNBT(nbt);
data.putAll(DataConverter.instance().toNova(nbt));
});
}
@Override
public void load(Data data) {
Storable.super.load(data);
getTileEntity().ifPresent(tile -> tile.readFromNBT(DataConverter.instance().toNative(data)));
}
@Override
public String getLocalizedName() {
return mcBlock.getLocalizedName();
}
@Override
public String getUnlocalizedName() {
return mcBlock.getUnlocalizedName();
}
@Override
public String toString() {
return "BWBlock{" + mcBlock + ", " + getTileEntity() + "}";
}
}