private bool RequiresStand(BlockPos pos, Vec3i vector) { BlockMPBase block = Api.World.BlockAccessor.GetBlock(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z) as BlockMPBase; if (block == null) { return(true); } BlockPos sidePos = new BlockPos(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z); BEBehaviorMPBase bemp = Api.World.BlockAccessor.GetBlockEntity(sidePos)?.GetBehavior <BEBehaviorMPBase>(); if (bemp == null) { return(true); } BEBehaviorMPAxle bempaxle = bemp as BEBehaviorMPAxle; if (bempaxle == null) { if (bemp is BEBehaviorMPBrake || bemp is BEBehaviorMPCreativeRotor) { BlockFacing side = BlockFacing.FromNormal(vector); if (side != null && block.HasMechPowerConnectorAt(Api.World, sidePos, side.Opposite)) { return(false); } } return(true); } if (IsAttachedToBlock(Api.World.BlockAccessor, block, sidePos)) { return(false); } return(bempaxle.RequiresStand(sidePos, vector)); }
public bool tryConnect(BlockFacing toFacing) { MechanicalNetwork newNetwork; BlockPos pos = Position.AddCopy(toFacing); IMechanicalPowerBlock connectedToBlock = Api.World.BlockAccessor.GetBlock(pos) as IMechanicalPowerBlock; if (DEBUG) { Api.Logger.Notification("tryConnect at " + this.Position + " towards " + toFacing + " " + pos); } if (connectedToBlock == null || !connectedToBlock.HasMechPowerConnectorAt(Api.World, pos, toFacing.Opposite)) { return(false); } newNetwork = connectedToBlock.GetNetwork(Api.World, pos); if (newNetwork != null) { IMechanicalPowerDevice node = Api.World.BlockAccessor.GetBlockEntity(pos).GetBehavior <BEBehaviorMPBase>() as IMechanicalPowerDevice; connectedToBlock.DidConnectAt(Api.World, pos, toFacing.Opposite); //do this first to set the new Angled Gear block correctly prior to getting propagation direction BlockFacing newTurnDir = node.GetPropagationDirectionInput(); MechPowerPath curPath = new MechPowerPath(toFacing, node.GetGearedRatio(toFacing), pos, !node.IsPropagationDirection(Position, toFacing)); SetPropagationDirection(curPath); MechPowerPath[] paths = GetMechPowerExits(curPath); JoinNetwork(newNetwork); for (int i = 0; i < paths.Length; i++) { //if (paths[i].OutFacing == toFacing) continue; if (DEBUG) { Api.Logger.Notification("== spreading path " + (paths[i].invert ? "-" : "") + paths[i].OutFacing + " " + paths[i].gearingRatio); } BlockPos exitPos = Position.AddCopy(paths[i].OutFacing); bool chunkLoaded = spreadTo(Api, newNetwork, exitPos, paths[i], out _); if (!chunkLoaded) { LeaveNetwork(); return(true); } } return(true); } else if (this.network != null) { BEBehaviorMPBase node = Api.World.BlockAccessor.GetBlockEntity(pos)?.GetBehavior <BEBehaviorMPBase>(); if (node != null) { return(node.tryConnect(toFacing.Opposite)); } } return(false); }
public override void OnNeighbourBlockChange(IWorldAccessor world, BlockPos pos, BlockPos neibpos) { string orients = Orientation; if (orients.Length == 2 && orients[0] == orients[1]) { orients = "" + orients[0]; } BlockFacing[] facings; facings = orients.Length == 1 ? new BlockFacing[] { BlockFacing.FromFirstLetter(orients[0]) } : new BlockFacing[] { BlockFacing.FromFirstLetter(orients[0]), BlockFacing.FromFirstLetter(orients[1]) }; List <BlockFacing> lostFacings = new List <BlockFacing>(); foreach (BlockFacing facing in facings) { BlockPos npos = pos.AddCopy(facing); IMechanicalPowerBlock nblock = world.BlockAccessor.GetBlock(npos) as IMechanicalPowerBlock; if (nblock == null || !nblock.HasMechPowerConnectorAt(world, npos, facing.Opposite) || world.BlockAccessor.GetBlockEntity(pos)?.GetBehavior <BEBehaviorMPBase>()?.disconnected == true) { lostFacings.Add(facing); } } if (lostFacings.Count == orients.Length) { world.BlockAccessor.BreakBlock(pos, null); return; } if (lostFacings.Count > 0) { MechanicalNetwork nw = GetNetwork(world, pos); orients = orients.Replace("" + lostFacings[0].Code[0], ""); Block toPlaceBlock = world.GetBlock(new AssetLocation(FirstCodePart() + "-" + orients)); (toPlaceBlock as BlockMPBase).ExchangeBlockAt(world, pos); BlockEntity be = world.BlockAccessor.GetBlockEntity(pos); BEBehaviorMPBase bemp = be.GetBehavior <BEBehaviorMPBase>(); bemp.LeaveNetwork(); //check for connect to adjacent valid facings, similar to TryPlaceBlock BlockFacing firstFace = BlockFacing.FromFirstLetter(orients[0]); BlockPos firstPos = pos.AddCopy(firstFace); BlockEntity beNeib = world.BlockAccessor.GetBlockEntity(firstPos); IMechanicalPowerBlock neighbour = beNeib?.Block as IMechanicalPowerBlock; BEBehaviorMPAxle bempaxle = beNeib?.GetBehavior <BEBehaviorMPAxle>(); if (bempaxle != null && !BEBehaviorMPAxle.IsAttachedToBlock(world.BlockAccessor, neighbour as Block, firstPos)) { return; } neighbour?.DidConnectAt(world, firstPos, firstFace.Opposite); WasPlaced(world, pos, firstFace); } }
public virtual void WasPlaced(IWorldAccessor world, BlockPos ownPos, BlockFacing connectedOnFacing) { if (connectedOnFacing == null) { return; } BEBehaviorMPBase beMechBase = world.BlockAccessor.GetBlockEntity(ownPos)?.GetBehavior <BEBehaviorMPBase>(); beMechBase?.tryConnect(connectedOnFacing); }
internal void ExchangeBlockAt(IWorldAccessor world, BlockPos pos) { world.BlockAccessor.ExchangeBlock(BlockId, pos); BlockEntity be = world.BlockAccessor.GetBlockEntity(pos); BEBehaviorMPBase bemp = be.GetBehavior <BEBehaviorMPBase>(); bemp.Block = this; bemp.SetOrientations(); bemp.Shape = Shape; }
internal void ExchangeBlockAt(IWorldAccessor world, BlockPos pos) { world.BlockAccessor.ExchangeBlock(BlockId, pos); BlockEntity be = world.BlockAccessor.GetBlockEntity(pos); BEBehaviorMPBase bemp = be?.GetBehavior <BEBehaviorMPBase>(); if (bemp != null) { bemp.SetOrientations(); bemp.Shape = Shape; be.MarkDirty(); } }
public override void DidConnectAt(IWorldAccessor world, BlockPos pos, BlockFacing face) { if (IsDeadEnd()) { BlockFacing nowFace = BlockFacing.FromFirstLetter(Orientation[0]); if (nowFace.IsAdjacent(face)) { Block toPlaceBlock = getGearBlock(world, false, Facings[0], face); MechanicalNetwork nw = GetNetwork(world, pos); (toPlaceBlock as BlockMPBase).ExchangeBlockAt(world, pos); BEBehaviorMPBase bemp = world.BlockAccessor.GetBlockEntity(pos)?.GetBehavior <BEBehaviorMPBase>(); } } }
private bool RequiresStand(BlockPos pos, Vec3i vector) { try { BlockMPBase block = Api.World.BlockAccessor.GetBlock(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z) as BlockMPBase; if (block == null) { return(true); } BlockPos sidePos = new BlockPos(pos.X + vector.X, pos.Y + vector.Y, pos.Z + vector.Z); BEBehaviorMPBase bemp = Api.World.BlockAccessor.GetBlockEntity(sidePos)?.GetBehavior <BEBehaviorMPBase>(); if (bemp == null) { return(true); } BEBehaviorMPAxle bempaxle = bemp as BEBehaviorMPAxle; if (bempaxle == null) { if (bemp is BEBehaviorMPBrake || bemp is BEBehaviorMPCreativeRotor) { BlockFacing side = BlockFacing.FromNormal(vector); if (side != null && block.HasMechPowerConnectorAt(Api.World, sidePos, side.Opposite)) { return(false); } } return(true); } if (IsAttachedToBlock(Api.World.BlockAccessor, block, sidePos)) { return(false); } return(bempaxle.RequiresStand(sidePos, vector)); } catch (Exception e) { #if DEBUG throw (e); #else Api.Logger.Error("Exception thrown in RequiresStand, will log exception but silently ignore it"); Api.Logger.Error("{0}", e); return(false); #endif } }
protected virtual bool spreadTo(ICoreAPI api, MechanicalNetwork network, BlockPos exitPos, MechPowerPath propagatePath, out Vec3i missingChunkPos) { missingChunkPos = null; BEBehaviorMPBase beMechBase = api.World.BlockAccessor.GetBlockEntity(exitPos)?.GetBehavior <BEBehaviorMPBase>(); IMechanicalPowerBlock mechBlock = beMechBase?.Block as IMechanicalPowerBlock; if (DEBUG) { api.Logger.Notification("attempting spread to " + exitPos + (beMechBase == null ? " -" : "")); } if (beMechBase == null && api.World.BlockAccessor.GetChunkAtBlockPos(exitPos) == null) { if (OutsideMap(api.World.BlockAccessor, exitPos)) { return(true); //Network discovery should not fail if there cannot be a block in this position } missingChunkPos = new Vec3i(exitPos.X / api.World.BlockAccessor.ChunkSize, exitPos.Y / api.World.BlockAccessor.ChunkSize, exitPos.Z / api.World.BlockAccessor.ChunkSize); return(false); } if (beMechBase != null && mechBlock.HasMechPowerConnectorAt(api.World, exitPos, propagatePath.OutFacing.Opposite)) { beMechBase.Api = api; if (!beMechBase.JoinAndSpreadNetworkToNeighbours(api, network, propagatePath, out missingChunkPos)) { return(false); } } else if (DEBUG) { api.Logger.Notification("no connector at " + exitPos + " " + propagatePath.OutFacing.Opposite); } return(true); }
public virtual MechanicalNetwork CreateJoinAndDiscoverNetwork(BlockFacing powerOutFacing) { BlockPos neibPos = Position.AddCopy(powerOutFacing); IMechanicalPowerBlock neibMechBlock = null; neibMechBlock = Api.World.BlockAccessor.GetBlock(neibPos) as IMechanicalPowerBlock; MechanicalNetwork neibNetwork = neibMechBlock == null ? null : neibMechBlock.GetNetwork(Api.World, neibPos); if (neibNetwork == null || !neibNetwork.Valid) { MechanicalNetwork newNetwork = this.network; if (newNetwork == null) { newNetwork = manager.CreateNetwork(this); JoinNetwork(newNetwork); if (DEBUG) { Api.Logger.Notification("===setting inturn at " + Position + " " + powerOutFacing); } SetPropagationDirection(new MechPowerPath(powerOutFacing, 1)); } Vec3i missingChunkPos; bool chunksLoaded = spreadTo(Api, newNetwork, neibPos, new MechPowerPath(GetPropagationDirection(), this.gearedRatio), out missingChunkPos); if (network == null) { if (DEBUG) { Api.Logger.Notification("Incomplete chunkloading, possible issues with mechanical network around block " + neibPos); } return(null); } if (!chunksLoaded) { network.AwaitChunkThenDiscover(missingChunkPos); manager.testFullyLoaded(network); // To trigger that allFullyLoaded gets false return(network); } else { IMechanicalPowerDevice node = Api.World.BlockAccessor.GetBlockEntity(neibPos)?.GetBehavior <BEBehaviorMPBase>() as IMechanicalPowerDevice; if (node != null) { BlockFacing facing = node.GetPropagationDirectionInput(); SetPropagationDirection(new MechPowerPath(facing, node.GetGearedRatio(facing), neibPos)); } } } else { BEBehaviorMPBase neib = Api.World.BlockAccessor.GetBlockEntity(neibPos).GetBehavior <BEBehaviorMPBase>(); if (OutFacingForNetworkDiscovery != null) { if (tryConnect(OutFacingForNetworkDiscovery)) { this.gearedRatio = neib.GetGearedRatio(OutFacingForNetworkDiscovery); //no need to set propagationDir, it's already been set by tryConnect } } else { JoinNetwork(neibNetwork); SetPropagationDirection(new MechPowerPath(neib.propagationDir, neib.GetGearedRatio(neib.propagationDir), neibPos)); } } return(network); }
public override bool TryPlaceBlock(IWorldAccessor world, IPlayer byPlayer, ItemStack itemstack, BlockSelection blockSel, ref string failureCode) { List <BlockPos> smallGears = new List <BlockPos>(); if (!CanPlaceBlock(world, byPlayer, blockSel, ref failureCode, smallGears)) { return(false); } bool ok = base.DoPlaceBlock(world, byPlayer, blockSel, itemstack); if (ok) { int dx, dz; BlockEntity beOwn = world.BlockAccessor.GetBlockEntity(blockSel.Position); List <BlockFacing> connections = new List <BlockFacing>(); foreach (var smallGear in smallGears) { dx = smallGear.X - blockSel.Position.X; dz = smallGear.Z - blockSel.Position.Z; char orient = 'n'; if (dx == 1) { orient = 'e'; } else if (dx == -1) { orient = 'w'; } else if (dz == 1) { orient = 's'; } BlockMPBase toPlaceBlock = world.GetBlock(new AssetLocation("angledgears-" + orient + orient)) as BlockMPBase; BlockFacing bf = BlockFacing.FromFirstLetter(orient); toPlaceBlock.ExchangeBlockAt(world, smallGear); toPlaceBlock.DidConnectAt(world, smallGear, bf.Opposite); connections.Add(bf); //IGearAcceptor beg = beOwn as IGearAcceptor; //if (beg == null) world.Logger.Error("large gear wrong block entity type - not a gear acceptor"); //beg?.AddGear(smallGear); } PlaceFakeBlocks(world, blockSel.Position, smallGears); BEBehaviorMPBase beMechBase = beOwn?.GetBehavior <BEBehaviorMPBase>(); BlockPos pos = blockSel.Position.DownCopy(); if (world.BlockAccessor.GetBlock(pos) is IMechanicalPowerBlock block && block.HasMechPowerConnectorAt(world, pos, BlockFacing.UP)) { block.DidConnectAt(world, pos, BlockFacing.UP); connections.Add(BlockFacing.DOWN); } else { pos = blockSel.Position.UpCopy(); block = world.BlockAccessor.GetBlock(pos) as IMechanicalPowerBlock; if (block != null && block.HasMechPowerConnectorAt(world, pos, BlockFacing.DOWN)) { block.DidConnectAt(world, pos, BlockFacing.DOWN); connections.Add(BlockFacing.UP); } } foreach (BlockFacing face in connections) { beMechBase?.WasPlaced(face); } }