Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[феатуре] ms paint #279

Merged
merged 8 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Content.Client/Crayon/CrayonComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;

/* // WWDP EDIT - DEFUNCT - Merged into one shared CrayonComponent.
namespace Content.Client.Crayon
{
[RegisterComponent]
public sealed partial class CrayonComponent : SharedCrayonComponent
{
[ViewVariables(VVAccess.ReadWrite)] public bool UIUpdateNeeded;

[ViewVariables] public int Charges { get; set; }
[ViewVariables] public int Capacity { get; set; }
}
}
*/
69 changes: 60 additions & 9 deletions Content.Client/Crayon/CrayonSystem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
using Content.Client._White.Overlays;
using Content.Client.Hands.Systems;
using Content.Client.Items;
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.Crayon;
using Content.Shared.Hands;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
Expand All @@ -13,25 +21,68 @@ namespace Content.Client.Crayon;

public sealed class CrayonSystem : SharedCrayonSystem
{
// Didn't do in shared because I don't think most of the server stuff can be predicted.
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
[Dependency] private readonly HandsSystem _hands = default!;

// Didn't do in shared because I don't think most of the server stuff can be predicted. // if i had arms long enough to reach around the globe i would strangle you.
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CrayonComponent, ComponentHandleState>(OnCrayonHandleState);
// SubscribeLocalEvent<CrayonComponent, ComponentHandleState>(OnCrayonHandleState); // WWDP EDIT - DEFUNCT - Moved to using AutoState system.
Subs.ItemStatus<CrayonComponent>(ent => new StatusControl(ent));

// WWDP EDIT START
SubscribeLocalEvent<CrayonComponent, AfterAutoHandleStateEvent>(CrayonAfterAutoState);
SubscribeLocalEvent<CrayonComponent, AfterInteractEvent>(CrayonAfterInteract);
SubscribeLocalEvent<CrayonComponent, ComponentRemove>(CrayonRemoved);
SubscribeLocalEvent<CrayonComponent, EntityTerminatingEvent>(CrayonEntRemoved);
// WWDP EDIT END
}

// WWDP EDIT START
private void CrayonAfterInteract(EntityUid uid, CrayonComponent comp, AfterInteractEvent args)
{
if (comp.Charges <= 1)
_ui.CloseUi(uid, CrayonComponent.CrayonUiKey.Key, args.User);
}

private void CrayonRemoved(EntityUid uid, CrayonComponent comp, ComponentRemove args)
{
if (_player.LocalEntity is not EntityUid player ||
uid != _hands.GetActiveItem(player))
return;
_overlay.RemoveOverlay<CrayonPreviewOverlay>();
}

private static void OnCrayonHandleState(EntityUid uid, CrayonComponent component, ref ComponentHandleState args)
private void CrayonEntRemoved(EntityUid uid, CrayonComponent comp, EntityTerminatingEvent args)
{
if (args.Current is not CrayonComponentState state) return;
if (_player.LocalEntity is not EntityUid player ||
uid != _hands.GetActiveItem(player))
return;
_overlay.RemoveOverlay<CrayonPreviewOverlay>();
}

component.Color = state.Color;
component.SelectedState = state.State;
component.Charges = state.Charges;
component.Capacity = state.Capacity;
private void CrayonAfterAutoState(EntityUid uid, CrayonComponent comp, AfterAutoHandleStateEvent args)
{
comp.UIUpdateNeeded = true;
}

component.UIUpdateNeeded = true;
protected override void OnCrayonHandSelected(EntityUid uid, CrayonComponent component, HandSelectedEvent args) // WWDP EDIT
{
base.OnCrayonHandSelected(uid, component, args);
_overlay.RemoveOverlay<CrayonPreviewOverlay>(); // if i still fucked up somewhere and did not remove the event when i should've, this will catch it.
_overlay.AddOverlay(new CrayonPreviewOverlay(_sprite, component));
}

protected override void OnCrayonHandDeselected(EntityUid uid, CrayonComponent component, HandDeselectedEvent args) // WWDP EDIT
{
base.OnCrayonHandDeselected(uid, component, args);
_overlay.RemoveOverlay<CrayonPreviewOverlay>();
}
// WWDP EDIT END

private sealed class StatusControl : Control
{
Expand Down
14 changes: 14 additions & 0 deletions Content.Client/Hands/Systems/HandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using Robust.Shared.Graphics;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Content.Shared._White.Hands;

namespace Content.Client.Hands.Systems
{
Expand Down Expand Up @@ -68,10 +69,23 @@ public override void Initialize()

SubscribeLocalEvent<HoldingDropComponent, ComponentInit>(HoldingDropComponentInit); // WWDP
SubscribeLocalEvent<HoldingDropComponent, ComponentShutdown>(HoldingDropComponentShutdown); // WWDP
SubscribeNetworkEvent<HandDeselectedNetworkCrutchWrap>(OnHandDeselectedCrutchWrap); // WWDP

OnHandSetActive += OnHandActivated;
}

// WWDP EDIT START
/// <summary>
/// Throw code doesn't run on client so the HandDeselectedEvent that is raised serverside does not get raised clientside.
/// This is awful, but it fixes the issue.
/// </summary>
/// <param name="ev"></param>
private void OnHandDeselectedCrutchWrap(HandDeselectedNetworkCrutchWrap ev)
{
RaiseLocalEvent(GetEntity(ev.Target), new HandDeselectedEvent(GetEntity(ev.User))); // i think i'm starting to get desensitized to this kind of stuff.
}
// WWDP EDIT END

#region StateHandling
private void HandleComponentState(EntityUid uid, HandsComponent component, ref ComponentHandleState args)
{
Expand Down
81 changes: 81 additions & 0 deletions Content.Client/_White/Overlays/CrayonPreviewOverlay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Content.Client.Crayon;
using Content.Shared._White.Hands.Components;
using Content.Shared.Crayon;
using Content.Shared.Decals;
using Content.Shared.Interaction;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
using System.Numerics;

namespace Content.Client._White.Overlays;

public sealed class CrayonPreviewOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;

[Dependency] private readonly IInputManager _input = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IEyeManager _eye = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;

private readonly CrayonComponent _crayonComp;
private readonly EntityUid _crayonUid;
private string _currentState;

private Texture _tex;
private readonly SpriteSystem _sprite;

public CrayonPreviewOverlay(SpriteSystem sprite, CrayonComponent comp)
{
IoCManager.InjectDependencies(this);
_sprite = sprite;

_crayonComp = comp;
_crayonUid = comp.Owner;
_currentState = comp.SelectedState;
if (_proto.TryIndex<DecalPrototype>(_currentState, out var proto))
_tex = _sprite.Frame0(proto.Sprite);
else
_tex = Texture.Transparent;
}

protected override void Draw(in OverlayDrawArgs args)
{
if (!_entMan.EntityExists(_crayonUid) || // failsafe
_player.LocalEntity is not EntityUid playerUid ||
_entMan.HasComponent<HoldingDropComponent>(playerUid))
return;

var handle = args.WorldHandle;

if (_currentState != _crayonComp.SelectedState)
{
_currentState = _crayonComp.SelectedState;
if (_proto.TryIndex<DecalPrototype>(_currentState, out var proto))
_tex = _sprite.Frame0(proto.Sprite);
else
_tex = Texture.Transparent;
}

var mouseScreenPos = _input.MouseScreenPosition.Position;

var angle = _crayonComp.Angle - _eye.CurrentEye.Rotation;
var mouseMapPos = _eye.ScreenToMap(mouseScreenPos);
var playerMapPos = _entMan.GetComponent<TransformComponent>(playerUid).MapPosition;

float alpha = 0.6f;
if ((mouseMapPos.Position - playerMapPos.Position).LengthSquared() > SharedInteractionSystem.InteractionRangeSquared)
alpha = 0.1f;


#pragma warning disable RA0002 // ffs
handle.DrawTexture(_tex, mouseMapPos.Position - new Vector2(0.5f, 0.5f), angle, _crayonComp.Color.WithAlpha(alpha));
#pragma warning restore RA0002
}
}

2 changes: 2 additions & 0 deletions Content.Server/Crayon/CrayonComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Robust.Server.GameObjects;
using Robust.Shared.Audio;

/* // WWDP EDIT - DEFUNCT - Merged into one shared CrayonComponent.
namespace Content.Server.Crayon
{
[RegisterComponent]
Expand All @@ -26,3 +27,4 @@ public sealed partial class CrayonComponent : SharedCrayonComponent
public bool DeleteEmpty = true;
}
}
*/
59 changes: 22 additions & 37 deletions Content.Server/Crayon/CrayonSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Content.Shared.Decals;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Movement.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
Expand All @@ -26,23 +27,26 @@ public sealed class CrayonSystem : SharedCrayonSystem
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CrayonComponent, ComponentInit>(OnCrayonInit);
SubscribeLocalEvent<CrayonComponent, CrayonSelectMessage>(OnCrayonBoundUI);
SubscribeLocalEvent<CrayonComponent, CrayonColorMessage>(OnCrayonBoundUIColor);
// SubscribeLocalEvent<CrayonComponent, CrayonSelectMessage>(OnCrayonBoundUI); // WWDP EDIT - Moved to Shared.
// SubscribeLocalEvent<CrayonComponent, CrayonColorMessage>(OnCrayonBoundUIColor); // WWDP EDIT - Moved to Shared.
SubscribeLocalEvent<CrayonComponent, UseInHandEvent>(OnCrayonUse, before: new[] { typeof(FoodSystem) });
SubscribeLocalEvent<CrayonComponent, AfterInteractEvent>(OnCrayonAfterInteract, after: new[] { typeof(FoodSystem) });
SubscribeLocalEvent<CrayonComponent, DroppedEvent>(OnCrayonDropped);
SubscribeLocalEvent<CrayonComponent, ComponentGetState>(OnCrayonGetState);
// SubscribeLocalEvent<CrayonComponent, DroppedEvent>(OnCrayonDropped); // WWDP EDIT - Moved to Shared.
// SubscribeLocalEvent<CrayonComponent, ComponentGetState>(OnCrayonGetState); // WWDP EDIT - DEFUNCT - Moved to using AutoState system.
}

/* WWDP EDIT - DEFUNCT - Moved to using AutoState system.
private static void OnCrayonGetState(EntityUid uid, CrayonComponent component, ref ComponentGetState args)
{
args.State = new CrayonComponentState(component.Color, component.SelectedState, component.Charges, component.Capacity);
}
*/

private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, AfterInteractEvent args)
{
Expand All @@ -66,10 +70,18 @@ private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, Aft
args.Handled = true;
return;
}

// WWDP EDIT START
Angle rot = 0f;
if (TryComp<InputMoverComponent>(args.User, out var mover))
{
rot = mover.TargetRelativeRotation;
}

if (!_decals.TryAddDecal(component.SelectedState, args.ClickLocation.Offset(new Vector2(-0.5f, -0.5f)), out _, component.Color, cleanable: true))
if (!_decals.TryAddDecal(component.SelectedState, args.ClickLocation.Offset(new Vector2(-0.5f, -0.5f)), out _, component.Color, rot + component.Angle + 0.01f, cleanable: true))
return;

// WWDP EDIT END

if (component.UseSound != null)
_audio.PlayPvs(component.UseSound, uid, AudioParams.Default.WithVariation(0.125f));

Expand All @@ -88,7 +100,7 @@ private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, Aft
if (component.DeleteEmpty && component.Charges <= 0)
UseUpCrayon(uid, args.User);
else
_uiSystem.ServerSendUiMessage(uid, SharedCrayonComponent.CrayonUiKey.Key, new CrayonUsedMessage(component.SelectedState));
_uiSystem.ServerSendUiMessage(uid, CrayonComponent.CrayonUiKey.Key, new CrayonUsedMessage(component.SelectedState)); // WWDP EDIT
}

private void OnCrayonUse(EntityUid uid, CrayonComponent component, UseInHandEvent args)
Expand All @@ -97,39 +109,17 @@ private void OnCrayonUse(EntityUid uid, CrayonComponent component, UseInHandEven
if (args.Handled)
return;

if (!_uiSystem.HasUi(uid, SharedCrayonComponent.CrayonUiKey.Key))
if (!_uiSystem.HasUi(uid, CrayonComponent.CrayonUiKey.Key)) // WWDP EDIT
{
return;
}

_uiSystem.TryToggleUi(uid, SharedCrayonComponent.CrayonUiKey.Key, args.User);
_uiSystem.TryToggleUi(uid, CrayonComponent.CrayonUiKey.Key, args.User); // WWDP EDIT

_uiSystem.SetUiState(uid, SharedCrayonComponent.CrayonUiKey.Key, new CrayonBoundUserInterfaceState(component.SelectedState, component.SelectableColor, component.Color));
_uiSystem.SetUiState(uid, CrayonComponent.CrayonUiKey.Key, new CrayonBoundUserInterfaceState(component.SelectedState, component.SelectableColor, component.Color)); // WWDP EDIT
args.Handled = true;
}

private void OnCrayonBoundUI(EntityUid uid, CrayonComponent component, CrayonSelectMessage args)
{
// Check if the selected state is valid
if (!_prototypeManager.TryIndex<DecalPrototype>(args.State, out var prototype) || !prototype.Tags.Contains("crayon"))
return;

component.SelectedState = args.State;

Dirty(uid, component);
}

private void OnCrayonBoundUIColor(EntityUid uid, CrayonComponent component, CrayonColorMessage args)
{
// you still need to ensure that the given color is a valid color
if (!component.SelectableColor || args.Color == component.Color)
return;

component.Color = args.Color;
Dirty(uid, component);

}

private void OnCrayonInit(EntityUid uid, CrayonComponent component, ComponentInit args)
{
component.Charges = component.Capacity;
Expand All @@ -140,11 +130,6 @@ private void OnCrayonInit(EntityUid uid, CrayonComponent component, ComponentIni
Dirty(uid, component);
}

private void OnCrayonDropped(EntityUid uid, CrayonComponent component, DroppedEvent args)
{
// TODO: Use the existing event.
_uiSystem.CloseUi(uid, SharedCrayonComponent.CrayonUiKey.Key, args.User);
}

private void UseUpCrayon(EntityUid uid, EntityUid user)
{
Expand Down
7 changes: 6 additions & 1 deletion Content.Server/Hands/Systems/HandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.Serialization;
using Content.Shared._White.Hands;

namespace Content.Server.Hands.Systems
{
Expand Down Expand Up @@ -288,7 +290,10 @@ hands.ActiveHandEntity is not { } throwEnt ||
// This can grief the above event so we raise it afterwards
if (IsHolding(player, throwEnt, out _, hands) && !TryDrop(player, throwEnt, handsComp: hands))
return false;

// WWDP EDIT START
var deselEv = new HandDeselectedEvent(player); // because throwcode is serverside, the HandDeselectedEvent doesn't get raised on client.
RaiseNetworkEvent(new HandDeselectedNetworkCrutchWrap(GetNetEntity(throwEnt), GetNetEntity(player))); // This is the best i've came up with.
// WWDP EDIT END
_throwingSystem.TryThrow(ev.ItemUid, ev.Direction, ev.ThrowSpeed, ev.PlayerUid, compensateFriction: !HasComp<LandAtCursorComponent>(ev.ItemUid));

return true;
Expand Down
Loading
Loading