Skip to content

Commit

Permalink
Merge branch 'master' into particles_od
Browse files Browse the repository at this point in the history
  • Loading branch information
amylizzle authored Feb 20, 2025
2 parents 51638ab + fa88b9d commit dceeccd
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 13 deletions.
1 change: 1 addition & 0 deletions DMCompiler/DM/DMObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public DMObject GetOrCreateDMObject(DreamPath path) {
case "client":
case "datum":
case "list":
case "vector":
case "savefile":
case "world":
parent = GetOrCreateDMObject(DreamPath.Root);
Expand Down
27 changes: 27 additions & 0 deletions DMCompiler/DMStandard/Types/Vector.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/vector
// TODO: Verify these default values
var/len = 2 as num
var/size = 0 as num
var/x = 0 as num
var/y = 0 as num
var/z = 0 as num

proc/New(x, y, z)

proc/Cross(vector/B)
set opendream_unimplemented = TRUE

proc/Dot(vector/B)
set opendream_unimplemented = TRUE

proc/Interpolate(vector/B, t)
set opendream_unimplemented = TRUE

proc/Normalize()
set opendream_unimplemented = TRUE

proc/Turn(angle)
set opendream_unimplemented = TRUE

/proc/vector(x, y, z)
return new /vector(x, y, z)
1 change: 1 addition & 0 deletions DMCompiler/DMStandard/_Standard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ proc/winset(player, control_id, params)
#include "Types\Regex.dm"
#include "Types\Savefile.dm"
#include "Types\Sound.dm"
#include "Types\Vector.dm"
#include "Types\World.dm"
#include "Types\Atoms\_Atom.dm"
#include "Types\Atoms\Area.dm"
Expand Down
4 changes: 4 additions & 0 deletions OpenDreamRuntime/Objects/DreamObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public sealed class DreamObjectTree {
public TreeEntry DatabaseQuery { get; private set; }
public TreeEntry Regex { get; private set; }
public TreeEntry Filter { get; private set; }
public TreeEntry Vector { get; private set; }
public TreeEntry Icon { get; private set; }
public TreeEntry Image { get; private set; }
public TreeEntry MutableAppearance { get; private set; }
Expand Down Expand Up @@ -185,6 +186,8 @@ public DreamObject CreateObject(TreeEntry type) {
throw new Exception("New turfs must be created by the map manager");
if (type.ObjectDefinition.IsSubtypeOf(Exception))
return new DreamObjectException(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Vector))
return new DreamObjectVector(type.ObjectDefinition);

return new DreamObject(type.ObjectDefinition);
}
Expand Down Expand Up @@ -302,6 +305,7 @@ private void LoadTypesFromJson(DreamTypeJson[] types, ProcDefinitionJson[]? proc
DatabaseQuery = GetTreeEntry("/database/query");
Regex = GetTreeEntry("/regex");
Filter = GetTreeEntry("/dm_filter");
Vector = GetTreeEntry("/vector");
Icon = GetTreeEntry("/icon");
Image = GetTreeEntry("/image");
MutableAppearance = GetTreeEntry("/mutable_appearance");
Expand Down
147 changes: 147 additions & 0 deletions OpenDreamRuntime/Objects/Types/DreamObjectVector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System.Linq;
using OpenDreamRuntime.Procs;

namespace OpenDreamRuntime.Objects.Types;

public sealed class DreamObjectVector(DreamObjectDefinition definition) : DreamObject(definition) {
public float X, Y;

public float Z {
get => Is3D ? _z : 0;
set {
if (!Is3D)
return;
_z = value;
}
}

public bool Is3D { get; private set; }

public float Size {
get => MathF.Sqrt(X * X + Y * Y + Z * Z);
set {
if (X == 0 && Y == 0 && Z == 0)
return;

var magnitude = Size;
X = X / magnitude * value;
Y = Y / magnitude * value;
Z = Z / magnitude * value;
}
}

private float _z;

public override void Initialize(DreamProcArguments args) {
base.Initialize(args);

var arg1 = args.GetArgument(0);
if (arg1.TryGetValueAsFloat(out var x) && args.Count is 2 or 3) { // X, Y, optionally Z
X = x;
Y = args.GetArgument(1).UnsafeGetValueAsFloat();
if (args.Count == 3) {
Is3D = true;
Z = args.GetArgument(2).UnsafeGetValueAsFloat();
}

return;
} else if (arg1.TryGetValueAsString(out var vectorStr)) { // Numbers with a comma or 'x' as a delimiter
var components = vectorStr.Split(',', 'x');

if (components.Length is 2 or 3) {
X = float.Parse(components[0]);
Y = float.Parse(components[1]);
if (components.Length == 3) {
Is3D = true;
Z = float.Parse(components[2]);
}

return;
}
} else if (arg1.TryGetValueAsDreamList(out var vectorList)) { // list(X, Y) or list(X, Y, Z)
var components = vectorList.GetValues();

if (components.Count is 2 or 3 && components.All(v => v.Type == DreamValue.DreamValueType.Float)) {
X = components[0].UnsafeGetValueAsFloat();
Y = components[1].UnsafeGetValueAsFloat();
if (components.Count == 3) {
Is3D = true;
Z = components[2].UnsafeGetValueAsFloat();
}

return;
}
} else if (arg1.TryGetValueAsDreamObject<DreamObjectVector>(out var vectorCopy)) { // new /vector(vector)
Is3D = vectorCopy.Is3D;
X = vectorCopy.X;
Y = vectorCopy.Y;
Z = vectorCopy.Z;

return;
}

// TODO: Allow pixloc as an arg
throw new Exception($"Bad vector arguments {args.ToString()}");
}

protected override bool TryGetVar(string varName, out DreamValue value) {
switch (varName) {
case "type":
value = new(ObjectDefinition.TreeEntry);
return true;
case "len":
value = new(Is3D ? 3 : 2);
return true;
case "size":
value = new(Size);
return true;
case "x":
value = new(X);
return true;
case "y":
value = new(Y);
return true;
case "z":
value = new(Z);
return true;
default:
// Hide the base vars
throw new Exception($"Invalid vector variable \"{varName}\"");
}
}

protected override void SetVar(string varName, DreamValue value) {
switch (varName) {
case "type":
throw new Exception("Cannot set type var");
case "len":
var newLen = value.UnsafeGetValueAsFloat();

// Something like 2.3 actually isn't valid here; it doesn't cast to an int
if (!newLen.Equals(2f) && !newLen.Equals(3f)) {
throw new Exception($"Invalid vector len {value}");
}

Is3D = newLen.Equals(3f);
break;
case "size":
Size = value.UnsafeGetValueAsFloat();
break;
case "x":
X = value.UnsafeGetValueAsFloat();
break;
case "y":
Y = value.UnsafeGetValueAsFloat();
break;
case "z":
Z = value.UnsafeGetValueAsFloat();
break;
default:
// Hide the base vars
throw new Exception($"Invalid vector variable \"{varName}\"");
}
}

// TODO: Operators, supports indexing and "most math"
// TODO: For loop support
}
15 changes: 14 additions & 1 deletion OpenDreamRuntime/Procs/DreamProcArguments.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.CompilerServices;
using System.Text;

namespace OpenDreamRuntime.Procs;

Expand Down Expand Up @@ -29,6 +30,18 @@ public DreamValue GetArgument(int argumentPosition) {
}

public override string ToString() {
return $"<Arguments {Count}>";
var strBuilder = new StringBuilder((Count * 2 - 1) + 4);

strBuilder.Append("<Arguments ");
strBuilder.Append(Count);
strBuilder.Append(">(");
for (int i = 0; i < Count; i++) {
strBuilder.Append(Values[i]);
if (i != Count - 1)
strBuilder.Append(", ");
}

strBuilder.Append(')');
return strBuilder.ToString();
}
}
37 changes: 25 additions & 12 deletions OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,20 +1529,33 @@ private static void JsonEncode(Utf8JsonWriter writer, DreamValue value) {
writer.WriteEndArray();
}
} else if (value.TryGetValueAsDreamObject(out var dreamObject)) {
if (dreamObject == null)
writer.WriteNullValue();
else if (dreamObject is DreamObjectMatrix matrix) { // Special behaviour for /matrix values
writer.WriteStartArray();
switch (dreamObject) {
case null:
writer.WriteNullValue();
break;
case DreamObjectMatrix matrix: { // Special behaviour for /matrix values
writer.WriteStartArray();

foreach (var f in DreamObjectMatrix.EnumerateMatrix(matrix)) {
writer.WriteNumberValue(f);
}
foreach (var f in DreamObjectMatrix.EnumerateMatrix(matrix)) {
writer.WriteNumberValue(f);
}

writer.WriteEndArray();
// This doesn't have any corresponding snowflaking in CreateValueFromJsonElement()
// because BYOND actually just forgets that this was a matrix after doing json encoding.
} else
writer.WriteStringValue(value.Stringify());
writer.WriteEndArray();
// This doesn't have any corresponding snowflaking in CreateValueFromJsonElement()
// because BYOND actually just forgets that this was a matrix after doing json encoding.
break;
}
case DreamObjectVector vector: { // Special behaviour for /vector values
if (vector.Is3D)
writer.WriteStringValue($"vector({vector.X},{vector.Y},{vector.Z})");
else
writer.WriteStringValue($"vector({vector.X},{vector.Y})");
break;
}
default:
writer.WriteStringValue(value.Stringify());
break;
}
} else if (value.TryGetValueAsDreamResource(out var dreamResource)) {
writer.WriteStringValue(dreamResource.ResourcePath);
} else {
Expand Down

0 comments on commit dceeccd

Please sign in to comment.