public async Task GrantsAndRevokesItemActions()
        {
            var serverOptions = new ServerIntegrationOptions {
                ExtraPrototypes = PROTOTYPES
            };
            var clientOptions = new ClientIntegrationOptions {
                ExtraPrototypes = PROTOTYPES
            };

            var(client, server) = await StartConnectedServerClientPair(serverOptions : serverOptions, clientOptions : clientOptions);

            await server.WaitIdleAsync();

            await client.WaitIdleAsync();

            var serverPlayerManager = server.ResolveDependency <Robust.Server.Interfaces.Player.IPlayerManager>();
            var serverEntManager    = server.ResolveDependency <IEntityManager>();
            var serverGameTiming    = server.ResolveDependency <IGameTiming>();

            var cooldown = Cooldowns.SecondsFromNow(30, serverGameTiming);

            ServerActionsComponent serverActionsComponent = null;
            ClientActionsComponent clientActionsComponent = null;
            IEntity serverPlayerEnt  = null;
            IEntity serverFlashlight = null;

            await server.WaitAssertion(() =>
            {
                serverPlayerEnt        = serverPlayerManager.GetAllPlayers().Single().AttachedEntity;
                serverActionsComponent = serverPlayerEnt.GetComponent <ServerActionsComponent>();

                // spawn and give them an item that has actions
                serverFlashlight = serverEntManager.SpawnEntity("TestFlashlight",
                                                                new EntityCoordinates(new EntityUid(1), (0, 0)));
                Assert.That(serverFlashlight.TryGetComponent <ItemActionsComponent>(out var itemActions));
                // we expect this only to have a toggle light action initially
                var actionConfigs = itemActions.ActionConfigs.ToList();
                Assert.That(actionConfigs.Count == 1);
                Assert.That(actionConfigs[0].ActionType == ItemActionType.ToggleLight);
                Assert.That(actionConfigs[0].Enabled);

                // grant an extra item action, before pickup, initially disabled
                itemActions.GrantOrUpdate(ItemActionType.DebugToggle, false);
                serverPlayerEnt.GetComponent <HandsComponent>().PutInHand(serverFlashlight.GetComponent <ItemComponent>(), false);
                // grant an extra item action, after pickup, with a cooldown
                itemActions.GrantOrUpdate(ItemActionType.DebugInstant, cooldown: cooldown);

                Assert.That(serverActionsComponent.TryGetItemActionStates(serverFlashlight.Uid, out var state));
                // they should have been granted all 3 actions
                Assert.That(state.Count == 3);
                Assert.That(state.TryGetValue(ItemActionType.ToggleLight, out var toggleLightState));
                Assert.That(toggleLightState.Equals(new ActionState(true)));
                Assert.That(state.TryGetValue(ItemActionType.DebugInstant, out var debugInstantState));
                Assert.That(debugInstantState.Equals(new ActionState(true, cooldown: cooldown)));
                Assert.That(state.TryGetValue(ItemActionType.DebugToggle, out var debugToggleState));
                Assert.That(debugToggleState.Equals(new ActionState(false)));
            });

            await server.WaitRunTicks(5);

            await client.WaitRunTicks(5);

            // check that client has the actions, and toggle the light on via the action slot it was auto-assigned to
            var       clientPlayerMgr  = client.ResolveDependency <IPlayerManager>();
            var       clientUIMgr      = client.ResolveDependency <IUserInterfaceManager>();
            var       clientEntMgr     = client.ResolveDependency <IEntityManager>();
            EntityUid clientFlashlight = default;
            await client.WaitAssertion(() =>
            {
                var local              = clientPlayerMgr.LocalPlayer;
                var controlled         = local.ControlledEntity;
                clientActionsComponent = controlled.GetComponent <ClientActionsComponent>();

                var lightEntry = clientActionsComponent.ItemActionStates()
                                 .Where(entry => entry.Value.ContainsKey(ItemActionType.ToggleLight))
                                 .FirstOrNull();
                clientFlashlight = lightEntry.Value.Key;
                Assert.That(lightEntry, Is.Not.Null);
                Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.ToggleLight, out var lightState));
                Assert.That(lightState.Equals(new ActionState(true)));
                Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.DebugInstant, out var debugInstantState));
                Assert.That(debugInstantState.Equals(new ActionState(true, cooldown: cooldown)));
                Assert.That(lightEntry.Value.Value.TryGetValue(ItemActionType.DebugToggle, out var debugToggleState));
                Assert.That(debugToggleState.Equals(new ActionState(false)));

                var actionsUI = clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is ActionsUI) as ActionsUI;
                Assert.That(actionsUI, Is.Not.Null);

                var toggleLightSlot = actionsUI.Slots.FirstOrDefault(slot => slot.Action is ItemActionPrototype
                {
                    ActionType: ItemActionType.ToggleLight
                });
                Assert.That(toggleLightSlot, Is.Not.Null);

                clientActionsComponent.AttemptAction(toggleLightSlot);
            });
예제 #2
0
        public ActionMenu(ClientActionsComponent actionsComponent, ActionsUI actionsUI)
        {
            _actionsComponent = actionsComponent;
            _actionsUI        = actionsUI;
            _actionManager    = IoCManager.Resolve <ActionManager>();
            _gameHud          = IoCManager.Resolve <IGameHud>();

            Title             = Loc.GetString("Actions");
            CustomMinimumSize = (300, 300);

            Contents.AddChild(new VBoxContainer
            {
                Children =
                {
                    new HBoxContainer
                    {
                        Children =
                        {
                            (_searchBar             = new LineEdit
                            {
                                StyleClasses        ={ StyleNano.StyleClassActionSearchBox                    },
                                SizeFlagsHorizontal = SizeFlags.FillExpand,
                                PlaceHolder         = Loc.GetString("Search")
                            }),
                            (_filterButton          = new MultiselectOptionButton <string>()
                            {
                                Label               = Loc.GetString("Filter")
                            }),
                        }
                    },
                    (_clearButton = new Button
                    {
                        Text = Loc.GetString("Clear"),
                    }),
                    (_filterLabel = new Label()),
                    new ScrollContainer
                    {
                        //TODO: needed? CustomMinimumSize = new Vector2(200.0f, 0.0f),
                        SizeFlagsVertical   = SizeFlags.FillExpand,
                        SizeFlagsHorizontal = SizeFlags.FillExpand,
                        Children            =
                        {
                            (_resultsGrid = new GridContainer
                            {
                                MaxWidth  = 300
                            })
                        }
                    }
                }
            });

            // populate filters from search tags
            var filterTags = new List <string>();

            foreach (var action in _actionManager.EnumerateActions())
            {
                filterTags.AddRange(action.Filters);
            }

            // special one to filter to only include item actions
            filterTags.Add(ItemTag);
            filterTags.Add(NotItemTag);
            filterTags.Add(InstantActionTag);
            filterTags.Add(ToggleActionTag);
            filterTags.Add(TargetActionTag);
            filterTags.Add(AllActionsTag);
            filterTags.Add(GrantedActionsTag);

            foreach (var tag in filterTags.Distinct().OrderBy(tag => tag))
            {
                _filterButton.AddItem(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(tag), tag);
            }

            UpdateFilterLabel();

            _dragShadow = new TextureRect
            {
                CustomMinimumSize = (64, 64),
                Stretch           = TextureRect.StretchMode.Scale,
                Visible           = false
            };
            UserInterfaceManager.PopupRoot.AddChild(_dragShadow);
            LayoutContainer.SetSize(_dragShadow, (64, 64));

            _dragDropHelper = new DragDropHelper <ActionMenuItem>(OnBeginActionDrag, OnContinueActionDrag, OnEndActionDrag);
        }
예제 #3
0
        public ActionsUI(ClientActionsComponent actionsComponent)
        {
            _actionsComponent = actionsComponent;
            _actionManager    = IoCManager.Resolve <ActionManager>();
            _entityManager    = IoCManager.Resolve <IEntityManager>();
            _gameTiming       = IoCManager.Resolve <IGameTiming>();
            _gameHud          = IoCManager.Resolve <IGameHud>();
            _menu             = new ActionMenu(_actionsComponent, this);

            LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.End);
            LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.End);
            LayoutContainer.SetAnchorTop(this, 0f);
            LayoutContainer.SetAnchorBottom(this, 0.8f);
            LayoutContainer.SetMarginLeft(this, 13);
            LayoutContainer.SetMarginTop(this, 110);

            SizeFlagsHorizontal = SizeFlags.None;
            SizeFlagsVertical   = SizeFlags.FillExpand;

            var resourceCache = IoCManager.Resolve <IResourceCache>();

            // everything needs to go within an inner panel container so the panel resizes to fit the elements.
            // Because ActionsUI is being anchored by layoutcontainer, the hotbar backing would appear too tall
            // if ActionsUI was the panel container

            var panelContainer = new PanelContainer()
            {
                StyleClasses        = { StyleNano.StyleClassHotbarPanel },
                SizeFlagsHorizontal = SizeFlags.None,
                SizeFlagsVertical   = SizeFlags.None
            };

            AddChild(panelContainer);

            var hotbarContainer = new VBoxContainer
            {
                SeparationOverride  = 3,
                SizeFlagsHorizontal = SizeFlags.None
            };

            panelContainer.AddChild(hotbarContainer);

            var settingsContainer = new HBoxContainer
            {
                SizeFlagsHorizontal = SizeFlags.FillExpand
            };

            hotbarContainer.AddChild(settingsContainer);

            settingsContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1
            });
            _lockTexture   = resourceCache.GetTexture("/Textures/Interface/Nano/lock.svg.192dpi.png");
            _unlockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock_open.svg.192dpi.png");
            _lockButton    = new TextureButton
            {
                TextureNormal         = _unlockTexture,
                SizeFlagsHorizontal   = SizeFlags.ShrinkCenter,
                SizeFlagsVertical     = SizeFlags.ShrinkCenter,
                SizeFlagsStretchRatio = 1,
                Scale = (0.5f, 0.5f)
            };
            settingsContainer.AddChild(_lockButton);
            settingsContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2
            });
            _settingsButton = new TextureButton
            {
                TextureNormal         = resourceCache.GetTexture("/Textures/Interface/Nano/gear.svg.192dpi.png"),
                SizeFlagsHorizontal   = SizeFlags.ShrinkCenter,
                SizeFlagsVertical     = SizeFlags.ShrinkCenter,
                SizeFlagsStretchRatio = 1,
                Scale = (0.5f, 0.5f)
            };
            settingsContainer.AddChild(_settingsButton);
            settingsContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1
            });

            // this allows a 2 column layout if window gets too small
            _slotContainer = new GridContainer
            {
                MaxHeight = CalcMaxHeight()
            };
            hotbarContainer.AddChild(_slotContainer);

            _loadoutContainer = new HBoxContainer
            {
                SizeFlagsHorizontal = SizeFlags.FillExpand,
                MouseFilter         = MouseFilterMode.Stop
            };
            hotbarContainer.AddChild(_loadoutContainer);

            _loadoutContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1
            });
            var previousHotbarIcon = new TextureRect()
            {
                Texture               = resourceCache.GetTexture("/Textures/Interface/Nano/left_arrow.svg.192dpi.png"),
                SizeFlagsHorizontal   = SizeFlags.ShrinkCenter,
                SizeFlagsVertical     = SizeFlags.ShrinkCenter,
                SizeFlagsStretchRatio = 1,
                TextureScale          = (0.5f, 0.5f)
            };

            _loadoutContainer.AddChild(previousHotbarIcon);
            _loadoutContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2
            });
            _loadoutNumber = new Label
            {
                Text = "1",
                SizeFlagsStretchRatio = 1
            };
            _loadoutContainer.AddChild(_loadoutNumber);
            _loadoutContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2
            });
            var nextHotbarIcon = new TextureRect
            {
                Texture               = resourceCache.GetTexture("/Textures/Interface/Nano/right_arrow.svg.192dpi.png"),
                SizeFlagsHorizontal   = SizeFlags.ShrinkCenter,
                SizeFlagsVertical     = SizeFlags.ShrinkCenter,
                SizeFlagsStretchRatio = 1,
                TextureScale          = (0.5f, 0.5f)
            };

            _loadoutContainer.AddChild(nextHotbarIcon);
            _loadoutContainer.AddChild(new Control {
                SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1
            });

            _slots = new ActionSlot[ClientActionsComponent.Slots];

            _dragShadow = new TextureRect
            {
                CustomMinimumSize = (64, 64),
                Stretch           = TextureRect.StretchMode.Scale,
                Visible           = false
            };
            UserInterfaceManager.PopupRoot.AddChild(_dragShadow);
            LayoutContainer.SetSize(_dragShadow, (64, 64));

            for (byte i = 0; i < ClientActionsComponent.Slots; i++)
            {
                var slot = new ActionSlot(this, _menu, actionsComponent, i);
                _slotContainer.AddChild(slot);
                _slots[i] = slot;
            }

            DragDropHelper = new DragDropHelper <ActionSlot>(OnBeginActionDrag, OnContinueActionDrag, OnEndActionDrag);
        }
예제 #4
0
        public ActionsUI(ClientActionsComponent actionsComponent)
        {
            SetValue(LayoutContainer.DebugProperty, true);
            _actionsComponent = actionsComponent;
            _actionManager    = IoCManager.Resolve <ActionManager>();
            _entityManager    = IoCManager.Resolve <IEntityManager>();
            _gameTiming       = IoCManager.Resolve <IGameTiming>();
            _gameHud          = IoCManager.Resolve <IGameHud>();
            _menu             = new ActionMenu(_actionsComponent, this);

            LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.End);
            LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.Constrain);
            LayoutContainer.SetAnchorTop(this, 0f);
            LayoutContainer.SetAnchorBottom(this, 0.8f);
            LayoutContainer.SetMarginLeft(this, 13);
            LayoutContainer.SetMarginTop(this, 110);

            HorizontalAlignment = HAlignment.Left;
            VerticalExpand      = true;

            var resourceCache = IoCManager.Resolve <IResourceCache>();

            // everything needs to go within an inner panel container so the panel resizes to fit the elements.
            // Because ActionsUI is being anchored by layoutcontainer, the hotbar backing would appear too tall
            // if ActionsUI was the panel container

            var panelContainer = new PanelContainer()
            {
                StyleClasses        = { StyleNano.StyleClassHotbarPanel },
                HorizontalAlignment = HAlignment.Left,
                VerticalAlignment   = VAlignment.Top
            };

            AddChild(panelContainer);

            var hotbarContainer = new BoxContainer
            {
                Orientation         = LayoutOrientation.Vertical,
                SeparationOverride  = 3,
                HorizontalAlignment = HAlignment.Left
            };

            panelContainer.AddChild(hotbarContainer);

            var settingsContainer = new BoxContainer
            {
                Orientation      = LayoutOrientation.Horizontal,
                HorizontalExpand = true
            };

            hotbarContainer.AddChild(settingsContainer);

            settingsContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 1
            });
            _lockTexture   = resourceCache.GetTexture("/Textures/Interface/Nano/lock.svg.192dpi.png");
            _unlockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock_open.svg.192dpi.png");
            _lockButton    = new TextureButton
            {
                TextureNormal         = _unlockTexture,
                HorizontalAlignment   = HAlignment.Center,
                VerticalAlignment     = VAlignment.Center,
                SizeFlagsStretchRatio = 1,
                Scale        = (0.5f, 0.5f),
                ToolTip      = Loc.GetString("ui-actionsui-function-lock-action-slots"),
                TooltipDelay = CustomTooltipDelay
            };
            settingsContainer.AddChild(_lockButton);
            settingsContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 2
            });
            _settingsButton = new TextureButton
            {
                TextureNormal         = resourceCache.GetTexture("/Textures/Interface/Nano/gear.svg.192dpi.png"),
                HorizontalAlignment   = HAlignment.Center,
                VerticalAlignment     = VAlignment.Center,
                SizeFlagsStretchRatio = 1,
                Scale        = (0.5f, 0.5f),
                ToolTip      = Loc.GetString("ui-actionsui-function-open-abilities-menu"),
                TooltipDelay = CustomTooltipDelay
            };
            settingsContainer.AddChild(_settingsButton);
            settingsContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 1
            });

            // this allows a 2 column layout if window gets too small
            _slotContainer = new GridContainer
            {
                MaxGridHeight = CalcMaxHeight()
            };
            hotbarContainer.AddChild(_slotContainer);

            _loadoutContainer = new BoxContainer
            {
                Orientation      = LayoutOrientation.Horizontal,
                HorizontalExpand = true,
                MouseFilter      = MouseFilterMode.Stop
            };
            hotbarContainer.AddChild(_loadoutContainer);

            _loadoutContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 1
            });
            var previousHotbarIcon = new TextureRect()
            {
                Texture               = resourceCache.GetTexture("/Textures/Interface/Nano/left_arrow.svg.192dpi.png"),
                HorizontalAlignment   = HAlignment.Center,
                VerticalAlignment     = VAlignment.Center,
                SizeFlagsStretchRatio = 1,
                TextureScale          = (0.5f, 0.5f)
            };

            _loadoutContainer.AddChild(previousHotbarIcon);
            _loadoutContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 2
            });
            _loadoutNumber = new Label
            {
                Text = "1",
                SizeFlagsStretchRatio = 1
            };
            _loadoutContainer.AddChild(_loadoutNumber);
            _loadoutContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 2
            });
            var nextHotbarIcon = new TextureRect
            {
                Texture               = resourceCache.GetTexture("/Textures/Interface/Nano/right_arrow.svg.192dpi.png"),
                HorizontalAlignment   = HAlignment.Center,
                VerticalAlignment     = VAlignment.Center,
                SizeFlagsStretchRatio = 1,
                TextureScale          = (0.5f, 0.5f)
            };

            _loadoutContainer.AddChild(nextHotbarIcon);
            _loadoutContainer.AddChild(new Control {
                HorizontalExpand = true, SizeFlagsStretchRatio = 1
            });

            _slots = new ActionSlot[ClientActionsComponent.Slots];

            _dragShadow = new TextureRect
            {
                MinSize = (64, 64),
                Stretch = TextureRect.StretchMode.Scale,
                Visible = false,
                SetSize = (64, 64)
            };
            UserInterfaceManager.PopupRoot.AddChild(_dragShadow);

            for (byte i = 0; i < ClientActionsComponent.Slots; i++)
            {
                var slot = new ActionSlot(this, _menu, actionsComponent, i);
                _slotContainer.AddChild(slot);
                _slots[i] = slot;
            }

            DragDropHelper = new DragDropHelper <ActionSlot>(OnBeginActionDrag, OnContinueActionDrag, OnEndActionDrag);

            MinSize = (10, 400);
        }