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

Implement get_steps_to() and get_step_to() #2170

Merged
merged 6 commits into from
Jan 17, 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
1 change: 1 addition & 0 deletions Content.Tests/ContentUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Reflection;
using OpenDreamClient;
using OpenDreamRuntime;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Rendering;
using OpenDreamShared;
using OpenDreamShared.Rendering;
Expand Down
6 changes: 5 additions & 1 deletion Content.Tests/DummyDreamMapManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DMCompiler.Json;
using OpenDreamRuntime;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs;
Expand Down Expand Up @@ -54,4 +54,8 @@ public void SetWorldSize(Vector2i size) { }
public EntityUid GetZLevelEntity(int z) {
return EntityUid.Invalid;
}

public IEnumerable<AtomDirection> CalculateSteps((int X, int Y, int Z) loc, (int X, int Y, int Z) dest, int distance) {
yield break;
}
}
10 changes: 2 additions & 8 deletions DMCompiler/DMStandard/_Standard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ proc/flist(Path) as /list
proc/floor(A) as num
proc/fract(n) as num
proc/ftime(File, IsCreationTime = 0) as num
proc/get_step_to(Ref, Trg, Min=0) as num
proc/get_steps_to(Ref, Trg, Min=0) as /list
proc/gradient(A, index)
proc/hascall(Object, ProcName) as num
proc/hearers(Depth = world.view, Center = usr) as /list
Expand Down Expand Up @@ -161,14 +163,6 @@ proc/replacetextEx_char(Haystack as text, Needle, Replacement, Start = 1, End =
var/step_dir = get_dir(Ref, Trg)
return step(Ref, step_dir, Speed)

/proc/get_step_to(Ref, Trg, Min=0)
set opendream_unimplemented = TRUE
CRASH("/get_step_to() is not implemented")

/proc/get_steps_to(Ref, Trg, Min=0) as /list
set opendream_unimplemented = TRUE
CRASH("/get_steps_to() is not implemented")

/proc/walk_away(Ref,Trg,Max=5,Lag=0,Speed=0)
set opendream_unimplemented = TRUE
CRASH("/walk_away() is not implemented")
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/AtomManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs.Native;
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/DreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading;
using DMCompiler.Bytecode;
using DMCompiler.Json;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs;
Expand Down
5 changes: 2 additions & 3 deletions OpenDreamRuntime/Input/MouseInputSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Text;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects.Types;
using OpenDreamShared.Input;

Expand Down
110 changes: 110 additions & 0 deletions OpenDreamRuntime/Map/DreamMapManager.Pathfinding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System.Diagnostics.CodeAnalysis;
using OpenDreamRuntime.Procs.Native;
using OpenDreamShared.Dream;

namespace OpenDreamRuntime.Map;

public partial class DreamMapManager {
private sealed class PathFindNode : IDisposable, IEquatable<PathFindNode> {
private static readonly Stack<PathFindNode> Pool = new();

public int X, Y;
public PathFindNode? Parent;
public int NeededSteps;

public static PathFindNode GetNode(int x, int y) {
if (!Pool.TryPop(out var node)) {
node = new();
}

node.Parent = null;
node.X = x;
node.Y = y;
node.NeededSteps = 0;
return node;
}

public void Dispose() {
Pool.Push(this);
}

public bool Equals(PathFindNode? other) {
if (other is null)
return false;
return X == other.X && Y == other.Y;
}

[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
public override int GetHashCode() {
return HashCode.Combine(X, Y);
}
}

public IEnumerable<AtomDirection> CalculateSteps((int X, int Y, int Z) loc, (int X, int Y, int Z) dest, int distance) {
int z = loc.Z;
if (z != dest.Z) // Different Z-levels are unreachable
yield break;

HashSet<PathFindNode> explored = new();
Queue<PathFindNode> toExplore = new();

toExplore.Enqueue(PathFindNode.GetNode(loc.X, loc.Y));

void Explore(PathFindNode current, int offsetX, int offsetY) {
var nextX = current.X + offsetX;
var nextY = current.Y + offsetY;
if (nextX < 1 || nextX > Size.X || nextY < 1 || nextY > Size.Y)
return; // This is outside of map bounds

var next = PathFindNode.GetNode(nextX, nextY);
if (explored.Contains(next))
return;
if (!TryGetCellAt(new(next.X, next.Y), z, out var cell) || cell.Turf.IsDense)
return;

if (!toExplore.Contains(next))
toExplore.Enqueue(next);
else if (next.NeededSteps >= current.NeededSteps + 1)
return;

next.NeededSteps = current.NeededSteps + 1;
next.Parent = current;
}

while (toExplore.TryDequeue(out var node)) {
var distX = node.X - dest.X;
var distY = node.Y - dest.Y;
if (Math.Sqrt(distX * distX + distY * distY) <= distance) { // Path to the destination was found
Stack<AtomDirection> path = new(node.NeededSteps);

while (node.Parent != null) {
var stepDir = DreamProcNativeHelpers.GetDir((node.Parent.X, node.Parent.Y, z), (node.X, node.Y, z));

node = node.Parent;
path.Push(stepDir);
}

while (path.TryPop(out var step)) {
yield return step;
}

break;
}

explored.Add(node);
Explore(node, 1, 0);
Explore(node, 1, 1);
Explore(node, 0, 1);
Explore(node, -1, 1);
Explore(node, -1, 0);
Explore(node, -1, -1);
Explore(node, 0, -1);
Explore(node, 1, -1);
}

foreach (var node in explored)
node.Dispose();
foreach (var node in toExplore)
node.Dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
using Level = OpenDreamRuntime.IDreamMapManager.Level;
using Cell = OpenDreamRuntime.IDreamMapManager.Cell;
using Level = OpenDreamRuntime.Map.IDreamMapManager.Level;
using Cell = OpenDreamRuntime.Map.IDreamMapManager.Cell;

namespace OpenDreamRuntime;
namespace OpenDreamRuntime.Map;

public sealed class DreamMapManager : IDreamMapManager {
public sealed partial class DreamMapManager : IDreamMapManager {
[Dependency] private readonly DreamManager _dreamManager = default!;
[Dependency] private readonly AtomManager _atomManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
Expand Down Expand Up @@ -497,4 +497,6 @@ public Cell(DreamObjectArea area, DreamObjectTurf turf) {
public void SetZLevels(int levels);
public void SetWorldSize(Vector2i size);
public EntityUid GetZLevelEntity(int z);

public IEnumerable<AtomDirection> CalculateSteps((int X, int Y, int Z) loc, (int X, int Y, int Z) dest, int distance);
}
1 change: 1 addition & 0 deletions OpenDreamRuntime/Objects/DreamObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using DMCompiler.Bytecode;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Rendering;
using OpenDreamRuntime.Resources;
Expand Down
2 changes: 1 addition & 1 deletion OpenDreamRuntime/Objects/DreamObjectDefinition.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Procs;
using OpenDreamRuntime.Rendering;
using OpenDreamRuntime.Resources;
using OpenDreamShared.Dream;
using Robust.Server.GameObjects;
using Robust.Server.GameStates;
using Robust.Server.Player;
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Objects/DreamObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text.Json;
using System.Threading.Tasks;
using DMCompiler.Json;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs;
using OpenDreamRuntime.Procs.DebugAdapter;
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Objects/Types/DreamList.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using System.Runtime.CompilerServices;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Procs;
using OpenDreamRuntime.Rendering;
using OpenDreamShared.Dream;
Expand Down
5 changes: 4 additions & 1 deletion OpenDreamRuntime/Objects/Types/DreamObjectTurf.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OpenDreamShared.Dream;
using OpenDreamRuntime.Map;
using OpenDreamShared.Dream;

namespace OpenDreamRuntime.Objects.Types;

Expand All @@ -8,6 +9,8 @@ public sealed class DreamObjectTurf : DreamObjectAtom {
public ImmutableAppearance Appearance;
public IDreamMapManager.Cell Cell;

public bool IsDense => GetVariable("density").IsTruthy();

public DreamObjectTurf(DreamObjectDefinition objectDefinition, int x, int y, int z) : base(objectDefinition) {
X = x;
Y = y;
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Procs/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using DMCompiler.Bytecode;
using DMCompiler.DM;
using DMCompiler.Json;
using OpenDreamRuntime.Map;
using OpenDreamRuntime.Objects;
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs.DebugAdapter;
Expand Down
6 changes: 4 additions & 2 deletions OpenDreamRuntime/Procs/Native/DreamProcNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public static void SetupNativeProcs(DreamObjectTree objectTree) {
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_floor);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_fract);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_ftime);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_get_step_to);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_get_steps_to);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_hascall);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_hearers);
objectTree.SetGlobalNativeProc(DreamProcNativeRoot.NativeProc_html_decode);
Expand Down Expand Up @@ -145,14 +147,14 @@ public static void SetupNativeProcs(DreamObjectTree objectTree) {

objectTree.SetNativeProc(objectTree.Savefile, DreamProcNativeSavefile.NativeProc_ExportText);
objectTree.SetNativeProc(objectTree.Savefile, DreamProcNativeSavefile.NativeProc_Flush);

objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_Export);
objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_GetConfig);
objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_Profile);
objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_SetConfig);
objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_ODHotReloadInterface);
objectTree.SetNativeProc(objectTree.World, DreamProcNativeWorld.NativeProc_ODHotReloadResource);

objectTree.SetNativeProc(objectTree.Database, DreamProcNativeDatabase.NativeProc_Close);
objectTree.SetNativeProc(objectTree.Database, DreamProcNativeDatabase.NativeProc_Error);
objectTree.SetNativeProc(objectTree.Database, DreamProcNativeDatabase.NativeProc_ErrorMsg);
Expand Down
16 changes: 11 additions & 5 deletions OpenDreamRuntime/Procs/Native/DreamProcNativeHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text.RegularExpressions;
using OpenDreamRuntime.Objects.Types;
using System.Text;
using OpenDreamRuntime.Map;

namespace OpenDreamRuntime.Procs.Native;

Expand Down Expand Up @@ -541,21 +542,26 @@ public static AtomDirection GetDir(AtomManager atomManager, DreamObjectAtom loc1
var loc1Pos = atomManager.GetAtomPosition(loc1);
var loc2Pos = atomManager.GetAtomPosition(loc2);

if (loc1Pos.Z != loc2Pos.Z) // They must be on the same z-level
return GetDir(loc1Pos, loc2Pos);
}

/// <inheritdoc cref="GetDir(OpenDreamRuntime.AtomManager,OpenDreamRuntime.Objects.Types.DreamObjectAtom,OpenDreamRuntime.Objects.Types.DreamObjectAtom)"/>
public static AtomDirection GetDir((int X, int Y, int Z) loc1, (int X, int Y, int Z) loc2) {
if (loc1.Z != loc2.Z) // They must be on the same z-level
return 0;

AtomDirection direction = AtomDirection.None;

// East or West
if (loc2Pos.X < loc1Pos.X)
if (loc2.X < loc1.X)
direction |= AtomDirection.West;
else if (loc2Pos.X > loc1Pos.X)
else if (loc2.X > loc1.X)
direction |= AtomDirection.East;

// North or South
if (loc2Pos.Y < loc1Pos.Y)
if (loc2.Y < loc1.Y)
direction |= AtomDirection.South;
else if (loc2Pos.Y > loc1Pos.Y)
else if (loc2.Y > loc1.Y)
direction |= AtomDirection.North;

return direction;
Expand Down
Loading
Loading