Skip to content

Commit

Permalink
The actual cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Centronias committed Feb 8, 2025
1 parent 7ee4205 commit 58f562d
Show file tree
Hide file tree
Showing 24 changed files with 384 additions and 430 deletions.
30 changes: 30 additions & 0 deletions Content.Client/Tabletop/TabletopDraggableVisualizerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Numerics;
using Content.Shared.Tabletop;
using Content.Shared.Tabletop.Components;
using Robust.Client.GameObjects;

namespace Content.Client.Tabletop;

public sealed class TabletopDraggableVisualizerSystem : VisualizerSystem<TabletopDraggableComponent>
{
private static readonly Vector2 DraggedScale = new(1.25f);
private static readonly Vector2 NotDraggedScale = Vector2.Zero;

private const int DraggedDrawDepth = (int)Shared.DrawDepth.DrawDepth.Items + 1;
private const int NotDraggedDrawDepth = (int)Shared.DrawDepth.DrawDepth.Items;

protected override void OnAppearanceChange(EntityUid uid,
TabletopDraggableComponent comp,
ref AppearanceChangeEvent args)
{
if (args.Sprite != null &&
AppearanceSystem.TryGetData<bool>(uid,
TabletopItemVisuals.BeingDragged,
out var beingDragged,
args.Component))
{
args.Sprite.Scale = beingDragged ? DraggedScale : NotDraggedScale;
args.Sprite.DrawDepth = beingDragged ? DraggedDrawDepth : NotDraggedDrawDepth;
}
}
}
127 changes: 52 additions & 75 deletions Content.Client/Tabletop/TabletopSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Content.Shared.Tabletop.Components;
using Content.Shared.Tabletop.Events;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
Expand All @@ -26,7 +25,6 @@ public sealed class TabletopSystem : SharedTabletopSystem
[Dependency] private readonly IUserInterfaceManager _uiManger = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;

// Time in seconds to wait until sending the location of a dragged entity to the server again
Expand All @@ -50,12 +48,11 @@ public override void Initialize()

SubscribeNetworkEvent<TabletopPlayEvent>(OnTabletopPlay);
SubscribeLocalEvent<TabletopDraggableComponent, ComponentRemove>(HandleDraggableRemoved);
SubscribeLocalEvent<TabletopDraggableComponent, AppearanceChangeEvent>(OnAppearanceChange);
}

private void HandleDraggableRemoved(EntityUid uid, TabletopDraggableComponent component, ComponentRemove args)
private void HandleDraggableRemoved(Entity<TabletopDraggableComponent> entity, ref ComponentRemove args)
{
if (_draggedEntity == uid)
if (_draggedEntity == entity)
StopDragging(false);
}

Expand All @@ -76,9 +73,10 @@ public override void FrameUpdate(float frameTime)
}

// If no entity is being dragged or no viewport is clicked, return
if (_draggedEntity == null || _viewport == null) return;
if (_draggedEntity is not { } draggedEntity || _viewport == null)
return;

if (!CanDrag(playerEntity, _draggedEntity.Value, out var draggableComponent))
if (!CanDrag(playerEntity, draggedEntity, out var draggableComponent))
{
StopDragging();
return;
Expand All @@ -97,19 +95,21 @@ public override void FrameUpdate(float frameTime)
var coords = _viewport.PixelToMap(_inputManager.MouseScreenPosition.Position);

// Clamp coordinates to viewport
var clampedCoords = ClampPositionToViewport(coords, _viewport);
if (clampedCoords.Equals(MapCoordinates.Nullspace)) return;
if (ClampPositionToViewport(coords, _viewport) is not { } clampedCoords)
return;

// Move the entity locally every update
_transformSystem.SetWorldPosition(_draggedEntity.Value, clampedCoords.Position);
_transformSystem.SetWorldPosition(draggedEntity, clampedCoords.Position);

// Increment total time passed
_timePassed += frameTime;

// Only send new position to server when Delay is reached
if (_timePassed >= Delay && _table != null)
if (_timePassed >= Delay && _table is { } table)
{
RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(_draggedEntity.Value), clampedCoords, GetNetEntity(_table.Value)));
RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(draggedEntity),
clampedCoords,
GetNetEntity(table)));
_timePassed -= Delay;
}
}
Expand All @@ -130,7 +130,7 @@ private void OnTabletopPlay(TabletopPlayEvent msg)
// Get the camera entity that the server has created for us
var camera = GetEntity(msg.CameraUid);

if (!EntityManager.TryGetComponent<EyeComponent>(camera, out var eyeComponent))
if (!TryComp<EyeComponent>(camera, out var eyeComponent))
{
// If there is no eye, print error and do not open any window
Log.Error("Camera entity does not have eye component!");
Expand All @@ -142,17 +142,17 @@ private void OnTabletopPlay(TabletopPlayEvent msg)
{
MinWidth = 500,
MinHeight = 436,
Title = msg.Title
Title = msg.Title,
};

_window.OnClose += OnWindowClose;
}

private void OnWindowClose()
{
if (_table != null)
if (_table is { } table)
{
RaiseNetworkEvent(new TabletopStopPlayingEvent(GetNetEntity(_table.Value)));
RaiseNetworkEvent(new TabletopStopPlayingEvent(GetNetEntity(table)));
}

StopDragging();
Expand All @@ -167,70 +167,47 @@ private bool OnUse(in PointerInputCmdArgs args)
return args.State switch
{
BoundKeyState.Down => OnMouseDown(args),
BoundKeyState.Up => OnMouseUp(args),
_ => false
BoundKeyState.Up => OnMouseUp(),
_ => false,
};
}
private bool OnUseSecondary(in PointerInputCmdArgs args)
{
if (_draggedEntity != null && _table != null)

bool OnMouseDown(in PointerInputCmdArgs args)
{
var ev = new TabletopRequestTakeOut
{
Entity = GetNetEntity(_draggedEntity.Value),
TableUid = GetNetEntity(_table.Value)
};
RaiseNetworkEvent(ev);
}
return false;
}
// Return if no player entity
if (_playerManager.LocalEntity is not { } playerEntity)
return false;

private bool OnMouseDown(in PointerInputCmdArgs args)
{
// Return if no player entity
if (_playerManager.LocalEntity is not { } playerEntity)
return false;
// Return if can not see table or stunned/no hands
if (!CanSeeTable(playerEntity, _table) || !CanDrag(playerEntity, args.EntityUid, out _))
return false;

var entity = args.EntityUid;
// Try to get the viewport under the cursor
if (_uiManger.MouseGetControl(args.ScreenCoordinates) as ScalingViewport is not { } viewport)
return false;

// Return if can not see table or stunned/no hands
if (!CanSeeTable(playerEntity, _table) || !CanDrag(playerEntity, entity, out _))
{
return false;
StartDragging(args.EntityUid, viewport);
return true;
}

// Try to get the viewport under the cursor
if (_uiManger.MouseGetControl(args.ScreenCoordinates) as ScalingViewport is not { } viewport)
bool OnMouseUp()
{
StopDragging();
return false;
}

StartDragging(entity, viewport);
return true;
}

private bool OnMouseUp(in PointerInputCmdArgs args)
{
StopDragging();
return false;
}

private void OnAppearanceChange(EntityUid uid, TabletopDraggableComponent comp, ref AppearanceChangeEvent args)
private bool OnUseSecondary(in PointerInputCmdArgs args)
{
if (args.Sprite == null)
return;

// TODO: maybe this can work more nicely, by maybe only having to set the item to "being dragged", and have
// the appearance handle the rest
if (_appearance.TryGetData<Vector2>(uid, TabletopItemVisuals.Scale, out var scale, args.Component))
if (_draggedEntity is { } draggedEntity && _table is { } table)
{
args.Sprite.Scale = scale;
RaiseNetworkEvent(new TabletopRequestTakeOut
{
Entity = GetNetEntity(draggedEntity),
TableUid = GetNetEntity(table)
});
}

if (_appearance.TryGetData<int>(uid, TabletopItemVisuals.DrawDepth, out var drawDepth, args.Component))
{
args.Sprite.DrawDepth = drawDepth;
}
return false;
}

#endregion
Expand All @@ -257,10 +234,12 @@ private void StartDragging(EntityUid draggedEntity, ScalingViewport viewport)
private void StopDragging(bool broadcast = true)
{
// Set the dragging player on the component to noone
if (broadcast && _draggedEntity != null && EntityManager.HasComponent<TabletopDraggableComponent>(_draggedEntity.Value))
if (broadcast && _draggedEntity is { } draggedEntity && HasComp<TabletopDraggableComponent>(draggedEntity))
{
RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(_draggedEntity.Value), Transforms.GetMapCoordinates(_draggedEntity.Value), GetNetEntity(_table!.Value)));
RaisePredictiveEvent(new TabletopDraggingPlayerChangedEvent(GetNetEntity(_draggedEntity.Value), false));
RaisePredictiveEvent(new TabletopMoveEvent(GetNetEntity(draggedEntity),
Transforms.GetMapCoordinates(draggedEntity),
GetNetEntity(_table!.Value)));
RaisePredictiveEvent(new TabletopDraggingPlayerChangedEvent(GetNetEntity(draggedEntity), false));
}

_draggedEntity = null;
Expand All @@ -273,15 +252,12 @@ private void StopDragging(bool broadcast = true)
/// <param name="coordinates">The coordinates to be clamped.</param>
/// <param name="viewport">The viewport to clamp the coordinates to.</param>
/// <returns>Coordinates clamped to the viewport.</returns>
private static MapCoordinates ClampPositionToViewport(MapCoordinates coordinates, ScalingViewport viewport)
private static MapCoordinates? ClampPositionToViewport(MapCoordinates coordinates, ScalingViewport viewport)
{
if (coordinates == MapCoordinates.Nullspace) return MapCoordinates.Nullspace;

var eye = viewport.Eye;
if (eye == null)
return MapCoordinates.Nullspace;
if (coordinates == MapCoordinates.Nullspace || viewport.Eye is not { } eye)
return null;

var size = (Vector2) viewport.ViewportSize / EyeManager.PixelsPerMeter; // Convert to tiles instead of pixels
var size = (Vector2)viewport.ViewportSize / EyeManager.PixelsPerMeter; // Convert to tiles instead of pixels
var eyePosition = eye.Position.Position;
var eyeRotation = eye.Rotation;
var eyeScale = eye.Scale;
Expand All @@ -290,7 +266,8 @@ private static MapCoordinates ClampPositionToViewport(MapCoordinates coordinates
var max = (eyePosition + size / 2) / eyeScale;

// If 90/270 degrees rotated, flip X and Y
if (MathHelper.CloseToPercent(eyeRotation.Degrees % 180d, 90d) || MathHelper.CloseToPercent(eyeRotation.Degrees % 180d, -90d))
if (MathHelper.CloseToPercent(eyeRotation.Degrees % 180d, 90d) ||
MathHelper.CloseToPercent(eyeRotation.Degrees % 180d, -90d))
{
(min.Y, min.X) = (min.X, min.Y);
(max.Y, max.X) = (max.X, max.Y);
Expand Down
2 changes: 1 addition & 1 deletion Content.Client/Tabletop/UI/TabletopWindow.xaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:viewport="clr-namespace:Content.Client.Viewport">
xmlns:viewport="clr-namespace:Content.Client.Viewport">
<viewport:ScalingViewport Name="ScalingVp" MouseFilter="Stop" RenderScaleMode="CeilInt">
<Button Name="FlipButton"
Text="{ Loc 'tabletop-chess-flip' }"
Expand Down
4 changes: 2 additions & 2 deletions Content.Client/Tabletop/UI/TabletopWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ private void Flip(BaseButton.ButtonEventArgs args)
{
eye.Rotation = eye.Rotation.Opposite();

// Flip alignmento of the button
// Flip alignment of the button
FlipButton.HorizontalAlignment = FlipButton.HorizontalAlignment == HAlignment.Right
? HAlignment.Left
: HAlignment.Right;
}
}
}
}
18 changes: 10 additions & 8 deletions Content.Server/Tabletop/Components/TabletopGameComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Numerics;
using Content.Server.Tabletop.Game;

namespace Content.Server.Tabletop.Components;

Expand All @@ -12,29 +13,30 @@ public sealed partial class TabletopGameComponent : Component
/// The localized name of the board. Shown in the UI.
/// </summary>
[DataField]
public LocId BoardName { get; private set; } = "tabletop-default-board-name";
public LocId BoardName = "tabletop-default-board-name";

/// <summary>
/// The type of method used to set up a tabletop.
/// </summary>
[DataField(required: true)]
public TabletopSetup Setup { get; private set; } = new Game.TabletopChessSetup();
[DataField(required: true), ViewVariables(VVAccess.ReadOnly)]
public TabletopSetup Setup = new TabletopEmptySetup();

/// <summary>
/// The size of the viewport being opened. Must match the board dimensions otherwise you'll get the space parallax (unless that's what you want).
/// The size of the viewport being opened. Must match the board dimensions otherwise you'll get the space parallax
/// (unless that's what you want).
/// </summary>
[DataField]
public Vector2i Size { get; private set; } = (300, 300);
public Vector2i Size = (300, 300);

/// <summary>
/// The zoom of the viewport camera.
/// </summary>
[DataField]
public Vector2 CameraZoom { get; private set; } = Vector2.One;
public Vector2 CameraZoom = Vector2.One;

/// <summary>
/// The specific session of this tabletop.
/// </summary>
[ViewVariables]
public TabletopSession? Session { get; set; } = null;
[ViewVariables(VVAccess.ReadOnly)]
public TabletopSession? Session = null;
}
8 changes: 4 additions & 4 deletions Content.Server/Tabletop/Components/TabletopGamerComponent.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Content.Server.Tabletop.Components;

/// <summary>
/// Component for marking an entity as currently playing a tabletop.
/// Component for marking an entity as currently playing a tabletop.
/// </summary>
[RegisterComponent, Access(typeof(TabletopSystem))]
public sealed partial class TabletopGamerComponent : Component
{
[DataField("tabletop")]
public EntityUid Tabletop { get; set; } = EntityUid.Invalid;
}
[DataField]
public EntityUid Tabletop = EntityUid.Invalid;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
namespace Content.Server.Tabletop;
namespace Content.Server.Tabletop.Components;

/// <summary>
/// This is used for tracking pieces that are simply "holograms" shown on the tabletop
/// </summary>
[RegisterComponent]
public sealed partial class TabletopHologramComponent : Component
{

}
public sealed partial class TabletopHologramComponent : Component;
Loading

0 comments on commit 58f562d

Please sign in to comment.