Exemple #1
0
        private void ClientPlaceAt(List <Vector2Ushort> tilePositions, IProtoTile selectedProtoTile, bool isRepeat)
        {
            var terrainHeightMode     = this.settings.SelectedHeightMode.Value;
            var isAllowTileKindChange = this.settings.IsAllowTileKindChange;
            var isAllowTileProtoChangeOnlyOnTheSameHeight = this.settings.IsAllowTileProtoChangeOnlyOnTheSameHeight;
            var isApplyOnlyOnTheSameTileProto             = this.settings.IsApplyOnlyOnTheSameTileProto;

            if (this.settings.IsFillMode)
            {
                if (isRepeat)
                {
                    // fill doesn't support repeat
                    return;
                }

                tilePositions = EditorTileHelper.GatherAllTilePositionsOfTheSameProtoTile(
                    tilePositions[0],
                    onlyOnTheSameHeight: isAllowTileProtoChangeOnlyOnTheSameHeight,
                    ignoreCliffsAndSlopes: false);

                // don't change the tile heights in the fill mode
                terrainHeightMode = TerrainHeightMode.Keep;
            }

            var worldService = Client.World;

            byte       targetHeight = 0;
            IProtoTile targetProto  = null;

            if (isRepeat)
            {
                // use target height from previous iteration
                targetHeight = this.lastTargetHeight;
                targetProto  = this.lastTargetProto;
            }
            else
            {
                if (isApplyOnlyOnTheSameTileProto)
                {
                    targetProto = EditorTileHelper.CalculateMostFrequentTileProto(tilePositions);
                }

                switch (terrainHeightMode)
                {
                case TerrainHeightMode.Keep:
                case TerrainHeightMode.Flatten:
                    // calculate average height for all the tiles
                    targetHeight = EditorTileHelper.CalculateAverageHeight(tilePositions);
                    break;

                case TerrainHeightMode.Increase:
                    targetHeight = byte.MaxValue;
                    goto case TerrainHeightMode.Decrease;

                case TerrainHeightMode.Decrease:
                    // calculate target height
                    foreach (var tilePosition in tilePositions)
                    {
                        var tile = worldService.GetTile(tilePosition);
                        var calculatedNewTileHeight = this.CalculateNewTileHeight(tile, terrainHeightMode);

                        if (terrainHeightMode == TerrainHeightMode.Increase &&
                            calculatedNewTileHeight < targetHeight ||
                            terrainHeightMode == TerrainHeightMode.Decrease &&
                            calculatedNewTileHeight > targetHeight)
                        {
                            targetHeight = calculatedNewTileHeight;
                        }
                    }

                    break;
                }
            }

            this.lastTargetHeight = targetHeight;
            this.lastTargetProto  = targetProto;

            var tilesToModify = new List <TerrainEditingSystem.TileModifyRequest>();

            foreach (var tilePosition in tilePositions)
            {
                var tile = worldService.GetTile(tilePosition);
                var previousProtoTile  = tile.ProtoTile;
                var previousTileHeight = tile.Height;
                var previousIsSlope    = tile.IsSlope;

                var newProtoTile = selectedProtoTile ?? previousProtoTile;
                var newIsSlope   = tile.IsSlope;

                if (isApplyOnlyOnTheSameTileProto &&
                    previousProtoTile != targetProto)
                {
                    continue;
                }

                if (isAllowTileProtoChangeOnlyOnTheSameHeight &&
                    this.lastTargetHeight != previousTileHeight)
                {
                    continue;
                }

                if (!isAllowTileKindChange &&
                    previousProtoTile.Kind != newProtoTile.Kind &&
                    previousProtoTile.Kind != TileKind.Placeholder)
                {
                    continue;
                }

                var newTileHeight = previousTileHeight;
                if (terrainHeightMode == TerrainHeightMode.Flatten)
                {
                    if (IsValidHeightFotTile(tile, targetHeight))
                    {
                        // can set tile height to target height
                        newTileHeight = targetHeight;
                    }
                }
                else if (terrainHeightMode == TerrainHeightMode.Increase ||
                         terrainHeightMode == TerrainHeightMode.Decrease)
                {
                    newTileHeight = this.CalculateNewTileHeight(tile, terrainHeightMode);
                    if (newTileHeight != targetHeight)
                    {
                        // cannot change tile height
                        newTileHeight = previousTileHeight;
                    }
                }

                if (previousProtoTile == newProtoTile &&
                    newTileHeight == previousTileHeight &&
                    newIsSlope == previousIsSlope)
                {
                    // nothing to change - the tile is already as desired
                    continue;
                }

                tilesToModify.Add(new TerrainEditingSystem.TileModifyRequest(
                                      tilePosition,
                                      newProtoTile.SessionIndex,
                                      newTileHeight,
                                      newIsSlope));
            }

            TerrainEditingSystem.ClientModifyTerrain(tilesToModify);
        }
Exemple #2
0
        private void ClientPlaceAt(List <Vector2Ushort> tilePositions, IProtoTile selectedProtoTile, bool isRepeat)
        {
            var terrainHeightMode     = this.settings.SelectedHeightMode.Value;
            var isAllowTileKindChange = this.settings.IsAllowTileKindChange;
            var isAllowTileProtoChangeOnlyOnTheSameHeight = this.settings.IsAllowTileProtoChangeOnlyOnTheSameHeight;
            var isApplyOnlyOnTheSameTileProto             = this.settings.IsApplyOnlyOnTheSameTileProto;

            if (this.settings.IsFillMode)
            {
                if (isRepeat)
                {
                    // fill doesn't support repeat
                    return;
                }

                tilePositions = EditorTileHelper.GatherAllTilePositionsOfTheSameProtoTile(
                    tilePositions[0],
                    onlyOnTheSameHeight: isAllowTileProtoChangeOnlyOnTheSameHeight,
                    ignoreCliffsAndSlopes: false);

                // don't change the tile heights in the fill mode
                terrainHeightMode = TerrainHeightMode.Keep;
            }

            var worldService = Client.World;

            byte       targetHeight = 0;
            IProtoTile targetProto  = null;

            if (isRepeat)
            {
                // use target height from previous iteration
                targetHeight = this.lastTargetHeight;
                targetProto  = this.lastTargetProto;
            }
            else
            {
                if (isApplyOnlyOnTheSameTileProto)
                {
                    targetProto = EditorTileHelper.CalculateMostFrequentTileProto(tilePositions);
                }

                switch (terrainHeightMode)
                {
                case TerrainHeightMode.Keep:
                case TerrainHeightMode.Flatten:
                    // calculate average height for all the tiles
                    targetHeight = EditorTileHelper.CalculateAverageHeight(tilePositions);
                    break;

                case TerrainHeightMode.Increase:
                    targetHeight = byte.MaxValue;
                    goto case TerrainHeightMode.Decrease;

                case TerrainHeightMode.Decrease:
                    // calculate target height
                    foreach (var tilePosition in tilePositions)
                    {
                        var tile = worldService.GetTile(tilePosition);
                        var calculatedNewTileHeight = this.CalculateNewTileHeight(tile, terrainHeightMode);

                        if (terrainHeightMode == TerrainHeightMode.Increase &&
                            calculatedNewTileHeight < targetHeight ||
                            terrainHeightMode == TerrainHeightMode.Decrease &&
                            calculatedNewTileHeight > targetHeight)
                        {
                            targetHeight = calculatedNewTileHeight;
                        }
                    }

                    break;
                }
            }

            this.lastTargetHeight = targetHeight;
            this.lastTargetProto  = targetProto;

            var tilesToModify = new List <List <TileModifyRequest> >();
            var tilesToRevert = new List <List <TileModifyRequest> >();

            // separate on groups of world chunk size
            var worldChunkSize = 10 * ScriptingConstants.WorldChunkSize;
            var groups         = tilePositions
                                 .GroupBy(g => new Vector2Ushort((ushort)(g.X / worldChunkSize),
                                                                 (ushort)(g.Y / worldChunkSize)))
                                 .ToList();

            // gather tile modifications for each group
            foreach (var group in groups)
            {
                var groupTilesToModify = new List <TileModifyRequest>();
                var groupTilesToRevert = new List <TileModifyRequest>();

                foreach (var tilePosition in group)
                {
                    var tile = worldService.GetTile(tilePosition);
                    var previousProtoTile  = tile.ProtoTile;
                    var previousTileHeight = tile.Height;
                    var previousIsSlope    = tile.IsSlope;

                    var newProtoTile = selectedProtoTile ?? previousProtoTile;
                    var newIsSlope   = tile.IsSlope;

                    if (isApplyOnlyOnTheSameTileProto &&
                        previousProtoTile != targetProto)
                    {
                        continue;
                    }

                    if (isAllowTileProtoChangeOnlyOnTheSameHeight &&
                        this.lastTargetHeight != previousTileHeight)
                    {
                        continue;
                    }

                    if (!isAllowTileKindChange &&
                        previousProtoTile.Kind != newProtoTile.Kind &&
                        previousProtoTile.Kind != TileKind.Placeholder)
                    {
                        continue;
                    }

                    var newTileHeight = previousTileHeight;
                    if (terrainHeightMode == TerrainHeightMode.Flatten)
                    {
                        if (IsValidHeightFotTile(tile, targetHeight))
                        {
                            // can set tile height to target height
                            newTileHeight = targetHeight;
                        }
                    }
                    else if (terrainHeightMode == TerrainHeightMode.Increase ||
                             terrainHeightMode == TerrainHeightMode.Decrease)
                    {
                        newTileHeight = this.CalculateNewTileHeight(tile, terrainHeightMode);
                        if (newTileHeight != targetHeight)
                        {
                            // cannot change tile height
                            newTileHeight = previousTileHeight;
                        }
                    }

                    if (previousProtoTile == newProtoTile &&
                        newTileHeight == previousTileHeight &&
                        newIsSlope == previousIsSlope)
                    {
                        // nothing to change - the tile is already as desired
                        continue;
                    }

                    groupTilesToModify.Add(new TileModifyRequest(tilePosition,
                                                                 newProtoTile.SessionIndex,
                                                                 newTileHeight,
                                                                 newIsSlope));
                    groupTilesToRevert.Add(new TileModifyRequest(tilePosition,
                                                                 previousProtoTile.SessionIndex,
                                                                 previousTileHeight,
                                                                 previousIsSlope));
                }

                if (groupTilesToModify.Count == 0)
                {
                    // nothing to modify in this group
                    continue;
                }

                tilesToModify.Add(groupTilesToModify);
                tilesToRevert.Add(groupTilesToRevert);
            }

            if (tilesToModify.Count == 0)
            {
                // nothing to modify
                return;
            }

            EditorClientSystem.DoAction(
                "Modify terrain tiles",
                onDo: () => tilesToModify.ForEach(
                    chunk => this.CallServer(_ => _.ServerRemote_PlaceAt(chunk))),
                onUndo: () => tilesToRevert.ForEach(
                    chunk => this.CallServer(_ => _.ServerRemote_PlaceAt(chunk))));
        }
Exemple #3
0
        private void ClientOnPaintZone(List <Vector2Ushort> tilePositions, bool isRepeat)
        {
            var selectedZoneForBrush = this.settings.SelectedZoneForBrush;

            if (selectedZoneForBrush is null ||
                !selectedZoneForBrush.IsRendered)
            {
                // no zone selected for brush or zone is not visible
                return;
            }

            var protoZone    = selectedZoneForBrush.Zone;
            var zoneProvider = ClientZoneProvider.Get(protoZone);

            if (!zoneProvider.IsDataReceived)
            {
                return;
            }

            var world = Client.World;
            var onlyOnTheSameHeight = this.settings.IsAllowZoneChangeOnlyOnTheSameHeight;

            if (this.settings.IsFillZoneMode)
            {
                if (isRepeat)
                {
                    // fill doesn't support repeat
                    return;
                }

                tilePositions = EditorTileHelper.GatherAllTilePositionsOfTheSameProtoTile(
                    tilePositions[0],
                    onlyOnTheSameHeight,
                    ignoreCliffsAndSlopes: true);
            }

            this.lastUsedZoneProvider = zoneProvider;

            if (onlyOnTheSameHeight &&
                !isRepeat)
            {
                // capture height when starting painting the zone
                this.capturedHeight = this.settings.IsFillZoneMode
                                          ? world.GetTile(tilePositions[0]).Height
                                          : EditorTileHelper.CalculateAverageHeight(tilePositions);
            }

            var onlyOnTheSameTileProto = this.settings.IsAllowZoneChangeOnlyOnTheSameTileProto;

            if (onlyOnTheSameTileProto &&
                !isRepeat)
            {
                // capture tile proto when starting painting the zone
                this.capturedTileProto = this.settings.IsFillZoneMode
                                             ? world.GetTile(tilePositions[0]).ProtoTile
                                             : EditorTileHelper.CalculateMostFrequentTileProto(tilePositions);
            }

            // determine the mode - adding points to zone or removing them
            var isAddMode = ClientInputManager.IsButtonHeld(GameButton.ActionUseCurrentItem, evenIfHandled: true) ||
                            ClientInputManager.IsButtonUp(GameButton.ActionUseCurrentItem, evenIfHandled: true);

            if (isAddMode)
            {
                // remove points which are already added to the zone
                tilePositions.RemoveAll(tilePosition => zoneProvider.IsFilledPosition(tilePosition));
            }
            else
            {
                // remove points which are not presented in the zone
                tilePositions.RemoveAll(tilePosition => !zoneProvider.IsFilledPosition(tilePosition));
            }

            if (tilePositions.Count == 0)
            {
                // nothing to add/remove
                return;
            }

            if (onlyOnTheSameHeight)
            {
                // remove tiles with different height
                tilePositions.RemoveAll(
                    tilePosition =>
                {
                    var tile = world.GetTile(tilePosition);
                    return(tile.Height != this.capturedHeight
                           // also do not allow painting on cliffs and slopes
                           || tile.IsCliff ||
                           tile.IsSlope);
                });
                if (tilePositions.Count == 0)
                {
                    // nothing to add/remove
                    return;
                }
            }

            if (onlyOnTheSameTileProto)
            {
                // remove tiles with different proto
                var worldService = Client.World;
                tilePositions.RemoveAll(
                    tilePosition => worldService.GetTile(tilePosition).ProtoTile
                    != this.capturedTileProto);

                if (tilePositions.Count == 0)
                {
                    // nothing to add/remove
                    return;
                }
            }

            foreach (var tilePosition in tilePositions)
            {
                if (isAddMode)
                {
                    // add point to the zone
                    zoneProvider.SetFilledPosition(tilePosition);
                }
                else
                {
                    // remove point from the zone
                    zoneProvider.ResetFilledPosition(tilePosition);
                }
            }

            this.lastUsedZoneProvider.ApplyClientChanges(forcePushChangesImmediately: tilePositions.Count > 10000);
        }