/// <summary>
        /// Generates a list of all owners of the cubegrid and all grids that are statically attached to it.
        /// </summary>
        /// <param name="cubeGrid"></param>
        /// <returns></returns>
        public static List <long> GetAllSmallOwners(this IMyCubeGrid cubeGrid)
        {
            List <IMyCubeGrid> allGrids       = cubeGrid.GetAttachedGrids(AttachedGrids.Static);
            HashSet <long>     allSmallOwners = new HashSet <long>();

            foreach (var owner in allGrids.SelectMany(myCubeGrid => myCubeGrid.SmallOwners))
            {
                allSmallOwners.Add(owner);
            }

            return(allSmallOwners.ToList());
        }
        // TODO: deal with cubes that need to be rotated.
        // LargeBlockBeacon, SmallBlockBeacon, ConveyorTube, ConveyorTubeSmall

        private bool ScaleShip(ulong steamId, IMyCubeGrid shipEntity, MyCubeSize newScale)
        {
            if (shipEntity == null)
            {
                return(false);
            }

            if (shipEntity.GridSizeEnum == newScale)
            {
                MyAPIGateway.Utilities.SendMessage(steamId, "scaledown", "Ship is already the right scale.");
                return(true);
            }

            var grids = shipEntity.GetAttachedGrids();

            var newGrids = new MyObjectBuilder_CubeGrid[grids.Count];

            foreach (var cubeGrid in grids)
            {
                // ejects any player prior to deleting the grid.
                cubeGrid.EjectControllingPlayers();
                cubeGrid.Physics.Enabled = false;
            }

            var tempList  = new List <MyObjectBuilder_EntityBase>();
            var gridIndex = 0;

            foreach (var cubeGrid in grids)
            {
                var blocks = new List <IMySlimBlock>();
                cubeGrid.GetBlocks(blocks);

                var gridObjectBuilder = cubeGrid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid;

                gridObjectBuilder.EntityId = 0;
                Regex rgx      = new Regex(Regex.Escape(gridObjectBuilder.GridSizeEnum.ToString()));
                var   rgxScale = Regex.Escape(newScale.ToString());
                gridObjectBuilder.GridSizeEnum = newScale;
                var removeList = new List <MyObjectBuilder_CubeBlock>();

                foreach (var block in gridObjectBuilder.CubeBlocks)
                {
                    MyCubeBlockDefinition definition;
                    string newSubType = null;
                    if (newScale == MyCubeSize.Small && LargeToSmall.ContainsKey(block.SubtypeName))
                    {
                        newSubType = LargeToSmall[block.SubtypeName];
                    }
                    else if (newScale == MyCubeSize.Large && SmallToLarge.ContainsKey(block.SubtypeName))
                    {
                        newSubType = SmallToLarge[block.SubtypeName];
                    }
                    else
                    {
                        newSubType = rgx.Replace(block.SubtypeName, rgxScale, 1);

                        // Match using the BlockPairName if there is a matching cube.
                        if (MyDefinitionManager.Static.TryGetCubeBlockDefinition(new MyDefinitionId(block.GetType(), block.SubtypeName), out definition))
                        {
                            var newDef = MyDefinitionManager.Static.GetAllDefinitions().Where(d => d is MyCubeBlockDefinition && ((MyCubeBlockDefinition)d).BlockPairName == definition.BlockPairName && ((MyCubeBlockDefinition)d).CubeSize == newScale).FirstOrDefault();
                            if (newDef != null)
                            {
                                newSubType = newDef.Id.SubtypeName;
                            }
                        }
                    }
                    if (MyDefinitionManager.Static.TryGetCubeBlockDefinition(new MyDefinitionId(block.GetType(), newSubType), out definition) && definition.CubeSize == newScale)
                    {
                        block.SubtypeName = newSubType;
                        //block.EntityId = 0;
                    }
                    else
                    {
                        removeList.Add(block);
                    }
                }

                foreach (var block in removeList)
                {
                    gridObjectBuilder.CubeBlocks.Remove(block);
                }

                // This will Delete the entity and sync to all.
                // Using this, also works with player ejection in the same Tick.
                cubeGrid.SyncObject.SendCloseRequest();

                var name = cubeGrid.DisplayName;
                MyAPIGateway.Utilities.SendMessage(steamId, "ship", "'{0}' resized.", name);

                tempList.Add(gridObjectBuilder);

                gridIndex++;
            }

            // TODO: reposition multiple grids so rotors and pistons re-attach.

            tempList.CreateAndSyncEntities();
            return(true);
        }
示例#3
0
        private void _cubeGrid_OnBlockOwnershipChanged(IMyCubeGrid cubeGrid)
        {
            // only execute on server instance
            if (ChatCommandLogic.Instance != null && ChatCommandLogic.Instance.ServerCfg == null)
            {
                return;
            }

            if (_firstOwnershipChange)
            {
                _firstOwnershipChange = false;
                _cachedOwners         = new List <long>(cubeGrid.GetAllSmallOwners());
                return;
            }

            var allSmallOwners = cubeGrid.GetAllSmallOwners();

            if (_cachedOwners == allSmallOwners)
            {
                return;
            }

            // if the grid wasn't owned or a owner was removed, we dont need to do anything but update the cached owners
            if (_cachedOwners.Count == 0 || _cachedOwners.Count > allSmallOwners.Count)
            {
                _cachedOwners = new List <long>(allSmallOwners);
                return;
            }

            var newOwners = allSmallOwners.Except(_cachedOwners).ToList();

            if (newOwners.Count == 0)
            {
                return;
            }

            if (!ProtectionHandler.IsProtected(cubeGrid))
            {
                _cachedOwners = new List <long>(allSmallOwners);
                return;
            }

            Dictionary <long, int> blocksPerOwner = new Dictionary <long, int>();

            foreach (IMyCubeGrid attachedCubeGrid in cubeGrid.GetAttachedGrids(AttachedGrids.Static))
            {
                List <IMySlimBlock> blocks = new List <IMySlimBlock>();
                attachedCubeGrid.GetBlocks(blocks, b => b.FatBlock != null);


                foreach (IMySlimBlock block in blocks)
                {
                    long ownerId = block.FatBlock.OwnerId;

                    // we dont want the new owners, the small owners or the 'nobody' (0)
                    if (ownerId == 0 || !attachedCubeGrid.BigOwners.Contains(ownerId) || newOwners.Contains(ownerId))
                    {
                        continue;
                    }

                    if (!blocksPerOwner.ContainsKey(ownerId))
                    {
                        blocksPerOwner.Add(ownerId, 1);
                    }
                    else
                    {
                        blocksPerOwner[ownerId]++;
                    }
                }
            }

            var sortedBpo = new List <KeyValuePair <long, int> >(blocksPerOwner.OrderBy(pair => pair.Value));

            // if we cannot identify an owner we allow the change
            if (sortedBpo.Count == 0)
            {
                _cachedOwners = new List <long>(allSmallOwners);
                return;
            }

            var bigOwner = sortedBpo[0].Key;

            List <IMySlimBlock> ownershipChangedBlocks = new List <IMySlimBlock>();

            cubeGrid.GetBlocks(ownershipChangedBlocks, b => b.FatBlock != null && newOwners.Contains(b.FatBlock.OwnerId));
            foreach (IMySlimBlock slimBlock in ownershipChangedBlocks)
            {
                var block = (Sandbox.Game.Entities.MyCubeBlock)slimBlock.FatBlock; // TODO check if the block was created/built just moments ago, do not change owner otherwise
                block.ChangeOwner(bigOwner, MyOwnershipShareModeEnum.None);
                ConnectionHelper.SendMessageToAllPlayers(new MessageSyncBlockOwner()
                {
                    OwnerId = bigOwner, EntityId = block.EntityId
                });
                // no need to update the cached owners as we don't want them to change
            }

            // TODO maybe allow the faction to build...
        }
        // TODO: deal with cubes that need to be rotated.
        // LargeBlockBeacon, SmallBlockBeacon, ConveyorTube, ConveyorTubeSmall
        public static bool ScaleShip(IMyCubeGrid shipEntity, MyCubeSize newScale)
        {
            if (shipEntity == null)
                return false;

            if (shipEntity.GridSizeEnum == newScale)
            {
                MyAPIGateway.Utilities.ShowMessage("scaledown", "Ship is already the right scale.");
                return true;
            }

            var grids = shipEntity.GetAttachedGrids();

            var newGrids = new MyObjectBuilder_CubeGrid[grids.Count];

            foreach (var cubeGrid in grids)
            {
                // ejects any player prior to deleting the grid.
                cubeGrid.EjectControllingPlayers();
                cubeGrid.Physics.Enabled = false;
            }

            var tempList = new List<MyObjectBuilder_EntityBase>();
            var gridIndex = 0;
            foreach (var cubeGrid in grids)
            {
                var blocks = new List<Sandbox.ModAPI.IMySlimBlock>();
                cubeGrid.GetBlocks(blocks);

                var gridObjectBuilder = cubeGrid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid;

                gridObjectBuilder.EntityId = 0;
                Regex rgx = new Regex(Regex.Escape(gridObjectBuilder.GridSizeEnum.ToString()));
                var rgxScale = Regex.Escape(newScale.ToString());
                gridObjectBuilder.GridSizeEnum = newScale;
                var removeList = new List<MyObjectBuilder_CubeBlock>();

                foreach (var block in gridObjectBuilder.CubeBlocks)
                {
                    MyCubeBlockDefinition defintion;
                    string newSubType = null;
                    if (newScale == MyCubeSize.Small && LargeToSmall.ContainsKey(block.SubtypeName))
                        newSubType = LargeToSmall[block.SubtypeName];
                    else if (newScale == MyCubeSize.Large && SmallToLarge.ContainsKey(block.SubtypeName))
                        newSubType = SmallToLarge[block.SubtypeName];
                    else
                    {
                        newSubType = rgx.Replace(block.SubtypeName, rgxScale, 1);

                        // Match using the BlockPairName if there is a matching cube.
                        if (MyDefinitionManager.Static.TryGetCubeBlockDefinition(new MyDefinitionId(block.GetType(), block.SubtypeName), out defintion))
                        {
                            var newDef = MyDefinitionManager.Static.GetAllDefinitions().Where(d => d is MyCubeBlockDefinition && ((MyCubeBlockDefinition)d).BlockPairName == defintion.BlockPairName && ((MyCubeBlockDefinition)d).CubeSize == newScale).FirstOrDefault();
                            if (newDef != null)
                                newSubType = newDef.Id.SubtypeName;
                        }
                    }
                    if (MyDefinitionManager.Static.TryGetCubeBlockDefinition(new MyDefinitionId(block.GetType(), newSubType), out defintion) && defintion.CubeSize == newScale)
                    {
                        block.SubtypeName = newSubType;
                        //block.EntityId = 0;
                    }
                    else
                    {
                        removeList.Add(block);
                    }
                }

                foreach (var block in removeList)
                {
                    gridObjectBuilder.CubeBlocks.Remove(block);
                }

                // This will Delete the entity and sync to all.
                // Using this, also works with player ejection in the same Tick.
                cubeGrid.SyncObject.SendCloseRequest();

                var name = cubeGrid.DisplayName;
                MyAPIGateway.Utilities.ShowMessage("ship", "'{0}' resized.", name);

                tempList.Add(gridObjectBuilder);

                gridIndex++;
            }

            // TODO: reposition multiple grids so rotors and pistons re-attach.

            tempList.CreateAndSyncEntities();
            return true;
        }
        private void _cubeGrid_OnBlockOwnershipChanged(IMyCubeGrid cubeGrid)
        {
            // only execute on server instance
            if (ChatCommandLogic.Instance != null && ChatCommandLogic.Instance.ServerCfg == null)
                return;

            if (_firstOwnershipChange)
            {
                _firstOwnershipChange = false;
                _cachedOwners = new List<long>(cubeGrid.GetAllSmallOwners());
                return;
            }

            var allSmallOwners = cubeGrid.GetAllSmallOwners();

            if (_cachedOwners == allSmallOwners)
                return;

            // if the grid wasn't owned or a owner was removed, we dont need to do anything but update the cached owners
            if (_cachedOwners.Count == 0 || _cachedOwners.Count > allSmallOwners.Count)
            {
                _cachedOwners = new List<long>(allSmallOwners);
                return;
            }

            var newOwners = allSmallOwners.Except(_cachedOwners).ToList();

            if (newOwners.Count == 0)
                return;

            if (!ProtectionHandler.IsProtected(cubeGrid))
            {
                _cachedOwners = new List<long>(allSmallOwners);
                return;
            }

            Dictionary<long, int> blocksPerOwner = new Dictionary<long, int>();

            foreach (IMyCubeGrid attachedCubeGrid in cubeGrid.GetAttachedGrids(AttachedGrids.Static))
            {

                List<IMySlimBlock> blocks = new List<IMySlimBlock>();
                attachedCubeGrid.GetBlocks(blocks, b => b.FatBlock != null);

                foreach (IMySlimBlock block in blocks)
                {
                    long ownerId = block.FatBlock.OwnerId;

                    // we dont want the new owners, the small owners or the 'nobody' (0)
                    if (ownerId == 0 || !attachedCubeGrid.BigOwners.Contains(ownerId) || newOwners.Contains(ownerId))
                        continue;

                    if (!blocksPerOwner.ContainsKey(ownerId))
                        blocksPerOwner.Add(ownerId, 1);
                    else
                        blocksPerOwner[ownerId]++;
                }
            }

            var sortedBpo = new List<KeyValuePair<long, int>>(blocksPerOwner.OrderBy(pair => pair.Value));

            // if we cannot identify an owner we allow the change
            if (sortedBpo.Count == 0)
            {
                _cachedOwners = new List<long>(allSmallOwners);
                return;
            }

            var bigOwner = sortedBpo[0].Key;

            List<IMySlimBlock> ownershipChangedBlocks = new List<IMySlimBlock>();
            cubeGrid.GetBlocks(ownershipChangedBlocks, b => b.FatBlock != null && newOwners.Contains(b.FatBlock.OwnerId));
            foreach (IMySlimBlock slimBlock in ownershipChangedBlocks)
            {
                var block = (Sandbox.Game.Entities.MyCubeBlock)slimBlock.FatBlock;
                block.ChangeOwner(bigOwner, MyOwnershipShareModeEnum.None);
                ConnectionHelper.SendMessageToAllPlayers(new MessageSyncBlockOwner() {OwnerId = bigOwner, EntityId = block.EntityId});
                // no need to update the cached owners as we don't want them to change
            }

            // TODO maybe allow the faction to build...
        }