diff --git a/.github/workflows/build-test-debug-win.yml b/.github/workflows/build-test-debug-win.yml new file mode 100644 index 00000000000..d2b40726f9a --- /dev/null +++ b/.github/workflows/build-test-debug-win.yml @@ -0,0 +1,63 @@ +name: Build & Test Debug Windows + +on: + # push: + # branches: [ master, staging, trying ] + # merge_group: + # pull_request: + # types: [ opened, reopened, synchronize, ready_for_review ] + # branches: [ master ] + workflow_dispatch: # ручной запуск + +jobs: + build: + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false + strategy: + matrix: + os: [ windows-latest ] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout Master + uses: actions/checkout@v3.6.0 + + - name: Setup Submodule + run: | + git submodule update --init --recursive + + - name: Pull engine updates + uses: space-wizards/submodule-dependency@v0.1.5 + + - name: Update Engine Submodules + run: | + cd RobustToolbox/ + git submodule update --init --recursive + + - name: Setup .NET Core + uses: actions/setup-dotnet@v3.2.0 + with: + dotnet-version: 8.0.x + + - name: Install dependencies + run: dotnet restore + + - name: Build Project + run: dotnet build --configuration DebugOpt --no-restore /p:WarningsAsErrors=nullable /m + + - name: Run Content.Tests + run: dotnet test --no-build --configuration DebugOpt Content.Tests/Content.Tests.csproj -- NUnit.ConsoleOut=0 + + - name: Run Content.IntegrationTests + shell: pwsh + run: | + $env:DOTNET_gcServer=1 + dotnet test --no-build --configuration DebugOpt Content.IntegrationTests/Content.IntegrationTests.csproj -- NUnit.ConsoleOut=0 NUnit.MapWarningTo=Failed + ci-success: + name: Build & Test Debug + needs: + - build + runs-on: windows-latest + steps: + - name: CI succeeded + run: exit 0 diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index a4ad8996eb9..ee29ca68d57 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -1,4 +1,4 @@ -name: Build & Test Debug +name: Build & Test Debug Linux # ADT-Tweak on: push: diff --git a/.github/workflows/labeler-needsreview.yml b/.github/workflows/labeler-needsreview.yml index 819b34b7bbd..311048acb0f 100644 --- a/.github/workflows/labeler-needsreview.yml +++ b/.github/workflows/labeler-needsreview.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "S: Needs Review" + labels: "Status: Needs Review" - uses: actions-ecosystem/action-remove-labels@v1 with: - labels: "S: Awaiting Changes" + labels: "Status: Awaiting Changes" diff --git a/Content.Client/ADT/Animations/FlipOnHitSystem.cs b/Content.Client/ADT/Animations/FlipOnHitSystem.cs new file mode 100644 index 00000000000..4bf491ad406 --- /dev/null +++ b/Content.Client/ADT/Animations/FlipOnHitSystem.cs @@ -0,0 +1,76 @@ +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Shared.Animations; +using Robust.Shared.Timing; +using Content.Shared.Animations; + +namespace Content.Client.Animations; + +public sealed class FlipOnHitSystem : SharedFlipOnHitSystem +{ + [Dependency] private readonly AnimationPlayerSystem _animationSystem = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAnimationComplete); + SubscribeAllEvent(ev => PlayAnimation(GetEntity(ev.User))); + } + + private void OnAnimationComplete(Entity ent, ref AnimationCompletedEvent args) + { + if (args.Key != FlippingComponent.AnimationKey) + return; + + PlayAnimation(ent); + } + + protected override void PlayAnimation(EntityUid user) + { + if (!_timing.IsFirstTimePredicted) + return; + + if (TerminatingOrDeleted(user)) + return; + + if (_animationSystem.HasRunningAnimation(user, FlippingComponent.AnimationKey)) + { + EnsureComp(user); + return; + } + + RemComp(user); + + var baseAngle = Angle.Zero; + if (EntityManager.TryGetComponent(user, out SpriteComponent? sprite)) + baseAngle = sprite.Rotation; + + var degrees = baseAngle.Degrees; + + var animation = new Animation + { + Length = TimeSpan.FromMilliseconds(500), + AnimationTracks = + { + new AnimationTrackComponentProperty + { + ComponentType = typeof(SpriteComponent), + Property = nameof(SpriteComponent.Rotation), + InterpolationMode = AnimationInterpolationMode.Linear, + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 180), 0.25f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 360), 0.25f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), + } + } + } + }; + + + _animationSystem.Play(user, animation, FlippingComponent.AnimationKey); + } +} diff --git a/Content.Client/ADT/Animations/FlippingComponent.cs b/Content.Client/ADT/Animations/FlippingComponent.cs new file mode 100644 index 00000000000..0d0f6ade090 --- /dev/null +++ b/Content.Client/ADT/Animations/FlippingComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Client.Animations; + +[RegisterComponent] +public sealed partial class FlippingComponent : Component +{ + public const string AnimationKey = "flip"; +} diff --git a/Content.Client/ADT/BookPrinter/BookPrinterBoundUserInterface.cs b/Content.Client/ADT/BookPrinter/BookPrinterBoundUserInterface.cs index 156c598170c..dd1a76fd38a 100644 --- a/Content.Client/ADT/BookPrinter/BookPrinterBoundUserInterface.cs +++ b/Content.Client/ADT/BookPrinter/BookPrinterBoundUserInterface.cs @@ -1,3 +1,5 @@ +// Оригинал данного файла был сделан @temporaldarkness (discord). Код был взят с https://github.com/ss14-ganimed/ENT14-Master. + using Content.Shared.ADT.BookPrinter; using Content.Shared.Containers.ItemSlots; using JetBrains.Annotations; diff --git a/Content.Client/ADT/BookPrinter/BookPrinterWindow.xaml b/Content.Client/ADT/BookPrinter/BookPrinterWindow.xaml index 8555f68cbf8..92c172a445a 100644 --- a/Content.Client/ADT/BookPrinter/BookPrinterWindow.xaml +++ b/Content.Client/ADT/BookPrinter/BookPrinterWindow.xaml @@ -1,3 +1,5 @@ + + _sections = new(); + public MiningShopBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + _miningPoints = EntMan.System(); + } + + protected override void Open() + { + _window = new MiningShopWindow(); + _window.OnClose += Close; + _window.Title = EntMan.GetComponentOrNull(Owner)?.EntityName ?? "MiningShop"; + + if (!EntMan.TryGetComponent(Owner, out MiningShopComponent? vendor)) + return; + var sections = _prototype.EnumeratePrototypes().ToList(); + sections.Sort((x, y) => x.Name[0].CompareTo(x.Name[0])); + + foreach (var section in sections) + { + var uiSection = new MiningShopSection(); + uiSection.Label.SetMessage(GetSectionName(section)); + _sections.Add(section); + + foreach (var entry in section.Entries) + { + var uiEntry = new MiningShopEntry(); + + if (_prototype.TryIndex(entry.Id, out var entity)) + { + uiEntry.Texture.Textures = SpriteComponent.GetPrototypeTextures(entity, _resource) + .Select(o => o.Default) + .ToList(); + uiEntry.Panel.Button.Label.Text = entry.Name?.Replace("\\n", "\n") ?? entity.Name; + + var name = entity.Name; + var color = MiningShopPanel.DefaultColor; + var borderColor = MiningShopPanel.DefaultBorderColor; + var hoverColor = MiningShopPanel.DefaultBorderColor; + + uiEntry.Panel.Color = color; + uiEntry.Panel.BorderColor = borderColor; + uiEntry.Panel.HoveredColor = hoverColor; + + var msg = new FormattedMessage(); + msg.AddText(name); + msg.PushNewline(); + + if (!string.IsNullOrWhiteSpace(entity.Description)) + msg.AddText(entity.Description); + + var tooltip = new Tooltip(); + tooltip.SetMessage(msg); + tooltip.MaxWidth = 250f; + + uiEntry.TooltipLabel.ToolTip = entity.Description; + uiEntry.TooltipLabel.TooltipDelay = 0; + uiEntry.TooltipLabel.TooltipSupplier = _ => tooltip; + + uiEntry.Panel.Button.OnPressed += _ => OnButtonPressed(entry); + } + + uiSection.Entries.AddChild(uiEntry); + } + + _window.Sections.AddChild(uiSection); + } + + _window.Express.OnPressed += _ => OnExpressDeliveryButtonPressed(); + _window.Search.OnTextChanged += OnSearchChanged; + + Refresh(); + + _window.OpenCentered(); + } + + private void OnButtonPressed(Content.Shared.ADT.MiningShop.MiningShopEntry entry) + { + var msg = new MiningShopBuiMsg(entry); + SendMessage(msg); + Refresh(); + } + + private void OnExpressDeliveryButtonPressed() + { + var msg = new MiningShopExpressDeliveryBuiMsg(); + SendMessage(msg); + Refresh(); + } + + private void OnSearchChanged(LineEditEventArgs args) + { + if (_window == null) + return; + + foreach (var sectionControl in _window.Sections.Children) + { + if (sectionControl is not MiningShopSection section) + continue; + + var any = false; + foreach (var entriesControl in section.Entries.Children) + { + if (entriesControl is not MiningShopEntry entry) + continue; + + if (string.IsNullOrWhiteSpace(args.Text)) + entry.Visible = true; + else + entry.Visible = entry.Panel.Button.Label.Text?.Contains(args.Text, OrdinalIgnoreCase) ?? false; + + if (entry.Visible) + any = true; + } + + section.Visible = any; + } + } + + public void Refresh() + { + if (_window == null || _player.LocalEntity == null) + return; + + if (!EntMan.TryGetComponent(Owner, out MiningShopComponent? vendor)) + return; + + List names = new List(); + + foreach (var order in vendor.OrderList) + { + var name = _prototype.TryIndex(order.Id, out var entity) ? entity.Name : order.Name; + if (name != null) + names.Add(name); + } + var orders = string.Join(", ", names); + + var userpoints = _miningPoints.TryFindIdCard(_player.LocalEntity.Value)?.Comp?.Points ?? 0; + + _window.YourPurchases.Text = $"Заказы: {orders}"; + + _window.Express.Text = $"Экспресс доставка"; + + _window.PointsLabel.Text = $"Осталось очков: {userpoints}"; + + var sections = _prototype.EnumeratePrototypes(); + + for (var sectionIndex = 0; sectionIndex < _sections.Count; sectionIndex++) + { + var section = _sections[sectionIndex]; + var uiSection = (MiningShopSection)_window.Sections.GetChild(sectionIndex); + uiSection.Label.SetMessage(GetSectionName(section)); + + var sectionDisabled = false; + + for (var entryIndex = 0; entryIndex < section.Entries.Count; entryIndex++) + { + var entry = section.Entries[entryIndex]; + var uiEntry = (MiningShopEntry)uiSection.Entries.GetChild(entryIndex); + var disabled = sectionDisabled; + + if (userpoints < entry.Price) + { + disabled = true; + } + + uiEntry.Price.Text = $"{entry.Price}P"; + + uiEntry.Panel.Button.Disabled = disabled; + } + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + _window?.Dispose(); + } + + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + switch (message) + { + case MiningShopRefreshBuiMsg: + Refresh(); + break; + } + } + + private FormattedMessage GetSectionName(SharedMiningShopSectionPrototype section) + { + var name = new FormattedMessage(); + name.PushTag(new MarkupNode("bold", new MarkupParameter(section.Name.ToUpperInvariant()), null)); + name.AddText(section.Name.ToUpperInvariant()); + + name.Pop(); + return name; + } +} diff --git a/Content.Client/ADT/MiningShop/MiningShopButton.xaml b/Content.Client/ADT/MiningShop/MiningShopButton.xaml new file mode 100644 index 00000000000..0b4faeac7c2 --- /dev/null +++ b/Content.Client/ADT/MiningShop/MiningShopButton.xaml @@ -0,0 +1,7 @@ + + + + diff --git a/Content.Client/ADT/MiningShop/MiningShopButton.xaml.cs b/Content.Client/ADT/MiningShop/MiningShopButton.xaml.cs new file mode 100644 index 00000000000..28c60b97223 --- /dev/null +++ b/Content.Client/ADT/MiningShop/MiningShopButton.xaml.cs @@ -0,0 +1,22 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.ADT.MiningShop; + +[GenerateTypedNameReferences] +public sealed partial class MiningShopButton : Button +{ + public event Action? OnDrawModeChanged; + + public MiningShopButton() + { + RobustXamlLoader.Load(this); + } + + protected override void DrawModeChanged() + { + OnDrawModeChanged?.Invoke(); + } +} + diff --git a/Content.Client/ADT/MiningShop/MiningShopEntry.xaml b/Content.Client/ADT/MiningShop/MiningShopEntry.xaml new file mode 100644 index 00000000000..0dd760fa904 --- /dev/null +++ b/Content.Client/ADT/MiningShop/MiningShopEntry.xaml @@ -0,0 +1,13 @@ + + + +