Skip to content

Instantly share code, notes, and snippets.

@Daomephsta
Created June 29, 2018 06:17
Show Gist options
  • Save Daomephsta/0288c0cd521ba59590cee10c3316e843 to your computer and use it in GitHub Desktop.
Save Daomephsta/0288c0cd521ba59590cee10c3316e843 to your computer and use it in GitHub Desktop.
Material network for Builder's Drawers
java.lang.NullPointerException: Unexpected error
at daomephsta.buildersdrawers.common.tileentities.MaterialNetwork.merge(MaterialNetwork.java:89)
at daomephsta.buildersdrawers.common.tileentities.MaterialNetwork.connect(MaterialNetwork.java:79)
at daomephsta.buildersdrawers.common.tileentities.TileEntityBuildersDrawers.connectTo(TileEntityBuildersDrawers.java:41)
at daomephsta.buildersdrawers.common.tileentities.MaterialNetwork.merge(MaterialNetwork.java:92)
at daomephsta.buildersdrawers.common.tileentities.MaterialNetwork.connect(MaterialNetwork.java:79)
at daomephsta.buildersdrawers.common.tileentities.TileEntityBuildersDrawers.connectTo(TileEntityBuildersDrawers.java:41)
at daomephsta.buildersdrawers.common.tileentities.TileEntityBuildersDrawers.findNetwork(TileEntityBuildersDrawers.java:67)
at daomephsta.buildersdrawers.common.tileentities.TileEntityBuildersDrawers.onBlockPlaced(TileEntityBuildersDrawers.java:46)
at daomephsta.buildersdrawers.common.blocks.BlockBuildersDrawers.onBlockPlacedBy(BlockBuildersDrawers.java:46)
at net.minecraft.item.ItemBlock.placeBlockAt(ItemBlock.java:205)
at com.jaquadro.minecraft.storagedrawers.item.ItemDrawers.placeBlockAt(ItemDrawers.java:44)
at net.minecraft.item.ItemBlock.onItemUse(ItemBlock.java:57)
at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:201)
at net.minecraft.client.multiplayer.PlayerControllerMP.processRightClickBlock(PlayerControllerMP.java:499)
at net.minecraft.client.Minecraft.rightClickMouse(Minecraft.java:1692)
at net.minecraft.client.Minecraft.processKeyBinds(Minecraft.java:2379)
at net.minecraft.client.Minecraft.runTickKeyboard(Minecraft.java:2145)
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1933)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1186)
at net.minecraft.client.Minecraft.run(Minecraft.java:441)
at net.minecraft.client.main.Main.main(Main.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
at GradleStart.main(GradleStart.java:25)
package daomephsta.buildersdrawers.common.blocks;
import com.jaquadro.minecraft.storagedrawers.api.storage.BlockType;
import com.jaquadro.minecraft.storagedrawers.api.storage.EnumBasicDrawer;
import com.jaquadro.minecraft.storagedrawers.block.BlockDrawers;
import com.jaquadro.minecraft.storagedrawers.block.dynamic.StatusModelData;
import com.jaquadro.minecraft.storagedrawers.block.tile.TileEntityDrawers;
import daomephsta.buildersdrawers.common.BuildersDrawers;
import daomephsta.buildersdrawers.common.tileentities.TileEntityBuildersDrawers;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockBuildersDrawers extends BlockDrawers
{
private final StatusModelData statusModel;
private final EnumBasicDrawer drawerType;
public BlockBuildersDrawers(EnumBasicDrawer drawerType)
{
super(Material.ROCK, "builders_drawers_" + drawerType.getName(),
BuildersDrawers.MODID + ".buildersDrawers." + drawerType.getName());
this.drawerType = drawerType;
this.statusModel = new StatusModelData(3,
new ResourceLocation(BuildersDrawers.MODID,
"models/block/dynamic/builders_drawers_" + drawerType.getName() + ".json"));
setSoundType(SoundType.STONE);
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase entity, ItemStack itemStack)
{
super.onBlockPlacedBy(world, pos, state, entity, itemStack);
TileEntityBuildersDrawers drawersTE = (TileEntityBuildersDrawers) world.getTileEntity(pos);
drawersTE.onBlockPlaced(world, pos, state, entity, itemStack);
}
@Override
public void breakBlock(World world, BlockPos pos, IBlockState state)
{
TileEntityBuildersDrawers drawersTE = (TileEntityBuildersDrawers) world.getTileEntity(pos);
drawersTE.onBlockBroken(world, pos, state);
super.breakBlock(world, pos, state);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ)
{
boolean superResult = super.onBlockActivated(world, pos, state, player, hand, side, hitX, hitY, hitZ);
if (!world.isRemote)
{
TileEntityBuildersDrawers drawersTE = (TileEntityBuildersDrawers) world.getTileEntity(pos);
player.sendStatusMessage(new TextComponentString("Connected to " + drawersTE.getMaterialNetwork().getNetworkID()), true);
return false;
}
return superResult;
}
@Override
public TileEntity createNewTileEntity(World world, int meta)
{
return new TileEntityBuildersDrawers(drawerType.getDrawerCount());
}
@Override
public IBlockState getStateFromMeta(int meta)
{
return getDefaultState();
}
@Override
public int getMetaFromState(IBlockState state)
{
return 0;
}
@Override
protected BlockStateContainer createBlockState()
{
return new BlockStateContainer(this, FACING);
}
@Override
protected int getDrawerSlot(int drawerCount, int side, float hitX, float hitY, float hitZ)
{
if(hitTop(hitY)) return 0;
return hitLeft(side, hitX, hitZ) ? 1 : 2;
}
@Override
public boolean isHalfDepth(IBlockState state)
{
// Mojang code is wonderful...
if(drawerType == null) return false;
return drawerType.isHalfDepth();
}
@Override
public boolean isFullCube (IBlockState state) {
return isOpaqueCube(state);
}
@Override
public boolean isOpaqueCube (IBlockState state)
{
return !isHalfDepth(state);
}
@Override
public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face)
{
if (isHalfDepth(state))
{
TileEntityDrawers tile = getTileEntity(world, pos);
return (tile != null && tile.getDirection() == face.getOpposite().getIndex());
} else
return true;
}
@Override
@SuppressWarnings("deprecation")
public boolean shouldSideBeRendered (IBlockState state, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) {
if(isHalfDepth(state))
{
TileEntityDrawers tile = getTileEntity(blockAccess, pos);
if (tile != null && tile.getDirection() == side.getIndex())
return true;
}
return super.shouldSideBeRendered(state, blockAccess, pos, side);
}
@Override
public boolean causesSuffocation (IBlockState state)
{
return false;
}
@Override
public BlockType retrimType()
{
// Builder's drawers cannot be retrimmed
return super.retrimType();
}
public EnumBasicDrawer getDrawerType()
{
return drawerType;
}
@Override
public StatusModelData getStatusInfo(IBlockState state)
{
return statusModel;
}
@Override
public int getDrawerCount(IBlockState state)
{
return drawerType.getDrawerCount();
}
}
package daomephsta.buildersdrawers.common.tileentities;
import java.util.*;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class MaterialNetwork
{
private static int nextID = 0;
// An ID for debug purposes. Not synced between sides.
private final int networkID;
private final World world;
private BlockPos master;
private Material storedMaterial;
private int storedQuantity;
private Set<BlockPos> nodes = new HashSet<>();
private MaterialNetwork(World world, BlockPos master)
{
this.networkID = nextID++;
this.world = world;
this.master = master;
nodes.add(master);
}
public static MaterialNetwork createSingletonNetwork(World world, BlockPos master)
{
return new MaterialNetwork(world, master);
}
public static MaterialNetwork constructNewNetwork(World world, BlockPos master)
{
MaterialNetwork network = new MaterialNetwork(world, master);
// Breadth first search
Queue<BlockPos> toVisit = new ArrayDeque<>();
Set<BlockPos> visited = new HashSet<>();
toVisit.add(master);
while(!toVisit.isEmpty())
{
BlockPos nodePos = toVisit.remove();
for (EnumFacing facing : EnumFacing.values())
{
BlockPos neighbourPos = nodePos.offset(facing);
if (visited.contains(neighbourPos))
continue;
TileEntity te = world.getTileEntity(neighbourPos);
if (te instanceof TileEntityBuildersDrawers)
{
((TileEntityBuildersDrawers) te).connectTo(network);
toVisit.add(neighbourPos);
}
}
visited.add(nodePos);
}
return network;
}
MaterialNetwork connect(BlockPos pos)
{
/* Find networks other than this neighbouring the connecting position.
* Use a set to avoid duplicates.*/
Collection<MaterialNetwork> otherNetworks = new HashSet<>();
for (EnumFacing facing : EnumFacing.values())
{
BlockPos neighbourPos = pos.offset(facing);
TileEntity te = world.getTileEntity(neighbourPos);
if (te instanceof TileEntityBuildersDrawers)
{
MaterialNetwork network = ((TileEntityBuildersDrawers) te).getMaterialNetwork();
if(network != this) otherNetworks.add(network);
}
}
// If other networks were found, merge them with this network.
if(!otherNetworks.isEmpty()) merge(otherNetworks);
/* Finally add the new node to the network. This must be done
* after merging.*/
nodes.add(pos);
//System.out.println(String.format("Connected %s to network %d", pos, networkID));
return this;
}
private void merge(Collection<MaterialNetwork> otherNetworks)
{
for(MaterialNetwork mergingNetwork : otherNetworks)
{
for (BlockPos slavePos : mergingNetwork.nodes)
{
TileEntityBuildersDrawers te = (TileEntityBuildersDrawers) world.getTileEntity(slavePos);
te.connectTo(this);
}
}
}
void disconnect(BlockPos pos)
{
nodes.remove(pos);
// Find neighbouring nodes
Collection<BlockPos> neighbouringNodes = new HashSet<>();
for (EnumFacing facing : EnumFacing.values())
{
BlockPos neighbourPos = pos.offset(facing);
if (nodes.contains(neighbourPos))
neighbouringNodes.add(neighbourPos);
}
// If there are multiple neighbours, the network has split.
if(neighbouringNodes.size() > 1)
{
for(BlockPos nodePos : neighbouringNodes)
{
TileEntityBuildersDrawers te = (TileEntityBuildersDrawers) world.getTileEntity(nodePos);
te.resetNetwork();
}
}
}
public Material getStoredMaterial()
{
return storedMaterial;
}
public void setStoredMaterial(Material storedMaterial)
{
this.storedMaterial = storedMaterial;
}
public int getStoredQuantity()
{
return storedQuantity;
}
public void setStoredQuantity(int storedQuantity)
{
this.storedQuantity = storedQuantity;
}
public int getNetworkID()
{
return networkID;
}
}
package daomephsta.buildersdrawers.common.tileentities;
import com.jaquadro.minecraft.chameleon.block.tiledata.TileDataShim;
import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository;
import com.jaquadro.minecraft.storagedrawers.api.storage.*;
import com.jaquadro.minecraft.storagedrawers.block.tile.TileEntityDrawers;
import com.jaquadro.minecraft.storagedrawers.capabilities.CapabilityItemRepository;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class TileEntityBuildersDrawers extends TileEntityDrawers
{
private IDrawerGroup group;
private MaterialNetwork materialNetwork;
public TileEntityBuildersDrawers() {}
public TileEntityBuildersDrawers(int drawerCount)
{
this.group = new DrawerGroup(drawerCount);
}
@Override
public IDrawerGroup getGroup()
{
return group;
}
void connectTo(MaterialNetwork network)
{
materialNetwork = network.connect(pos);
}
public void onBlockPlaced(World world, BlockPos pos, IBlockState state, EntityLivingBase entity, ItemStack itemStack)
{
if (!findNetwork())
connectTo(MaterialNetwork.createSingletonNetwork(world, pos));
}
public void onBlockBroken(World world, BlockPos pos, IBlockState state)
{
materialNetwork.disconnect(pos);
}
public MaterialNetwork getMaterialNetwork()
{
return materialNetwork;
}
private boolean findNetwork()
{
for(EnumFacing facing : EnumFacing.values())
{
TileEntity te = world.getTileEntity(pos.offset(facing));
if(te instanceof TileEntityBuildersDrawers)
{
connectTo(((TileEntityBuildersDrawers) te).getMaterialNetwork());
return true;
}
}
return false;
}
/** Creates a new network with this TE as the master node
* and then makes the network construct itself from the master node.
*/
public void resetNetwork()
{
connectTo(MaterialNetwork.constructNewNetwork(world, pos));
}
@Override
protected void readFromFixedNBT(NBTTagCompound tag)
{
super.readFromFixedNBT(tag);
group = new DrawerGroup(tag.getInteger("drawerCount"));
}
@Override
protected NBTTagCompound writeToFixedNBT(NBTTagCompound tag)
{
tag = super.writeToFixedNBT(tag);
tag.setInteger("drawerCount", getGroup().getDrawerCount());
return tag;
}
private static final class DrawerGroup extends TileDataShim implements IDrawerGroup
{
private final int drawerCount;
private /*final*/ IItemHandler inventory;
private /*final*/ IItemRepository itemRepo;
private DrawerGroup(int drawerCount)
{
this.drawerCount = drawerCount;
}
@Override
public int getDrawerCount()
{
return drawerCount;
}
@Override
public IDrawer getDrawer(int slot)
{
return Drawers.DISABLED;
}
@Override
public int[] getAccessibleDrawerSlots()
{
return new int[0];
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
return false; //capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY
//|| capability == CapabilityItemRepository.ITEM_REPOSITORY_CAPABILITY;
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(inventory);
if (capability == CapabilityItemRepository.ITEM_REPOSITORY_CAPABILITY)
return CapabilityItemRepository.ITEM_REPOSITORY_CAPABILITY.cast(itemRepo);
return IDrawerGroup.super.getCapability(capability, facing);
}
@Override
public void readFromNBT(NBTTagCompound tag)
{
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag)
{
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment