private static void CollectLabelExclusionBoundsForBlueprint(
            RectangleInt originBounds,
            List <RectangleInt> result)
        {
            foreach (var landClaim in
                     Api.Client.World.GetStaticWorldObjectsOfProto <IProtoObjectLandClaim>())
            {
                var protoObjectLandClaim    = (IProtoObjectLandClaim)landClaim.ProtoGameObject;
                var landClaimCenterPosition = LandClaimSystem
                                              .SharedCalculateLandClaimObjectCenterTilePosition(
                    landClaim.TilePosition,
                    protoObjectLandClaim);

                var landClaimBounds = LandClaimSystem.SharedCalculateLandClaimAreaBounds(
                    landClaimCenterPosition,
                    protoObjectLandClaim.LandClaimWithGraceAreaSize);

                var intersectionDepth = CalculateIntersectionDepth(originBounds, landClaimBounds);
                if (intersectionDepth < 0)
                {
                    // no intersection
                    continue;
                }

                intersectionDepth = (intersectionDepth + 1) / 2;
                intersectionDepth = Math.Min(intersectionDepth,
                                             protoObjectLandClaim.LandClaimGraceAreaPaddingSizeOneDirection + 1);

                var deflated = landClaimBounds.Inflate(-intersectionDepth);
                result.Add(deflated);
            }
        }
Example #2
0
        public override void ClientSetupBlueprint(Tile tile, IClientBlueprint blueprint)
        {
            base.ClientSetupBlueprint(tile, blueprint);

            if (!ConstructionPlacementSystem.IsObjectPlacementComponentEnabled)
            {
                return;
            }

            // display area only when player placing a blueprint
            var areaSprite = Api.Client.Rendering.CreateSpriteRenderer(
                blueprint.SceneObject,
                null,
                DrawOrder.Overlay);

            ClientBlueprintAreaRenderingMaterial.EffectParameters.Set(
                "Color",
                blueprint.IsCanBuild
                    ? ColorGreen
                    : ColorRed);

            areaSprite.RenderingMaterial           = ClientBlueprintAreaRenderingMaterial;
            areaSprite.SortByWorldPosition         = false;
            areaSprite.IgnoreTextureQualityScaling = true;
            areaSprite.Scale = this.LandClaimSize;

            var offset = LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(Vector2Ushort.Zero, this);

            areaSprite.PositionOffset = (offset.X - this.LandClaimSize / 2,
                                         offset.Y - this.LandClaimSize / 2);
        }
Example #3
0
        public void SetupAreaProperties(LandClaimAreaPrivateState privateState)
        {
            var structure            = privateState.ServerLandClaimWorldObject;
            var protoObjectLandClaim = (IProtoObjectLandClaim)structure.ProtoStaticWorldObject;

            var tilePosition = LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(structure);

            this.LandClaimCenterTilePosition = tilePosition;
            this.LandClaimTier = protoObjectLandClaim.LandClaimTier;
        }
        private static void SetupBoundsForLandClaimsInScope(
            IClientSceneObject sceneObject,
            Vector2D sceneObjectPosition,
            Vector2Ushort originTilePosition,
            RectangleInt originBounds,
            IProtoObjectLandClaim originProtoObjectLandClaim)
        {
            var landClaims = Api.Client.World.GetStaticWorldObjectsOfProto <IProtoObjectLandClaim>();

            foreach (var landClaim in landClaims)
            {
                var protoObjectLandClaim    = (IProtoObjectLandClaim)landClaim.ProtoGameObject;
                var landClaimCenterPosition = LandClaimSystem
                                              .SharedCalculateLandClaimObjectCenterTilePosition(
                    landClaim.TilePosition,
                    protoObjectLandClaim);

                var landClaimBounds = LandClaimSystem.SharedCalculateLandClaimAreaBounds(
                    landClaimCenterPosition,
                    protoObjectLandClaim.LandClaimWithGraceAreaSize);

                var intersectionDepth = CalculateIntersectionDepth(originBounds, landClaimBounds);
                if (intersectionDepth < 0)
                {
                    // no intersection
                    continue;
                }

                intersectionDepth = (intersectionDepth + 1) / 2;
                intersectionDepth = Math.Min(intersectionDepth,
                                             originProtoObjectLandClaim.LandClaimGraceAreaPaddingSizeOneDirection + 1);

                var exceptBounds = originBounds.Inflate(-intersectionDepth);
                using var tempList = Api.Shared.WrapObjectInTempList(exceptBounds);

                AddBoundLabels(sceneObject,
                               sceneObjectPosition,
                               exceptBounds: tempList.AsList(),
                               protoObjectLandClaim,
                               positionOffset: landClaimCenterPosition.ToVector2D()
                               - originTilePosition.ToVector2D());
            }
        }
Example #5
0
        public ObjectLandClaimCanUpgradeCheckResult SharedCanUpgrade(
            IStaticWorldObject worldObjectLandClaim,
            IProtoObjectLandClaim protoUpgradedLandClaim,
            ICharacter character,
            out IConstructionUpgradeEntryReadOnly upgradeEntry,
            bool writeErrors = true)
        {
            if (!this.SharedCanInteract(character,
                                        worldObjectLandClaim,
                                        writeToLog: writeErrors))
            {
                upgradeEntry = null;
                return(ObjectLandClaimCanUpgradeCheckResult.ErrorUnknown);
            }

            upgradeEntry = null;
            foreach (var entry in this.ConfigUpgrade.Entries)
            {
                if (entry.ProtoStructure == protoUpgradedLandClaim)
                {
                    upgradeEntry = entry;
                    break;
                }
            }

            var currentLandClaimArea = GetPublicState(worldObjectLandClaim).LandClaimAreaObject;
            var founderName          = LandClaimArea.GetPrivateState(currentLandClaimArea).LandClaimFounder;

            var result = ObjectLandClaimCanUpgradeCheckResult.Success;

            if (upgradeEntry == null)
            {
                result = ObjectLandClaimCanUpgradeCheckResult.ErrorUnknown;
            }

            if (result == ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                if (character.Name != founderName &&
                    !CreativeModeSystem.SharedIsInCreativeMode(character))
                {
                    result = ObjectLandClaimCanUpgradeCheckResult.ErrorNotFounder;
                }
            }

            if (result == ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                // validate player know the tech, have enough items, etc
                if (!upgradeEntry.CheckRequirementsSatisfied(character))
                {
                    upgradeEntry = null;
                    result       = ObjectLandClaimCanUpgradeCheckResult.ErrorRequirementsNotSatisfied;
                }
            }

            if (result == ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                // check there will be no intersection with other areas
                var landClaimCenterTilePosition =
                    LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(worldObjectLandClaim);
                if (!LandClaimSystem.SharedCheckCanPlaceOrUpgradeLandClaimThere(
                        protoUpgradedLandClaim,
                        landClaimCenterTilePosition,
                        character))
                {
                    result = ObjectLandClaimCanUpgradeCheckResult.ErrorAreaIntersection;
                }
            }

            if (result == ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                if (!InteractionCheckerSystem.SharedHasInteraction(character,
                                                                   worldObjectLandClaim,
                                                                   requirePrivateScope: true))
                {
                    result = ObjectLandClaimCanUpgradeCheckResult.ErrorNoActiveInteraction;
                }
            }

            if (result == ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                if (LandClaimSystem.SharedIsUnderRaidBlock(character, worldObjectLandClaim))
                {
                    // the building is in an area under the raid
                    LandClaimSystem.SharedSendNotificationActionForbiddenUnderRaidblock(character);
                    result = ObjectLandClaimCanUpgradeCheckResult.ErrorUnderRaid;
                }
            }

            if (writeErrors &&
                result != ObjectLandClaimCanUpgradeCheckResult.Success)
            {
                Logger.Warning(
                    $"Can\'t upgrade: {worldObjectLandClaim} to {protoUpgradedLandClaim}: error code - {result}",
                    character);
            }

            return(result);
        }
Example #6
0
        public override void ClientSetupBlueprint(Tile tile, IClientBlueprint blueprint)
        {
            base.ClientSetupBlueprint(tile, blueprint);

            if (!ConstructionPlacementSystem.IsObjectPlacementComponentEnabled)
            {
                return;
            }

            // display area only when player placing a blueprint
            Color color;
            var   sizeWithGraceArea = this.LandClaimWithGraceAreaSize;

            if (blueprint.IsCanBuild)
            {
                color = BlueprintAreaColorGreen;
                ClientBlueprintAreaRenderingMaterial.EffectParameters.Set("Color", color);
                CreateBlueprintAreaRenderer(ClientBlueprintAreaRenderingMaterial, this.LandClaimSize);
                CreateBlueprintAreaRenderer(ClientBlueprintGraceAreaRenderingMaterial, sizeWithGraceArea);

                // can build a land claim area, but highlight the restricted tiles
                var world             = Client.World;
                var startTilePosition = tile.Position;
                var halfSize          = sizeWithGraceArea / 2;
                for (var x = 1 - halfSize; x <= halfSize; x++)
                {
                    for (var y = 1 - halfSize; y <= halfSize; y++)
                    {
                        var checkTile = world.GetTile(startTilePosition.X + x,
                                                      startTilePosition.Y + y,
                                                      logOutOfBounds: false);
                        ProcessFutureLandClaimAreaTile(checkTile, x, y);
                    }
                }
            }
            else // cannot build a land claim there
            {
                color = BlueprintAreaColorRed;
                ClientBlueprintAreaRenderingMaterial.EffectParameters.Set("Color", color);
                CreateBlueprintAreaRenderer(ClientBlueprintAreaRenderingMaterial,
                                            size: sizeWithGraceArea);
            }

            void CreateBlueprintAreaRenderer(RenderingMaterial renderingMaterial, int size)
            {
                var offset        = LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(Vector2Ushort.Zero, this);
                var areaBlueprint = Api.Client.Rendering.CreateSpriteRenderer(
                    blueprint.SceneObject,
                    null,
                    DrawOrder.Overlay);

                areaBlueprint.RenderingMaterial           = renderingMaterial;
                areaBlueprint.SortByWorldPosition         = false;
                areaBlueprint.IgnoreTextureQualityScaling = true;
                areaBlueprint.Scale = size;

                areaBlueprint.PositionOffset = (offset.X - size / 2,
                                                offset.Y - size / 2);
            }

            void ProcessFutureLandClaimAreaTile(Tile checkTile, int offsetX, int offsetY)
            {
                if (!checkTile.IsValidTile)
                {
                    return;
                }

                var isRestrictedTile = IsRestrictedTile(checkTile);

                if (!isRestrictedTile)
                {
                    foreach (var neighborTile in checkTile.EightNeighborTiles)
                    {
                        if (IsRestrictedTile(neighborTile))
                        {
                            isRestrictedTile = true;
                            break;
                        }
                    }
                }

                if (!isRestrictedTile)
                {
                    return;
                }

                // display red tile as player cannot construct there
                var tileRenderer = Api.Client.Rendering.CreateSpriteRenderer(
                    blueprint.SceneObject,
                    ClientLandClaimGroupRenderer.TextureResourceLandClaimAreaCell,
                    DrawOrder.Overlay);

                tileRenderer.RenderingMaterial           = ClientBlueprintRestrictedTileRenderingMaterial;
                tileRenderer.SortByWorldPosition         = false;
                tileRenderer.IgnoreTextureQualityScaling = true;
                tileRenderer.Scale          = 1;
                tileRenderer.PositionOffset = (offsetX, offsetY);
            }

            bool IsRestrictedTile(Tile t)
            => t.IsCliffOrSlope ||
            t.ProtoTile.Kind != TileKind.Solid ||
            t.ProtoTile.IsRestrictingConstruction;
        }
        public static void SetupBlueprint(
            Tile tile,
            IClientBlueprint blueprint,
            IProtoObjectLandClaim protoObjectLandClaim)
        {
            if (!blueprint.IsEnabled)
            {
                return;
            }

            var sceneObject       = blueprint.SceneObject;
            var world             = Api.Client.World;
            var rendering         = Api.Client.Rendering;
            var character         = ClientCurrentCharacterHelper.Character;
            var startTilePosition = LandClaimSystem.SharedCalculateLandClaimObjectCenterTilePosition(
                tile.Position,
                protoObjectLandClaim);
            var sizeWithGraceArea   = protoObjectLandClaim.LandClaimWithGraceAreaSize;
            var blueprintAreaBounds = LandClaimSystem.SharedCalculateLandClaimAreaBounds(startTilePosition,
                                                                                         sizeWithGraceArea);

            SetupBoundsForLandClaimsInScope(sceneObject,
                                            sceneObjectPosition: tile.Position.ToVector2D(),
                                            startTilePosition,
                                            blueprintAreaBounds,
                                            protoObjectLandClaim);

            using var tempListExceptBounds = Api.Shared.GetTempList <RectangleInt>();
            CollectLabelExclusionBoundsForBlueprint(blueprintAreaBounds, tempListExceptBounds.AsList());

            ClientLandClaimAreaManager.AddBlueprintRenderer(startTilePosition,
                                                            protoObjectLandClaim);

            // additionally highlight the restricted tiles
            var halfSize = sizeWithGraceArea / 2;

            for (var x = 1 - halfSize; x <= halfSize; x++)
            {
                for (var y = 1 - halfSize; y <= halfSize; y++)
                {
                    var checkTile = world.GetTile(startTilePosition.X + x,
                                                  startTilePosition.Y + y,
                                                  logOutOfBounds: false);
                    ProcessFutureLandClaimAreaTile(checkTile, x, y);
                }
            }

            AddBoundSquares(sceneObject,
                            protoObjectLandClaim,
                            positionOffset: (0, 0));
            AddBoundLabels(sceneObject,
                           sceneObjectPosition: tile.Position.ToVector2D(),
                           exceptBounds: tempListExceptBounds.AsList(),
                           protoObjectLandClaim,
                           positionOffset: (0, 0));

            void ProcessFutureLandClaimAreaTile(Tile checkTile, int offsetX, int offsetY)
            {
                if (!checkTile.IsValidTile)
                {
                    return;
                }

                var isRestrictedTile = IsRestrictedTile(checkTile);

                if (!isRestrictedTile)
                {
                    foreach (var neighborTile in checkTile.EightNeighborTiles)
                    {
                        if (IsRestrictedTile(neighborTile))
                        {
                            isRestrictedTile = true;
                            break;
                        }
                    }
                }

                if (!isRestrictedTile)
                {
                    return;
                }

                // display red tile as player cannot construct there
                var tileRenderer = rendering.CreateSpriteRenderer(
                    sceneObject,
                    ClientLandClaimGroupRenderer.TextureResourceLandClaimAreaCell,
                    DrawOrder.Overlay);

                tileRenderer.RenderingMaterial   = ClientBlueprintRestrictedTileRenderingMaterial;
                tileRenderer.SortByWorldPosition = false;
                tileRenderer.Scale          = 1;
                tileRenderer.PositionOffset = (offsetX + 1, offsetY + 1);
            }

            bool IsRestrictedTile(Tile t)
            => t.IsCliffOrSlope ||
            t.ProtoTile.Kind != TileKind.Solid ||
            t.ProtoTile.IsRestrictingConstruction ||
            !LandClaimSystem.SharedIsPositionInsideOwnedOrFreeArea(
                t.Position,
                character,
                addGracePaddingWithoutBuffer: true);
        }