add IFacadePluggable, let mods define their own IFacadePluggables and query facades; NPE fixes on rare world corruptions

This commit is contained in:
asiekierka 2015-01-22 13:49:08 +01:00
parent 7d9892bc13
commit a14eb3b55f
9 changed files with 92 additions and 38 deletions

View file

@ -48,8 +48,8 @@ public interface IPipeTile extends IInjectable {
IPipe getPipe(); IPipe getPipe();
int getPipeColor(); int getPipeColor();
PipePluggable getPipePluggable(ForgeDirection direction); PipePluggable getPipePluggable(ForgeDirection direction); // Now in IPluggableProvider
boolean hasPipePluggable(ForgeDirection direction); boolean hasPipePluggable(ForgeDirection direction); // Now in IPluggableProvider
boolean hasBlockingPluggable(ForgeDirection direction); boolean hasBlockingPluggable(ForgeDirection direction);
void scheduleNeighborChange(); void scheduleNeighborChange();
@ -57,6 +57,6 @@ public interface IPipeTile extends IInjectable {
// For compatibility with BC 6.2.x and below // For compatibility with BC 6.2.x and below
int injectItem(ItemStack stack, boolean doAdd, ForgeDirection from, EnumColor color); int injectItem(ItemStack stack, boolean doAdd, ForgeDirection from, EnumColor color);
@Deprecated @Deprecated // Now in IInjectable
int injectItem(ItemStack stack, boolean doAdd, ForgeDirection from); int injectItem(ItemStack stack, boolean doAdd, ForgeDirection from);
} }

View file

@ -6,7 +6,7 @@
* Please check the contents of the license, which should be located * Please check the contents of the license, which should be located
* as "LICENSE.API" in the BuildCraft source code distribution. * as "LICENSE.API" in the BuildCraft source code distribution.
*/ */
@API(apiVersion = "3.0", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|transport") @API(apiVersion = "3.1", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|transport")
package buildcraft.api.transport; package buildcraft.api.transport;
import cpw.mods.fml.common.API; import cpw.mods.fml.common.API;

View file

@ -0,0 +1,10 @@
package buildcraft.api.transport.pluggable;
import net.minecraft.block.Block;
public interface IFacadePluggable {
public Block getCurrentBlock();
public int getCurrentMetadata();
public boolean isTransparent();
public boolean isHollow();
}

View file

@ -11,11 +11,12 @@ import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.transport.IPipeTile; import buildcraft.api.transport.IPipeTile;
import buildcraft.api.transport.pluggable.IFacadePluggable;
import buildcraft.api.transport.pluggable.IPipePluggableRenderer; import buildcraft.api.transport.pluggable.IPipePluggableRenderer;
import buildcraft.api.transport.pluggable.PipePluggable; import buildcraft.api.transport.pluggable.PipePluggable;
import buildcraft.core.utils.MatrixTranformations; import buildcraft.core.utils.MatrixTranformations;
public class FacadePluggable extends PipePluggable { public class FacadePluggable extends PipePluggable implements IFacadePluggable {
public ItemFacade.FacadeState[] states; public ItemFacade.FacadeState[] states;
private ItemFacade.FacadeState activeState; private ItemFacade.FacadeState activeState;
@ -26,7 +27,7 @@ public class FacadePluggable extends PipePluggable {
public FacadePluggable(ItemFacade.FacadeState[] states) { public FacadePluggable(ItemFacade.FacadeState[] states) {
this.states = states; this.states = states;
activeState = states.length > 0 ? states[0] : null; prepareStates();
} }
public FacadePluggable() { public FacadePluggable() {
@ -51,7 +52,7 @@ public class FacadePluggable extends PipePluggable {
if (states != null) { if (states != null) {
return new ItemStack[] { ItemFacade.getFacade(states) }; return new ItemStack[] { ItemFacade.getFacade(states) };
} else { } else {
return new ItemStack[] { ItemFacade.getFacade(new ItemFacade.FacadeState(getRenderingBlock(), getRenderingMeta(), null, isHollow())) }; return new ItemStack[] { ItemFacade.getFacade(new ItemFacade.FacadeState(getCurrentBlock(), getCurrentMetadata(), null, isHollow())) };
} }
} }
@ -60,13 +61,28 @@ public class FacadePluggable extends PipePluggable {
return !isHollow(); return !isHollow();
} }
public boolean isHollow() { @Override
return states == null ? renderAsHollow : states[0].hollow; public Block getCurrentBlock() {
prepareStates();
return activeState == null ? block : activeState.block;
} }
public Block getRenderingBlock() { return block; } @Override
public int getRenderingMeta() { return meta; } public int getCurrentMetadata() {
public boolean getRenderingTransparent() { return transparent; } prepareStates();
return activeState == null ? meta : activeState.metadata;
}
@Override
public boolean isTransparent() {
prepareStates();
return activeState == null ? transparent : activeState.transparent;
}
public boolean isHollow() {
prepareStates();
return activeState == null ? renderAsHollow : activeState.hollow;
}
@Override @Override
public AxisAlignedBB getBoundingBox(ForgeDirection side) { public AxisAlignedBB getBoundingBox(ForgeDirection side) {
@ -97,9 +113,7 @@ public class FacadePluggable extends PipePluggable {
@Override @Override
public void writeData(ByteBuf data) { public void writeData(ByteBuf data) {
if (activeState == null) { prepareStates();
activeState = states.length > 0 ? states[0] : null;
}
if (activeState == null || activeState.block == null) { if (activeState == null || activeState.block == null) {
data.writeShort(0); data.writeShort(0);
@ -114,7 +128,6 @@ public class FacadePluggable extends PipePluggable {
@Override @Override
public void readData(ByteBuf data) { public void readData(ByteBuf data) {
int blockId = data.readUnsignedShort(); int blockId = data.readUnsignedShort();
if (blockId > 0) { if (blockId > 0) {
block = Block.getBlockById(blockId); block = Block.getBlockById(blockId);
@ -129,6 +142,12 @@ public class FacadePluggable extends PipePluggable {
renderAsHollow = (flags & 0x40) > 0; renderAsHollow = (flags & 0x40) > 0;
} }
private void prepareStates() {
if (activeState == null) {
activeState = states != null && states.length > 0 ? states[0] : null;
}
}
protected void setActiveState(int id) { protected void setActiveState(int id) {
if (id >= 0 && id < states.length) { if (id >= 0 && id < states.length) {
activeState = states[id]; activeState = states[id];

View file

@ -27,6 +27,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World; import net.minecraft.world.World;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
@ -244,8 +245,12 @@ public class ItemFacade extends ItemBuildCraft implements IFacadeItem, IPipePlug
private void registerValidFacades(Block block, Item item) { private void registerValidFacades(Block block, Item item) {
//for (int i = 0; i < 16; i++) { //for (int i = 0; i < 16; i++) {
ArrayList<ItemStack> stacks = new ArrayList<ItemStack>(16); ArrayList<ItemStack> stacks = new ArrayList<ItemStack>(16);
for (CreativeTabs tab : item.getCreativeTabs()) { if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) {
block.getSubBlocks(item, tab, stacks); block.getSubBlocks(item, null, stacks);
} else {
for (int i = 0; i < 16; i++) {
stacks.add(new ItemStack(item, 1, i));
}
} }
for (ItemStack stack : stacks) { for (ItemStack stack : stacks) {
try { try {

View file

@ -231,6 +231,10 @@ public class PipeTransportItems extends PipeTransport {
if (entity instanceof IPipeTile) { if (entity instanceof IPipeTile) {
Pipe<?> pipe = (Pipe<?>) ((IPipeTile) entity).getPipe(); Pipe<?> pipe = (Pipe<?>) ((IPipeTile) entity).getPipe();
if (pipe == null || pipe.transport == null) {
return false;
}
//return !pipe.pipe.isClosed() && pipe.pipe.transport instanceof PipeTransportItems; //return !pipe.pipe.isClosed() && pipe.pipe.transport instanceof PipeTransportItems;
return pipe.inputOpen(o.getOpposite()) && pipe.transport instanceof PipeTransportItems; return pipe.inputOpen(o.getOpposite()) && pipe.transport instanceof PipeTransportItems;
} else if (entity instanceof IInventory && item.getInsertionHandler().canInsertItem(item, (IInventory) entity)) { } else if (entity instanceof IInventory && item.getInsertionHandler().canInsertItem(item, (IInventory) entity)) {

View file

@ -49,6 +49,7 @@ import buildcraft.api.transport.IPipeConnection;
import buildcraft.api.transport.IPipeTile; import buildcraft.api.transport.IPipeTile;
import buildcraft.api.transport.PipeManager; import buildcraft.api.transport.PipeManager;
import buildcraft.api.transport.PipeWire; import buildcraft.api.transport.PipeWire;
import buildcraft.api.transport.pluggable.IFacadePluggable;
import buildcraft.api.transport.pluggable.PipePluggable; import buildcraft.api.transport.pluggable.PipePluggable;
import buildcraft.core.DefaultProps; import buildcraft.core.DefaultProps;
import buildcraft.core.IDropControlInventory; import buildcraft.core.IDropControlInventory;
@ -348,8 +349,10 @@ public class TileGenericPipe extends TileEntity implements IFluidHandler,
worldObj.notifyBlockOfNeighborChange(xCoord, yCoord, zCoord, getBlock()); worldObj.notifyBlockOfNeighborChange(xCoord, yCoord, zCoord, getBlock());
scheduleRenderUpdate(); scheduleRenderUpdate();
sendUpdateToClient(); sendUpdateToClient();
if (pipe != null) {
BlockGenericPipe.updateNeighbourSignalState(pipe); BlockGenericPipe.updateNeighbourSignalState(pipe);
} }
}
@Override @Override
public void updateEntity() { public void updateEntity() {
@ -896,7 +899,7 @@ public class TileGenericPipe extends TileEntity implements IFluidHandler,
if (direction == null || direction == ForgeDirection.UNKNOWN) { if (direction == null || direction == ForgeDirection.UNKNOWN) {
return false; return false;
} else { } else {
return sideProperties.pluggables[direction.ordinal()] instanceof FacadePluggable; return sideProperties.pluggables[direction.ordinal()] instanceof IFacadePluggable;
} }
} }
@ -940,7 +943,7 @@ public class TileGenericPipe extends TileEntity implements IFluidHandler,
} }
public boolean hasEnabledFacade(ForgeDirection direction) { public boolean hasEnabledFacade(ForgeDirection direction) {
return hasFacade(direction) && !((FacadePluggable) getPipePluggable(direction)).getRenderingTransparent(); return hasFacade(direction) && !((FacadePluggable) getPipePluggable(direction)).isTransparent();
} }
public DockingStation getStation(ForgeDirection direction) { public DockingStation getStation(ForgeDirection direction) {

View file

@ -6,6 +6,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess; import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.transport.pluggable.IFacadePluggable;
import buildcraft.api.transport.pluggable.PipePluggable; import buildcraft.api.transport.pluggable.PipePluggable;
import buildcraft.transport.BlockGenericPipe; import buildcraft.transport.BlockGenericPipe;
import buildcraft.transport.FacadePluggable; import buildcraft.transport.FacadePluggable;
@ -22,13 +23,13 @@ public class FacadeBlockAccess implements IBlockAccess {
@Override @Override
public Block getBlock(int x, int y, int z) { public Block getBlock(int x, int y, int z) {
System.out.println("Querying block at " + x + ", " + y + ", " + z); //System.out.println("Querying block at " + x + ", " + y + ", " + z);
TileEntity tile = world.getTileEntity(x, y, z); TileEntity tile = world.getTileEntity(x, y, z);
if (tile instanceof TileGenericPipe) { if (tile instanceof TileGenericPipe) {
PipePluggable p = ((TileGenericPipe) tile).getPipePluggable(side); PipePluggable p = ((TileGenericPipe) tile).getPipePluggable(side);
if (p instanceof FacadePluggable) { if (p instanceof IFacadePluggable) {
System.out.println("Found facade"); //System.out.println("Found facade");
return ((FacadePluggable) p).getRenderingBlock(); return ((IFacadePluggable) p).getCurrentBlock();
} }
} }
return Blocks.air; return Blocks.air;
@ -46,13 +47,13 @@ public class FacadeBlockAccess implements IBlockAccess {
@Override @Override
public int getBlockMetadata(int x, int y, int z) { public int getBlockMetadata(int x, int y, int z) {
System.out.println("Querying block metadata at " + x + ", " + y + ", " + z); //System.out.println("Querying block metadata at " + x + ", " + y + ", " + z);
TileEntity tile = world.getTileEntity(x, y, z); TileEntity tile = world.getTileEntity(x, y, z);
if (tile instanceof TileGenericPipe) { if (tile instanceof TileGenericPipe) {
PipePluggable p = ((TileGenericPipe) tile).getPipePluggable(side); PipePluggable p = ((TileGenericPipe) tile).getPipePluggable(side);
if (p instanceof FacadePluggable) { if (p instanceof IFacadePluggable) {
System.out.println("Found facade " + ((FacadePluggable) p).getRenderingMeta()); //System.out.println("Found facade " + ((FacadePluggable) p).getRenderingMeta());
return ((FacadePluggable) p).getRenderingMeta(); return ((IFacadePluggable) p).getCurrentMetadata();
} }
} }
return 0; return 0;

View file

@ -17,6 +17,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.BuildCraftTransport; import buildcraft.BuildCraftTransport;
import buildcraft.api.core.render.ITextureStates; import buildcraft.api.core.render.ITextureStates;
import buildcraft.api.transport.pluggable.IFacadePluggable;
import buildcraft.api.transport.pluggable.PipePluggable;
import buildcraft.core.CoreConstants; import buildcraft.core.CoreConstants;
import buildcraft.core.utils.MatrixTranformations; import buildcraft.core.utils.MatrixTranformations;
import buildcraft.transport.BlockGenericPipe; import buildcraft.transport.BlockGenericPipe;
@ -102,19 +104,24 @@ public final class FacadeRenderHelper {
//block_statemachine.setRenderAllSides(); //block_statemachine.setRenderAllSides();
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
if (!(tile.getPipePluggable(direction) instanceof FacadePluggable)) { if (!(tile.getPipePluggable(direction) instanceof IFacadePluggable)) {
continue; continue;
} }
FacadePluggable pluggable = (FacadePluggable) tile.getPipePluggable(direction); IFacadePluggable pluggable = (IFacadePluggable) tile.getPipePluggable(direction);
Block renderBlock = pluggable.getRenderingBlock(); if (((PipePluggable) pluggable).getRenderer() != null) {
// This IFacadePluggable provides its own renderer.
continue;
}
Block renderBlock = pluggable.getCurrentBlock();
if (renderBlock != null) { if (renderBlock != null) {
IBlockAccess facadeBlockAccess = new FacadeBlockAccess(tile.getWorldObj(), direction); IBlockAccess facadeBlockAccess = new FacadeBlockAccess(tile.getWorldObj(), direction);
// If the facade is meant to render in the current pass // If the facade is meant to render in the current pass
if (renderBlock.canRenderInPass(PipeRendererWorld.renderPass)) { if (renderBlock.canRenderInPass(PipeRendererWorld.renderPass)) {
int renderMeta = pluggable.getRenderingMeta(); int renderMeta = pluggable.getCurrentMetadata();
for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
textures[side.ordinal()] = renderBlock.getIcon( textures[side.ordinal()] = renderBlock.getIcon(
@ -126,11 +133,11 @@ public final class FacadeRenderHelper {
if (side == direction || side == direction.getOpposite()) { if (side == direction || side == direction.getOpposite()) {
blockStateMachine.setRenderSide(side, true); blockStateMachine.setRenderSide(side, true);
} else { } else {
if (!(tile.getPipePluggable(side) instanceof FacadePluggable)) { if (!(tile.getPipePluggable(side) instanceof IFacadePluggable)) {
blockStateMachine.setRenderSide(side, true); blockStateMachine.setRenderSide(side, true);
} else { } else {
FacadePluggable pluggable2 = (FacadePluggable) tile.getPipePluggable(side); IFacadePluggable pluggable2 = (IFacadePluggable) tile.getPipePluggable(side);
blockStateMachine.setRenderSide(side, pluggable2.getRenderingBlock() == null); blockStateMachine.setRenderSide(side, pluggable2.getCurrentBlock() == null);
} }
} }
} }
@ -212,8 +219,13 @@ public final class FacadeRenderHelper {
// Always render connectors in pass 0 // Always render connectors in pass 0
if (PipeRendererWorld.renderPass == 0) { if (PipeRendererWorld.renderPass == 0) {
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
if (tile.getPipePluggable(direction) instanceof FacadePluggable) { if (tile.getPipePluggable(direction) instanceof IFacadePluggable) {
FacadePluggable pluggable = (FacadePluggable) tile.getPipePluggable(direction); IFacadePluggable pluggable = (IFacadePluggable) tile.getPipePluggable(direction);
if (((PipePluggable) pluggable).getRenderer() != null) {
// This IFacadePluggable provides its own renderer.
continue;
}
if (!pluggable.isHollow()) { if (!pluggable.isHollow()) {
float[][] rotated = MatrixTranformations.deepClone(zeroStateSupport); float[][] rotated = MatrixTranformations.deepClone(zeroStateSupport);