use of pl.asie.charset.api.wires.WireFace in project Charset by CharsetMC.
the class PartWireNormal method propagate.
@Override
public void propagate(int color) {
if (DEBUG) {
System.out.println("--- PROPAGATE " + getPos().toString() + " " + location.name() + " (" + getWorld().getTotalWorldTime() + ") ---");
}
int maxSignal = 0;
int oldSignal = signalLevel;
int[] neighborLevel = new int[7];
boolean[] isWire = new boolean[7];
boolean hasRedstoneWire = false;
PartWireBase.PROPAGATING = true;
if (type == WireKind.NORMAL) {
if (location != WireFace.CENTER) {
EnumFacing facing = location.facing;
BlockPos pos = getPos().offset(facing);
IBlockState state = getWorld().getBlockState(pos);
int power = WireUtils.getRedstoneLevel(getWorld(), pos, state, facing, location, false);
if (power > 0) {
neighborLevel[facing.ordinal()] = Math.min(15, power) << 8 | 0xFF;
}
}
}
if (internalConnections > 0) {
for (WireFace location : WireFace.VALUES) {
if (connectsInternal(location)) {
isWire[location.ordinal()] = true;
neighborLevel[location.ordinal()] = getRedstoneLevel(getContainer(), location);
}
}
}
for (EnumFacing facing : EnumFacing.VALUES) {
int facidx = facing.ordinal();
if (facing == location.facing && type == WireKind.NORMAL) {
BlockPos pos = getPos().offset(facing);
int i = 0;
for (EnumFacing enumfacing : EnumFacing.values()) {
if (enumfacing == facing.getOpposite()) {
continue;
}
IBlockState state = getWorld().getBlockState(pos.offset(enumfacing));
Block block = state.getBlock();
if (!(block instanceof BlockRedstoneWire)) {
int power = WireUtils.getRedstoneLevel(getWorld(), pos.offset(enumfacing), state, enumfacing, location, true);
if (power >= 15) {
i = 15;
break;
}
if (power > i) {
i = power;
}
}
}
if (i > 0) {
neighborLevel[facidx] = (i << 8) | 0xFF;
}
} else if (connectsExternal(facing)) {
BlockPos pos = getPos().offset(facing);
IMultipartContainer container = MultipartHelper.getPartContainer(getWorld(), pos);
if (WireUtils.getWire(container, location) != null) {
isWire[facidx] = true;
neighborLevel[facidx] = getRedstoneLevel(container, location);
} else {
IBlockState state = getWorld().getBlockState(pos);
int power = WireUtils.getRedstoneLevel(getWorld(), pos, state, facing, location, true);
if (state.getBlock() instanceof BlockRedstoneWire) {
isWire[facidx] = true;
hasRedstoneWire = true;
power--;
}
if (power > 0) {
neighborLevel[facidx] = (Math.min(power, 15) << 8) | 0xFF;
}
}
} else if (connectsCorner(facing)) {
IMultipartContainer container = MultipartHelper.getPartContainer(getWorld(), getPos().offset(facing).offset(location.facing));
if (container != null) {
isWire[facidx] = true;
neighborLevel[facidx] = getRedstoneLevel(container, WireFace.get(facing.getOpposite()));
}
}
}
PartWireBase.PROPAGATING = false;
int maxSignalNonWire = 0;
for (int i = 0; i < 7; i++) {
if (neighborLevel[i] > maxSignal) {
maxSignal = neighborLevel[i];
}
if (!isWire[i] && neighborLevel[i] > maxSignalNonWire) {
maxSignalNonWire = neighborLevel[i];
}
}
if (DEBUG) {
System.out.println("ConnectionCache: " + Integer.toBinaryString(internalConnections) + " " + Integer.toBinaryString(externalConnections) + " " + Integer.toBinaryString(cornerConnections));
System.out.println("Levels: " + Arrays.toString(neighborLevel));
}
if (maxSignal > signalLevel) {
signalLevel = maxSignal - 1;
if ((signalLevel & 0xFF) == 0 || (signalLevel & 0xFF) == 0xFF) {
signalLevel = 0;
}
} else {
signalLevel = maxSignalNonWire;
}
if (oldSignal == signalLevel) {
return;
}
if (DEBUG) {
System.out.println("Switch: " + oldSignal + " -> " + signalLevel);
}
if (signalLevel == 0) {
for (WireFace nLoc : WireFace.VALUES) {
if (connectsInternal(nLoc)) {
if (neighborLevel[nLoc.ordinal()] > 0) {
WireUtils.getWire(getContainer(), nLoc).onSignalChanged(type.color());
}
} else if (nLoc != WireFace.CENTER) {
EnumFacing facing = nLoc.facing;
if (connectsExternal(facing)) {
IMultipartContainer container = MultipartHelper.getPartContainer(getWorld(), getPos().offset(facing));
if (container == null || WireUtils.getWire(container, location) == null || neighborLevel[facing.ordinal()] > 0) {
propagateNotify(facing, type.color());
}
} else if (connectsCorner(facing)) {
if (neighborLevel[nLoc.ordinal()] > 0) {
propagateNotifyCorner(location.facing, facing, type.color());
}
} else if (type == WireKind.NORMAL && facing.getOpposite() != location.facing) {
TileEntity nt = getWorld().getTileEntity(getPos().offset(facing));
if (!(nt instanceof IRedstoneReceiver)) {
getWorld().notifyBlockOfStateChange(getPos().offset(facing), MCMultiPartMod.multipart);
}
}
}
}
} else {
for (WireFace nLoc : WireFace.VALUES) {
if (neighborLevel[nLoc.ordinal()] < signalLevel - 1 || neighborLevel[nLoc.ordinal()] > (signalLevel + 1)) {
if (connectsInternal(nLoc)) {
WireUtils.getWire(getContainer(), nLoc).onSignalChanged(type.color());
} else if (nLoc != WireFace.CENTER) {
EnumFacing facing = nLoc.facing;
if (connectsExternal(facing)) {
propagateNotify(facing, type.color());
} else if (connectsCorner(facing)) {
propagateNotifyCorner(location.facing, facing, type.color());
} else if (type == WireKind.NORMAL && facing.getOpposite() != location.facing) {
TileEntity nt = getWorld().getTileEntity(getPos().offset(facing));
if (!(nt instanceof IRedstoneReceiver)) {
getWorld().notifyBlockOfStateChange(getPos().offset(facing), MCMultiPartMod.multipart);
}
}
}
}
}
}
if (type == WireKind.NORMAL) {
if ((oldSignal & 0xF00) != (signalLevel & 0xF00)) {
scheduleRenderUpdate();
if (location != WireFace.CENTER) {
BlockPos uPos = getPos().offset(location.facing);
getWorld().notifyNeighborsOfStateExcept(uPos, MCMultiPartMod.multipart, location.facing.getOpposite());
}
}
} else {
if ((oldSignal & 0xF00) != (signalLevel & 0xF00)) {
if (location != WireFace.CENTER) {
getWorld().notifyBlockOfStateChange(getPos().offset(location.facing), MCMultiPartMod.multipart);
}
}
}
finishPropagation();
}
use of pl.asie.charset.api.wires.WireFace in project Charset by CharsetMC.
the class PartWireBase method updateConnections.
public void updateConnections() {
Set<WireFace> validSides = EnumSet.noneOf(WireFace.class);
Set<WireFace> invalidCornerSides = EnumSet.noneOf(WireFace.class);
for (WireFace facing : WireFace.VALUES) {
if (facing == location) {
continue;
}
if (facing != WireFace.CENTER && location != WireFace.CENTER && location.facing.getAxis() == facing.facing.getAxis()) {
continue;
}
validSides.add(facing);
}
int oldConnectionCache = internalConnections << 12 | externalConnections << 6 | cornerConnections;
internalConnections = externalConnections = cornerConnections = occludedSides = cornerOccludedSides = 0;
// Occlusion test
EnumFacing[] connFaces = WireUtils.getConnectionsForRender(location);
List<IMultipart> parts = new ArrayList<IMultipart>();
for (IMultipart p : getContainer().getParts()) {
if (p != this && p instanceof IOccludingPart && !(p instanceof PartWireBase)) {
parts.add(p);
}
}
if (parts.size() > 0) {
for (int i = 0; i < connFaces.length; i++) {
WireFace face = WireFace.get(connFaces[i]);
if (validSides.contains(face)) {
boolean found = false;
AxisAlignedBB mask = getBox(i + 1);
if (mask != null) {
if (!OcclusionHelper.occlusionTest(parts, this, mask)) {
occludedSides |= 1 << connFaces[i].ordinal();
validSides.remove(face);
found = true;
}
}
if (!found && location != WireFace.CENTER) {
BlockPos cPos = getPos().offset(connFaces[i]);
AxisAlignedBB cornerMask = getCornerBox(i ^ 1);
if (cornerMask != null) {
IMultipartContainer cornerContainer = MultipartHelper.getPartContainer(getWorld(), cPos);
if (cornerContainer != null) {
if (!OcclusionHelper.occlusionTest(cornerContainer.getParts(), cornerMask)) {
cornerOccludedSides |= 1 << connFaces[i].ordinal();
invalidCornerSides.add(face);
}
} else {
List<AxisAlignedBB> boxes = new ArrayList<AxisAlignedBB>();
IBlockState cState = getWorld().getBlockState(cPos);
cState.getBlock().addCollisionBoxesToList(getWorld(), cPos, cState, cornerMask.offset(cPos.getX(), cPos.getY(), cPos.getZ()), boxes, null);
if (boxes.size() > 0) {
cornerOccludedSides |= 1 << connFaces[i].ordinal();
invalidCornerSides.add(face);
}
}
}
}
}
}
}
if (validSides.contains(WireFace.CENTER)) {
AxisAlignedBB mask = getCenterBox(1 + location.ordinal());
if (mask != null) {
if (!OcclusionHelper.occlusionTest(parts, this, mask)) {
occludedSides |= 1 << 6;
validSides.remove(WireFace.CENTER);
}
}
}
for (WireFace facing : validSides) {
if (WireUtils.canConnectInternal(this, facing)) {
internalConnections |= 1 << facing.ordinal();
} else if (facing != WireFace.CENTER) {
if (WireUtils.canConnectExternal(this, facing.facing)) {
externalConnections |= 1 << facing.ordinal();
} else if (location != WireFace.CENTER && !invalidCornerSides.contains(facing) && WireUtils.canConnectCorner(this, facing.facing)) {
cornerConnections |= 1 << facing.ordinal();
}
}
}
int newConnectionCache = internalConnections << 12 | externalConnections << 6 | cornerConnections;
if (oldConnectionCache != newConnectionCache) {
scheduleNeighborUpdate((oldConnectionCache ^ newConnectionCache) >> 6);
schedulePropagationUpdate();
scheduleRenderUpdate();
}
}
use of pl.asie.charset.api.wires.WireFace in project Charset by CharsetMC.
the class TileWire method readNBTData.
@Override
public void readNBTData(NBTTagCompound nbt, boolean isClient) {
if (nbt.hasKey("f")) {
WireProvider factory = WireManager.REGISTRY.getValue(nbt.getByte("f"));
if (factory != null) {
WireFace location = WireFace.VALUES[nbt.getByte("l")];
wire = factory.create(this, location);
wire.readNBTData(nbt, isClient);
}
if (isClient) {
markBlockForRenderUpdate();
}
} else {
if (wire != null) {
wire = null;
if (isClient) {
markBlockForRenderUpdate();
}
}
}
}
use of pl.asie.charset.api.wires.WireFace in project Charset by CharsetMC.
the class ItemWire method placeBlockAtTested.
@Override
public boolean placeBlockAtTested(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, IBlockState newState) {
WireProvider factory = WireManager.REGISTRY.getValue(stack.getMetadata() >> 1);
WireFace location = (stack.getMetadata() & 1) != 0 ? WireFace.CENTER : WireFace.get(facing.getOpposite());
if (!factory.canPlace(world, pos, location)) {
return false;
}
if (factory.canProvidePower()) {
newState = newState.withProperty(BlockWire.REDSTONE, true);
}
if (super.placeBlockAtTested(stack, player, world, pos, facing, hitX, hitY, hitZ, newState)) {
TileEntity tileEntity = world.getTileEntity(pos);
if (tileEntity instanceof TileWire) {
((TileWire) tileEntity).onPlacedBy(WireFace.get(facing != null ? facing.getOpposite() : null), stack);
}
return true;
} else {
return false;
}
}
use of pl.asie.charset.api.wires.WireFace in project Charset by CharsetMC.
the class WireUtils method canConnectInternal.
public static boolean canConnectInternal(PartWireBase wire, WireFace side) {
WireFace location = wire.location;
IMultipartContainer container = wire.getContainer();
if (side == location) {
return false;
}
if (side != WireFace.CENTER && location != WireFace.CENTER) {
if (isBlockingPart(container, PartSlot.getEdgeSlot(side.facing, location.facing))) {
return false;
}
}
PartWireBase wire2 = getWire(container, side);
return wire2 != null && wire2.type.connects(wire.type);
}
Aggregations