Skip to content
Open
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
11 changes: 7 additions & 4 deletions OpenDreamClient/ClientVerbSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public sealed class ClientVerbSystem : VerbSystem {
[Dependency] private readonly ITaskManager _taskManager = default!;
[Dependency] private readonly ITimerManager _timerManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly DreamClientSystem _dreamClientSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;

private EntityQuery<DMISpriteComponent> _spriteQuery;
Expand Down Expand Up @@ -83,8 +84,10 @@ public IEnumerable<VerbInfo> GetAllVerbs() {
/// <returns>The ID, src, and information of every executable verb</returns>
public IEnumerable<(int Id, ClientObjectReference Src, VerbInfo VerbInfo)> GetExecutableVerbs(bool ignoreHiddenAttr = false) {
sbyte? seeInvisibility = null;
if (_playerManager.LocalEntity != null) {
_sightQuery.TryGetComponent(_playerManager.LocalEntity.Value, out var mobSight);

EntityUid mob = _dreamClientSystem.MobUid;
if (mob.IsValid()) {
_sightQuery.TryGetComponent(mob, out var mobSight);

seeInvisibility = mobSight?.SeeInvisibility;
}
Expand Down Expand Up @@ -120,12 +123,12 @@ public IEnumerable<VerbInfo> GetAllVerbs() {
// Check the verb's "set src" allows us to execute this
switch (verb.Accessibility) {
case VerbAccessibility.Usr:
if (entity != _playerManager.LocalEntity)
if (entity != mob)
continue;

break;
case VerbAccessibility.InUsr:
if (_transformSystem.GetParentUid(entity) != _playerManager.LocalEntity)
if (_transformSystem.GetParentUid(entity) != mob)
continue;

break;
Expand Down
65 changes: 65 additions & 0 deletions OpenDreamClient/DreamClientSystem.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,57 @@
using OpenDreamClient.Interface;
using OpenDreamClient.Rendering;
using OpenDreamShared.Dream;
using OpenDreamShared.Network.Messages;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Player;

namespace OpenDreamClient;

internal sealed class DreamClientSystem : EntitySystem {
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IDreamInterfaceManager _interfaceManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;

// Current NetEntityof player's mob, or Invalid if could not be determined.
private NetEntity _mobNet = NetEntity.Invalid;

// Current Entity of player's mob, or Invalid if could not be determined.
private EntityUid _mobUid = EntityUid.Invalid;

// Sometimes we get mob info before we know all the net entities, so store the net entity and refer to it
public EntityUid MobUid {
get {
// if entity of mob is invalid but net entity isn't, try referring to known net entities
if (! _mobUid.IsValid() && _mobNet.IsValid() && _entityManager.TryGetEntity(_mobNet, out var ent)) {
_mobUid = ent.GetValueOrDefault(EntityUid.Invalid);
}

return _mobUid;
}
}

// Current Entity of player's eye, or Invalid if could not be determined.
private ClientObjectReference _eyeRef = new(NetEntity.Invalid);

public ClientObjectReference EyeRef {
get {
if (_eyeRef.Type == ClientObjectReference.RefType.Entity && !_eyeRef.Entity.IsValid()) {
return new(_entityManager.GetNetEntity(MobUid));
} else {
return _eyeRef;
}
}
private set {
_eyeManager.CurrentEye = new DreamClientEye(_eyeManager.CurrentEye, value, _entityManager, _transformSystem);
_eyeRef = value;
}
}

public bool IsEyeMissing() {
return EyeRef.Type == ClientObjectReference.RefType.Client;
}

public override void Initialize() {
SubscribeLocalEvent<LocalPlayerAttachedEvent>(OnPlayerAttached);
Expand All @@ -15,4 +62,22 @@ private void OnPlayerAttached(LocalPlayerAttachedEvent e) {
// So we have to set it again
_interfaceManager.DefaultWindow?.Macro.SetActive();
}

public void RxNotifyMobEyeUpdate(MsgNotifyMobEyeUpdate msg) {
var prevMobNet = _mobNet;
_mobNet = msg.MobNetEntity;

if (prevMobNet != _mobNet) {
// mark mob cache as dirty/invalid
_mobUid = EntityUid.Invalid;
}

var incomingEyeRef = msg.EyeRef;

if (incomingEyeRef.Type == ClientObjectReference.RefType.Entity && !incomingEyeRef.Entity.IsValid()) {
EyeRef = new(msg.MobNetEntity);
} else {
EyeRef = incomingEyeRef;
}
}
}
4 changes: 3 additions & 1 deletion OpenDreamClient/Input/ContextMenu/ContextMenuPopup.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ internal sealed partial class ContextMenuPopup : Popup {
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
private readonly ClientAppearanceSystem _appearanceSystem;
private readonly DreamClientSystem _dreamClientSystem;
private readonly ClientVerbSystem _verbSystem;
private readonly DMISpriteSystem _spriteSystem;
private readonly EntityLookupSystem _lookupSystem;
Expand All @@ -37,6 +38,7 @@ public ContextMenuPopup() {

_verbSystem = _entitySystemManager.GetEntitySystem<ClientVerbSystem>();
_appearanceSystem = _entitySystemManager.GetEntitySystem<ClientAppearanceSystem>();
_dreamClientSystem = _entitySystemManager.GetEntitySystem<DreamClientSystem>();
_spriteSystem = _entitySystemManager.GetEntitySystem<DMISpriteSystem>();
_lookupSystem = _entitySystemManager.GetEntitySystem<EntityLookupSystem>();
_mouseInputSystem = _entitySystemManager.GetEntitySystem<MouseInputSystem>();
Expand Down Expand Up @@ -115,7 +117,7 @@ public void SetActiveItem(ContextMenuItem item) {
private sbyte GetSeeInvisible() {
if (_playerManager.LocalSession == null)
return 127;
if (!_mobSightQuery.TryGetComponent(_playerManager.LocalSession.AttachedEntity, out DreamMobSightComponent? sight))
if (!_mobSightQuery.TryGetComponent(_dreamClientSystem.MobUid, out DreamMobSightComponent? sight))
return 127;

return sight.SeeInvisibility;
Expand Down
6 changes: 6 additions & 0 deletions OpenDreamClient/Input/MouseInputSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal sealed class MouseInputSystem : SharedMouseInputSystem {
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IDreamInterfaceManager _dreamInterfaceManager = default!;
[Dependency] private readonly ClientAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly DreamClientSystem _dreamClientSystem = default!;
[Dependency] private readonly IClyde _clyde = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private ISawmill _sawmill = default!;
Expand Down Expand Up @@ -144,6 +145,11 @@ public void HandleAtomMouseMove(ScalingViewport viewport, Vector2 relativePos, C
}

public (ClientObjectReference Atom, Vector2i IconPosition)? GetTurfUnderMouse(MapCoordinates mapCoords, out uint? turfId) {
if (_dreamClientSystem.IsEyeMissing()) {
turfId = null;
return null;
}

// Grid coordinates are half a meter off from entity coordinates
mapCoords = new MapCoordinates(mapCoords.Position + new Vector2(0.5f), mapCoords.MapId);

Expand Down
21 changes: 13 additions & 8 deletions OpenDreamClient/Interface/DreamInterfaceManager.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
using System.IO;
using System.Text;
using System.Globalization;
using OpenDreamShared.Network.Messages;
using OpenDreamClient.Interface.Controls;
using OpenDreamShared.Interface.Descriptors;
using OpenDreamShared.Interface.DMF;
using OpenDreamClient.Interface.Controls;
using OpenDreamClient.Interface.Prompts;
using OpenDreamClient.Resources;
using OpenDreamClient.Resources.ResourceTypes;
using OpenDreamShared.Dream;
using OpenDreamShared.Interface.Descriptors;
using OpenDreamShared.Interface.DMF;
using OpenDreamShared.Network.Messages;
using Robust.Client;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.ContentPack;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using SixLabors.ImageSharp;
using System.Globalization;
using System.IO;
using System.Linq;
using Robust.Shared.Map;
using System.Text;

namespace OpenDreamClient.Interface;

Expand Down Expand Up @@ -131,9 +131,14 @@ public void Initialize() {
_netManager.RegisterNetMessage<MsgLoadInterface>(RxLoadInterface);
_netManager.RegisterNetMessage<MsgAckLoadInterface>();
_netManager.RegisterNetMessage<MsgUpdateClientInfo>(RxUpdateClientInfo);
_netManager.RegisterNetMessage<MsgNotifyMobEyeUpdate>(RxNotifyMobEyeUpdate);
_clyde.OnWindowFocused += OnWindowFocused;
}

private void RxNotifyMobEyeUpdate(MsgNotifyMobEyeUpdate message) {
_entitySystemManager.GetEntitySystem<DreamClientSystem>().RxNotifyMobEyeUpdate(message);
}

private void RxUpdateStatPanels(MsgUpdateStatPanels message) {
DefaultInfo?.UpdateStatPanels(message);
}
Expand Down
101 changes: 101 additions & 0 deletions OpenDreamClient/Rendering/DreamClientEye.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using OpenDreamShared.Dream;
using Robust.Client.GameObjects;
using Robust.Shared.Graphics;
using Robust.Shared.Map;

namespace OpenDreamClient.Rendering;

public sealed class DreamClientEye: IEye {
private readonly ClientObjectReference _eyeRef;
private readonly IEntityManager _entityManager;
private readonly TransformSystem _transformSystem;

public DreamClientEye(IEye baseEye, ClientObjectReference eyeRef, IEntityManager entityManager, TransformSystem transformSystem) {
Rotation = baseEye.Rotation;
Scale = baseEye.Scale;
DrawFov = baseEye.DrawFov;
DrawLight = baseEye.DrawLight;

_eyeRef = eyeRef;
_entityManager = entityManager;
_transformSystem = transformSystem;
}

[ViewVariables(VVAccess.ReadOnly)]
public MapCoordinates Position {
get {
switch (_eyeRef.Type) {
case ClientObjectReference.RefType.Entity:
var ent = _entityManager.GetEntity(_eyeRef.Entity);
if (_entityManager.TryGetComponent<TransformComponent>(ent, out var pos)) {
return _transformSystem.GetMapCoordinates(pos);
}

break;

case ClientObjectReference.RefType.Turf:
return new(new(_eyeRef.TurfX, _eyeRef.TurfY), new(_eyeRef.TurfZ));
}

// Nullspace position stops all rendering but we still want to render certain screen space objects...
//return MapCoordinates.Nullspace;
return new(0, 0, new(1));
}
}

public void GetViewMatrix(out Matrix3x2 viewMatrix, Vector2 renderScale) {
var pos = Position;
viewMatrix = Matrix3Helpers.CreateInverseTransform(
pos.X + Offset.X,
pos.Y + Offset.Y,
(float)-Rotation.Theta,
1 / (Scale.X * renderScale.X),
1 / (Scale.Y * renderScale.Y));
}

public void GetViewMatrixNoOffset(out Matrix3x2 viewMatrix, Vector2 renderScale) {
var pos = Position;
viewMatrix = Matrix3Helpers.CreateInverseTransform(
pos.X,
pos.Y,
(float)-Rotation.Theta,
1 / (Scale.X * renderScale.X),
1 / (Scale.Y * renderScale.Y));
}

public void GetViewMatrixInv(out Matrix3x2 viewMatrixInv, Vector2 renderScale) {
var pos = Position;
viewMatrixInv = Matrix3Helpers.CreateTransform(
pos.X + Offset.X,
pos.Y + Offset.Y,
(float)-Rotation.Theta,
1 / (Scale.X * renderScale.X),
1 / (Scale.Y * renderScale.Y));
}

private Vector2 _scale = Vector2.One / 2f;

[ViewVariables(VVAccess.ReadWrite)]
public bool DrawFov { get; set; }

[ViewVariables]
public bool DrawLight { get; set; }

[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Offset { get; set; }

[ViewVariables(VVAccess.ReadWrite)]
public Angle Rotation { get; set; }

[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Zoom {
get => new(1 / _scale.X, 1 / _scale.Y);
set => _scale = new Vector2(1 / value.X, 1 / value.Y);
}

[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Scale {
get => _scale;
set => _scale = value;
}
}
5 changes: 4 additions & 1 deletion OpenDreamClient/Rendering/DreamPlane.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ public void Draw(DreamViewOverlay overlay, DrawingHandleWorld handle, Box2 world
/// <summary>
/// Draws this plane's mouse map onto the current render target
/// </summary>
public void DrawMouseMap(DrawingHandleWorld handle, DreamViewOverlay overlay, Vector2i renderTargetSize, Box2 worldAABB) {
public void DrawMouseMap(DrawingHandleWorld handle, DreamViewOverlay overlay, Vector2i renderTargetSize, Box2 worldAABB, bool onlyDrawScreenSprites = false) {
if (Master?.MouseOpacity == MouseOpacity.Transparent || !Enabled)
return;

handle.UseShader(overlay.BlockColorInstance);
foreach (var sprite in Sprites) {
if (onlyDrawScreenSprites && !sprite.IsScreen)
continue;

if (sprite.MouseOpacity == MouseOpacity.Transparent || sprite.ShouldPassMouse)
continue;

Expand Down
Loading
Loading