Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
45b0cce
Impliments a BUNCH of procs
CatoChristopherMrow May 9, 2026
7194ead
even more implimentations
CatoChristopherMrow May 9, 2026
d3eaf27
blending fixes
CatoChristopherMrow May 9, 2026
b6e75ea
qdel changes
CatoChristopherMrow May 9, 2026
39fa199
Various bug updates
CatoChristopherMrow May 9, 2026
ff79dc9
bounds
CatoChristopherMrow May 9, 2026
32a4f5d
more fixes
CatoChristopherMrow May 9, 2026
72db6d5
more optimization and runtime fixes
CatoChristopherMrow May 9, 2026
f322b76
another batch
CatoChristopherMrow May 9, 2026
4d75707
another batch to revolve review
CatoChristopherMrow May 9, 2026
75c9f3a
review changes
CatoChristopherMrow May 9, 2026
e49a79e
mor
CatoChristopherMrow May 9, 2026
386f7ca
even mor implimentations
CatoChristopherMrow May 9, 2026
5b605f7
Update DreamInterfaceManager.cs
CatoChristopherMrow May 9, 2026
6184778
v
CatoChristopherMrow May 9, 2026
ad48f4a
Implement BYOND 516 compatibility work
CatoChristopherMrow May 9, 2026
d47a006
mmm
CatoChristopherMrow May 9, 2026
0125f32
Update .gitignore
CatoChristopherMrow May 9, 2026
7150244
Expand BYOND 516 implementation coverage
CatoChristopherMrow May 9, 2026
d9a9d0e
Merge remote-tracking branch 'origin/implimentations' into implimenta…
CatoChristopherMrow May 9, 2026
f5e2efa
old debug removal
CatoChristopherMrow May 9, 2026
79d99f7
Merge remote-tracking branch 'origin/implimentations' into implimenta…
CatoChristopherMrow May 9, 2026
47c1c93
review fixes
CatoChristopherMrow May 9, 2026
70665fb
oops
CatoChristopherMrow May 9, 2026
5104c18
unit test fixes
CatoChristopherMrow May 9, 2026
44dfb39
Optimize the view algorithm (#2565)
wixoaGit May 14, 2026
76b6c00
Batch appearance removals (#2566)
wixoaGit May 14, 2026
01a19e0
Batch new appearances (#2567)
wixoaGit May 14, 2026
ad91ebf
Compress `NewAppearancesEvent` (#2568)
wixoaGit May 15, 2026
a1fcaa1
Merge remote-tracking branch 'upstream/master' into implimentations
CatoChristopherMrow May 15, 2026
64db83f
checkpoint
CatoChristopherMrow May 16, 2026
fb91335
pushing for another to seeee
CatoChristopherMrow May 16, 2026
79e6186
checkpoint
CatoChristopherMrow May 16, 2026
bf4e8ea
mmmmore optimizations
CatoChristopherMrow May 16, 2026
3ab3cb3
moreg
CatoChristopherMrow May 16, 2026
8fa66b3
icon state fixes
CatoChristopherMrow May 16, 2026
72075fe
more updates
CatoChristopherMrow May 17, 2026
317d424
even more fixes.
CatoChristopherMrow May 17, 2026
274aae9
upda
CatoChristopherMrow May 17, 2026
bf6ea77
Another massive batch, mostly bugfixes
CatoChristopherMrow May 18, 2026
e0e3d23
ALL. UNIT. TESTS. PASSED.
CatoChristopherMrow May 19, 2026
7b81801
MOREBG fixes ough
CatoChristopherMrow May 19, 2026
d29df91
I wish to perish
CatoChristopherMrow May 22, 2026
fae5fd9
teeeeeheeee
CatoChristopherMrow May 23, 2026
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,4 @@ ehthumbs.db
# OpenDream-generated files for TestGame
TestGame/preprocessor_dump.dm
TestGame/environment.dmd
/.tmp-build
88 changes: 88 additions & 0 deletions Content.Tests/AppearanceOffsetTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using NUnit.Framework;
using OpenDreamShared.Dream;
using Robust.Shared.Maths;

namespace Content.Tests;

[TestFixture]
public sealed class AppearanceOffsetTests {
[Test]
public void IconOffsetActsAsNegativePixelWZ() {
MutableAppearance appearance = MutableAppearance.Get();
try {
appearance.PixelOffset = new Vector2i(1, 2);
appearance.PixelOffset2 = new Vector2i(8, 16);
appearance.IconOffset = new Vector2i(3, 5);

var immutable = new ImmutableAppearance(appearance, null);

Assert.That(immutable.GetTotalPixelOffset(MapFormat.Side), Is.EqualTo(new Vector2i(6, 13)));
} finally {
appearance.Dispose();
}
}

[Test]
public void SideMapRootIconsApplyBoundingBoxAnchor() {
MutableAppearance appearance = MutableAppearance.Get();
try {
appearance.PixelOffset2 = new Vector2i(8, 16);
appearance.IconOffset = new Vector2i(3, 5);

var immutable = new ImmutableAppearance(appearance, null);

Assert.That(
AppearancePositioning.GetPixelOffset(immutable, MapFormat.Side, new Vector2i(32, 32), new Vector2i(4, 7), true),
Is.EqualTo(new Vector2i(9, 18)));
} finally {
appearance.Dispose();
}
}

[Test]
public void IsometricRootIconsAnchorByLeftCorner() {
MutableAppearance appearance = MutableAppearance.Get();
try {
var immutable = new ImmutableAppearance(appearance, null);

Assert.That(
AppearancePositioning.GetPixelOffset(immutable, MapFormat.Isometric, new Vector2i(32, 64), Vector2i.Zero, true),
Is.EqualTo(new Vector2i(0, -32)));
} finally {
appearance.Dispose();
}
}

[Test]
public void OverlaysDoNotApplyRootMapFormatAnchors() {
MutableAppearance appearance = MutableAppearance.Get();
try {
var immutable = new ImmutableAppearance(appearance, null);

Assert.That(
AppearancePositioning.GetPixelOffset(immutable, MapFormat.Isometric, new Vector2i(32, 64), new Vector2i(9, 11), false),
Is.EqualTo(Vector2i.Zero));
} finally {
appearance.Dispose();
}
}

[Test]
public void IconOffsetIsCopiedIntoMutableAppearances() {
MutableAppearance appearance = MutableAppearance.Get();
try {
appearance.IconOffset = new Vector2i(4, 7);

var immutable = new ImmutableAppearance(appearance, null);
MutableAppearance copy = immutable.ToMutable();

try {
Assert.That(copy.IconOffset, Is.EqualTo(new Vector2i(4, 7)));
} finally {
copy.Dispose();
}
} finally {
appearance.Dispose();
}
}
}
55 changes: 55 additions & 0 deletions Content.Tests/BrowserBridgeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using NUnit.Framework;
using OpenDreamClient.Interface;
using OpenDreamShared.Interface.DMF;

namespace Content.Tests;

[TestFixture]
public sealed class BrowserBridgeTests {
[Test]
public void WildcardWingetJsonUsesRawStringValues() {
var json = BrowserBridgeJson.EncodePropertyMap([
("size", new DMFPropertySize(640, 456)),
("pos", new DMFPropertyPos(12, 34))
], rawStringValues: true);

Assert.Multiple(() => {
Assert.That(json, Does.Contain("\"size\":\"640x456\""));
Assert.That(json, Does.Contain("\"pos\":\"12,34\""));
Assert.That(json, Does.Not.Contain("\"size\":{\"x\""));
Assert.That(json, Does.Not.Contain("\"pos\":{\"x\""));
});
}

[Test]
public void ExplicitJsonWingetKeepsTypedValues() {
var json = BrowserBridgeJson.EncodePropertyMap([
("size", new DMFPropertySize(640, 456)),
("pos", new DMFPropertyPos(12, 34))
], rawStringValues: false);

Assert.Multiple(() => {
Assert.That(json, Does.Contain("\"size\":{\"x\":640"));
Assert.That(json, Does.Contain("\"y\":456"));
Assert.That(json, Does.Contain("\"pos\":{\"x\":12"));
Assert.That(json, Does.Contain("\"y\":34"));
});
}

[Test]
public void TguiOutputMessageBecomesBrowserUpdateCall() {
const string message = "%7b%22type%22%3a%22props%22%2c%22payload%22%3a%7b%22size%22%3a%22640x456%22%7d%7d";

var script = BrowserBridgeScript.FormatOutputCall("update", message);

Assert.That(script, Is.EqualTo("update(\"{\\\"type\\\":\\\"props\\\",\\\"payload\\\":{\\\"size\\\":\\\"640x456\\\"}}\")"));
}

[Test]
public void OutputParamsBecomeSeparateBrowserArguments() {
var arguments = BrowserBridgeScript.FormatOutputArguments("first%20arg&second%22arg");

Assert.That(arguments, Is.EqualTo("\"first arg\",\"second\\\"arg\""));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// NOBYOND - OpenDream-specific animate(null) compatibility smoke test
/proc/RunTest()
ASSERT(isnull(animate(null)))
ASSERT(isnull(animate(null, alpha = 128, time = 1)))
ASSERT(isnull(animate(alpha = 128, time = 1)))

var/obj/O = new()
animate(O, pixel_x = 8, time = 1)
animate(pixel_y = 4, time = 1)
25 changes: 25 additions & 0 deletions Content.Tests/DMProject/Tests/Appearance/OverlaySourceRefcount.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// NOBYOND - OpenDream refcount regression test
/proc/RunTest()
world.maxx = 1
world.maxy = 1
world.maxz = 1

var/obj/owner = new(locate(1, 1, 1))
var/obj/source = new(locate(1, 1, 1))
var/baseline = refcount(source)

owner.overlays += source
var/after_add = refcount(source)
if (after_add != baseline + 1)
CRASH("Expected overlays += source to hold one source ref; baseline [baseline], got [after_add]")

owner.overlays.Cut()
ASSERT(refcount(source) == baseline)

owner.overlays = list(source)
var/after_replace = refcount(source)
if (after_replace != baseline + 1)
CRASH("Expected overlays = list(source) to hold one source ref; baseline [baseline], got [after_replace]")

owner.overlays -= source
ASSERT(refcount(source) == baseline)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/proc/RunTest()
var/atom/A = new /obj()
var/mutable_appearance/underlay = new /mutable_appearance()
underlay.plane = 1
A.underlays += underlay

var/mutable_appearance/copy = new(A)
copy.plane = 2

for (var/mutable_appearance/current as anything in copy.underlays)
if (current.plane != copy.plane)
copy.underlays -= current

ASSERT(length(copy.underlays) == 0)
16 changes: 16 additions & 0 deletions Content.Tests/DMProject/Tests/Area/contents_assignment.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/area/contents_assignment

/proc/RunTest()
world.maxx = 1
world.maxy = 1
world.maxz = 1

var/turf/turf = locate(1, 1, 1)
var/area/old_area = turf.loc
var/area/contents_assignment/new_area = new

new_area.contents = list(turf)

ASSERT(turf.loc == new_area)
ASSERT(turf in new_area.contents)
ASSERT(!(turf in old_area.contents))
7 changes: 7 additions & 0 deletions Content.Tests/DMProject/Tests/Atom/color_default.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/proc/RunTest()
var/atom/A = new /obj()
ASSERT(isnull(A.color))
ASSERT(isnull(initial(A.color)))

A.color = "#ff0000"
ASSERT(A.color == "#ff0000")
16 changes: 16 additions & 0 deletions Content.Tests/DMProject/Tests/Atom/empty_icon_state_is_null.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// NOBYOND - OpenDream normalizes empty appearance icon_state values to null
/obj/empty_icon_state
icon_state = ""

/proc/RunTest()
var/obj/empty_icon_state/type_path = /obj/empty_icon_state
var/obj/empty_icon_state/instance = new

ASSERT(isnull(initial(type_path.icon_state)))
ASSERT(isnull(instance.icon_state))

instance.icon_state = "filled"
ASSERT(instance.icon_state == "filled")

instance.icon_state = ""
ASSERT(isnull(instance.icon_state))
6 changes: 6 additions & 0 deletions Content.Tests/DMProject/Tests/Atom/icon_state_default.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/proc/RunTest()
var/atom/A = /atom
var/obj/O = /obj

ASSERT(isnull(initial(A.icon_state)))
ASSERT(isnull(initial(O.icon_state)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/obj/implicit_parent_appearance/child
icon_state = "child"

/proc/RunTest()
var/obj/implicit_parent_appearance/parent_type = /obj/implicit_parent_appearance
var/obj/implicit_parent_appearance/child/child_type = /obj/implicit_parent_appearance/child

ASSERT(isnull(initial(parent_type.icon_state)))
ASSERT(initial(child_type.icon_state) == "child")

for(var/obj/obj_path as anything in typesof(/obj/implicit_parent_appearance) - /obj/implicit_parent_appearance)
if(obj_path == /obj/implicit_parent_appearance/child)
ASSERT(initial(obj_path.icon_state) == "child")
continue

ASSERT(isnull(initial(obj_path.icon_state)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/proc/RunTest()
var/list/decoded = json_decode(@'["alpha","beta"]')

ASSERT(decoded[1] == "alpha")
ASSERT(decoded[2] == "beta")
ASSERT(isnull(decoded["alpha"]))
ASSERT(isnull(decoded["beta"]))
7 changes: 7 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/Replacetext.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@
// /regex can be used as a Needle
ASSERT(replacetext(str, new /regex("."), "G") == "GBCDEF");
ASSERT(replacetext(str, new /regex(".", "g"), "G") == "GGGGGG");

var/lizard_speech = "She is so sassy"
lizard_speech = replacetextEx(lizard_speech, new /regex("s+", "g"), "sss")
lizard_speech = replacetextEx(lizard_speech, new /regex("S+", "g"), "SSS")
ASSERT(lizard_speech == "SSShe isss ssso sssasssy")

ASSERT(replacetextEx("X-ray X box", new /regex(@"\bX([\-|r|R]|\b)", "g"), "ECKS$1") == "ECKS-ray ECKS box")
12 changes: 11 additions & 1 deletion Content.Tests/DMProject/Tests/Builtins/callee.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
ASSERT(callee.desc == "bar description")
return callee

/proc/leaf()
ASSERT(callee.name == "leaf")
ASSERT(caller.name == "middle")

/proc/middle()
ASSERT(caller.name == "RunTest")
leaf()

/proc/RunTest()
ASSERT(callee.name == "RunTest")
ASSERT(copytext(callee.file, -9) == "callee.dm")

middle()

var/callee/expired_callee = bar()
var/failed = FALSE
try
var/name = expired_callee.name
catch (var/exception/E)
failed = TRUE
ASSERT(failed)
ASSERT(failed)
6 changes: 6 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/deleted_object_null.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/proc/RunTest()
var/datum/thing = new()
del(thing)

ASSERT(isnull(thing))
ASSERT("[thing]" == "")
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/proc/RunTest()
var/atom/movable/A = new /obj()

A.filters += filter(type = "color")
ASSERT(length(A.filters) == 1)
6 changes: 6 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/get_step_deleted.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/proc/RunTest()
var/obj/item = new /obj()
del(item)

ASSERT(isnull(get_step(item, NORTH)))
ASSERT(isnull(get_step(item, 0)))
7 changes: 7 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/icon_states_modes.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/proc/RunTest()
var/list/default_states = icon_states('turf.dmi')
ASSERT(length(default_states))
ASSERT(!("" in default_states))

ASSERT(length(icon_states('turf.dmi', 1)) == length(default_states))
ASSERT(length(icon_states('turf.dmi', 2)) == length(default_states))
9 changes: 9 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/ispath_dynamic_path.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/obj/ispath_dynamic_parent

/obj/ispath_dynamic_parent/child

/proc/RunTest()
var/list/allowed = list(/obj/ispath_dynamic_parent)
var/type = allowed[1]

ASSERT(ispath(/obj/ispath_dynamic_parent/child, type))
10 changes: 10 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/istype_dynamic_path.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/obj/istype_dynamic_parent

/obj/istype_dynamic_parent/child

/proc/RunTest()
var/obj/O = new /obj/istype_dynamic_parent/child
var/list/allowed = list(/obj/istype_dynamic_parent)
var/type = allowed[1]

ASSERT(istype(O, type))
Loading
Loading