Signal Bus Release

This commit is contained in:
tmcgeorge committed 2013-11-07 22:23:20 -06:00
1 parent d4bfef708c
commit eb7cb19441
34 files changed
+5508 -12

No files matched your search

+9 -1
View File
@@ -1,4 +1,12 @@
/build/
/bin/
/download/
/src/com/xcompwiz/
#Remove OS generated garbage
*/.DS_Store
.DS_Store
.DS_Store?
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
+7 -1
View File
@@ -100,6 +100,9 @@ block.fancybrick.stone.name=Fancy Stone Brick
tile.rail.wood.name=Wooden Rail
tile.signalbus.name=Signal Bus
tile.signalterminal.name=Signal Terminal
tile.cloth.white.slab.name=Wool Slab
tile.cloth.orange.slab.name=Orange Wool Slab
tile.cloth.magenta.slab.name=Magenta Wool Slab
@@ -125,7 +128,10 @@ item.oreberry.aluminum.name=Aluminum Oreberry
item.oreberry.essence.name=Concentrated Essence Berry
item.goldenhead.name=Golden Head
item.tconstruct.titleicon.name=Spawn
item.tconstruct.titleicon.name=Spawn
item.spoolwire.name=Spool of Wire
item.lengthwire.name=Length of Wire
item.InfiTool.Pickaxe.name=Pickaxe
item.InfiTool.Shovel.name=Shovel
Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

+7
View File
@@ -13,10 +13,13 @@ import java.util.logging.Logger;
import net.minecraft.crash.CallableMinecraftVersion;
import net.minecraft.world.gen.structure.MapGenStructureIO;
import net.minecraftforge.common.MinecraftForge;
import tconstruct.blocks.SignalBus;
import tconstruct.client.SignalTetherWorldOverlayRenderer;
import tconstruct.client.event.EventCloakRender;
import tconstruct.common.*;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.crafting.*;
import tconstruct.library.multiblock.MultiblockEventHandler;
import tconstruct.library.util.TabTools;
import tconstruct.util.*;
import tconstruct.util.config.*;
@@ -95,6 +98,8 @@ public class TConstruct
proxy.addNames();
proxy.readManuals();
proxy.registerKeys();
MinecraftForge.EVENT_BUS.register(new MultiblockEventHandler());
GameRegistry.registerWorldGenerator(new TBaseWorldGenerator());
MinecraftForge.TERRAIN_GEN_BUS.register(new TerrainGenEventHandler());
@@ -135,6 +140,8 @@ public class TConstruct
if (event.getSide() == Side.CLIENT)
{
MinecraftForge.EVENT_BUS.register(new EventCloakRender());
MinecraftForge.EVENT_BUS.register(TConstruct.instance.content.signalBus);
MinecraftForge.EVENT_BUS.register(new SignalTetherWorldOverlayRenderer());
}
content.intermodCommunication();
+601
View File
@@ -0,0 +1,601 @@
package tconstruct.blocks;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.naming.Context;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import tconstruct.TConstruct;
import tconstruct.blocks.SignalTerminal.TerminalGeometry;
import tconstruct.blocks.logic.CastingChannelLogic;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.blocks.logic.SignalTerminalLogic;
import tconstruct.client.block.BlockRenderCastingChannel;
import tconstruct.client.block.SignalBusRender;
import tconstruct.items.blocks.SignalBusItem;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.multiblock.IMultiblockMember;
import tconstruct.library.multiblock.MultiblockMasterBaseLogic;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChatMessageComponent;
import net.minecraft.util.EnumMovingObjectType;
import net.minecraft.util.Icon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.ForgeSubscribe;
public class SignalBus extends Block implements ITileEntityProvider {
public static class Geometry {
public static double cable_width_min = 0.375D;
public static double cable_width_max = 1 - cable_width_min;
public static double cable_low_height = 0.2D;
public static double cable_low_offset = 0.0D;
public static double cable_high_height = 1.0D;
public static double cable_high_offset = 1 - cable_low_height;
public static double cable_extend_min = 0.0D;
public static double cable_extend_max = 1.0D;
public static double cable_corner_min = cable_high_offset - 1;
public static double cable_corner_max = cable_low_height + 1;
public static double zfight = 0.0000001D;
}
public static int HITBOXES = 6;
public Icon[] icons;
public String[] textureNames = new String[] { "signalbus" };
public SignalBus(int par1) {
super(par1, Material.circuits);
this.setHardness(0.1F);
this.setResistance(1);
this.setStepSound(soundMetalFootstep);
setCreativeTab(TConstructRegistry.blockTab);
}
@Override
public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) {
if (par1World.isRemote) { return false; }
TileEntity te = par1World.getBlockTileEntity(par2, par3, par4);
if (te != null && te instanceof SignalBusLogic) {
TConstruct.logger.info(((SignalBusLogic)te).debugString());
if (((SignalBusLogic)te).getMultiblockMaster() != null) {
TConstruct.logger.info((((SignalBusLogic)te).getMultiblockMaster().debugString()));
}
}
return false;
}
@Override
public void onNeighborTileChange(World world, int x, int y, int z, int tileX, int tileY, int tileZ) {
TileEntity te = world.getBlockTileEntity(tileX, tileY, tileZ);
if (te instanceof SignalBusLogic) {
if (((SignalBusLogic)te).getMultiblockMaster() != null) {
((SignalBusLogic)te).getMultiblockMaster().detachBlock((IMultiblockMember)te, false);
}
}
}
@Override
public void onBlockAdded(World world, int x, int y, int z) {
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te != null && te instanceof SignalBusLogic) {
((SignalBusLogic)te).onBlockAdded(world, x, y, z);
}
}
@Override
@SideOnly(Side.CLIENT)
public Icon getIcon (int side, int metadata)
{
return icons[0];
}
@Override
@SideOnly(Side.CLIENT)
public void registerIcons (IconRegister iconRegister)
{
this.icons = new Icon[textureNames.length];
for (int i = 0; i < this.icons.length; ++i)
{
this.icons[i] = iconRegister.registerIcon("tinker:" + textureNames[i]);
}
}
// @Override
// public void setBlockBoundsBasedOnState (IBlockAccess world, int x, int y, int z)
// {
// SignalBusLogic tile = (SignalBusLogic) world.getBlockTileEntity(x, y, z);
// if (!(tile instanceof SignalBusLogic)) return;
// float minX = 0.375F;
// float maxX = 0.625F;
// float minZ = 0.375F;
// float maxZ = 0.625F;
// if (tile.isConnected(ForgeDirection.DOWN, ForgeDirection.NORTH))
// minZ = 0F;
// if (tile.isConnected(ForgeDirection.DOWN, ForgeDirection.SOUTH))
// maxZ = 1F;
// if (tile.isConnected(ForgeDirection.DOWN, ForgeDirection.WEST))
// minX = 0F;
// if (tile.isConnected(ForgeDirection.DOWN, ForgeDirection.EAST))
// maxX = 1F;
//
// //this.setBlockBounds(minX, 0.0F, minZ, maxX, 0.2F, maxZ);
// this.setBlockBounds(0, 0, 0, 1, 1, 1);
// }
@Override
public boolean renderAsNormalBlock ()
{
return false;
}
@Override
public boolean isOpaqueCube ()
{
return false;
}
@Override
public int getRenderType ()
{
return SignalBusRender.renderID;
}
public void addCollisionBoxesToList (World world, int x, int y, int z, AxisAlignedBB collisionTest, List collisionBoxList, Entity entity)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalBusLogic)
{
for (AxisAlignedBB aabb : getBoxes((SignalBusLogic) te))
{
if (aabb == null)
{
continue;
}
aabb = AxisAlignedBB.getBoundingBox(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ);
aabb.minX += x;
aabb.minY += y;
aabb.minZ += z;
aabb.maxX += x;
aabb.maxY += y;
aabb.maxZ += z;
if (collisionTest.intersectsWith(aabb))
{
collisionBoxList.add(aabb);
}
}
}
else
{
super.addCollisionBoxesToList(world, x, y, z, collisionTest, collisionBoxList, entity);
}
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered (IBlockAccess par1iBlockAccess, int par2, int par3, int par4, int par5)
{
return true;
}
@Override
public MovingObjectPosition collisionRayTrace (World world, int x, int y, int z, Vec3 start, Vec3 end)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalBusLogic)
{
MovingObjectPosition closest = null;
AxisAlignedBB[] boxes = getBoxes((SignalBusLogic)te);
double closestCalc = Double.MAX_VALUE;
double hitDistance = 0D;
for (int i = 0; i < boxes.length; i++)
{
if (boxes[i] == null)
{
continue;
}
this.setBlockBounds((float)boxes[i].minX, (float)boxes[i].minY, (float)boxes[i].minZ, (float)boxes[i].maxX, (float)boxes[i].maxY, (float)boxes[i].maxZ);
MovingObjectPosition hit = super.collisionRayTrace(world, x, y, z, start, end);
if (hit != null)
{
hitDistance = start.distanceTo(hit.hitVec);
if (hitDistance < closestCalc)
{
closestCalc = hitDistance;
closest = hit;
}
}
}
return closest;
}
return null;
}
private static AxisAlignedBB[] getBoxes (SignalBusLogic logic)
{
boolean placed[] = logic.placedSides();
boolean connected[];
boolean corners[];
boolean renderDir[];
AxisAlignedBB[] parts = new AxisAlignedBB[HITBOXES];
double minX;
double minY;
double minZ;
double maxX;
double maxY;
double maxZ;
boolean didRender = false;
if (placed[ForgeDirection.DOWN.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.DOWN);
corners = logic.getRenderCorners(ForgeDirection.DOWN);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_low_offset;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_low_height;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
parts[0] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (placed[ForgeDirection.UP.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.UP);
corners = logic.getRenderCorners(ForgeDirection.UP);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_high_offset;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_high_height;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
parts[1] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (placed[ForgeDirection.NORTH.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.NORTH);
corners = logic.getRenderCorners(ForgeDirection.NORTH);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_low_offset;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_low_height;
parts[2] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (placed[ForgeDirection.SOUTH.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.SOUTH);
corners = logic.getRenderCorners(ForgeDirection.SOUTH);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_high_offset;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_high_height;
parts[3] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (placed[ForgeDirection.WEST.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.WEST);
corners = logic.getRenderCorners(ForgeDirection.WEST);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = Geometry.cable_low_offset;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_low_height;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
parts[4] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (placed[ForgeDirection.EAST.ordinal()])
{
connected = logic.connectedSides(ForgeDirection.EAST);
corners = logic.getRenderCorners(ForgeDirection.EAST);
renderDir = new boolean[] {
(connected[0] || placed[0] || corners[0]),
(connected[1] || placed[1] || corners[1]),
(connected[2] || placed[2] || corners[2]),
(connected[3] || placed[3] || corners[3]),
(connected[4] || placed[4] || corners[4]),
(connected[5] || placed[5] || corners[5])
};
minX = Geometry.cable_high_offset;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_high_height;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
parts[5] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
didRender = true;
}
if (!didRender)
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_low_offset;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_low_height;
maxZ = Geometry.cable_width_max;
parts[0] = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
}
return parts;
}
private static int closestClicked (EntityPlayer player, double reachDistance, SignalBusLogic terminal, AxisAlignedBB[] parts)
{
int closest = -1;
Vec3 playerPosition = Vec3.createVectorHelper(player.posX - terminal.xCoord, player.posY - terminal.yCoord + player.getEyeHeight(), player.posZ - terminal.zCoord);
Vec3 playerLook = player.getLookVec();
Vec3 playerViewOffset = Vec3.createVectorHelper(playerPosition.xCoord + playerLook.xCoord * reachDistance, playerPosition.yCoord + playerLook.yCoord * reachDistance, playerPosition.zCoord
+ playerLook.zCoord * reachDistance);
double closestCalc = Double.MAX_VALUE;
double hitDistance = 0D;
for (int i = 0; i < parts.length; i++)
{
if (parts[i] == null)
{
continue;
}
MovingObjectPosition hit = parts[i].calculateIntercept(playerPosition, playerViewOffset);
if (hit != null)
{
hitDistance = playerPosition.distanceTo(hit.hitVec);
if (hitDistance < closestCalc)
{
closestCalc = hitDistance;
closest = i;
}
}
}
return closest;
}
@SideOnly(Side.CLIENT)
@ForgeSubscribe
public void onBlockHighlight (DrawBlockHighlightEvent event)
{
return;
// if (event.target.typeOfHit == EnumMovingObjectType.TILE && event.player.worldObj.getBlockId(event.target.blockX, event.target.blockY, event.target.blockZ) == this.blockID)
// {
// TileEntity te = event.player.worldObj.getBlockTileEntity(event.target.blockX, event.target.blockY, event.target.blockZ);
// if (!(te instanceof SignalBusLogic))
// {
// return;
// }
// AxisAlignedBB[] boxes = getBoxes((SignalBusLogic)te);
// double reach = Minecraft.getMinecraft().playerController.getBlockReachDistance();
// int hitbox = closestClicked(event.player, reach, (SignalBusLogic)te, boxes);
//
// if (hitbox > 0 && hitbox < HITBOXES)
// {
// float f1 = 0.002F;
// double d0 = event.player.lastTickPosX + (event.player.posX - event.player.lastTickPosX) * (double)event.partialTicks;
// double d1 = event.player.lastTickPosY + (event.player.posY - event.player.lastTickPosY) * (double)event.partialTicks;
// double d2 = event.player.lastTickPosZ + (event.player.posZ - event.player.lastTickPosZ) * (double)event.partialTicks;
// drawOutlinedBoundingBox(boxes[hitbox].expand((double)f1, (double)f1, (double)f1).getOffsetBoundingBox(-d0, -d1, -d2));
//
// }
// event.setCanceled(true);
// }
}
/**
* Draws lines for the edges of the bounding box.
*/
private static void drawOutlinedBoundingBox(AxisAlignedBB par1AxisAlignedBB)
{
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawing(3);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
tessellator.draw();
tessellator.startDrawing(3);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
tessellator.draw();
tessellator.startDrawing(1);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ);
tessellator.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ);
tessellator.draw();
}
@Override
public TileEntity createTileEntity(World world, int metadata) {
return new SignalBusLogic();
}
@Override
public TileEntity createNewTileEntity(World world) {
return new SignalBusLogic();
}
@Override
public ArrayList<ItemStack> getBlockDropped (World world, int x, int y, int z, int metadata, int fortune)
{
return new ArrayList<ItemStack>();
}
@Override
public void onBlockPlacedBy (World world, int x, int y, int z, EntityLivingBase entityLiving, ItemStack itemStack)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalBusLogic)
{
NBTTagCompound data = itemStack.stackTagCompound;
if (data != null && data.hasKey("connectedSide"))
{
((SignalBusLogic) te).addPlacedSide(data.getInteger("connectedSide"));
itemStack.stackTagCompound = null;
}
}
}
@Override
public void onNeighborBlockChange (World par1World, int par2, int par3, int par4, int par5)
{
super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
if (par5 == this.blockID)
{
return;
}
TileEntity te = par1World.getBlockTileEntity(par2, par3, par4);
if (te instanceof SignalBusLogic)
{
((SignalBusLogic)te).forceNeighborCheck();
}
}
@Override
public void breakBlock (World world, int x, int y, int z, int id, int meta)
{
int dropBus, dropWire = 0;
float jumpX, jumpY, jumpZ;
ItemStack tempStack;
Random rand = new Random();
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalBusLogic)
{
dropBus = ((SignalBusLogic) te).getDroppedBuses();
dropWire = ((SignalBusLogic) te).getDroppedWire();
if (dropBus > 0)
{
tempStack = new ItemStack(TConstruct.instance.content.signalBus.blockID, dropBus, 0);
jumpX = rand.nextFloat() * 0.8F + 0.1F;
jumpY = rand.nextFloat() * 0.8F + 0.1F;
jumpZ = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem = new EntityItem(world, (double) ((float) x + jumpX), (double) ((float) y + jumpY), (double) ((float) z + jumpZ), tempStack);
float offset = 0.05F;
entityitem.motionX = (double) ((float) rand.nextGaussian() * offset);
entityitem.motionY = (double) ((float) rand.nextGaussian() * offset + 0.2F);
entityitem.motionZ = (double) ((float) rand.nextGaussian() * offset);
world.spawnEntityInWorld(entityitem);
}
if (dropWire > 0)
{
tempStack = new ItemStack(TConstruct.instance.content.lengthWire, dropWire);
jumpX = rand.nextFloat() * 0.8F + 0.1F;
jumpY = rand.nextFloat() * 0.8F + 0.1F;
jumpZ = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem = new EntityItem(world, (double) ((float) x + jumpX), (double) ((float) y + jumpY), (double) ((float) z + jumpZ), tempStack);
float offset = 0.05F;
entityitem.motionX = (double) ((float) rand.nextGaussian() * offset);
entityitem.motionY = (double) ((float) rand.nextGaussian() * offset + 0.2F);
entityitem.motionZ = (double) ((float) rand.nextGaussian() * offset);
world.spawnEntityInWorld(entityitem);
}
((SignalBusLogic) te).notifyBreak();
}
super.breakBlock(world, x, y, z, id, meta);
}
}
+567
View File
@@ -0,0 +1,567 @@
package tconstruct.blocks;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import codechicken.nei.api.IHighlightHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import tconstruct.TConstruct;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.blocks.logic.SignalTerminalLogic;
import tconstruct.client.block.SignalBusRender;
import tconstruct.client.block.SignalTerminalRender;
import tconstruct.library.TConstructRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumMovingObjectType;
import net.minecraft.util.Icon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.ForgeDirection.*;
import net.minecraftforge.event.ForgeSubscribe;
public class SignalTerminal extends Block implements ITileEntityProvider
{
public static class TerminalGeometry
{
public static float plate_width_min = 0.25F;
public static float plate_width_max = 0.75F;
public static float plate_low_max = 0.15F;
public static float plate_high_max = 1.0F;
public static float plate_low_min = 0.0F;
public static float plate_high_min = 1 - plate_low_max;
public static float center_min = 0.375F;
public static float center_max = 0.625F;
public static float channel_width_min = 0.375F;
public static float channel_width_max = 0.625F;
public static float channel_low_max = center_min;
public static float channel_high_max = plate_high_min;
public static float channel_low_min = plate_low_max;
public static float channel_high_min = center_max;
}
public static int HITBOXES = 13;
public static int[] sideBoxMapping = new int[] { -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
public Icon[] icons;
public Icon[] channelIcons;
public String[] textureNames = new String[] { "signalbus" };
public String[] channelTextureNames = new String[] { "white", "orange", "magenta", "lightblue", "yellow", "lime", "pink", "gray", "lightgray", "cyan", "purple", "blue", "brown", "green", "red",
"black" };
public SignalTerminal(int par1)
{
super(par1, Material.circuits);
this.setHardness(0.1F);
this.setResistance(1);
this.setStepSound(soundMetalFootstep);
setCreativeTab(TConstructRegistry.blockTab);
}
@Override
@SideOnly(Side.CLIENT)
public Icon getIcon (int side, int metadata)
{
return icons[0];
}
public Icon getChannelIcon (int channel)
{
if (channel < 0 || channel >= channelIcons.length)
{
return channelIcons[0];
}
return channelIcons[channel];
}
@Override
@SideOnly(Side.CLIENT)
public void registerIcons (IconRegister iconRegister)
{
this.icons = new Icon[textureNames.length];
for (int i = 0; i < this.icons.length; ++i)
{
this.icons[i] = iconRegister.registerIcon("tinker:" + textureNames[i]);
}
this.channelIcons = new Icon[channelTextureNames.length];
for (int i = 0; i < this.channelIcons.length; ++i)
{
this.channelIcons[i] = iconRegister.registerIcon("tinker:glass/stainedglass_" + channelTextureNames[i]);
}
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
* cleared to be reused)
*/
public AxisAlignedBB getCollisionBoundingBoxFromPool (World par1World, int par2, int par3, int par4)
{
return null;
}
/**
* Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two
* adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
*/
public boolean isOpaqueCube ()
{
return false;
}
/**
* If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
*/
public boolean renderAsNormalBlock ()
{
return false;
}
@Override
public boolean isBlockSolidOnSide (World world, int x, int y, int z, ForgeDirection side)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te != null && te instanceof SignalTerminalLogic)
{
if (((SignalTerminalLogic) te).getConnectedSides()[side.ordinal()] != -1)
{
return true;
}
}
return false;
}
/**
* The type of render function that is called for this block
*/
@Override
public int getRenderType ()
{
return SignalTerminalRender.renderID;
}
/**
* How many world ticks before ticking
*/
public int tickRate (World par1World)
{
return 1;
}
/**
* checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
*/
public boolean canPlaceBlockOnSide (World world, int x, int y, int z, int side)
{
ForgeDirection dir = ForgeDirection.getOrientation(side);
return true || (dir == ForgeDirection.NORTH && world.isBlockSolidOnSide(x, y, z + 1, ForgeDirection.NORTH))
|| (dir == ForgeDirection.SOUTH && world.isBlockSolidOnSide(x, y, z - 1, ForgeDirection.SOUTH))
|| (dir == ForgeDirection.WEST && world.isBlockSolidOnSide(x + 1, y, z, ForgeDirection.WEST))
|| (dir == ForgeDirection.EAST && world.isBlockSolidOnSide(x - 1, y, z, ForgeDirection.EAST)) || (dir == ForgeDirection.UP && world.isBlockSolidOnSide(x, y - 1, z, ForgeDirection.UP))
|| (dir == ForgeDirection.DOWN && world.isBlockSolidOnSide(x, y + 1, z, ForgeDirection.DOWN));
}
/**
* Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
*/
public boolean canPlaceBlockAt (World world, int x, int y, int z)
{
return world.isBlockSolidOnSide(x - 1, y, z, ForgeDirection.EAST) || world.isBlockSolidOnSide(x + 1, y, z, ForgeDirection.WEST) || world.isBlockSolidOnSide(x, y, z - 1, ForgeDirection.SOUTH)
|| world.isBlockSolidOnSide(x, y, z + 1, ForgeDirection.NORTH) || world.isBlockSolidOnSide(x, y - 1, z, ForgeDirection.UP)
|| world.isBlockSolidOnSide(x, y + 1, z, ForgeDirection.DOWN);
}
/**
* Updates the blocks bounds based on its current state. Args: world, x, y, z
*/
public void setBlockBoundsBasedOnState (IBlockAccess world, int x, int y, int z)
{
float minX = 1;
float minY = 1;
float minZ = 1;
float maxX = 0;
float maxY = 0;
float maxZ = 0;
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
for (AxisAlignedBB aabb : getBoxes((SignalTerminalLogic) te))
{
if (aabb == null)
{
continue;
}
minX = Math.min(minX, (float) aabb.minX);
minY = Math.min(minY, (float) aabb.minY);
minZ = Math.min(minZ, (float) aabb.minZ);
maxX = Math.max(maxX, (float) aabb.maxX);
maxY = Math.max(maxY, (float) aabb.maxY);
maxZ = Math.max(maxZ, (float) aabb.maxZ);
}
setBlockBounds(minX, minY, minZ, maxX, maxY, maxZ);
}
else
{
this.setBlockBounds(0.375F, 0.375F, 0.375F, 0.625F, 0.625F, 0.625F);
}
return;
}
public void addCollisionBoxesToList (World world, int x, int y, int z, AxisAlignedBB collisionTest, List collisionBoxList, Entity entity)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
for (AxisAlignedBB aabb : getBoxes((SignalTerminalLogic) te))
{
if (aabb == null)
{
continue;
}
aabb = AxisAlignedBB.getBoundingBox(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ);
aabb.minX += x;
aabb.minY += y;
aabb.minZ += z;
aabb.maxX += x;
aabb.maxY += y;
aabb.maxZ += z;
if (collisionTest.intersectsWith(aabb))
{
collisionBoxList.add(aabb);
}
}
}
else
{
super.addCollisionBoxesToList(world, x, y, z, collisionTest, collisionBoxList, entity);
}
}
/**
* Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
* returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
* Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
*/
public int isProvidingWeakPower (IBlockAccess world, int x, int y, int z, int localSide)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
return ((SignalTerminalLogic) te).isProvidingWeakPower(localSide);
}
return 0;
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered (IBlockAccess par1iBlockAccess, int par2, int par3, int par4, int par5)
{
return true;
}
/**
* Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
* side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
*/
public int isProvidingStrongPower (IBlockAccess world, int x, int y, int z, int localSide)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
return ((SignalTerminalLogic) te).isProvidingStrongPower(localSide);
}
return 0;
}
@Override
public boolean shouldCheckWeakPower (World world, int x, int y, int z, int side)
{
return true;
}
/**
* Can this block provide power. Only wire currently seems to have this change based on its state.
*/
public boolean canProvidePower ()
{
return true;
}
@Override
public TileEntity createNewTileEntity (World world)
{
return new SignalTerminalLogic();
}
@Override
public void onNeighborBlockChange (World world, int x, int y, int z, int neighborID)
{
super.onNeighborBlockChange(world, x, y, z, neighborID);
// if (neighborID == blockID) {
// return;
// }
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
((SignalTerminalLogic) te).onNeighborBlockChange();
}
}
private static AxisAlignedBB[] getBoxes (SignalTerminalLogic logic)
{
byte connected[] = logic.getConnectedSides();
AxisAlignedBB[] parts = new AxisAlignedBB[HITBOXES];
// Center
parts[0] = AxisAlignedBB.getBoundingBox(TerminalGeometry.center_min, TerminalGeometry.center_min, TerminalGeometry.center_min, TerminalGeometry.center_max, TerminalGeometry.center_max,
TerminalGeometry.center_max);
if (connected[ForgeDirection.DOWN.ordinal()] != -1)
{
parts[1] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_width_min, TerminalGeometry.plate_low_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_max,
TerminalGeometry.plate_low_max, TerminalGeometry.plate_width_max);
parts[2] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_width_min, TerminalGeometry.channel_low_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_max,
TerminalGeometry.channel_low_max, TerminalGeometry.channel_width_max);
}
if (connected[ForgeDirection.UP.ordinal()] != -1)
{
parts[3] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_width_min, TerminalGeometry.plate_high_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_max,
TerminalGeometry.plate_high_max, TerminalGeometry.plate_width_max);
parts[4] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_width_min, TerminalGeometry.channel_high_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_max,
TerminalGeometry.channel_high_max, TerminalGeometry.channel_width_max);
}
if (connected[ForgeDirection.NORTH.ordinal()] != -1)
{
parts[5] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_high_min, TerminalGeometry.plate_width_max,
TerminalGeometry.plate_width_max, TerminalGeometry.plate_high_max);
parts[6] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_high_min, TerminalGeometry.channel_width_max,
TerminalGeometry.channel_width_max, TerminalGeometry.channel_high_max);
}
if (connected[ForgeDirection.SOUTH.ordinal()] != -1)
{
parts[7] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_low_min, TerminalGeometry.plate_width_max,
TerminalGeometry.plate_width_max, TerminalGeometry.plate_low_max);
parts[8] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_low_min, TerminalGeometry.channel_width_max,
TerminalGeometry.channel_width_max, TerminalGeometry.channel_low_max);
}
if (connected[ForgeDirection.WEST.ordinal()] != -1)
{
parts[9] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_low_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_low_max,
TerminalGeometry.plate_width_max, TerminalGeometry.plate_width_max);
parts[10] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_low_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_low_max,
TerminalGeometry.channel_width_max, TerminalGeometry.channel_width_max);
}
if (connected[ForgeDirection.EAST.ordinal()] != -1)
{
parts[11] = AxisAlignedBB.getBoundingBox(TerminalGeometry.plate_high_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_width_min, TerminalGeometry.plate_high_max,
TerminalGeometry.plate_width_max, TerminalGeometry.plate_width_max);
parts[12] = AxisAlignedBB.getBoundingBox(TerminalGeometry.channel_high_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_width_min, TerminalGeometry.channel_high_max,
TerminalGeometry.channel_width_max, TerminalGeometry.channel_width_max);
}
return parts;
}
private static int closestClicked (EntityPlayer player, double reachDistance, SignalTerminalLogic terminal, AxisAlignedBB[] parts)
{
int closest = -1;
Vec3 playerPosition = Vec3.createVectorHelper(player.posX - terminal.xCoord, player.posY - terminal.yCoord + player.getEyeHeight(), player.posZ - terminal.zCoord);
Vec3 playerLook = player.getLookVec();
Vec3 playerViewOffset = Vec3.createVectorHelper(playerPosition.xCoord + playerLook.xCoord * reachDistance, playerPosition.yCoord + playerLook.yCoord * reachDistance, playerPosition.zCoord
+ playerLook.zCoord * reachDistance);
double closestCalc = Double.MAX_VALUE;
double hitDistance = 0D;
for (int i = 0; i < parts.length; i++)
{
if (parts[i] == null)
{
continue;
}
MovingObjectPosition hit = parts[i].calculateIntercept(playerPosition, playerViewOffset);
if (hit != null)
{
hitDistance = playerPosition.distanceTo(hit.hitVec);
if (hitDistance < closestCalc)
{
closestCalc = hitDistance;
closest = i;
}
}
}
return closest;
}
@Override
public boolean onBlockActivated (World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
{
int meta = par1World.getBlockMetadata(par2, par3, par4);
TileEntity te = par1World.getBlockTileEntity(par2, par3, par4);
if (!par1World.isRemote)
{
if (te != null && te instanceof SignalTerminalLogic)
{
// ((SignalTerminalLogic) te).nextChannel();
if (!par1World.isRemote)
{
// par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 1);
// par1World.markBlockForRenderUpdate(par2, par3, par4);
par1World.markBlockForUpdate(par2, par3, par4);
}
int boxHit = closestClicked(par5EntityPlayer, 3.0F, (SignalTerminalLogic) te, getBoxes((SignalTerminalLogic) te));
if (boxHit < 0 || boxHit >= HITBOXES)
{
return false;
}
if (boxHit == 0)
{
return false;
}
int side = sideBoxMapping[boxHit];
if (side < 0 || side >= 6)
{
return false;
}
if (par5EntityPlayer.isSneaking())
{
((SignalTerminalLogic) te).prevChannel(side);
}
else
{
((SignalTerminalLogic) te).nextChannel(side);
}
}
}
if (te instanceof SignalTerminalLogic)
{
TConstruct.logger.info(((SignalTerminalLogic) te).debugString());
}
TConstruct.logger.info("meta: " + meta);
//this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
return false;
}
@Override
public void onBlockPlacedBy (World world, int x, int y, int z, EntityLivingBase entityLiving, ItemStack itemStack)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
NBTTagCompound data = itemStack.stackTagCompound;
if (data != null && data.hasKey("connectedSide"))
{
((SignalTerminalLogic) te).addPendingSide(data.getInteger("connectedSide"));
itemStack.stackTagCompound = null;
}
((SignalTerminalLogic) te).connectPending();
}
}
@Override
public ArrayList<ItemStack> getBlockDropped (World world, int x, int y, int z, int metadata, int fortune)
{
return new ArrayList<ItemStack>();
}
@Override
public void breakBlock (World world, int x, int y, int z, int id, int meta)
{
int dropTerm, dropWire = 0;
float jumpX, jumpY, jumpZ;
ItemStack tempStack;
Random rand = new Random();
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te instanceof SignalTerminalLogic)
{
dropTerm = ((SignalTerminalLogic) te).getDroppedTerminals();
dropWire = ((SignalTerminalLogic) te).getDroppedWire();
if (dropTerm > 0)
{
tempStack = new ItemStack(TConstruct.instance.content.signalTerminal.blockID, dropTerm, 0);
jumpX = rand.nextFloat() * 0.8F + 0.1F;
jumpY = rand.nextFloat() * 0.8F + 0.1F;
jumpZ = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem = new EntityItem(world, (double) ((float) x + jumpX), (double) ((float) y + jumpY), (double) ((float) z + jumpZ), tempStack);
float offset = 0.05F;
entityitem.motionX = (double) ((float) rand.nextGaussian() * offset);
entityitem.motionY = (double) ((float) rand.nextGaussian() * offset + 0.2F);
entityitem.motionZ = (double) ((float) rand.nextGaussian() * offset);
world.spawnEntityInWorld(entityitem);
}
if (dropWire > 0)
{
tempStack = new ItemStack(TConstruct.instance.content.lengthWire, dropWire);
jumpX = rand.nextFloat() * 0.8F + 0.1F;
jumpY = rand.nextFloat() * 0.8F + 0.1F;
jumpZ = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem = new EntityItem(world, (double) ((float) x + jumpX), (double) ((float) y + jumpY), (double) ((float) z + jumpZ), tempStack);
float offset = 0.05F;
entityitem.motionX = (double) ((float) rand.nextGaussian() * offset);
entityitem.motionY = (double) ((float) rand.nextGaussian() * offset + 0.2F);
entityitem.motionZ = (double) ((float) rand.nextGaussian() * offset);
world.spawnEntityInWorld(entityitem);
}
((SignalTerminalLogic) te).notifyBreak();
}
super.breakBlock(world, x, y, z, id, meta);
}
}
@@ -0,0 +1,255 @@
package tconstruct.blocks.component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.library.multiblock.IMultiblockMember;
import tconstruct.library.multiblock.MultiblockMasterBaseLogic;
import tconstruct.library.util.CoordTuple;
public class SignalBusMasterLogic extends MultiblockMasterBaseLogic
{
private boolean forceUpdate = false;
private boolean signalUpdate = false;
private byte[] masterSignals = new byte[16];
private CoordTuple[] signalProviderCoords = new CoordTuple[16];
//private List<CoordTuple> tetheredBuses = new LinkedList<CoordTuple>(); // Buses that contain linked Terminals
private Map<CoordTuple, byte[]> tetheredBuses = new HashMap<CoordTuple, byte[]>();
public SignalBusMasterLogic(World world)
{
super(world);
for (int i = 0; i < 16; i++)
{
masterSignals[i] = 0;
}
}
@Override
public boolean doUpdate ()
{
if (worldObj.isRemote || !forceUpdate)
{
return false;
}
forceUpdate = false;
TileEntity te;
// Calculate new signals from last tick's information
byte[] oldSignals = masterSignals;
masterSignals = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (byte[] signals : tetheredBuses.values())
{
calcSignals(signals);
}
if (!Arrays.equals(oldSignals, masterSignals))
{
// Send updates to SignalBuses
for (CoordTuple coord : tetheredBuses.keySet())
{
if (worldObj.getChunkProvider().chunkExists(coord.x >> 4, coord.z >> 4))
{
te = worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (te instanceof SignalBusLogic)
{
((SignalBusLogic) te).updateLocalSignals(masterSignals);
((SignalBusLogic) te).multiBlockTick();
}
}
}
}
return true;
}
public void updateBusSignals (CoordTuple bus, byte[] signals)
{
if (!Arrays.equals(tetheredBuses.get(bus), signals))
{
tetheredBuses.put(bus, signals);
forceUpdate = true;
}
}
public byte[] getSignals ()
{
return masterSignals.clone();
}
@Override
protected void onBlockAdded (IMultiblockMember newMember)
{
}
@Override
protected void onBlockRemoved (IMultiblockMember oldMember)
{
if (tetheredBuses.containsKey(oldMember.getCoordInWorld()))
{
tetheredBuses.remove(oldMember.getCoordInWorld());
forceUpdate = true;
}
}
@Override
protected void onDataMerge (MultiblockMasterBaseLogic newMaster)
{
byte[] oldSignals = ((SignalBusMasterLogic) newMaster).getSignals();
byte[] newMasterSignals = ((SignalBusMasterLogic) newMaster).getSignals();
if (tetheredBuses.size() > 0)
{
((SignalBusMasterLogic) newMaster).mergeTethered(tetheredBuses);
}
((SignalBusMasterLogic) newMaster).calcSignals(masterSignals);
if (!Arrays.equals(oldSignals, ((SignalBusMasterLogic) newMaster).getSignals()))
{
((SignalBusMasterLogic) newMaster).forceUpdate();
}
}
protected void calcSignals (byte[] signals)
{
if (signals[0] > masterSignals[0])
{
masterSignals[0] = signals[0];
}
if (signals[1] > masterSignals[1])
{
masterSignals[1] = signals[1];
}
if (signals[2] > masterSignals[2])
{
masterSignals[2] = signals[2];
}
if (signals[3] > masterSignals[3])
{
masterSignals[3] = signals[3];
}
if (signals[4] > masterSignals[4])
{
masterSignals[4] = signals[4];
}
if (signals[5] > masterSignals[5])
{
masterSignals[5] = signals[5];
}
if (signals[6] > masterSignals[6])
{
masterSignals[6] = signals[6];
}
if (signals[7] > masterSignals[7])
{
masterSignals[7] = signals[7];
}
if (signals[8] > masterSignals[8])
{
masterSignals[8] = signals[8];
}
if (signals[9] > masterSignals[9])
{
masterSignals[9] = signals[9];
}
if (signals[10] > masterSignals[10])
{
masterSignals[10] = signals[10];
}
if (signals[11] > masterSignals[11])
{
masterSignals[11] = signals[11];
}
if (signals[12] > masterSignals[12])
{
masterSignals[12] = signals[12];
}
if (signals[13] > masterSignals[13])
{
masterSignals[13] = signals[13];
}
if (signals[14] > masterSignals[14])
{
masterSignals[14] = signals[14];
}
if (signals[15] > masterSignals[15])
{
masterSignals[15] = signals[15];
}
}
protected void mergeTethered (Map<CoordTuple, byte[]> oldMasterTethered)
{
tetheredBuses.putAll(oldMasterTethered);
}
@Override
public void writeToNBT (NBTTagCompound data)
{
// Nothing important at the moment
}
@Override
public void readFromNBT (NBTTagCompound data)
{
// Nothing important at the moment
}
@Override
public void formatDescriptionPacket (NBTTagCompound data)
{
// Nothing important at the moment
}
@Override
public void decodeDescriptionPacket (NBTTagCompound data)
{
// Nothing important at the moment
}
@Override
public String debugString ()
{
String fromSuper = super.debugString();
if (worldObj.isRemote)
{
return fromSuper;
}
String tstring = "Tethered Buses: " + tetheredBuses.size() + "\n Signals: [";
for (int n = 0; n < 16; n++)
{
tstring += n + ":" + masterSignals[n];
if (n != 15)
tstring += ", ";
}
tstring += "]";
return fromSuper + "\n" + tstring;
}
public void forceUpdate ()
{
forceUpdate = true;
}
}
@@ -0,0 +1,690 @@
package tconstruct.blocks.logic;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.text.MaskFormatter;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidEvent;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;
import net.minecraftforge.fluids.IFluidTank;
import tconstruct.TConstruct;
import tconstruct.blocks.component.SignalBusMasterLogic;
import tconstruct.library.component.ISignalBusConnectable;
import tconstruct.library.multiblock.IMultiblockMember;
import tconstruct.library.multiblock.MultiblockBaseLogic;
import tconstruct.library.multiblock.MultiblockMasterBaseLogic;
import tconstruct.library.signal.ISignalTransceiver;
import tconstruct.library.util.CoordTuple;
import tconstruct.library.util.IActiveLogic;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class SignalBusLogic extends MultiblockBaseLogic implements IActiveLogic, ISignalBusConnectable
{
private int ticks = 0;
private Map<CoordTuple, byte[]> transceivers = new HashMap<CoordTuple, byte[]>();
private byte[] localHighSignals = new byte[16];
private byte[] cachedReceivedSignals = new byte[16];
private boolean southboundSignalsChanged = false;
private boolean northboundSignalsChanged = false;
private boolean forceCheck = false;
private boolean[] placedSides = new boolean[] { false, false, false, false, false, false };
public SignalBusLogic()
{
}
@Override
public boolean canUpdate ()
{
return true;
}
@Override
public IMultiblockMember[] getNeighboringMembers ()
{
List<IMultiblockMember> corners = new LinkedList<IMultiblockMember>();
int i, j;
int tX, tY, tZ;
TileEntity te;
for (i = 0; i < 6; ++i)
{
if (!placedSides[i])
{
continue;
}
for (j = 0; j < 6; ++j)
{
if (j == i || j == ForgeDirection.OPPOSITES[i])
{
continue;
}
tX = ForgeDirection.VALID_DIRECTIONS[j].offsetX + xCoord;
tY = ForgeDirection.VALID_DIRECTIONS[j].offsetY + yCoord;
tZ = ForgeDirection.VALID_DIRECTIONS[j].offsetZ + zCoord;
if (worldObj.isBlockOpaqueCube(tX, tY, tZ))
{
continue;
}
tX += ForgeDirection.VALID_DIRECTIONS[i].offsetX;
tY += ForgeDirection.VALID_DIRECTIONS[i].offsetY;
tZ += ForgeDirection.VALID_DIRECTIONS[i].offsetZ;
te = worldObj.getBlockTileEntity(tX, tY, tZ);
if (te instanceof IMultiblockMember && ((IMultiblockMember) te).isCompatible((Object) this))
{
corners.add((IMultiblockMember) te);
}
}
}
corners.addAll(Arrays.asList(super.getNeighboringMembers()));
IMultiblockMember[] tmp = new IMultiblockMember[corners.size()];
return corners.toArray(tmp);
}
public void broadcastSouthboundSignals ()
{
if (southboundSignalsChanged)
{
TileEntity te = null;
for (CoordTuple coord : transceivers.keySet())
{
if (worldObj.getChunkProvider().chunkExists(coord.x >> 4, coord.z >> 4))
{
te = worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (te instanceof ISignalTransceiver)
{
((ISignalTransceiver) te).receiveSignalUpdate(cachedReceivedSignals);
}
}
}
southboundSignalsChanged = false;
}
}
public void multiBlockTick ()
{
}
@Override
public void updateEntity ()
{
if (worldObj.isRemote)
{
return;
}
if (!this.isConnected())
{
return;
}
if (forceCheck)
{
forceCheck = false;
super.onBlockAdded(worldObj, xCoord, yCoord, zCoord);
this.getMultiblockMaster().revisitBlocks();
}
if (northboundSignalsChanged)
{
TileEntity te;
byte[] signals;
localHighSignals = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (CoordTuple coord : transceivers.keySet())
{
signals = transceivers.get(coord);
if (signals[0] > localHighSignals[0])
{
localHighSignals[0] = signals[0];
}
if (signals[1] > localHighSignals[1])
{
localHighSignals[1] = signals[1];
}
if (signals[2] > localHighSignals[2])
{
localHighSignals[2] = signals[2];
}
if (signals[3] > localHighSignals[3])
{
localHighSignals[3] = signals[3];
}
if (signals[4] > localHighSignals[4])
{
localHighSignals[4] = signals[4];
}
if (signals[5] > localHighSignals[5])
{
localHighSignals[5] = signals[5];
}
if (signals[6] > localHighSignals[6])
{
localHighSignals[6] = signals[6];
}
if (signals[7] > localHighSignals[7])
{
localHighSignals[7] = signals[7];
}
if (signals[8] > localHighSignals[8])
{
localHighSignals[8] = signals[8];
}
if (signals[9] > localHighSignals[9])
{
localHighSignals[9] = signals[9];
}
if (signals[10] > localHighSignals[10])
{
localHighSignals[10] = signals[10];
}
if (signals[11] > localHighSignals[11])
{
localHighSignals[11] = signals[11];
}
if (signals[12] > localHighSignals[12])
{
localHighSignals[12] = signals[12];
}
if (signals[13] > localHighSignals[13])
{
localHighSignals[13] = signals[13];
}
if (signals[14] > localHighSignals[14])
{
localHighSignals[14] = signals[14];
}
if (signals[15] > localHighSignals[15])
{
localHighSignals[15] = signals[15];
}
}
((SignalBusMasterLogic) getMultiblockMaster()).updateBusSignals(getCoordInWorld(), localHighSignals);
northboundSignalsChanged = false;
}
broadcastSouthboundSignals();
}
public boolean registerTerminal (World world, int x, int y, int z, boolean rehome)
{
if (worldObj.isRemote)
{
return false;
}
if (world == worldObj && world.isRemote == worldObj.isRemote)
{
if (worldObj.getBlockTileEntity(x, y, z) instanceof ISignalTransceiver)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
CoordTuple coords = new CoordTuple(x, y, z);
byte[] signals = null;
if (transceivers.containsKey(coords))
{
return true;
}
int dropWire = ((ISignalTransceiver) te).doUnregister(rehome);
if (dropWire > 0)
{
Random rand = new Random();
ItemStack tempStack = new ItemStack(TConstruct.instance.content.lengthWire, dropWire);
float jumpX = rand.nextFloat() * 0.8F + 0.1F;
float jumpY = rand.nextFloat() * 0.8F + 0.1F;
float jumpZ = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem = new EntityItem(world, (double) ((float) xCoord + jumpX), (double) ((float) yCoord + jumpY), (double) ((float) zCoord + jumpZ), tempStack);
float offset = 0.05F;
entityitem.motionX = (double) ((float) rand.nextGaussian() * offset);
entityitem.motionY = (double) ((float) rand.nextGaussian() * offset + 0.2F);
entityitem.motionZ = (double) ((float) rand.nextGaussian() * offset);
world.spawnEntityInWorld(entityitem);
}
((ISignalTransceiver) te).setBusCoords(world, xCoord, yCoord, zCoord);
signals = ((ISignalTransceiver) te).getReceivedSignals();
transceivers.put(coords, signals);
northboundSignalsChanged = true;
updateLocalSignals(((SignalBusMasterLogic)getMultiblockMaster()).getSignals());
((ISignalTransceiver) te).receiveSignalUpdate(cachedReceivedSignals);
return true;
}
}
return false;
}
@Override
public void onDetached (MultiblockMasterBaseLogic oldMaster)
{
super.onDetached(oldMaster);
}
@Override
public void onAttached (MultiblockMasterBaseLogic newMaster)
{
super.onAttached(newMaster);
if (transceivers != null || !transceivers.isEmpty())
{
northboundSignalsChanged = true;
updateLocalSignals(((SignalBusMasterLogic)getMultiblockMaster()).getSignals());
}
}
public boolean isRegisteredTerminal (World world, int x, int y, int z)
{
if (worldObj.isRemote)
{
return false;
}
return transceivers.containsKey(new CoordTuple(x, y, z));
}
public boolean unregisterTerminal (World world, int x, int y, int z)
{
if (worldObj.isRemote)
{
return false;
}
if (transceivers.remove(new CoordTuple(x, y, z)) != null)
{
northboundSignalsChanged = true;
return true;
}
return false;
}
public boolean hasTerminals ()
{
return (transceivers.size() > 0);
}
@Override
public boolean isCompatible (Object other)
{
return (other.getClass() == this.getClass());
}
@Override
public void readFromNBT (NBTTagCompound tags)
{
super.readFromNBT(tags);
readCustomNBT(tags);
}
public void readCustomNBT (NBTTagCompound tags)
{
int temp = tags.getInteger("placedSides");
for (int i = 0; i < 6; ++i)
{
placedSides[i] = (temp >> i & 1) == 1;
}
}
@Override
public void writeToNBT (NBTTagCompound tags)
{
super.writeToNBT(tags);
writeCustomNBT(tags);
}
public void writeCustomNBT (NBTTagCompound tags)
{
int temp = 0;
for (int i = 0; i < 6; ++i)
{
if (placedSides[i])
{
temp |= 1 << i;
}
}
tags.setInteger("placedSides", temp);
}
@Override
public Packet getDescriptionPacket ()
{
NBTTagCompound tag = new NBTTagCompound();
writeCustomNBT(tag);
return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, tag);
}
@Override
public void onDataPacket (INetworkManager net, Packet132TileEntityData packet)
{
readCustomNBT(packet.data);
this.worldObj.markBlockForRenderUpdate(this.xCoord, this.yCoord, this.zCoord);
}
@Override
public boolean getActive ()
{
// TODO Auto-generated method stub
return false;
}
@Override
public void setActive (boolean flag)
{
// TODO Auto-generated method stub
}
public boolean[] placedSides ()
{
return placedSides.clone();
}
public boolean[] connectedSides (ForgeDirection fromFace)
{
boolean[] connected = new boolean[6];
TileEntity te;
ForgeDirection dir;
int neighborX;
int neighborY;
int neighborZ;
for (int i = 0; i < 6; ++i)
{
if (i == fromFace.ordinal() || i == fromFace.getOpposite().ordinal())
{
continue;
}
dir = ForgeDirection.getOrientation(i);
neighborX = xCoord + dir.offsetX;
neighborY = yCoord + dir.offsetY;
neighborZ = zCoord + dir.offsetZ;
te = worldObj.getBlockTileEntity(neighborX, neighborY, neighborZ);
connected[i] = (te instanceof ISignalBusConnectable && ((ISignalBusConnectable) te).connectableOnFace(fromFace));
}
return connected;
}
// Face is the face in the block; e.g. DOWN = on top of the block below.
public boolean connectableOnFace (ForgeDirection side)
{
return placedSides[side.ordinal()];
}
public boolean isConnected (ForgeDirection side, ForgeDirection dir)
{
TileEntity te;
switch (dir)
{
case DOWN:
return (this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord - 1, this.zCoord) instanceof SignalBusLogic);
case NORTH:
return (this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord - 1) instanceof SignalBusLogic);
case SOUTH:
return (this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord + 1) instanceof SignalBusLogic);
case WEST:
return (this.worldObj.getBlockTileEntity(this.xCoord - 1, this.yCoord, this.zCoord) instanceof SignalBusLogic);
case EAST:
return (this.worldObj.getBlockTileEntity(this.xCoord + 1, this.yCoord, this.zCoord) instanceof SignalBusLogic);
default:
return false;
}
}
@Override
public MultiblockMasterBaseLogic getNewMultiblockMasterObject ()
{
return new SignalBusMasterLogic(this.worldObj);
}
public String debugString ()
{
return "Connected: " + transceivers.size();
}
public byte[] getLocalSignals ()
{
return localHighSignals;
}
public void updateTransceiverSignals (CoordTuple coords, byte[] signals)
{
if (!Arrays.equals(signals, transceivers.get(coords)))
{
transceivers.put(coords, signals);
northboundSignalsChanged = true;
}
}
// Southbound signals update from master
public void updateLocalSignals (byte[] signals)
{
if (!Arrays.equals(signals, cachedReceivedSignals))
{
cachedReceivedSignals = signals.clone();
southboundSignalsChanged = true;
}
}
public void addPlacedSide (int side)
{
placedSides[side] = true;
forceCheck = true;
}
public boolean[] getRenderCorners (ForgeDirection fromFace)
{
boolean[] corners = new boolean[6];
TileEntity te;
ForgeDirection dir;
int neighborX;
int neighborY;
int neighborZ;
for (int i = 0; i < 6; ++i)
{
if (i == fromFace.ordinal() || i == fromFace.getOpposite().ordinal())
{
continue;
}
dir = ForgeDirection.getOrientation(i);
neighborX = xCoord + dir.offsetX;
neighborY = yCoord + dir.offsetY;
neighborZ = zCoord + dir.offsetZ;
if (worldObj.isBlockOpaqueCube(neighborX, neighborY, neighborZ))
{
continue;
}
neighborX += fromFace.offsetX;
neighborY += fromFace.offsetY;
neighborZ += fromFace.offsetZ;
te = worldObj.getBlockTileEntity(neighborX, neighborY, neighborZ);
corners[i] = (te instanceof ISignalBusConnectable && ((ISignalBusConnectable) te).connectableOnCorner(fromFace.getOpposite(), dir.getOpposite()));
}
return corners;
}
@Override
public boolean connectableOnCorner (ForgeDirection side, ForgeDirection turn)
{
if (!placedSides[side.ordinal()] && placedSides[turn.ordinal()])
{
return true;
}
return false;
}
@Override
public boolean willConnect (CoordTuple coord)
{
int i, j;
ForgeDirection iDir, jDir;
TileEntity te;
for (i = 0; i < 6; ++i)
{
iDir = ForgeDirection.VALID_DIRECTIONS[i];
if (!placedSides[i])
{
continue;
}
for (j = 0; j < 6; ++j)
{
if (placedSides[j] || j == i || j == i || j == iDir.getOpposite().ordinal())
{
continue;
}
jDir = ForgeDirection.VALID_DIRECTIONS[j];
if (xCoord + jDir.offsetX == coord.x && yCoord + jDir.offsetY == coord.y && zCoord + jDir.offsetZ == coord.z)
{
te = worldObj.getBlockTileEntity(xCoord + jDir.offsetX, yCoord + jDir.offsetY, zCoord + jDir.offsetZ);
if (te instanceof ISignalBusConnectable && ((ISignalBusConnectable)te).connectableOnFace(iDir))
{
return true;
}
}
if (worldObj.isBlockOpaqueCube(xCoord + jDir.offsetX, yCoord + jDir.offsetY, zCoord + jDir.offsetZ))
{
continue;
}
if (xCoord + iDir.offsetX + jDir.offsetX == coord.x && yCoord + iDir.offsetY + jDir.offsetY == coord.y && xCoord + iDir.offsetZ + jDir.offsetZ == coord.z)
{
te = worldObj.getBlockTileEntity(xCoord + iDir.offsetX + jDir.offsetX, yCoord + iDir.offsetY + jDir.offsetY, zCoord + iDir.offsetZ + jDir.offsetZ);
if (te instanceof ISignalBusConnectable && ((ISignalBusConnectable)te).connectableOnCorner(iDir.getOpposite(), jDir.getOpposite()))
{
return true;
}
}
}
}
return false;
}
@Override
protected CoordTuple[] getNeighborCoords ()
{
List<CoordTuple> cornerCoords = new LinkedList<CoordTuple>();
int i, j;
ForgeDirection iDir, jDir;
CoordTuple coord;
for (i = 0; i < 6; ++i)
{
if (!placedSides[i])
{
continue;
}
iDir = ForgeDirection.VALID_DIRECTIONS[i];
for (j = 0; j < 6; ++j)
{
if (placedSides[j] || j == i || j == iDir.getOpposite().ordinal())
{
continue;
}
jDir = ForgeDirection.VALID_DIRECTIONS[j];
if (worldObj.isBlockOpaqueCube(xCoord + jDir.offsetX, yCoord + jDir.offsetY, zCoord + jDir.offsetZ))
{
continue;
}
coord = new CoordTuple(xCoord + iDir.offsetX + jDir.offsetX, yCoord + iDir.offsetY + jDir.offsetY, zCoord + iDir.offsetZ + jDir.offsetZ);
}
}
cornerCoords.addAll(Arrays.asList(super.getNeighborCoords()));
CoordTuple[] tmp = new CoordTuple[cornerCoords.size()];
return cornerCoords.toArray(tmp);
}
public void forceNeighborCheck ()
{
forceCheck = true;
}
public int getDroppedBuses ()
{
int calc = 0;
for (int i = 0; i < 6; ++i)
{
if (placedSides[i])
{
++calc;
}
}
return calc;
}
public int getDroppedWire ()
{
int calc = 0;
TileEntity te;
for (CoordTuple coord : transceivers.keySet())
{
te = worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (te instanceof ISignalTransceiver)
{
calc += ((ISignalTransceiver) te).getDroppedWire();
}
}
return calc;
}
public void notifyBreak ()
{
TileEntity te;
for (CoordTuple coord : transceivers.keySet())
{
te = worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (te instanceof ISignalTransceiver)
{
((ISignalTransceiver) te).doUnregister(true);
}
}
this.detachSelf(false);
}
}
@@ -0,0 +1,700 @@
package tconstruct.blocks.logic;
import java.util.Arrays;
import tconstruct.TConstruct;
import tconstruct.blocks.SignalTerminal;
import tconstruct.blocks.TConstructBlock;
import tconstruct.common.TContent;
import tconstruct.library.signal.ISignalTransceiver;
import tconstruct.library.util.CoordTuple;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Facing;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
public class SignalTerminalLogic extends TileEntity implements ISignalTransceiver
{
private byte[] connectedSides = new byte[6];
private byte[] receivingSides = new byte[6];
private byte[] sideChannel = new byte[6];
private boolean forceUpdateSide;
private boolean neighborChanged;
private byte[] cachedSouthboundSignals;
private int pendingSide = -1;
private CoordTuple signalBus = null;
private boolean doUpdate = false;
private boolean isRegistered = false;
public SignalTerminalLogic()
{
super();
for (int i = 0; i < 6; i++)
{
connectedSides[i] = -1;
receivingSides[i] = -1;
sideChannel[i] = 0;
forceUpdateSide = false;
}
neighborChanged = false;
}
private void tryRegister ()
{
boolean wasRegistered = isRegistered;
if (!(worldObj instanceof World))
{
return;
}
if (!(signalBus instanceof CoordTuple))
{
return;
}
TileEntity te = worldObj.getBlockTileEntity(signalBus.x, signalBus.y, signalBus.z);
if (!(te instanceof SignalBusLogic))
{
return;
}
isRegistered = ((SignalBusLogic) te).registerTerminal(worldObj, xCoord, yCoord, zCoord, false);
if (isRegistered != wasRegistered)
{
if (isRegistered)
{
doUpdate = true;
}
else
{
signalBus = null;
doUpdate = true;
}
}
}
@Override
public void readFromNBT (NBTTagCompound data)
{
super.readFromNBT(data);
sideChannel = data.getByteArray("sideChannel");
receivingSides = data.getByteArray("receivingSides");
connectedSides = data.getByteArray("connectedSides");
if (sideChannel.length != 6)
{
sideChannel = new byte[] { 0, 0, 0, 0, 0, 0 };
}
if (receivingSides.length != 6)
{
receivingSides = new byte[] { -1, -1, -1, -1, -1, -1 };
}
if (connectedSides.length != 6)
{
connectedSides = new byte[] { -1, -1, -1, -1, -1, -1 };
}
int tX = data.getInteger("BusX");
int tY = data.getInteger("BusY");
int tZ = data.getInteger("BusZ");
if (tX == xCoord && tY == yCoord && tZ == zCoord)
{
signalBus = null;
}
else
{
signalBus = new CoordTuple(tX, tY, tZ);
}
if (!isRegistered)
{
tryRegister();
}
doUpdate = true;
}
@Override
public void writeToNBT (NBTTagCompound data)
{
super.writeToNBT(data);
data.setByteArray("sideChannel", sideChannel);
data.setByteArray("receivingSides", receivingSides);
data.setByteArray("connectedSides", connectedSides);
if (signalBus != null)
{
data.setInteger("BusX", signalBus.x);
data.setInteger("BusY", signalBus.y);
data.setInteger("BusZ", signalBus.z);
}
else
{
data.setInteger("BusX", xCoord);
data.setInteger("BusY", yCoord);
data.setInteger("BusZ", zCoord);
}
}
@Override
public void updateEntity ()
{
if (pendingSide >= 0 && pendingSide < 6 && connectedSides[pendingSide] == -1)
{
connectedSides[pendingSide] = 0;
pendingSide = -1;
forceUpdateSide = true;
}
if (worldObj.isRemote)
{
return;
}
if (forceUpdateSide || neighborChanged)
{
checkNeighbors();
neighborChanged = false;
forceUpdateSide = false;
}
if (!doUpdate)
{
return;
}
if (!isRegistered)
{
tryRegister();
}
if (cachedSouthboundSignals != null)
{
processSignalUpdate(cachedSouthboundSignals);
}
doUpdate = false;
return;
}
// Receive Southbound Signal Updates
public void receiveSignalUpdate (byte[] signals)
{
if (!Arrays.equals(cachedSouthboundSignals, signals))
{
cachedSouthboundSignals = signals.clone();
doUpdate = true;
}
}
private void processSignalUpdate (byte[] signals)
{
int oldValue;
int targetX = 0;
int targetY = 0;
int targetZ = 0;
int oSide;
for (int i = 0; i < 6; i++)
{
if (connectedSides[i] != -1)
{
oldValue = connectedSides[i];
connectedSides[i] = signals[sideChannel[i]];
if (oldValue != connectedSides[i])
{
targetX = xCoord;
targetY = yCoord;
targetZ = zCoord;
switch (i)
{
case 0:
targetY += -1;
oSide = 1;
break;
case 1:
targetY += 1;
oSide = 0;
break;
case 2:
targetZ += 1;
oSide = 2;
break;
case 3:
targetZ += -1;
oSide = 3;
break;
case 4:
targetX += -1;
oSide = 5;
break;
case 5:
targetX += 1;
oSide = 4;
break;
default:
oSide = 0;
}
worldObj.notifyBlockOfNeighborChange(targetX, targetY, targetZ, TConstruct.instance.content.signalTerminal.blockID);
worldObj.notifyBlocksOfNeighborChange(targetX, targetY, targetZ, TConstruct.instance.content.signalTerminal.blockID, oSide);
//worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, TConstruct.instance.content.signalTerminal.blockID);
}
}
}
}
// Callback from Un/Registration
public void setBusCoords (World world, int x, int y, int z)
{
if (world.provider.dimensionId == worldObj.provider.dimensionId && !world.isRemote && !worldObj.isRemote)
{
signalBus = new CoordTuple(x, y, z);
world.markBlockForUpdate(xCoord, yCoord, zCoord);
}
doUpdate = true;
}
public int isProvidingWeakPower (int side)
{
return isProvidingStrongPower(side);
}
public int isProvidingStrongPower (int side)
{
int tside = side;
switch (side)
{
case 0:
tside = 1;
break;
case 1:
tside = 0;
break;
case 2:
tside = 2;
break;
case 3:
tside = 3;
break;
case 4:
tside = 5;
break;
case 5:
tside = 4;
break;
default:
tside = side;
}
if (tside >= 0 && tside < 6 && connectedSides[tside] > 0)
{
return connectedSides[tside] - 1;
}
return 0;
}
public void addPendingSide (int side)
{
pendingSide = side;
}
public void connectPending ()
{
if (pendingSide >= 0 && pendingSide < 6 && connectedSides[pendingSide] == -1)
{
connectedSides[pendingSide] = 0;
}
pendingSide = -1;
doUpdate = true;
}
public byte[] getConnectedSides ()
{
return connectedSides.clone();
}
public String debugString ()
{
String tstr = "";
if (!worldObj.isRemote)
{
byte tbyte = (byte) 0;
for (int n = 0; n < 6; n++)
{
if (connectedSides[n] != -1)
{
tbyte &= (1 << n);
}
}
tstr += "Sides: " + tbyte + "\n";
}
return tstr;
}
/* Packets */
@Override
public Packet getDescriptionPacket ()
{
NBTTagCompound tag = new NBTTagCompound();
writeToNBT(tag);
return new Packet132TileEntityData(xCoord, yCoord, zCoord, 1, tag);
}
@Override
public void onDataPacket (INetworkManager net, Packet132TileEntityData packet)
{
readFromNBT(packet.data);
onInventoryChanged();
worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord);
this.doUpdate = true;
}
public static Icon getChannelIcon (IBlockAccess world, int x, int y, int z, int side)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (te != null && te instanceof SignalTerminalLogic)
{
int channel = ((SignalTerminalLogic) te).sideChannel[side];
return ((SignalTerminal) TConstruct.instance.content.signalTerminal).getChannelIcon(channel);
}
return ((SignalTerminal) TConstruct.instance.content.signalTerminal).getChannelIcon(0);
}
public static Icon[] getChannelIcons ()
{
return ((SignalTerminal) TConstruct.instance.content.signalTerminal).channelIcons;
}
public static Icon getChannelIcon (int channel)
{
return getChannelIcons()[channel];
}
public Icon getChannelIconFromLogic (int side)
{
return getChannelIcons()[sideChannel[side]];
}
public void nextChannel (int side)
{
if (worldObj.isRemote)
{
return;
}
sideChannel[side]++;
if (sideChannel[side] >= 16)
{
sideChannel[side] = 0;
}
doUpdate = true;
}
public void prevChannel (int side)
{
if (worldObj.isRemote)
{
return;
}
sideChannel[side]--;
if (sideChannel[side] < 0)
{
sideChannel[side] = 15;
}
doUpdate = true;
}
public void notifyBreak ()
{
if (!(worldObj instanceof World) || worldObj.isRemote)
{
return;
}
if (!(signalBus instanceof CoordTuple))
{
return;
}
TileEntity te = worldObj.getBlockTileEntity(signalBus.x, signalBus.y, signalBus.z);
if (te == null || !(te instanceof SignalBusLogic))
{
return;
}
((SignalBusLogic) te).unregisterTerminal(worldObj, xCoord, yCoord, zCoord);
}
public void onNeighborBlockChange ()
{
if (worldObj.isRemote)
{
return;
}
neighborChanged = true;
}
public void checkNeighbors ()
{
if (signalBus != null && signalBus instanceof CoordTuple)
{
TileEntity te = worldObj.getBlockTileEntity(signalBus.x, signalBus.y, signalBus.z);
if (te instanceof SignalBusLogic)
{
((SignalBusLogic) te).updateTransceiverSignals(new CoordTuple(xCoord, yCoord, zCoord), getReceivedSignals());
}
}
else
{
// We can redistribute signals locally at least
receiveSignalUpdate(getReceivedSignals());
}
}
public Icon[] getSideIcons ()
{
Icon[] icons = getChannelIcons();
Icon[] sideIcons = new Icon[6];
for (int i = 0; i < 6; i++)
{
if (sideChannel[i] > 0)
{
sideIcons[i] = icons[sideChannel[i]];
}
else
{
sideIcons[i] = icons[0];
}
}
return sideIcons;
}
// Provide Northbound Signals
public byte[] getReceivedSignals (boolean vanillaRedstoneKludge)
{
byte[] highChannel = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] offset = new int[] { 0, 0, 0 };
int oSide;
int tempStrength;
byte temporarySide;
for (int i = 0; i < 6; i++)
{
if (connectedSides[i] != -1)
{
offset[0] = 0;
offset[1] = 0;
offset[2] = 0;
switch (i)
{
case 0:
offset[1] += -1;
oSide = 1;
break;
case 1:
offset[1] += 1;
oSide = 0;
break;
case 2:
offset[2] += 1;
oSide = 3;
break;
case 3:
offset[2] += -1;
oSide = 2;
break;
case 4:
offset[0] += -1;
oSide = 5;
break;
case 5:
offset[0] += 1;
oSide = 4;
break;
default:
oSide = i;
}
tempStrength = 0;
if (connectedSides[i] > 0)
{
// We are currently powering this side, we need to identify if we are the only source or not
temporarySide = connectedSides[i];
connectedSides[i] = -1;
tempStrength = worldObj.getIndirectPowerLevelTo(xCoord + offset[0], yCoord + offset[1], zCoord + offset[2], oSide);
//tempStrength = worldObj.getStrongestIndirectPower(xCoord + offset[0], yCoord + offset[1], zCoord + offset[2]);
if (tempStrength > 0 && tempStrength == (temporarySide - 1))
{
// Let's make sure we're not dealing with vanilla redstone
int bid = 0;
int power = 0;
int temp = 0;
for (int j = 0; j < 6; ++j)
{
if (offset[0] + Facing.offsetsXForSide[j] == 0 && offset[1] + Facing.offsetsYForSide[j] == 0 && offset[2] + Facing.offsetsZForSide[j] == 0)
{
continue;
}
temp = worldObj.getIndirectPowerLevelTo(xCoord + offset[0] + Facing.offsetsXForSide[j], yCoord + offset[1] + Facing.offsetsYForSide[j], zCoord + offset[2] + Facing.offsetsZForSide[j], j);
if (temp > power)
{
bid = worldObj.getBlockId(xCoord + offset[0] + Facing.offsetsXForSide[j], yCoord + offset[1] + Facing.offsetsYForSide[j], zCoord + offset[2]
+ Facing.offsetsZForSide[j]);
if (bid != Block.redstoneWire.blockID)
{
power = temp;
}
}
if (power == tempStrength)
{
// We've found our highest source that's not RS, let's save some cycles
break;
}
}
tempStrength = power;
}
connectedSides[i] = temporarySide;
}
else
{
tempStrength = worldObj.getIndirectPowerLevelTo(xCoord + offset[0], yCoord + offset[1], zCoord + offset[2], oSide);
// tempStrength = worldObj.getStrongestIndirectPower(xCoord + offset[0], yCoord + offset[1], zCoord + offset[2]);
}
// if (tempStrength > 0 && tempStrength < receivingSides[i]){
// receivingSides[i] = 0;
// connectedSides[i] = 0;
// }
// else {
// receivingSides[i] = (byte)Math.max((byte)tempStrength, 0);
// }
if (tempStrength > 0)
{
receivingSides[i] = (byte) (tempStrength - 1);
}
else
{
receivingSides[i] = 0;
}
// if ((receivingSides[i] - 1) > connectedSides[i]) {
// connectedSides[i] = (byte)(receivingSides[i] - 1);
// }
if (receivingSides[i] > highChannel[sideChannel[i]])
{
highChannel[sideChannel[i]] = (byte) receivingSides[i];
}
}
}
return highChannel;
}
@Override
public int doUnregister (boolean reHoming)
{
int dropWire = 0;
if (signalBus != null)
{
TileEntity te = worldObj.getBlockTileEntity(signalBus.x, signalBus.y, signalBus.z);
dropWire = Math.abs(xCoord - signalBus.x) + Math.abs(yCoord - signalBus.y) + Math.abs(zCoord - signalBus.z);
if (te instanceof SignalBusLogic)
{
((SignalBusLogic)te).unregisterTerminal(worldObj, xCoord, yCoord, zCoord);
}
}
// Remove signalBus coords
signalBus = null;
// Calculate new local received signals and provide them to local connections
receiveSignalUpdate(getReceivedSignals());
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
return (reHoming) ? dropWire : 0;
}
@Override
public byte[] getReceivedSignals ()
{
return getReceivedSignals(false);
}
public int getDroppedTerminals ()
{
int count = 0;
for (int i = 0; i < 6; ++i)
{
if (connectedSides[i] != -1)
{
++count;
}
}
return count;
}
public int getDroppedWire ()
{
int calcWire = 0;
if (signalBus instanceof CoordTuple)
{
calcWire += Math.abs(signalBus.x - xCoord);
calcWire += Math.abs(signalBus.y - yCoord);
calcWire += Math.abs(signalBus.z - zCoord);
return calcWire;
}
return 0;
}
@Override
public CoordTuple getBusCoords ()
{
return signalBus;
}
}
@@ -0,0 +1,119 @@
package tconstruct.client;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import org.lwjgl.opengl.GL11;
import codechicken.lib.math.MathHelper;
import tconstruct.TConstruct;
import tconstruct.library.signal.ISignalTransceiver;
import tconstruct.library.util.CoordTuple;
import tconstruct.library.util.CoordTuplePair;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.ForgeSubscribe;
public class SignalTetherWorldOverlayRenderer
{
@ForgeSubscribe
public void onWorldRenderLast (RenderWorldLastEvent event)
{
if (event.context.mc.thePlayer == null || event.context.mc.thePlayer.getHeldItem() == null)
{
return;
}
if (event.context.mc.thePlayer.getHeldItem().itemID == TConstruct.instance.content.spoolWire.itemID)
{
GL11.glPushMatrix();
Entity entity = event.context.mc.renderViewEntity;
double posX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * event.partialTicks;
double posY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * event.partialTicks;
double posZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * event.partialTicks;
GL11.glTranslated(-posX, -posY, -posZ);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glLineWidth(2.5F);
GL11.glBegin(GL11.GL_LINES);
GL11.glColor4f(1, 0, 0, 1);
World world = entity.worldObj;
int x1 = (int) entity.posX;
int z1 = (int) entity.posZ;
int y1 = (int) ((entity.posY > world.getHeight()-16) ? world.getHeight()-16 : ((entity.posY < 16) ? 16 : entity.posY));
AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0);
GL11.glColor4f(1, 0, 0, 1);
Chunk chunks[] = new Chunk[9];
chunks[4] = world.getChunkFromBlockCoords(x1, z1);
int cX = chunks[4].xPosition;
int cZ = chunks[4].zPosition;
chunks[0] = world.getChunkFromChunkCoords(cX - 1, cZ - 1);
chunks[1] = world.getChunkFromChunkCoords(cX , cZ - 1);
chunks[2] = world.getChunkFromChunkCoords(cX + 1, cZ - 1);
chunks[3] = world.getChunkFromChunkCoords(cX - 1, cZ );
chunks[5] = world.getChunkFromChunkCoords(cX + 1, cZ );
chunks[6] = world.getChunkFromChunkCoords(cX - 1, cZ + 1);
chunks[7] = world.getChunkFromChunkCoords(cX , cZ + 1);
chunks[8] = world.getChunkFromChunkCoords(cX + 1, cZ + 1);
Queue<CoordTuplePair> transceivers = new LinkedList<CoordTuplePair>();
CoordTuple src;
CoordTuple dst;
for (int c = 0; c < 9; ++c)
{
for(Object obj : chunks[c].chunkTileEntityMap.values())
{
if (obj instanceof ISignalTransceiver && obj instanceof TileEntity)
{
dst = ((ISignalTransceiver) obj).getBusCoords();
if (dst != null)
{
src = new CoordTuple(((TileEntity)obj).xCoord, ((TileEntity)obj).yCoord, ((TileEntity)obj).zCoord);
transceivers.add(new CoordTuplePair(src,dst));
}
}
}
}
CoordTuplePair renderPair;
while (transceivers.size() > 0)
{
renderPair = transceivers.remove();
GL11.glVertex3d(renderPair.a.x + 0.5, renderPair.a.y + 0.5, renderPair.a.z + 0.5);
GL11.glVertex3d(renderPair.b.x + 0.5, renderPair.b.y, renderPair.b.z + 0.5);
}
// GL11.glVertex3d(x, y+0.004, z);
// GL11.glVertex3d(x+1, y+0.004, z+1);
// GL11.glVertex3d(x+1, y+0.004, z);
// GL11.glVertex3d(x, y+0.004, z+1);
GL11.glEnd();
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
}
}
+6
View File
@@ -26,6 +26,7 @@ import net.minecraftforge.fluids.RenderBlockFluid;
import org.lwjgl.opengl.GL11;
import org.w3c.dom.Document;
import tconstruct.TConstruct;
import tconstruct.blocks.SignalTerminal;
import tconstruct.blocks.SlimeExplosive;
import tconstruct.blocks.logic.*;
import tconstruct.client.armor.RenderArmorCast;
@@ -45,6 +46,7 @@ import tconstruct.inventory.ContainerLandmine;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.client.*;
import tconstruct.library.crafting.ToolBuilder;
import tconstruct.library.multiblock.MultiblockServerTickHandler;
import tconstruct.library.tools.ToolCore;
import tconstruct.util.config.PHConstruct;
import tconstruct.util.player.*;
@@ -197,6 +199,7 @@ public class TProxyClient extends TProxyCommon
// TickRegistry.registerTickHandler(new TimeTicker(), Side.CLIENT);
// TickRegistry.registerTickHandler(new TCommonTickHandler(),
// Side.CLIENT);
TickRegistry.registerScheduledTickHandler(new MultiblockServerTickHandler(), Side.SERVER);
}
/* Registers any rendering code. */
@@ -223,6 +226,9 @@ public class TProxyClient extends TProxyCommon
RenderingRegistry.registerBlockHandler(new BlockRenderCastingChannel());
RenderingRegistry.registerBlockHandler(new SlimeChannelRender());
RenderingRegistry.registerBlockHandler(new SlimePadRender());
RenderingRegistry.registerBlockHandler(new SignalBusRender());
RenderingRegistry.registerBlockHandler(new SignalTerminalRender());
if (!PHConstruct.newSmeltery)
RenderingRegistry.registerBlockHandler(new SmelteryRender());
@@ -0,0 +1,458 @@
package tconstruct.client.block;
import org.lwjgl.opengl.GL11;
import tconstruct.blocks.logic.CastingChannelLogic;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.blocks.SignalBus.Geometry;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.ForgeDirection;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.client.registry.RenderingRegistry;
public class SignalBusRender implements ISimpleBlockRenderingHandler
{
public static int renderID = RenderingRegistry.getNextAvailableRenderId();
// public static double cable_width_min = 0.375D;
// public static double cable_width_max = 1 - cable_width_min;
// public static double cable_low_height = 0.2D;
// public static double cable_low_offset = 0.0D;
//
// public static double cable_high_height = 1.0D;
// public static double cable_high_offset = 1 - cable_low_height;
//
// public static double cable_extend_min = 0.0D;
// public static double cable_extend_max = 1.0D;
//
// public static double zfight = 0.0000001D;
//
@Override
public void renderInventoryBlock (Block block, int metadata, int modelID, RenderBlocks renderer)
{
//Base
renderer.setRenderBounds(0.375D, 0.0D, 0.375D, 0.625D, 0.2D, 0.625D);
this.renderStandardBlock(block, metadata, renderer);
//Extend Z-
renderer.setRenderBounds(0.375D, 0.0D, 0.0D, 0.625D, 0.2D, 0.375D);
this.renderStandardBlock(block, metadata, renderer);
//Extend Z+
renderer.setRenderBounds(0.375D, 0.0D, 0.625D, 0.625D, 0.2D, 1D);
this.renderStandardBlock(block, metadata, renderer);
}
@Override
public boolean renderWorldBlock (IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer)
{
boolean[] placedSides;
boolean[] connectedSides;
boolean[] corners;
boolean didRender = false;
if (modelId == renderID)
{
SignalBusLogic tile = (SignalBusLogic) world.getBlockTileEntity(x, y, z);
placedSides = tile.placedSides();
for (int i = 0; i < 6; ++i)
{
if (!placedSides[i]){
continue;
}
didRender = true;
connectedSides = tile.connectedSides(ForgeDirection.getOrientation(i));
corners = tile.getRenderCorners(ForgeDirection.getOrientation(i));
renderFaceWithConnections(renderer, block, x, y, z, i, placedSides, connectedSides, corners);
}
if (!didRender)
{
double minX = Geometry.cable_width_min;
double minY = Geometry.cable_low_offset;
double minZ = Geometry.cable_width_min;
double maxX = Geometry.cable_width_max;
double maxY = Geometry.cable_low_height;
double maxZ = Geometry.cable_width_max;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
}
return true;
}
private void renderFaceWithConnections (RenderBlocks renderer, Block block, int x, int y, int z, int side, boolean[] placed, boolean[] connectedSides, boolean[] corners)
{
double minX = 0D;
double minY = 0D;
double minZ = 0D;
double maxX = 1D;
double maxY = 1D;
double maxZ = 1D;
int renderCount = 0;
boolean[] renderDir = {
(connectedSides[0] || placed[0] || corners[0]),
(connectedSides[1] || placed[1] || corners[1]),
(connectedSides[2] || placed[2] || corners[2]),
(connectedSides[3] || placed[3] || corners[3]),
(connectedSides[4] || placed[4] || corners[4]),
(connectedSides[5] || placed[5] || corners[5])
};
switch (side)
{
case 0: // DOWN
// Render East/West
if (renderDir[ForgeDirection.WEST.ordinal()] || renderDir[ForgeDirection.EAST.ordinal()])
{
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_low_offset;
minZ = Geometry.cable_width_min;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_low_height;
maxZ = Geometry.cable_width_max;
maxY += Geometry.zfight;
minX = (corners[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_corner_min : minX;
maxX = (corners[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_corner_max : maxX;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render North/South
if (renderDir[ForgeDirection.NORTH.ordinal()] || renderDir[ForgeDirection.SOUTH.ordinal()])
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_low_offset;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_low_height;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
minZ = (corners[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_corner_min : minZ;
maxZ = (corners[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_corner_max : maxZ;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_low_offset;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_low_height;
maxZ = Geometry.cable_width_max;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
case 1: // UP
// Render East/West
if (renderDir[ForgeDirection.WEST.ordinal()] || renderDir[ForgeDirection.EAST.ordinal()])
{
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_high_offset;
minZ = Geometry.cable_width_min;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_high_height;
maxZ = Geometry.cable_width_max;
minY -= Geometry.zfight;
minX = (corners[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_corner_min : minX;
maxX = (corners[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_corner_max : maxX;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render North/South
if (renderDir[ForgeDirection.NORTH.ordinal()] || renderDir[ForgeDirection.SOUTH.ordinal()])
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_high_offset;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_high_height;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
minZ = (corners[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_corner_min : minZ;
maxZ = (corners[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_corner_max : maxZ;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_high_offset;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_high_height;
maxZ = Geometry.cable_width_max;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
case 2: // NORTH
// Render East/West
if (renderDir[ForgeDirection.WEST.ordinal()] || renderDir[ForgeDirection.EAST.ordinal()])
{
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_low_offset;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_low_height;
maxZ += Geometry.zfight;
minX = (corners[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_corner_min : minX;
maxX = (corners[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_corner_max : maxX;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render Up/Down
if (renderDir[ForgeDirection.DOWN.ordinal()] || renderDir[ForgeDirection.UP.ordinal()])
{
minX = Geometry.cable_width_min;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_low_offset;
maxX = Geometry.cable_width_max;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_low_height;
minY = (corners[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_corner_min : minY;
maxY = (corners[ForgeDirection.UP.ordinal()]) ? Geometry.cable_corner_max : maxY;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_low_offset;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_low_height;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
case 3: // SOUTH
// Render East/West
if (renderDir[ForgeDirection.WEST.ordinal()] || renderDir[ForgeDirection.EAST.ordinal()])
{
minX = (renderDir[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_high_offset;
maxX = (renderDir[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_high_height;
minZ -= Geometry.zfight;
minX = (corners[ForgeDirection.WEST.ordinal()]) ? Geometry.cable_corner_min : minX;
maxX = (corners[ForgeDirection.EAST.ordinal()]) ? Geometry.cable_corner_max : maxX;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render Up/Down
if (renderDir[ForgeDirection.DOWN.ordinal()] || renderDir[ForgeDirection.UP.ordinal()])
{
minX = Geometry.cable_width_min;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_high_offset;
maxX = Geometry.cable_width_max;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_high_height;
minY = (corners[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_corner_min : minY;
maxY = (corners[ForgeDirection.UP.ordinal()]) ? Geometry.cable_corner_max : maxY;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_width_min;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_high_offset;
maxX = Geometry.cable_width_max;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_high_height;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
case 4: // WEST
// Render North/South
if (renderDir[ForgeDirection.NORTH.ordinal()] || renderDir[ForgeDirection.SOUTH.ordinal()])
{
minX = Geometry.cable_low_offset;
minY = Geometry.cable_width_min;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_low_height;
maxY = Geometry.cable_width_max;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxX += Geometry.zfight;
minZ = (corners[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_corner_min : minZ;
maxZ = (corners[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_corner_max : maxZ;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render Up/Down
if (renderDir[ForgeDirection.DOWN.ordinal()] || renderDir[ForgeDirection.UP.ordinal()])
{
minX = Geometry.cable_low_offset;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_low_height;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_width_max;
minY = (corners[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_corner_min : minY;
maxY = (corners[ForgeDirection.UP.ordinal()]) ? Geometry.cable_corner_max : maxY;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_low_offset;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_low_height;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_width_max;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
case 5: // EAST
// Render North/South
if (renderDir[ForgeDirection.NORTH.ordinal()] || renderDir[ForgeDirection.SOUTH.ordinal()])
{
minX = Geometry.cable_high_offset;
minY = Geometry.cable_width_min;
minZ = (renderDir[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
maxX = Geometry.cable_high_height;
maxY = Geometry.cable_width_max;
maxZ = (renderDir[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
minX -= Geometry.zfight;
minZ = (corners[ForgeDirection.NORTH.ordinal()]) ? Geometry.cable_corner_min : minZ;
maxZ = (corners[ForgeDirection.SOUTH.ordinal()]) ? Geometry.cable_corner_max : maxZ;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
// Render Up/Down
if (renderDir[ForgeDirection.DOWN.ordinal()] || renderDir[ForgeDirection.UP.ordinal()])
{
minX = Geometry.cable_high_offset;
minY = (renderDir[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_extend_min : Geometry.cable_width_min;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_high_height;
maxY = (renderDir[ForgeDirection.UP.ordinal()]) ? Geometry.cable_extend_max : Geometry.cable_width_max;
maxZ = Geometry.cable_width_max;
minY = (corners[ForgeDirection.DOWN.ordinal()]) ? Geometry.cable_corner_min : minY;
maxY = (corners[ForgeDirection.UP.ordinal()]) ? Geometry.cable_corner_max : maxY;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
++renderCount;
}
if (renderCount == 0)
{
minX = Geometry.cable_high_offset;
minY = Geometry.cable_width_min;
minZ = Geometry.cable_width_min;
maxX = Geometry.cable_high_height;
maxY = Geometry.cable_width_max;
maxZ = Geometry.cable_width_max;
renderer.setRenderBounds(minX, minY, minZ, maxX, maxY, maxZ);
renderer.renderStandardBlock(block, x, y, z);
}
break;
default:
return;
}
}
private void renderStandardBlock (Block block, int meta, RenderBlocks renderer)
{
Tessellator tessellator = Tessellator.instance;
GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, -1.0F, 0.0F);
renderer.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(0, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 1.0F, 0.0F);
renderer.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(1, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 0.0F, -1.0F);
renderer.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(2, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 0.0F, 1.0F);
renderer.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(3, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(-1.0F, 0.0F, 0.0F);
renderer.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(4, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(1.0F, 0.0F, 0.0F);
renderer.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(5, meta));
tessellator.draw();
GL11.glTranslatef(0.5F, 0.5F, 0.5F);
}
@Override
public boolean shouldRender3DInInventory ()
{
// TODO Auto-generated method stub
return true;
}
@Override
public int getRenderId ()
{
return renderID;
}
}
@@ -0,0 +1,208 @@
package tconstruct.client.block;
import org.lwjgl.opengl.GL11;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.blocks.logic.SignalTerminalLogic;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.ForgeDirection;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.client.registry.RenderingRegistry;
import static tconstruct.blocks.SignalTerminal.TerminalGeometry.*;
public class SignalTerminalRender implements ISimpleBlockRenderingHandler
{
public static int renderID = RenderingRegistry.getNextAvailableRenderId();
@Override
public void renderInventoryBlock (Block block, int metadata, int modelID, RenderBlocks renderer)
{
// Render X-
renderer.setRenderBounds(plate_low_min, plate_width_min, plate_width_min, plate_low_max, plate_width_max, plate_width_max);
this.renderStandardBlock(block, metadata, renderer);
renderer.setRenderBounds(center_min, center_min, center_min, center_max, center_max, center_max);
this.renderStandardBlock(block, metadata, renderer);
renderer.setRenderBounds(channel_low_min, channel_width_min, channel_width_min, channel_low_max, channel_width_max, channel_width_max);
renderer.setOverrideBlockTexture(SignalTerminalLogic.getChannelIcon(0));
this.renderStandardBlock(block, metadata, renderer);
renderer.clearOverrideBlockTexture();
}
@Override
public boolean renderWorldBlock (IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer)
{
int sidesRendered = 0;
if (modelId == renderID)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
if (!(te instanceof SignalTerminalLogic))
{
// Render X-
renderer.setRenderBounds(plate_low_min, plate_width_min, plate_width_min, plate_low_max, plate_width_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(center_min, center_min, center_min, center_max, center_max, center_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_low_min, channel_width_min, channel_width_min, channel_low_max, channel_width_max, channel_width_max);
renderer.setOverrideBlockTexture(SignalTerminalLogic.getChannelIcon(0));
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
return true;
}
byte[] connectedSides = ((SignalTerminalLogic) te).getConnectedSides();
Icon channelIcons[] = ((SignalTerminalLogic) te).getSideIcons();
// Center
renderer.setRenderBounds(center_min, center_min, center_min, center_max, center_max, center_max);
renderer.renderStandardBlock(block, x, y, z);
if (connectedSides[ForgeDirection.WEST.ordinal()] != -1)
{
// Render X-
renderer.setRenderBounds(plate_low_min, plate_width_min, plate_width_min, plate_low_max, plate_width_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_low_min, channel_width_min, channel_width_min, channel_low_max, channel_width_max, channel_width_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.WEST.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (connectedSides[ForgeDirection.EAST.ordinal()] != -1)
{
//Extend X+
renderer.setRenderBounds(plate_high_min, plate_width_min, plate_width_min, plate_high_max, plate_width_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_high_min, channel_width_min, channel_width_min, channel_high_max, channel_width_max, channel_width_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.EAST.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (connectedSides[ForgeDirection.SOUTH.ordinal()] != -1)
{
//Extend Z-
renderer.setRenderBounds(plate_width_min, plate_width_min, plate_low_min, plate_width_max, plate_width_max, plate_low_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_width_min, channel_width_min, channel_low_min, channel_width_max, channel_width_max, channel_low_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.SOUTH.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (connectedSides[ForgeDirection.NORTH.ordinal()] != -1)
{
//Extend Z+
renderer.setRenderBounds(plate_width_min, plate_width_min, plate_high_min, plate_width_max, plate_width_max, plate_high_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_width_min, channel_width_min, channel_high_min, channel_width_max, channel_width_max, channel_high_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.NORTH.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (connectedSides[ForgeDirection.DOWN.ordinal()] != -1)
{
//Extend Y-
renderer.setRenderBounds(plate_width_min, plate_low_min, plate_width_min, plate_width_max, plate_low_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_width_min, channel_low_min, channel_width_min, channel_width_max, channel_low_max, channel_width_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.DOWN.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (connectedSides[ForgeDirection.UP.ordinal()] != -1)
{
//Extend Y+
renderer.setRenderBounds(plate_width_min, plate_high_min, plate_width_min, plate_width_max, plate_high_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_width_min, channel_high_min, channel_width_min, channel_width_max, channel_high_max, channel_width_max);
renderer.setOverrideBlockTexture(channelIcons[ForgeDirection.UP.ordinal()]);
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
sidesRendered++;
}
if (sidesRendered == 0)
{
// Render X-
renderer.setRenderBounds(plate_low_min, plate_width_min, plate_width_min, plate_low_max, plate_width_max, plate_width_max);
renderer.renderStandardBlock(block, x, y, z);
renderer.setRenderBounds(channel_low_min, channel_width_min, channel_width_min, channel_low_max, channel_width_max, channel_width_max);
renderer.setOverrideBlockTexture(SignalTerminalLogic.getChannelIcon(0));
renderer.renderStandardBlock(block, x, y, z);
renderer.clearOverrideBlockTexture();
}
return true;
}
return false;
}
private void renderStandardBlock (Block block, int meta, RenderBlocks renderer)
{
Tessellator tessellator = Tessellator.instance;
GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, -1.0F, 0.0F);
renderer.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(0, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 1.0F, 0.0F);
renderer.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(1, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 0.0F, -1.0F);
renderer.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(2, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(0.0F, 0.0F, 1.0F);
renderer.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(3, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(-1.0F, 0.0F, 0.0F);
renderer.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, block.getIcon(4, meta));
tessellator.draw();
tessellator.startDrawingQuads();
tessellator.setNormal(1.0F, 0.0F, 0.0F);
renderer.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, block.getIcon(5, meta));
tessellator.draw();
GL11.glTranslatef(0.5F, 0.5F, 0.5F);
}
@Override
public boolean shouldRender3DInInventory ()
{
return true;
}
@Override
public int getRenderId ()
{
return this.renderID;
}
}
@@ -0,0 +1,102 @@
package tconstruct.common;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
public class SpoolRepairRecipe implements IRecipe
{
ItemStack spool;
ItemStack wire;
public SpoolRepairRecipe(ItemStack spool, ItemStack wire)
{
this.spool = spool.copy();
this.spool.setItemDamage(256);
this.wire = wire.copy();
}
@Override
public boolean matches (InventoryCrafting inventorycrafting, World world)
{
int invLength = inventorycrafting.getSizeInventory();
boolean foundSpool = false;
int countWire = 0;
ItemStack tmpStack;
for (int i = 0; i < invLength; ++i)
{
tmpStack = inventorycrafting.getStackInSlot(i);
if (tmpStack instanceof ItemStack)
{
if (tmpStack.itemID == spool.itemID)
{
if (foundSpool)
{
return false;
}
foundSpool = true;
}
else if (tmpStack.itemID == wire.itemID && tmpStack.getItemDamage() == wire.getItemDamage())
{
++countWire;
}
else
{
return false;
}
}
if (countWire > 0 && foundSpool)
{
return true;
}
}
return false;
}
@Override
public ItemStack getCraftingResult (InventoryCrafting inventorycrafting)
{
int invLength = inventorycrafting.getSizeInventory();
boolean foundSpool = false;
ItemStack newSpool = null;
int countWire = 0;
ItemStack tmpStack;
for (int i = 0; i < invLength; ++i)
{
tmpStack = inventorycrafting.getStackInSlot(i);
if (tmpStack instanceof ItemStack)
{
if (tmpStack.itemID == spool.itemID)
{
newSpool = tmpStack.copy();
foundSpool = true;
}
else if (tmpStack.itemID == wire.itemID && tmpStack.getItemDamage() == wire.getItemDamage())
{
++countWire;
}
}
}
if (countWire > 0 && newSpool != null)
{
newSpool.setItemDamage(newSpool.getItemDamage() - countWire);
}
return newSpool;
}
@Override
public int getRecipeSize ()
{
// TODO Auto-generated method stub
return 9;
}
@Override
public ItemStack getRecipeOutput ()
{
return spool.copy();
}
}
+35 -3
View File
@@ -279,6 +279,13 @@ public class TContent implements IFuelHandler
public static Item leggingsWood;
public static Item bootsWood;
public static EnumArmorMaterial materialWood;
//Signal & Logic
public static Block signalBus;
public static Block signalTerminal;
public static Item spoolWire;
public static Item lengthWire;
//Temporary items
//public static Item armorTest = new ArmorStandard(2445, 4, EnumArmorPart.HELMET).setCreativeTab(CreativeTabs.tabAllSearch);
@@ -825,6 +832,16 @@ public class TContent implements IFuelHandler
//Rail
woodenRail = new WoodRail(PHConstruct.woodenRail).setStepSound(Block.soundWoodFootstep).setCreativeTab(TConstructRegistry.blockTab).setUnlocalizedName("rail.wood");
GameRegistry.registerBlock(woodenRail, "rail.wood");
//Signal & Logic
signalBus = (new SignalBus(PHConstruct.signalBus)).setUnlocalizedName("tconstruct.signalbus");
GameRegistry.registerBlock(signalBus, SignalBusItem.class, "SignalBus");
GameRegistry.registerTileEntity(SignalBusLogic.class, "SignalBus");
signalTerminal = (new SignalTerminal(PHConstruct.signalTerminal)).setUnlocalizedName("tconstruct.signalterminal");
GameRegistry.registerBlock(signalTerminal, SignalTerminalItem.class, "SignalTerminal");
GameRegistry.registerTileEntity(SignalTerminalLogic.class, "SignalTerminal");
}
void registerItems ()
@@ -964,6 +981,9 @@ public class TContent implements IFuelHandler
leggingsWood = new ArmorBasic(PHConstruct.woodPants, materialWood, 2, "wood").setUnlocalizedName("tconstruct.leggingsWood");
bootsWood = new ArmorBasic(PHConstruct.woodBoots, materialWood, 3, "wood").setUnlocalizedName("tconstruct.bootsWood");
spoolWire = new SpoolOfWire(PHConstruct.spoolWire).setUnlocalizedName("spoolwire");
lengthWire = new LengthWire(PHConstruct.lengthWire).setUnlocalizedName("lengthwire");
// essenceCrystal = new EssenceCrystal(PHConstruct.essenceCrystal).setUnlocalizedName("tconstruct.crystal.essence");
String[] materialStrings = { "paperStack", "greenSlimeCrystal", "searedBrick", "ingotCobalt", "ingotArdite", "ingotManyullyn", "mossBall", "lavaCrystal", "necroticBone", "ingotCopper",
@@ -989,7 +1009,10 @@ public class TContent implements IFuelHandler
TConstructRegistry.addItemStackToDirectory("canisterEmpty", new ItemStack(heartCanister, 1, 0));
TConstructRegistry.addItemStackToDirectory("miniRedHeart", new ItemStack(heartCanister, 1, 1));
TConstructRegistry.addItemStackToDirectory("canisterRedHeart", new ItemStack(heartCanister, 1, 2));
TConstructRegistry.addItemStackToDirectory("spoolWire", new ItemStack(spoolWire, 1, 0));
TConstructRegistry.addItemStackToDirectory("lengthWire", new ItemStack(lengthWire, 1, 0));
//Vanilla stack sizes
Item.doorWood.setMaxStackSize(16);
Item.doorIron.setMaxStackSize(16);
@@ -1341,6 +1364,13 @@ public class TContent implements IFuelHandler
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(landmine, 1, 3), "mcm", "rpr", 'm', Item.redstoneRepeater, 'c', new ItemStack(blankPattern, 1, 1), 'r', Item.redstone, 'p',
Block.pressurePlateStone));
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(signalBus.blockID, 1, 0), "www", "sss", 'w', lengthWire, 's', new ItemStack(Block.stoneSingleSlab, 1, OreDictionary.WILDCARD_VALUE)));
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(signalTerminal.blockID, 1, 0), "b", "g", "b", 'b', new ItemStack(signalBus.blockID, 1, 0), 'g', new ItemStack(Block.glass, 1, OreDictionary.WILDCARD_VALUE)));
GameRegistry.addRecipe(new ItemStack(lengthWire, 8), "a", "a", 'a', aluBrass);
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(spoolWire, 1, 256 - 8), "www", "wrw", "www", 'w', lengthWire, 'r', "stoneRod"));
GameRegistry.addRecipe(new SpoolRepairRecipe(new ItemStack(spoolWire, 1, 256), new ItemStack(lengthWire, 1)));
//Ultra hardcore recipes
Object goldType = null;
RecipeRemover.removeShapedRecipe(new ItemStack(Item.appleGold));
@@ -1463,7 +1493,7 @@ public class TContent implements IFuelHandler
patternOutputs = new Item[] { toolRod, pickaxeHead, shovelHead, hatchetHead, swordBlade, wideGuard, handGuard, crossbar, binding, frypanHead, signHead, knifeBlade, chiselHead, toughRod,
toughBinding, largePlate, broadAxeHead, scytheBlade, excavatorHead, largeSwordBlade, hammerHead, fullGuard, null, null, arrowhead };
int[] nonMetals = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 17 };
int[] nonMetals = { 0, 1, 3, 4, 5, 6, 7, 8, 9 };
if (PHConstruct.craftMetalTools)
{
@@ -1597,6 +1627,7 @@ public class TContent implements IFuelHandler
//Buckets
ItemStack bucket = new ItemStack(Item.bucketEmpty);
for (int sc = 0; sc < 24; sc++)
{
tableCasting.addCastingRecipe(new ItemStack(buckets, 1, sc), new FluidStack(fluids[sc], FluidContainerRegistry.BUCKET_VOLUME), bucket, true, 10);
@@ -1732,6 +1763,7 @@ public class TContent implements IFuelHandler
Smeltery.addMelting(FluidType.Steel, new ItemStack(toolShard, 1, 16), 0, TConstruct.chunkLiquidValue);
// Items
Smeltery.addMelting(FluidType.AluminumBrass, new ItemStack(blankPattern, 4, 1), -50, TConstruct.ingotLiquidValue);
Smeltery.addMelting(FluidType.Gold, new ItemStack(blankPattern, 4, 1), -50, TConstruct.ingotLiquidValue);
@@ -2002,7 +2034,7 @@ public class TContent implements IFuelHandler
ensureOreIsRegistered("stoneMossy", new ItemStack(Block.stoneBrick, 1, 1));
ensureOreIsRegistered("stoneMossy", new ItemStack(Block.cobblestoneMossy));
ensureOreIsRegistered("crafterWood", new ItemStack(Block.workbench, 1));
String[] matNames = { "wood", "stone", "iron", "flint", "cactus", "bone", "obsidian", "netherrack", "slime", "paper", "cobalt", "ardite", "manyullyn", "copper", "bronze", "alumite", "steel",
+4
View File
@@ -2,6 +2,8 @@ package tconstruct.common;
import cpw.mods.fml.common.network.IGuiHandler;
import cpw.mods.fml.common.registry.LanguageRegistry;
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
@@ -9,6 +11,7 @@ import tconstruct.TConstruct;
import tconstruct.blocks.logic.TileEntityLandmine;
import tconstruct.inventory.*;
import tconstruct.library.blocks.InventoryLogic;
import tconstruct.library.multiblock.MultiblockServerTickHandler;
import tconstruct.util.player.TPlayerStats;
/**
@@ -85,6 +88,7 @@ public class TProxyCommon implements IGuiHandler
public void registerTickHandler ()
{
//TickRegistry.registerTickHandler(new TimeTicker(), Side.SERVER);
TickRegistry.registerScheduledTickHandler(new MultiblockServerTickHandler(), Side.SERVER);
}
/* Registers any rendering code. Does nothing server-side */
+58
View File
@@ -0,0 +1,58 @@
package tconstruct.items;
import java.util.List;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import tconstruct.library.TConstructRegistry;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Icon;
import net.minecraft.util.MathHelper;
public class LengthWire extends Item
{
public String[] textureNames = new String[] { "lengthwire" };
public String[] unlocalizedNames = new String[] { "lengthwire" };
public String folder = "logic/";
public Icon[] icons;
public LengthWire(int id)
{
super(id);
this.setCreativeTab(TConstructRegistry.toolTab);
this.maxStackSize = 64;
this.setHasSubtypes(false);
}
@SideOnly(Side.CLIENT)
public Icon getIconFromDamage (int meta)
{
int arr = MathHelper.clamp_int(meta, 0, unlocalizedNames.length);
return icons[arr];
}
@Override
@SideOnly(Side.CLIENT)
public void registerIcons (IconRegister iconRegister)
{
this.icons = new Icon[textureNames.length];
for (int i = 0; i < this.icons.length; ++i)
{
if (!(textureNames[i].equals("")))
this.icons[i] = iconRegister.registerIcon("tinker:" + folder + textureNames[i]);
}
}
public void getSubItems (int id, CreativeTabs tab, List list)
{
for (int i = 0; i < unlocalizedNames.length; i++)
if (!(textureNames[i].equals("")))
list.add(new ItemStack(id, 1, i));
}
}
+145
View File
@@ -0,0 +1,145 @@
package tconstruct.items;
import java.util.List;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import tconstruct.blocks.logic.SignalBusLogic;
import tconstruct.blocks.logic.SignalTerminalLogic;
import tconstruct.library.TConstructRegistry;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Icon;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class SpoolOfWire extends Item
{
public String textureName = "spoolwire";
public String unlocalizedName = "spoolwire";
public String folder = "logic/";
public Icon icon;
public SpoolOfWire(int id)
{
super(id);
this.setCreativeTab(TConstructRegistry.toolTab);
this.maxStackSize = 1;
this.setMaxDamage(256);
this.setHasSubtypes(true);
}
@Override
public ItemStack getContainerItemStack (ItemStack itemStack)
{
return new ItemStack(this.itemID, 1, this.getMaxDamage());
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation (ItemStack stack, EntityPlayer player, List list, boolean par4)
{
switch (stack.getItemDamage())
{
case 0:
list.add("Wirey!");
break;
}
}
public String getUnlocalizedName (ItemStack stack)
{
return "item." + unlocalizedName;
}
@Override
public boolean onItemUse (ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int par7, float par8, float par9, float par10)
{
TileEntity te = world.getBlockTileEntity(x, y, z);
NBTTagCompound data = itemstack.stackTagCompound;
NBTTagCompound spoolData = null;
if (world.isRemote)
{
return false;
}
if (data == null)
{
data = new NBTTagCompound();
itemstack.stackTagCompound = data;
}
if (te != null && te instanceof SignalBusLogic)
{
if (data.hasKey("spoolWireData"))
{
spoolData = data.getCompoundTag("spoolWireData");
int targetDim = spoolData.getInteger("targetDim");
int targetX = spoolData.getInteger("targetX");
int targetY = spoolData.getInteger("targetY");
int targetZ = spoolData.getInteger("targetZ");
int calc = Math.abs(targetX - x) + Math.abs(targetY - y) + Math.abs(targetZ - z);
if ((itemstack.getMaxDamage() - itemstack.getItemDamage()) < calc)
{
return false;
}
if (targetDim == world.provider.dimensionId && calc < 16)
{
((SignalBusLogic) te).registerTerminal(world, targetX, targetY, targetZ, true);
data.removeTag("spoolWireData");
itemstack.damageItem(calc, player);
return true;
}
}
return false;
}
if (te != null && te instanceof SignalTerminalLogic)
{
data = itemstack.stackTagCompound;
spoolData = null;
if (data.hasKey("spoolWireData"))
{
data.removeTag("spoolWireData");
}
spoolData = new NBTTagCompound();
spoolData.setInteger("targetDim", world.provider.dimensionId);
spoolData.setInteger("targetX", x);
spoolData.setInteger("targetY", y);
spoolData.setInteger("targetZ", z);
data.setCompoundTag("spoolWireData", spoolData);
return true;
}
return false;
}
@SideOnly(Side.CLIENT)
public Icon getIconFromDamage (int meta)
{
return icon;
}
@Override
@SideOnly(Side.CLIENT)
public void registerIcons (IconRegister iconRegister)
{
this.icon = iconRegister.registerIcon("tinker:" + folder + textureName);
}
public void getSubItems (int id, CreativeTabs tab, List list)
{
list.add(new ItemStack(id, 1, 0));
}
}
@@ -0,0 +1,167 @@
package tconstruct.items.blocks;
import java.util.List;
import tconstruct.blocks.logic.SignalBusLogic;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
public class SignalBusItem extends ItemBlock
{
public static final String blockType[] = { "signalbus" };
public SignalBusItem(int id)
{
super(id);
this.maxStackSize = 64;
this.setHasSubtypes(false);
}
public int getMetadata (int meta)
{
return meta;
}
public String getUnlocalizedName (ItemStack itemstack)
{
int pos = MathHelper.clamp_int(itemstack.getItemDamage(), 0, blockType.length - 1);
return (new StringBuilder()).append("tile.").append(blockType[pos]).toString();
}
@Override
@SideOnly(Side.CLIENT)
public boolean canPlaceItemBlockOnSide (World world, int x, int y, int z, int side, EntityPlayer entityPlayer, ItemStack itemStack)
{
return super.canPlaceItemBlockOnSide(world, x, y, z, side, entityPlayer, itemStack) || _canPlaceItemBlockOnSide(world, x, y, z, side);
}
@Override
public boolean onItemUse (ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
{
int tmpX = x;
int tmpY = y;
int tmpZ = z;
switch (side)
{
case 0:
tmpY += -1;
break;
case 1:
tmpY += 1;
break;
case 2:
tmpZ += -1;
break;
case 3:
tmpZ += 1;
break;
case 4:
tmpX += -1;
break;
case 5:
tmpX += 1;
break;
default:
break;
}
int tside = side;
switch (side)
{
case 0: // DOWN
case 1: // UP
case 2: // NORTH
case 3: // SOUTH
case 4: // EAST
case 5: // WEST
tside = ForgeDirection.OPPOSITES[side];
break;
default:
tside = side;
break;
}
NBTTagCompound data = new NBTTagCompound();
stack.stackTagCompound = data;
data.setInteger("connectedSide", tside);
if (super.onItemUse(stack, player, world, x, y, z, side, hitX, hitY, hitZ))
{
stack.stackTagCompound = null;
return true;
}
if (!(_canPlaceItemBlockOnSide(world, x, y, z, side)))
{
return false;
}
TileEntity te = world.getBlockTileEntity(tmpX, tmpY, tmpZ);
((SignalBusLogic) te).addPlacedSide(tside);
stack.stackTagCompound = null;
--stack.stackSize;
world.markBlockForRenderUpdate(x, y, z);
return true;
}
private boolean _canPlaceItemBlockOnSide (World world, int x, int y, int z, int side)
{
int tmpX = x;
int tmpY = y;
int tmpZ = z;
switch (side)
{
case 0:
tmpY += -1;
break;
case 1:
tmpY += 1;
break;
case 2:
tmpZ += -1;
break;
case 3:
tmpZ += 1;
break;
case 4:
tmpX += -1;
break;
case 5:
tmpX += 1;
break;
default:
break;
}
if (world.getBlockId(tmpX, tmpY, tmpZ) == this.getBlockID())
{
TileEntity te = world.getBlockTileEntity(tmpX, tmpY, tmpZ);
if (te == null || !(te instanceof SignalBusLogic))
{
return false;
}
return true;
}
return false;
}
}
@@ -0,0 +1,176 @@
package tconstruct.items.blocks;
import java.util.List;
import tconstruct.blocks.logic.SignalTerminalLogic;
import tconstruct.library.TConstructRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
public class SignalTerminalItem extends ItemBlock
{
public static final String blockType[] = { "signalterminal" };
public SignalTerminalItem(int id)
{
super(id);
this.maxStackSize = 64;
this.setHasSubtypes(false);
}
public int getMetadata (int meta)
{
return meta;
}
public String getUnlocalizedName (ItemStack itemstack)
{
int pos = MathHelper.clamp_int(itemstack.getItemDamage(), 0, blockType.length - 1);
return (new StringBuilder()).append("tile.").append(blockType[pos]).toString();
}
@Override
public boolean placeBlockAt (ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metadata)
{
return super.placeBlockAt(stack, player, world, x, y, z, side, hitX, hitY, hitZ, metadata);
}
@Override
@SideOnly(Side.CLIENT)
public boolean canPlaceItemBlockOnSide (World world, int x, int y, int z, int side, EntityPlayer entityPlayer, ItemStack itemStack)
{
if (super.canPlaceItemBlockOnSide(world, x, y, z, side, entityPlayer, itemStack) || _canPlaceItemBlockOnSide(world, x, y, z, side))
{
return true;
}
return false;
}
@Override
public boolean onItemUse (ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
{
int tmpX = x;
int tmpY = y;
int tmpZ = z;
switch (side)
{
case 0:
tmpY += -1;
break;
case 1:
tmpY += 1;
break;
case 2:
tmpZ += -1;
break;
case 3:
tmpZ += 1;
break;
case 4:
tmpX += -1;
break;
case 5:
tmpX += 1;
break;
default:
break;
}
int tside = side;
switch (side)
{
case 0: // DOWN
case 1: // UP
case 4: // EAST
case 5: // WEST
tside = ForgeDirection.OPPOSITES[side];
break;
default:
tside = side;
break;
}
NBTTagCompound data = new NBTTagCompound();
stack.stackTagCompound = data;
data.setInteger("connectedSide", tside);
if (super.onItemUse(stack, player, world, x, y, z, side, hitX, hitY, hitZ))
{
return true;
}
if (!(_canPlaceItemBlockOnSide(world, x, y, z, side)))
{
return false;
}
TileEntity te = world.getBlockTileEntity(tmpX, tmpY, tmpZ);
((SignalTerminalLogic) te).addPendingSide(tside);
((SignalTerminalLogic) te).connectPending();
stack.stackTagCompound = null;
--stack.stackSize;
world.markBlockForRenderUpdate(x, y, z);
return true;
}
private boolean _canPlaceItemBlockOnSide (World world, int x, int y, int z, int side)
{
int tmpX = x;
int tmpY = y;
int tmpZ = z;
switch (side)
{
case 0:
tmpY += -1;
break;
case 1:
tmpY += 1;
break;
case 2:
tmpZ += -1;
break;
case 3:
tmpZ += 1;
break;
case 4:
tmpX += -1;
break;
case 5:
tmpX += 1;
break;
default:
break;
}
if (world.getBlockId(tmpX, tmpY, tmpZ) == this.getBlockID())
{
TileEntity te = world.getBlockTileEntity(tmpX, tmpY, tmpZ);
if (te == null || !(te instanceof SignalTerminalLogic))
{
return false;
}
return true;
}
return false;
}
}
@@ -0,0 +1,10 @@
package tconstruct.library.component;
import net.minecraftforge.common.ForgeDirection;
public interface ISignalBusConnectable
{
public boolean connectableOnFace (ForgeDirection side);
public boolean connectableOnCorner (ForgeDirection side, ForgeDirection turn);
}
@@ -0,0 +1,20 @@
package tconstruct.library.multiblock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public abstract class BlockMultiblock extends BlockContainer
{
protected BlockMultiblock(int par1, Material par2Material)
{
super(par1, par2Material);
}
@Override
public abstract TileEntity createNewTileEntity (World world);
}
@@ -0,0 +1,52 @@
package tconstruct.library.multiblock;
import net.minecraft.world.World;
import tconstruct.library.util.CoordTuple;
public interface IMultiblockMember
{
public boolean isCompatible (Object other);
public boolean isConnected ();
public MultiblockMasterBaseLogic getMultiblockMaster ();
public CoordTuple getCoordInWorld ();
public void onAttached (MultiblockMasterBaseLogic newMaster);
public void onDetached (MultiblockMasterBaseLogic oldMaster);
public void createNewMultiblock ();
public MultiblockMasterBaseLogic getNewMultiblockMasterObject ();
public void onMasterMerged (MultiblockMasterBaseLogic newMaster);
public void setVisited ();
public void setUnivisted ();
public boolean isVisited ();
public void becomeMultiblockSaveDelegate ();
public void forfeitMultiblockSaveDelegate ();
public boolean isMultiblockSaveDelegate ();
public IMultiblockMember[] getNeighboringMembers ();
public void onBlockAdded (World world, int x, int y, int z);
public void onChunkLoad ();
public void onOrphaned ();
public void onChunkUnloaded ();
public World getWorldObj ();
public boolean willConnect (CoordTuple coord);
}
@@ -0,0 +1,395 @@
package tconstruct.library.multiblock;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import tconstruct.library.util.CoordTuple;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
public abstract class MultiblockBaseLogic extends TileEntity implements IMultiblockMember
{
private MultiblockMasterBaseLogic master;
private byte visited;
private static final byte kUnvisited = 0;
private static final byte kVisited = 1;
private boolean saveMultiblockData;
private NBTTagCompound cachedMultiblockData;
private boolean doUpdate;
public MultiblockBaseLogic()
{
super();
master = null;
visited = kUnvisited;
saveMultiblockData = false;
doUpdate = false;
cachedMultiblockData = null;
}
public boolean isCompatible (Object other)
{
return other.getClass().equals(this.getClass());
}
public void doMultiblockTick ()
{
}
@Override
public boolean isConnected ()
{
return (master != null);
}
@Override
public boolean willConnect (CoordTuple coord)
{
return true;
}
@Override
public MultiblockMasterBaseLogic getMultiblockMaster ()
{
return master;
}
@Override
public CoordTuple getCoordInWorld ()
{
return new CoordTuple(this.xCoord, this.yCoord, this.zCoord);
}
@Override
public void onAttached (MultiblockMasterBaseLogic newMaster)
{
this.master = newMaster;
}
@Override
public void onDetached (MultiblockMasterBaseLogic oldMaster)
{
if (this.master != oldMaster)
{
throw new IllegalArgumentException("Detaching from wrong master");
}
this.master = null;
}
@Override
public void createNewMultiblock ()
{
MultiblockMasterBaseLogic newMaster = getNewMultiblockMasterObject();
newMaster.attachBlock(this);
}
@Override
public void onMasterMerged (MultiblockMasterBaseLogic newMaster)
{
assert (this.master != newMaster);
this.master = newMaster;
}
@Override
public void setVisited ()
{
this.visited = kVisited;
}
@Override
public void setUnivisted ()
{
this.visited = kUnvisited;
}
@Override
public boolean isVisited ()
{
return this.visited != kUnvisited;
}
@Override
public void becomeMultiblockSaveDelegate ()
{
this.saveMultiblockData = true;
}
@Override
public void forfeitMultiblockSaveDelegate ()
{
this.saveMultiblockData = false;
}
@Override
public boolean isMultiblockSaveDelegate ()
{
return this.saveMultiblockData;
}
@Override
public IMultiblockMember[] getNeighboringMembers ()
{
CoordTuple[] neighbors = getNeighborCoords();
TileEntity te;
List<IMultiblockMember> neighborMembers = new LinkedList<IMultiblockMember>();
for (CoordTuple neighbor : neighbors)
{
te = this.worldObj.getBlockTileEntity(neighbor.x, neighbor.y, neighbor.z);
if (te instanceof IMultiblockMember)
{
// Verify compatible member
if (((IMultiblockMember) te).isCompatible((Object) this) && ((IMultiblockMember) te).willConnect(getCoordInWorld()))
{
neighborMembers.add((IMultiblockMember) te);
}
}
}
IMultiblockMember[] tmp = new IMultiblockMember[neighborMembers.size()];
return neighborMembers.toArray(tmp);
}
@Override
public void onBlockAdded (World world, int x, int y, int z)
{
IMultiblockMember[] neighbors = getNeighboringMembers();
List<MultiblockMasterBaseLogic> masters = new LinkedList<MultiblockMasterBaseLogic>();
for (IMultiblockMember neighbor : neighbors)
{
if (neighbor.isConnected() && !masters.contains(neighbor.getMultiblockMaster()))
{
masters.add(neighbor.getMultiblockMaster());
}
}
if (masters.size() > 0)
{
MultiblockMasterBaseLogic targetMaster = null;
for (MultiblockMasterBaseLogic candidateMaster : masters)
{
if (targetMaster == null)
{
targetMaster = candidateMaster;
}
else
{
int comparison = targetMaster.getReferenceCoord().compareTo(candidateMaster.getReferenceCoord());
if (comparison < 0)
{
continue;
}
else if (comparison == 0)
{
throw new IllegalStateException(String.format("Found two controllers (hashes %d, %d) with identical reference coord %s", targetMaster.hashCode(), candidateMaster.hashCode(),
targetMaster.getReferenceCoord().toString()));
}
else
{
targetMaster = candidateMaster;
}
}
}
assert (targetMaster != null);
masters.remove(targetMaster);
targetMaster.attachBlock(this);
if (masters.size() > 0)
{
CoordTuple hostLoc = this.master.getReferenceCoord();
this.master.beginMerging();
for (MultiblockMasterBaseLogic masterToMerge : masters)
{
this.master.merge(masterToMerge);
}
this.master.endMerging();
}
}
else
{
this.createNewMultiblock();
}
}
@Override
public void onOrphaned ()
{
if (this.isConnected())
{
// Turns out, we're not an orphan after all
return;
}
createNewMultiblock();
// Now for fun. Add all neighbors and DFS out into the world.
Queue<IMultiblockMember> membersToCheck = new LinkedList<IMultiblockMember>();
// Add all unconnected neighbors
CoordTuple[] neighborCoords = getNeighborCoords();
for (CoordTuple coord : neighborCoords)
{
TileEntity neighborTE = this.worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (neighborTE instanceof IMultiblockMember && !((IMultiblockMember) neighborTE).isConnected() && ((IMultiblockMember) neighborTE).willConnect(getCoordInWorld()))
{
membersToCheck.add((IMultiblockMember) neighborTE);
}
}
IMultiblockMember member;
while (!membersToCheck.isEmpty())
{
member = membersToCheck.remove();
if (member.isConnected())
{
// This member has better things to do
continue;
}
// We're already connected by virtue of the new master
this.master.attachBlock(member);
// Add all unconnected neighbors of this member
IMultiblockMember[] neighborMembers = member.getNeighboringMembers();
for (IMultiblockMember neighbor : neighborMembers)
{
if (!neighbor.isConnected())
{
membersToCheck.add(neighbor);
}
}
}
}
@Override
public void readFromNBT (NBTTagCompound data)
{
super.readFromNBT(data);
// We can't directly initialize a multiblock master yet, so we cache the data here until
// we receive a validate() call, which creates the controller and hands off the cached data.
if (data.hasKey("multiblockData"))
{
this.cachedMultiblockData = data.getCompoundTag("multiblockData");
}
}
@Override
public void writeToNBT (NBTTagCompound data)
{
super.writeToNBT(data);
if (this.saveMultiblockData)
{
NBTTagCompound multiblockData = new NBTTagCompound();
this.master.writeToNBT(multiblockData);
data.setCompoundTag("multiblockData", multiblockData);
}
}
// Ignore Vanilla TE updates
@Override
public boolean canUpdate ()
{
return false;
}
@Override
public void invalidate ()
{
super.invalidate();
detachSelf(false);
}
@Override
public void onChunkUnload ()
{
super.onChunkUnload();
if (this.worldObj.isRemote)
{
detachSelf(true);
}
}
@Override
public void onChunkLoad ()
{
if (this.cachedMultiblockData != null)
{
// We need to create a multiblock BUT we cannot check the world yet.
// So we do something stupid and special.
MultiblockMasterBaseLogic newMaster = getNewMultiblockMasterObject();
newMaster.restore(this.cachedMultiblockData);
this.cachedMultiblockData = null;
newMaster.attachBlock(this); // This should grab any other connected blocks in the chunk
}
else
{
if (!this.isConnected())
{
// Ignore blocks that are already connected
this.onBlockAdded(this.worldObj, xCoord, yCoord, zCoord);
}
}
}
@Override
public void onChunkUnloaded ()
{
detachSelf(true);
}
@Override
public void validate ()
{
super.validate();
if (!this.worldObj.isRemote)
{
MultiblockRegistry.registerMember(this.worldObj, ChunkCoordIntPair.chunkXZ2Int(xCoord >> 4, zCoord >> 4), this);
if (!this.worldObj.getChunkProvider().chunkExists(xCoord >> 4, zCoord >> 4))
{
boolean master = this.cachedMultiblockData != null;
MultiblockRegistry.onMemberLoad(this.worldObj, ChunkCoordIntPair.chunkXZ2Int(xCoord >> 4, zCoord >> 4), this, master);
}
}
}
@Override
public abstract MultiblockMasterBaseLogic getNewMultiblockMasterObject ();
protected void attachSelf (World world, MultiblockMasterBaseLogic newMaster)
{
this.master = newMaster;
this.master.attachBlock(this);
}
protected void detachSelf (boolean chunkUnloading)
{
if (this.master != null)
{
this.master.detachBlock(this, chunkUnloading);
this.master = null;
}
}
protected CoordTuple[] getNeighborCoords ()
{
return new CoordTuple[] { new CoordTuple(this.xCoord - 1, this.yCoord, this.zCoord), new CoordTuple(this.xCoord, this.yCoord - 1, this.zCoord),
new CoordTuple(this.xCoord, this.yCoord, this.zCoord - 1), new CoordTuple(this.xCoord, this.yCoord, this.zCoord + 1), new CoordTuple(this.xCoord, this.yCoord + 1, this.zCoord),
new CoordTuple(this.xCoord + 1, this.yCoord, this.zCoord) };
}
}
@@ -0,0 +1,42 @@
package tconstruct.library.multiblock;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.event.EventPriority;
import net.minecraftforge.event.ForgeSubscribe;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
public class MultiblockEventHandler
{
@ForgeSubscribe(priority = EventPriority.NORMAL)
public void onChunkLoad (ChunkEvent.Load loadEvent)
{
Chunk chunk = loadEvent.getChunk();
World world = loadEvent.world;
if (world.isRemote)
{
return;
}
MultiblockRegistry.onChunkLoaded(world, ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition));
}
@ForgeSubscribe(priority = EventPriority.NORMAL)
public void onChunkUnload (ChunkEvent.Unload unloadEvent)
{
Chunk chunk = unloadEvent.getChunk();
World world = unloadEvent.world;
if (world.isRemote)
{
return;
}
MultiblockRegistry.onChunkUnloaded(world, ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition));
}
@ForgeSubscribe(priority = EventPriority.NORMAL)
public void onWorldUnload (WorldEvent.Unload unloadWorldEvent)
{
MultiblockRegistry.onWorldUnloaded(unloadWorldEvent.world);
}
}
@@ -0,0 +1,400 @@
package tconstruct.library.multiblock;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChatMessageComponent;
import net.minecraft.world.World;
import tconstruct.library.util.CoordTuple;
public abstract class MultiblockMasterBaseLogic
{
protected World worldObj;
protected Set<CoordTuple> connectedBlocks;
protected CoordTuple referenceCoord;
protected CoordTuple minimumCoord;
protected CoordTuple maximumCoord;
protected boolean forceRecheck;
protected boolean chunksHaveLoaded;
protected boolean doUpdates;
protected MultiblockMasterBaseLogic(World world)
{
worldObj = world;
connectedBlocks = new CopyOnWriteArraySet<CoordTuple>();
referenceCoord = null;
minimumCoord = new CoordTuple(0, 0, 0);
maximumCoord = new CoordTuple(0, 0, 0);
forceRecheck = false;
chunksHaveLoaded = false;
doUpdates = true;
}
public void restore (NBTTagCompound savedData)
{
this.readFromNBT(savedData);
MultiblockRegistry.register(this);
}
public boolean hasBlock (CoordTuple blockCoord)
{
return connectedBlocks.contains(blockCoord);
}
public void attachBlock (IMultiblockMember member)
{
CoordTuple coords = member.getCoordInWorld();
boolean newMultiblock = this.connectedBlocks.isEmpty();
if (connectedBlocks.contains(coords))
{
return;
}
connectedBlocks.add(coords);
member.onAttached(this);
this.onBlockAdded(member);
this.worldObj.markBlockForUpdate(coords.x, coords.y, coords.z);
if (newMultiblock)
{
MultiblockRegistry.register(this);
}
if (this.referenceCoord == null)
{
referenceCoord = coords;
member.becomeMultiblockSaveDelegate();
}
else if (coords.compareTo(referenceCoord) < 0)
{
TileEntity te = this.worldObj.getBlockTileEntity(referenceCoord.x, referenceCoord.y, referenceCoord.z);
((IMultiblockMember) te).forfeitMultiblockSaveDelegate();
referenceCoord = coords;
member.becomeMultiblockSaveDelegate();
}
forceRecheck = true;
}
protected abstract void onBlockAdded (IMultiblockMember newMember);
protected abstract void onBlockRemoved (IMultiblockMember oldMember);
public void detachBlock (IMultiblockMember member, boolean chunkUnloading)
{
_detachBlock(member, chunkUnloading);
if (!chunkUnloading && forceRecheck)
{
this.revisitBlocks();
}
}
private void _detachBlock (IMultiblockMember member, boolean chunkUnloading)
{
CoordTuple coords = member.getCoordInWorld();
if (chunkUnloading)
{
this.disableUpdates();
}
if (connectedBlocks.contains(coords))
{
member.onDetached(this);
connectedBlocks.remove(coords);
this.onBlockRemoved(member);
if (referenceCoord != null && referenceCoord.equals(coords))
{
member.forfeitMultiblockSaveDelegate();
referenceCoord = null;
}
}
if (connectedBlocks.isEmpty())
{
MultiblockRegistry.unregister(this);
return;
}
if (!forceRecheck && chunkUnloading)
{
this.chunksHaveLoaded = true;
}
else if (this.chunksHaveLoaded)
{
this.chunksHaveLoaded = chunkUnloading;
}
forceRecheck = true;
if (referenceCoord == null)
{
if (!this.connectedBlocks.isEmpty())
{
for (CoordTuple tcoord : connectedBlocks)
{
TileEntity te = this.worldObj.getBlockTileEntity(tcoord.x, tcoord.y, tcoord.z);
if (te == null)
{
continue;
}
if (referenceCoord == null)
{
referenceCoord = tcoord;
}
else if (tcoord.compareTo(referenceCoord) < 0)
{
referenceCoord = tcoord;
}
}
}
if (referenceCoord != null)
{
TileEntity te = this.worldObj.getBlockTileEntity(referenceCoord.x, referenceCoord.y, referenceCoord.z);
((IMultiblockMember) te).becomeMultiblockSaveDelegate();
}
}
}
private void disableUpdates ()
{
doUpdates = false;
}
private void enableUpdates ()
{
doUpdates = true;
}
private boolean getUpdateState ()
{
return doUpdates;
}
public void beginMerging ()
{
}
public void merge (MultiblockMasterBaseLogic other)
{
if (this.referenceCoord.compareTo(other.referenceCoord) >= 0)
{
throw new IllegalArgumentException("You're doing it wrong");
}
TileEntity te;
Set<CoordTuple> acquiredMembers = new CopyOnWriteArraySet<CoordTuple>(other.connectedBlocks);
other.onMergedIntoOtherMaster(this);
IMultiblockMember acquiredMember;
for (CoordTuple coord : acquiredMembers)
{
this.connectedBlocks.add(coord);
te = this.worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
acquiredMember = (IMultiblockMember) te;
acquiredMember.onMasterMerged(this);
this.onBlockAdded(acquiredMember);
}
}
private void onMergedIntoOtherMaster (MultiblockMasterBaseLogic newMaster)
{
this.disableUpdates();
if (referenceCoord != null)
{
TileEntity te = this.worldObj.getBlockTileEntity(referenceCoord.x, referenceCoord.y, referenceCoord.z);
((IMultiblockMember) te).forfeitMultiblockSaveDelegate();
this.referenceCoord = null;
}
this.connectedBlocks.clear();
MultiblockRegistry.unregister(this);
this.onDataMerge(newMaster);
}
protected abstract void onDataMerge (MultiblockMasterBaseLogic newMaster);
public void endMerging ()
{
}
public final void doMultiblockTick ()
{
if (this.connectedBlocks.isEmpty())
{
MultiblockRegistry.unregister(this);
return;
}
if (this.forceRecheck)
{
// Recheck structure
this.doStructureCheck();
this.forceRecheck = false;
}
if (this.doUpdates)
{
if (doUpdate())
{
// Force save delegate to update data
}
}
}
// Override to provide sanity checking on structure
public void doStructureCheck ()
{
}
// Return true to force chunk saving
public boolean doUpdate ()
{
return false;
}
public void revisitBlocks ()
{
TileEntity te;
// Ensure that our current reference coords are valid. If not, invalidate it.
if (referenceCoord != null && this.worldObj.getBlockTileEntity(referenceCoord.x, referenceCoord.y, referenceCoord.z) == null)
{
referenceCoord = null;
}
// Reset visitations and find the minimum coordinate
for (CoordTuple coord : connectedBlocks)
{
if (!this.worldObj.getChunkProvider().chunkExists(coord.x >> 4, coord.z >> 4))
{
continue;
}
te = this.worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (te == null)
{
continue;
} // this happens during chunk unload; ignore it
((IMultiblockMember) te).setUnivisted();
if (referenceCoord == null)
{
referenceCoord = coord;
}
else if (coord.compareTo(referenceCoord) < 0)
{
referenceCoord = coord;
}
}
if (referenceCoord == null)
{
// There are no valid parts remaining. This is due to a chunk unload.
return;
}
// Now visit all connected parts, breadth-first, starting from reference coord.
LinkedList<IMultiblockMember> membersToCheck = new LinkedList<IMultiblockMember>();
IMultiblockMember[] nearbyMembers = null;
IMultiblockMember member = (IMultiblockMember) this.worldObj.getBlockTileEntity(referenceCoord.x, referenceCoord.y, referenceCoord.z);
membersToCheck.add(member);
while (!membersToCheck.isEmpty())
{
member = membersToCheck.removeFirst();
member.setVisited();
nearbyMembers = member.getNeighboringMembers();
for (IMultiblockMember nearbyMember : nearbyMembers)
{
// Ignore different machines
if (nearbyMember.getMultiblockMaster() != this)
{
continue;
}
if (!nearbyMember.isVisited())
{
nearbyMember.setVisited();
membersToCheck.add(nearbyMember);
}
}
}
// First, remove any blocks that are still disconnected
List<IMultiblockMember> orphans = new LinkedList<IMultiblockMember>();
List<CoordTuple> deadBlocks = new ArrayList<CoordTuple>();
for (CoordTuple coord : connectedBlocks)
{
if (!this.worldObj.getChunkProvider().chunkExists(coord.x >> 4, coord.z >> 4))
{
deadBlocks.add(coord);
continue;
}
member = (IMultiblockMember) this.worldObj.getBlockTileEntity(coord.x, coord.y, coord.z);
if (!member.isVisited())
{
orphans.add(member);
}
}
this.connectedBlocks.removeAll(deadBlocks);
// Remove all orphaned parts. i.e. Actually orphan them
for (IMultiblockMember orphan : orphans)
{
this._detachBlock(orphan, false);
}
// Now go through and start up as many new masters as possible
for (IMultiblockMember orphan : orphans)
{
if (!orphan.isConnected())
{
orphan.onOrphaned();
}
}
}
public CoordTuple getReferenceCoord ()
{
return referenceCoord;
}
public int getNumConnectedBlocks ()
{
return connectedBlocks.size();
}
public abstract void writeToNBT (NBTTagCompound data);
public abstract void readFromNBT (NBTTagCompound data);
public abstract void formatDescriptionPacket (NBTTagCompound data);
public abstract void decodeDescriptionPacket (NBTTagCompound data);
public String debugString ()
{
return "refCoords: [" + referenceCoord.x + "," + referenceCoord.y + "," + referenceCoord.z + "]";
}
}
@@ -0,0 +1,141 @@
package tconstruct.library.multiblock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import net.minecraft.world.World;
public class MultiblockRegistry
{
private static Set<MultiblockMasterBaseLogic> masters = new CopyOnWriteArraySet<MultiblockMasterBaseLogic>();
private static HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> preInitMembers = new HashMap<Integer, HashMap<Long, List<IMultiblockMember>>>();
private static HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> preInitMasters = new HashMap<Integer, HashMap<Long, List<IMultiblockMember>>>();
private static HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> loadedMembers = new HashMap<Integer, HashMap<Long, List<IMultiblockMember>>>();
public static void tick (World world)
{
for (MultiblockMasterBaseLogic logic : masters)
{
if (logic.worldObj == world && logic.worldObj.isRemote == world.isRemote)
{
logic.doMultiblockTick();
}
}
}
public static void register (MultiblockMasterBaseLogic logic)
{
masters.add(logic);
}
public static void unregister (MultiblockMasterBaseLogic logic)
{
masters.remove(logic);
}
public static void onMemberLoad (World world, Long chunkCoord, IMultiblockMember member, boolean master)
{
HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> pending = preInitMembers;
if (master)
{
pending = preInitMasters;
}
int dimensionId = world.provider.dimensionId;
putMemberInList(pending, dimensionId, chunkCoord, member);
}
public static void onChunkLoaded (World world, long chunkCoord)
{
int dimensionId = world.provider.dimensionId;
List<IMultiblockMember> pending = getMembersFromListForWorldChunk(preInitMasters, dimensionId, chunkCoord);
if (pending != null)
{
for (IMultiblockMember member : pending)
{
member.onChunkLoad();
}
preInitMasters.get(dimensionId).remove(chunkCoord);
}
pending = getMembersFromListForWorldChunk(preInitMembers, dimensionId, chunkCoord);
if (pending != null)
{
for (IMultiblockMember member : pending)
{
member.onChunkLoad();
}
preInitMembers.get(dimensionId).remove(chunkCoord);
}
}
public static void onChunkUnloaded (World world, long chunkCoord)
{
int dimensionId = world.provider.dimensionId;
List<IMultiblockMember> pending = getMembersFromListForWorldChunk(loadedMembers, dimensionId, chunkCoord);
if (pending != null)
{
for (IMultiblockMember member : pending)
{
member.onChunkUnloaded();
}
loadedMembers.get(dimensionId).remove(chunkCoord);
}
}
public static void registerMember (World world, long chunkCoord, IMultiblockMember member)
{
putMemberInList(loadedMembers, world.provider.dimensionId, chunkCoord, member);
}
public static void onWorldUnloaded (World world)
{
List<MultiblockMasterBaseLogic> mastersToRemove = new ArrayList<MultiblockMasterBaseLogic>();
for (MultiblockMasterBaseLogic master : mastersToRemove)
{
if (master.worldObj.isRemote == world.isRemote && master.worldObj.provider.dimensionId == world.provider.dimensionId)
{
mastersToRemove.add(master);
}
}
masters.removeAll(mastersToRemove);
}
private static List<IMultiblockMember> getMembersFromListForWorldChunk (HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> source, int dimensionId, long chunkCoord)
{
if (!source.containsKey(dimensionId))
{
return null;
}
if (!source.get(dimensionId).containsKey(chunkCoord))
{
return null;
}
return source.get(dimensionId).get(chunkCoord);
}
private static void putMemberInList (HashMap<Integer, HashMap<Long, List<IMultiblockMember>>> destList, int dimensionId, long chunkCoord, IMultiblockMember member)
{
if (!destList.containsKey(dimensionId))
{
destList.put(dimensionId, new HashMap<Long, List<IMultiblockMember>>());
}
HashMap<Long, List<IMultiblockMember>> innerMap = destList.get(dimensionId);
if (!innerMap.containsKey(chunkCoord))
{
innerMap.put(chunkCoord, new ArrayList<IMultiblockMember>());
}
innerMap.get(chunkCoord).add(member);
}
}
@@ -0,0 +1,47 @@
package tconstruct.library.multiblock;
import java.util.EnumSet;
import net.minecraft.world.World;
import cpw.mods.fml.common.IScheduledTickHandler;
import cpw.mods.fml.common.TickType;
public class MultiblockServerTickHandler implements IScheduledTickHandler
{
@Override
public void tickStart (EnumSet<TickType> type, Object... tickData)
{
return;
}
@Override
public void tickEnd (EnumSet<TickType> type, Object... tickData)
{
if (type.contains(TickType.WORLD))
{
World world = (World) tickData[0];
MultiblockRegistry.tick(world);
}
}
@Override
public EnumSet<TickType> ticks ()
{
return EnumSet.of(TickType.WORLD);
}
@Override
public String getLabel ()
{
return "TConstruct:MultiblockServerTickHandler";
}
@Override
public int nextTickSpacing ()
{
return 1;
}
}
@@ -0,0 +1,21 @@
package tconstruct.library.signal;
import tconstruct.library.util.CoordTuple;
import net.minecraft.world.World;
public interface ISignalTransceiver
{
void setBusCoords (World world, int xCoord, int yCoord, int zCoord);
CoordTuple getBusCoords ();
byte[] getReceivedSignals ();
void receiveSignalUpdate (byte[] signals);
int doUnregister (boolean reHoming);
int getDroppedWire ();
}
+36 -6
View File
@@ -13,6 +13,13 @@ public class CoordTuple implements Comparable
z = posZ;
}
public CoordTuple(CoordTuple tuple)
{
x = tuple.x;
y = tuple.y;
z = tuple.z;
}
public boolean equalCoords (int posX, int posY, int posZ)
{
if (this.x == posX && this.y == posY && this.z == posZ)
@@ -57,11 +64,34 @@ public class CoordTuple implements Comparable
{
if (o == null)
throw new NullPointerException("Object cannot be null");
CoordTuple coord = (CoordTuple) o;
if (coord.equals(this))
return 0;
return (x - coord.x) + (y - coord.y) + (z - coord.z);
CoordTuple coord = (CoordTuple) o;
if (x < coord.x)
{
return -1;
}
if (x > coord.x)
{
return 1;
}
if (y < coord.y)
{
return -1;
}
if (y > coord.y)
{
return 1;
}
if (z < coord.z)
{
return -1;
}
if (z > coord.z)
{
return 1;
}
return 0;
}
}
@@ -0,0 +1,19 @@
package tconstruct.library.util;
public class CoordTuplePair
{
public CoordTuple a;
public CoordTuple b;
public CoordTuplePair (CoordTuple a, CoordTuple b)
{
this.a = a;
this.b = b;
}
public CoordTuplePair (int aX, int aY, int aZ, int bX, int bY, int bZ)
{
this.a = new CoordTuple(aX, aY, aZ);
this.b = new CoordTuple(bX, bY, bZ);
}
}
+11 -1
View File
@@ -47,7 +47,6 @@ public class PHConstruct
keepHunger = config.get("Difficulty Changes", "Keep hunger on death", true).getBoolean(true);
keepLevels = config.get("Difficulty Changes", "Keep levels on death", true).getBoolean(true);
beginnerBook = config.get("Difficulty Changes", "Spawn beginner book", true).getBoolean(true);
superfunWorld = config.get("Superfun", "All the world is Superfun", false).getBoolean(false);
enableTWood = config.get("Difficulty Changes", "Enable mod wooden tools", true).getBoolean(true);
@@ -179,6 +178,8 @@ public class PHConstruct
slimeExplosive = config.getBlock("SDX", 3247).getInt(3247);
castingChannel = config.getBlock("Casting Channel", 3249).getInt(3249);
woodenRail = config.getBlock("Wooden Rail", 3250).getInt(3250);
signalBus = config.getBlock("Signal Bus", 3251).getInt(3251);
signalTerminal = config.getBlock("Signal Terminal", 3252).getInt(3252);
manual = config.getItem("Patterns and Misc", "Tinker's Manual", 14018).getInt(14018);
blankPattern = config.getItem("Patterns and Misc", "Blank Patterns", 14019).getInt(14019);
@@ -263,6 +264,9 @@ public class PHConstruct
essenceCrystal = config.getItem("Patterns and Misc", "Essence Crystal", 14114).getInt(14114);
jerky = config.getItem("Patterns and Misc", "Jerky", 14115).getInt(14115);
spoolWire = config.getItem("Logic", "SpoolWire", 14120).getInt(14120);
lengthWire = config.getItem("Logic", "LengthWire", 14121).getInt(14121);
boolean ic2 = true;
boolean xycraft = true;
try
@@ -410,6 +414,9 @@ public class PHConstruct
public static int dryingRack;
public static int woodenRail;
public static int signalBus;
public static int signalTerminal;
//Crops
public static int oreBerry;
@@ -578,6 +585,9 @@ public class PHConstruct
public static int knapsack;
public static int heartCanister;
public static int spoolWire;
public static int lengthWire;
//Ore values
public static boolean generateCopper;