public static IMechanicalPowerDevice getNeighbourDevice(IWorldAccessor world, BlockPos pos, BlockFacing facing, bool connected)
        {
            if (facing == null)
            {
                return(null);
            }

            BlockEntity te = world.BlockAccessor.GetBlockEntity(pos.Offset(facing));

            if (te is IMechanicalPowerDevice)
            {
                IMechanicalPowerDevice mechdevice = (IMechanicalPowerDevice)te;
                if (!mechdevice.exists())
                {
                    return(null);
                }

                if (!connected && mechdevice.hasConnectorAt(facing.GetOpposite()))
                {
                    return(mechdevice);
                }
                if (connected && mechdevice.isConnectedAt(facing.GetOpposite()))
                {
                    return(mechdevice);
                }
            }

            return(null);
        }
 internal void OnNodeRemoved(IMechanicalPowerDevice device)
 {
     if (device.Network != null)
     {
         RebuildNetwork(device.Network, device);
     }
 }
        public void trySetNetwork(long networkId, BlockFacing localFacing)
        {
            if (hasConnectorAt(localFacing))
            {
                this.networkId = networkId;

                IMechanicalPowerDevice device = getNeighbourDevice(localFacing, true);
                if (device != null)
                {
                    if (getNetwork(localFacing).getDirection() != 0)
                    {
                        clockwise = device.isClockWiseDirection(localFacing.GetOpposite());
                        setDirectionFromFacing(localFacing.GetOpposite());
                    }
                }
                else
                {
                    throw new Exception("Eh, a network coming from " + localFacing + ", but there is no device, instead " + api.World.BlockAccessor.GetBlock(pos.AddCopy(localFacing)) + "?!");
                }

                getNetwork(localFacing).register(this);

                api.World.BlockAccessor.MarkBlockEntityDirty(pos);
            }
            else
            {
                directionFromFacing = null;
                this.networkId      = 0;
            }
        }
Esempio n. 4
0
        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 MechanicalNetwork CreateNetwork(IMechanicalPowerDevice powerProducerNode)
        {
            MechanicalNetwork nw = new MechanicalNetwork(this, data.nextNetworkId);

            nw.fullyLoaded = true;

            data.networksById[data.nextNetworkId] = nw;
            data.nextNetworkId++;

            return(nw);
        }
Esempio n. 6
0
 public void register(IMechanicalPowerDevice device)
 {
     if (device is IMechanicalPowerNetworkNode && !powerNodes.Contains(device))
     {
         powerNodes.Add((IMechanicalPowerNetworkNode)device);
     }
     if (device is IMechanicalPowerNetworkRelay && !powerRelays.Contains(device))
     {
         powerRelays.Add((IMechanicalPowerNetworkRelay)device);
     }
 }
Esempio n. 7
0
        public void RebuildNetwork(MechanicalNetwork network, IMechanicalPowerDevice nowRemovedNode = null)
        {
            network.Valid = false;

            if (Api.Side == EnumAppSide.Server)
            {
                DeleteNetwork(network);
            }

            if (network.nodes.Values.Count == 0)
            {
                if (Api.Side == EnumAppSide.Server)
                {
                    Api.Logger.Notification("Network with id " + network.networkId + " had zero nodes?");
                }
                return;
            }

            var nnodes = network.nodes.Values.ToArray();

            foreach (var nnode in nnodes)
            {
                nnode.LeaveNetwork();
            }

            foreach (var nnode in nnodes)
            {
                if (!(nnode is IMechanicalPowerDevice))
                {
                    continue;
                }
                IMechanicalPowerDevice newnode = Api.World.BlockAccessor.GetBlockEntity((nnode as IMechanicalPowerDevice).Position)?.GetBehavior <BEBehaviorMPBase>() as IMechanicalPowerDevice;
                if (newnode == null)
                {
                    continue;
                }
                BlockFacing oldTurnDir = newnode.GetPropagationDirection();

                if (newnode.OutFacingForNetworkDiscovery != null && (nowRemovedNode == null || newnode.Position != nowRemovedNode.Position))
                {
                    MechanicalNetwork newnetwork = newnode.CreateJoinAndDiscoverNetwork(newnode.OutFacingForNetworkDiscovery);
                    bool reversed = newnode.GetPropagationDirection() == oldTurnDir.Opposite;
                    newnetwork.Speed                = reversed ? -network.Speed : network.Speed;
                    newnetwork.AngleRad             = network.AngleRad;
                    newnetwork.TotalAvailableTorque = reversed ? -network.TotalAvailableTorque : network.TotalAvailableTorque;
                    newnetwork.NetworkResistance    = network.NetworkResistance;
                    if (Api.Side == EnumAppSide.Server)
                    {
                        newnetwork.broadcastData();
                    }
                }
            }
        }
Esempio n. 8
0
        public void unregister(IMechanicalPowerDevice device)
        {
            if (device is IMechanicalPowerNetworkNode)
            {
                powerNodes.Remove((IMechanicalPowerNetworkNode)device);
            }
            if (device is IMechanicalPowerNetworkRelay)
            {
                powerRelays.Remove((IMechanicalPowerNetworkRelay)device);
            }

            rebuildNetwork();
        }
        // connected = true   => get connected devices
        // connected = false  => get connectible devices (= devices that could potentially connect to our own device)
        public Dictionary <BlockFacing, IMechanicalPowerDevice> getNeighbourDevices(bool connected)
        {
            Dictionary <BlockFacing, IMechanicalPowerDevice> connectibleNeighbours = new Dictionary <BlockFacing, IMechanicalPowerDevice>();

            foreach (BlockFacing facing in BlockFacing.ALLFACES)
            {
                IMechanicalPowerDevice neib = getNeighbourDevice(facing, connected);
                if (neib == null)
                {
                    continue;
                }
                connectibleNeighbours[facing] = neib;
            }
            return(connectibleNeighbours);
        }
        internal float RotationNeighbour(int side, bool allowIndirect)
        {
            BlockPos pos = Position.AddCopy(orients[side]);
            IMechanicalPowerBlock block = Api.World.BlockAccessor.GetBlock(pos) as IMechanicalPowerBlock;

            if (block?.HasMechPowerConnectorAt(Api.World, pos, orients[side].Opposite) != true)
            {
                block = null;
            }
            BlockEntity            be   = block == null ? null : Api.World.BlockAccessor.GetBlockEntity(pos);
            IMechanicalPowerDevice node = be?.GetBehavior <BEBehaviorMPBase>() as IMechanicalPowerDevice;

            if (node is BEBehaviorMPTransmission trans && !trans.engaged)
            {
                node = null;
            }
            float rot;

            if (node == null || node.Network == null)
            {
                if (this.engaged && allowIndirect)
                {
                    rot           = this.RotationNeighbour(1 - side, false);
                    rotPrev[side] = rot;
                }
                else
                {
                    rot = rotPrev[side];
                }
            }
            else
            {
                rot = node.Network.AngleRad * node.GearedRatio;
                bool invert = node.GetPropagationDirection() != orients[side];
                if (side == 1)
                {
                    invert = !invert;
                }
                if (invert)
                {
                    rot = GameMath.TWOPI - rot;
                }
                rotPrev[side] = rot;
            }
            return(rot);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        public virtual MechanicalNetwork GetNetwork(IWorldAccessor world, BlockPos pos)
        {
            IMechanicalPowerDevice be = world.BlockAccessor.GetBlockEntity(pos)?.GetBehavior <BEBehaviorMPBase>() as IMechanicalPowerDevice;

            return(be?.Network);
        }
        // Default behavior: Device is connected to all neighbor devices
        public bool isConnectedAt(BlockFacing facing)
        {
            IMechanicalPowerDevice device = getNeighbourDevice(facing, false);

            return(device != null && (device is IMechanicalPowerDevice));
        }
        public void handleMechanicalRelayPlacement()
        {
            Dictionary <BlockFacing, MechanicalNetwork> networks = new Dictionary <BlockFacing, MechanicalNetwork>();
            List <BlockFacing> nullnetworks = new List <BlockFacing>();

            foreach (BlockFacing facing in BlockFacing.ALLFACES)
            {
                IMechanicalPowerDevice neib = getNeighbourDevice(facing, true);

                if (neib == null)
                {
                    continue;
                }

                MechanicalNetwork network = neib.getNetwork(facing.GetOpposite());

                if (network != null && !networks.ContainsValue(network))
                {
                    networks[facing] = network;
                }

                if (network == null)
                {
                    nullnetworks.Add(facing);
                }
            }

            //System.out.println(worldObj.isRemote + " found " + networks.size() + " networks ");

            if (networks.Count == 1)
            {
                BlockFacing facing = networks.Keys.ToArray()[0];

                trySetNetwork(networks[facing].networkId, facing);

                foreach (BlockFacing nullnetworkfacing in nullnetworks)
                {
                    getNeighbourDevice(nullnetworkfacing, true).propagateNetworkToNeighbours(
                        MechNetworkManagerRegistry.ManagersByWorld[api.World].getUniquePropagationId(),
                        networkId,
                        nullnetworkfacing
                        );
                }
            }

            if (networks.Count > 1 && api.World is IClientWorldAccessor)
            {
                float             maxSpeedDifference = 0;
                MechanicalNetwork dominantNetwork    = null;

                foreach (MechanicalNetwork network in networks.Values)
                {
                    if (dominantNetwork == null)
                    {
                        dominantNetwork = network;
                        continue;
                    }

                    maxSpeedDifference = Math.Max(maxSpeedDifference, Math.Abs(network.getSpeed() - dominantNetwork.getSpeed()));

                    if (Math.Abs(network.getSpeed()) > Math.Abs(dominantNetwork.getSpeed()))
                    {
                        dominantNetwork = network;
                    }
                }

                // Here we could disallow connecting of networks if
                // maxSpeedDifference is larger than 1
                // e.g. immediately break the placed block again because it cannot handle
                // the large torque difference. But implementation will be somewhat complicated
                foreach (MechanicalNetwork network in networks.Values)
                {
                    if (network != dominantNetwork)
                    {
                        network.isDead = true;
                        MechNetworkManagerRegistry.ManagersByWorld[api.World].discardNetwork(network);
                    }
                }
                dominantNetwork.rebuildNetwork();

                api.World.BlockAccessor.MarkBlockEntityDirty(pos);
            }
        }
Esempio n. 15
0
 public void DidUnload(IMechanicalPowerDevice node)
 {
     fullyLoaded = false;
 }