IndustrialWires/src/main/java/malte0811/industrialWires/mech_mb/MultiblockMechMB.java

189 lines
5.8 KiB
Java

/*
* This file is part of Industrial Wires.
* Copyright (C) 2016-2018 malte0811
* Industrial Wires 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.
* Industrial Wires 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 Industrial Wires. If not, see <http://www.gnu.org/licenses/>.
*/
package malte0811.industrialWires.mech_mb;
import blusunrize.immersiveengineering.api.MultiblockHandler;
import blusunrize.immersiveengineering.api.crafting.IngredientStack;
import malte0811.industrialWires.IndustrialWires;
import malte0811.industrialWires.blocks.converter.MechanicalMBBlockType;
import malte0811.industrialWires.blocks.converter.TileEntityMechMB;
import malte0811.industrialWires.util.LocalSidedWorld;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static malte0811.industrialWires.blocks.converter.MechanicalMBBlockType.*;
public class MultiblockMechMB implements MultiblockHandler.IMultiblock {
public static MultiblockMechMB INSTANCE;
@Override
public String getUniqueName() {
return IndustrialWires.MODID+":mech_mb";
}
@Override
public boolean isBlockTrigger(IBlockState state) {
return MechMBPart.isValidDefaultCenter(state);
}
private boolean checkEnd(LocalSidedWorld w, BlockPos.PooledMutableBlockPos p) {
p.setPos(0, 0, 0);
if (!MechMBPart.isValidDefaultCenter(w.getBlockState(p))) {
return false;
}
p.setPos(0, -1, 0);
return MechMBPart.isValidDefaultCenter(w.getBlockState(p));
}
private void formEnd(LocalSidedWorld w, BlockPos.PooledMutableBlockPos p, MechanicalMBBlockType type,
BiConsumer<TileEntityMechMB, Boolean> init) {
p.setPos(0, 0, 0);
w.setBlockState(p, IndustrialWires.mechanicalMB.getStateFromMeta(type.ordinal()));
TileEntity te = w.getTileEntity(p);
if (te instanceof TileEntityMechMB) {
init.accept((TileEntityMechMB) te, true);
}
p.setPos(0, -1, 0);
w.setBlockState(p, IndustrialWires.mechanicalMB.getStateFromMeta(NO_MODEL.ordinal()));
te = w.getTileEntity(p);
if (te instanceof TileEntityMechMB) {
init.accept((TileEntityMechMB) te, false);
}
}
@Override
public boolean createStructure(World world, BlockPos pos, EnumFacing side, EntityPlayer player) {
if (side.getAxis().isVertical())
return false;
BlockPos.PooledMutableBlockPos mutPos = BlockPos.PooledMutableBlockPos.retain();
try {
LocalSidedWorld w = new LocalSidedWorld(world, pos, side.getOpposite(), false);
if (!checkEnd(w, mutPos)) {
return false;
}
boolean foundAll = false;
List<MechMBPart> parts = new ArrayList<>();
int lastLength = 1;
double weight = 0;
while (!foundAll) {
mutPos.setPos(0, 0, lastLength);
w.setOrigin(w.getRealPos(mutPos));
MechMBPart next = null;
List<MechMBPart> instances = new ArrayList<>(MechMBPart.INSTANCES.values());
instances.sort(MechMBPart.SORT_BY_COUNT.reversed());
MechMBPart last = instances.get(0);
for (MechMBPart part:instances) {
if (MechMBPart.SORT_BY_COUNT.compare(last, part)!=0&&
checkEnd(w, mutPos)) {
foundAll = true;
break;
}
last = part;
if (part.canForm(w)) {
next = part;
String key = MechMBPart.REGISTRY.inverse().get(part.getClass());
MechMBPart.cacheNewInstance(key);
break;
}
}
if (next != null) {
parts.add(next);
lastLength = next.getLength();
weight += next.getInertia();
} else if (!foundAll) {
return false;
}
}
if (parts.isEmpty()) {
return false;
}
double finalWeight = weight;
w.setOrigin(pos);
formEnd(w, mutPos, END, (te, master) -> {
if (master) {
te.offset = BlockPos.ORIGIN;
te.setMechanical(parts.toArray(new MechMBPart[0]), 0);
te.energyState = new MechEnergy(finalWeight, 0);
} else {
te.offset = new BlockPos(0, -1, 0);
}
te.facing = side;
te.formed = true;
});
lastLength = 1;
Consumer<TileEntityMechMB> init = (te) -> {
te.offset = te.getPos().subtract(pos);
te.facing = side;
te.formed = true;
};
for (MechMBPart part : parts) {
mutPos.setPos(0, 0, lastLength);
w = new LocalSidedWorld(world, w.getRealPos(mutPos), w.getFacing(), w.isMirrored());
part.form(w, init);
lastLength = part.getLength();
}
mutPos.setPos(0, 0, lastLength);
w = new LocalSidedWorld(w.getWorld(), w.getRealPos(mutPos), w.getFacing(), w.isMirrored());
formEnd(w, mutPos, OTHER_END, (te, __) -> init.accept(te));
return true;
} finally {
mutPos.release();
}
}
private ItemStack[][][] fakeStructure = {{{new ItemStack(Blocks.COMMAND_BLOCK)}}};
private IngredientStack[] fakeMats = {new IngredientStack(fakeStructure[0][0][0])};
@Override
public ItemStack[][][] getStructureManual() {
return fakeStructure;
}
@Override
public IngredientStack[] getTotalMaterials() {
return fakeMats;
}
@Override
public boolean overwriteBlockRender(ItemStack stack, int iterator) {
return false;
}
@Override
public float getManualScale() {
return 1;
}
@Override
public boolean canRenderFormedStructure() {
return false;
}
@Override
public void renderFormedStructure() {
}
}