diff --git a/Content.IntegrationTests/DMProject/Tests/string_interpolation.dm b/Content.IntegrationTests/DMProject/Tests/string_interpolation.dm
new file mode 100644
index 0000000000..f64128b0c1
--- /dev/null
+++ b/Content.IntegrationTests/DMProject/Tests/string_interpolation.dm
@@ -0,0 +1,13 @@
+/obj/blombo
+ name = "Blombo"
+ gender = FEMALE
+
+/obj/blorpo
+ name = "Blorpo"
+ gender = MALE
+
+/proc/test_string_interpolation()
+ var/obj/blombo/b = new
+ var/obj/blorpo/b2 = new
+ var/result_text = "[b]? Nobody likes \him. \He is awful! Unlike [b2]. \He is pretty cool!"
+ ASSERT(result_text == "Blombo? Nobody likes her. She is awful! Unlike Blorpo. He is pretty cool!")
\ No newline at end of file
diff --git a/Content.IntegrationTests/DMProject/code.dm b/Content.IntegrationTests/DMProject/code.dm
index a923928517..6e6827200f 100644
--- a/Content.IntegrationTests/DMProject/code.dm
+++ b/Content.IntegrationTests/DMProject/code.dm
@@ -34,4 +34,5 @@
test_nonlocal_var()
test_images()
test_filter_init()
+ test_string_interpolation()
world.log << "IntegrationTests successful, /world/New() exiting..."
\ No newline at end of file
diff --git a/Content.Tests/DMProject/Tests/Preprocessor/macro_newline_var.dm b/Content.Tests/DMProject/Tests/Preprocessor/macro_newline_var.dm
index 2d2d609cc8..4aa1d76373 100644
--- a/Content.Tests/DMProject/Tests/Preprocessor/macro_newline_var.dm
+++ b/Content.Tests/DMProject/Tests/Preprocessor/macro_newline_var.dm
@@ -1,8 +1,10 @@
+/datum/var/name
+
#define DEFINE_FLOORS(_PATH, _VARS) \
- /obj/simulated/floor/_PATH{_VARS};\
- /obj/unsimulated/floor/_PATH{_VARS};\
- /obj/simulated/floor/airless/_PATH{_VARS};\
- /obj/unsimulated/floor/airless/_PATH{_VARS};
+ /datum/simulated/floor/_PATH{_VARS};\
+ /datum/unsimulated/floor/_PATH{_VARS};\
+ /datum/simulated/floor/airless/_PATH{_VARS};\
+ /datum/unsimulated/floor/airless/_PATH{_VARS};
var/list/gvars_datum_init_order = list()
@@ -42,8 +44,8 @@ proc/RunTest()
ASSERT(test.len == 4)
InitGlobaltest2()
ASSERT(test2.len == 2)
- var/obj/simulated/floor/carpet/regalcarpet/C1 = new()
- var/obj/simulated/floor/carpet/regalcarpet/border/C2 = new()
+ var/datum/simulated/floor/carpet/regalcarpet/C1 = new()
+ var/datum/simulated/floor/carpet/regalcarpet/border/C2 = new()
ASSERT(C1.name == "regal carpet")
ASSERT(C2.name == "regal carpet border")
diff --git a/Content.Tests/DMProject/Tests/Preprocessor/macro_numeric_path.dm b/Content.Tests/DMProject/Tests/Preprocessor/macro_numeric_path.dm
index a3d4448a56..2adb74318d 100644
--- a/Content.Tests/DMProject/Tests/Preprocessor/macro_numeric_path.dm
+++ b/Content.Tests/DMProject/Tests/Preprocessor/macro_numeric_path.dm
@@ -1,15 +1,17 @@
-/obj/thing_1/dodaa
+/datum/var/name
+
+/datum/thing_1/dodaa
name = "underscore 1 test"
-#define NUMPATH_OBJDEF(num) /obj/thing_##num/name = #num
+#define NUMPATH_OBJDEF(num) /datum/thing_##num/name = #num
NUMPATH_OBJDEF(4)
NUMPATH_OBJDEF(stuff)
/proc/RunTest()
- var/obj/thing_1/dodaa/D = new
+ var/datum/thing_1/dodaa/D = new
ASSERT(D.name == "underscore 1 test")
- var/obj/thing_4/T = new
+ var/datum/thing_4/T = new
ASSERT(T.name == "4")
- var/obj/thing_stuff/Y = new
+ var/datum/thing_stuff/Y = new
ASSERT(Y.name == "stuff")
\ No newline at end of file
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation2.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation2.dm
index 385d9c0c88..1322bff03a 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation2.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation2.dm
@@ -1,8 +1,8 @@
-/obj/blombo
- name = "Blombo"
+/datum/blombo
+ var/name = "Blombo"
/proc/RunTest()
- var/obj/blombo/b = new
+ var/datum/blombo/b = new
var/result_text = "Nobody likes [b]!"
ASSERT(result_text == "Nobody likes Blombo!")
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation3.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation3.dm
index 54cb329034..20bea3f509 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation3.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation3.dm
@@ -1,14 +1,23 @@
+/datum/test/var/name
-/obj/blombo
- name = "Blombo"
- gender = FEMALE
-
-/obj/blorpo
- name = "Blorpo"
- gender = MALE
+/datum/test/test1
+ name = ""
+/datum/test/test2
+ name = " " // 3 spaces
+/datum/test/test3
+ name = "\t"
/proc/RunTest()
- var/obj/blombo/b = new
- var/obj/blorpo/b2 = new
- var/result_text = "[b]? Nobody likes \him. \He is awful! Unlike [b2]. \He is pretty cool!"
- ASSERT(result_text == "Blombo? Nobody likes her. She is awful! Unlike Blorpo. He is pretty cool!")
+ var/list/correct = list(
+ "/datum/test/test1: ",
+ "/datum/test/test2: ",
+ "/datum/test/test3: \t"
+ )
+ var/i = 1
+ for (var/T in typesof(/datum/test))
+ if(T == /datum/test)
+ continue
+ var/datum/test/D = new T()
+ var/true_text = correct[i]
+ ASSERT(true_text == "[T]: \the [D]")
+ ++i
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation4.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation4.dm
index 5688dd1030..e960741bb0 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation4.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation4.dm
@@ -1,21 +1,15 @@
-/obj/test1
- name = ""
-/obj/test2
- name = " " // 3 spaces
-/obj/test3
- name = "\t"
+
/proc/RunTest()
- var/list/correct = list(
- "/obj/test1: ",
- "/obj/test2: ",
- "/obj/test3: \t"
- )
- var/i = 1
- for (var/T in typesof(/obj))
- if(T == /obj)
- continue
- var/obj/O = new T()
- var/true_text = correct[i]
- ASSERT(true_text == "[T]: \the [O]")
- ++i
+ var/text = "["1"]\s"
+ ASSERT(text == "1s")
+ text = "[0]\s"
+ ASSERT(text == "0s")
+ text = "[null]\s"
+ ASSERT(text == "s")
+ text = "[1]\s"
+ ASSERT(text == "1")
+ text = "[1.00000001]\s"
+ ASSERT(text == "1")
+ text = "[1.0001]\s"
+ ASSERT(text == "1.0001s")
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation5.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation5.dm
index fc768b0371..d2b0eeb0cd 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation5.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation5.dm
@@ -1,11 +1,30 @@
/proc/RunTest()
- var/atom/O = new()
- O.name = "foo"
- O.gender = FEMALE
- var/atom/O2 = new
- O2.name = "foob"
- O2.gender = MALE
- var/text = "[O2], \ref[O], \his"
- ASSERT(findtextEx(text,", his") != 0)
+ var/text = "[0]\th"
+ ASSERT(text == "0th")
+ text = "[1]\th"
+ ASSERT(text == "1st")
+ text = "[2]\th"
+ ASSERT(text == "2nd")
+ text = "[3]\th"
+ ASSERT(text == "3rd")
+ text = "[4]\th"
+ ASSERT(text == "4th")
+ text = "[-1]\th"
+ ASSERT(text == "-1th")
+ text = "[4.52]\th"
+ ASSERT(text == "4th")
+ text = "the fitness [1.7]\th is a"
+ ASSERT(text == "the fitness 1st is a")
+ text = "the fitness [99999999]\th is a"
+ ASSERT(text == "the fitness 100000000th is a")
+ text = "[null]\th"
+ ASSERT(text == "0th")
+ var/datum/D = new
+ text = "[D]\th"
+ ASSERT(text == "0th")
+ var/foo = "bar"
+ text = "[foo]\th"
+ ASSERT(text == "0th")
+
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation6.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation6.dm
index e960741bb0..4d9b638105 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation6.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation6.dm
@@ -1,15 +1,11 @@
-
-
-/proc/RunTest()
- var/text = "["1"]\s"
- ASSERT(text == "1s")
- text = "[0]\s"
- ASSERT(text == "0s")
- text = "[null]\s"
- ASSERT(text == "s")
- text = "[1]\s"
- ASSERT(text == "1")
- text = "[1.00000001]\s"
- ASSERT(text == "1")
- text = "[1.0001]\s"
- ASSERT(text == "1.0001s")
+/proc/RunTest()
+ ASSERT("\roman[1.5]" == "i")
+ ASSERT("\roman [1.5]" == " i")
+ ASSERT("\Roman[1.5]" == "I")
+ ASSERT("\Roman [1.5]" == " I")
+ ASSERT("\roman shitposts [1]" == " shitposts i")
+ ASSERT("\roman shitposts [1] \the [2] [3]\s" == " shitposts i 3s")
+ ASSERT("\roman[1.#INF]" == "∞")
+ ASSERT("\roman[-1.#INF]" == "-∞")
+ ASSERT("\roman [-1.#INF]" == " -∞")
+ ASSERT("\roman[1.#IND]" == "�")
\ No newline at end of file
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation7.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation7.dm
index d2b0eeb0cd..9ff619a52a 100644
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation7.dm
+++ b/Content.Tests/DMProject/Tests/Text/StringInterpolation7.dm
@@ -1,30 +1,39 @@
+/datum/thing
+ var/name = "thing"
+/datum/Thing
+ var/name = "Thing"
+
+/datum/proper_thing
+ var/name = "\proper thing"
+
+/datum/plural_things
+ var/name = "things"
+ var/gender = PLURAL
/proc/RunTest()
- var/text = "[0]\th"
- ASSERT(text == "0th")
- text = "[1]\th"
- ASSERT(text == "1st")
- text = "[2]\th"
- ASSERT(text == "2nd")
- text = "[3]\th"
- ASSERT(text == "3rd")
- text = "[4]\th"
- ASSERT(text == "4th")
- text = "[-1]\th"
- ASSERT(text == "-1th")
- text = "[4.52]\th"
- ASSERT(text == "4th")
- text = "the fitness [1.7]\th is a"
- ASSERT(text == "the fitness 1st is a")
- text = "the fitness [99999999]\th is a"
- ASSERT(text == "the fitness 100000000th is a")
- text = "[null]\th"
- ASSERT(text == "0th")
- var/datum/D = new
- text = "[D]\th"
- ASSERT(text == "0th")
- var/foo = "bar"
- text = "[foo]\th"
- ASSERT(text == "0th")
+ // Lowercase \a on datums
+ ASSERT("\a [new /datum/thing]" == "a thing")
+ ASSERT("\a [new /datum/Thing]" == "Thing")
+ ASSERT("\a [new /datum/proper_thing]" == "thing")
+ ASSERT("\a [new /datum/plural_things]" == "some things")
+
+ // Uppercase \A on datums
+ ASSERT("\A [new /datum/thing]" == "A thing")
+ ASSERT("\A [new /datum/Thing]" == "Thing")
+ ASSERT("\A [new /datum/proper_thing]" == "thing")
+ ASSERT("\A [new /datum/plural_things]" == "Some things")
+
+ // Lowercase \a on strings
+ ASSERT("\a ["thing"]" == "a thing")
+ ASSERT("\a ["Thing"]" == "Thing")
+ ASSERT("\a ["\proper thing"]" == "thing")
+
+ // Uppercase \A on strings
+ ASSERT("\A ["thing"]" == "A thing")
+ ASSERT("\A ["Thing"]" == "Thing")
+ ASSERT("\A ["\proper thing"]" == "thing")
+ // Invalid \a
+ ASSERT("\a [123]" == "")
+ ASSERT("\A [123]" == "")
\ No newline at end of file
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation8.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation8.dm
deleted file mode 100644
index 4d9b638105..0000000000
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation8.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/proc/RunTest()
- ASSERT("\roman[1.5]" == "i")
- ASSERT("\roman [1.5]" == " i")
- ASSERT("\Roman[1.5]" == "I")
- ASSERT("\Roman [1.5]" == " I")
- ASSERT("\roman shitposts [1]" == " shitposts i")
- ASSERT("\roman shitposts [1] \the [2] [3]\s" == " shitposts i 3s")
- ASSERT("\roman[1.#INF]" == "∞")
- ASSERT("\roman[-1.#INF]" == "-∞")
- ASSERT("\roman [-1.#INF]" == " -∞")
- ASSERT("\roman[1.#IND]" == "�")
\ No newline at end of file
diff --git a/Content.Tests/DMProject/Tests/Text/StringInterpolation9.dm b/Content.Tests/DMProject/Tests/Text/StringInterpolation9.dm
deleted file mode 100644
index 9ff619a52a..0000000000
--- a/Content.Tests/DMProject/Tests/Text/StringInterpolation9.dm
+++ /dev/null
@@ -1,39 +0,0 @@
-/datum/thing
- var/name = "thing"
-
-/datum/Thing
- var/name = "Thing"
-
-/datum/proper_thing
- var/name = "\proper thing"
-
-/datum/plural_things
- var/name = "things"
- var/gender = PLURAL
-
-/proc/RunTest()
- // Lowercase \a on datums
- ASSERT("\a [new /datum/thing]" == "a thing")
- ASSERT("\a [new /datum/Thing]" == "Thing")
- ASSERT("\a [new /datum/proper_thing]" == "thing")
- ASSERT("\a [new /datum/plural_things]" == "some things")
-
- // Uppercase \A on datums
- ASSERT("\A [new /datum/thing]" == "A thing")
- ASSERT("\A [new /datum/Thing]" == "Thing")
- ASSERT("\A [new /datum/proper_thing]" == "thing")
- ASSERT("\A [new /datum/plural_things]" == "Some things")
-
- // Lowercase \a on strings
- ASSERT("\a ["thing"]" == "a thing")
- ASSERT("\a ["Thing"]" == "Thing")
- ASSERT("\a ["\proper thing"]" == "thing")
-
- // Uppercase \A on strings
- ASSERT("\A ["thing"]" == "A thing")
- ASSERT("\A ["Thing"]" == "Thing")
- ASSERT("\A ["\proper thing"]" == "thing")
-
- // Invalid \a
- ASSERT("\a [123]" == "")
- ASSERT("\A [123]" == "")
\ No newline at end of file
diff --git a/OpenDream.sln.DotSettings b/OpenDream.sln.DotSettings
index 3c4c83094e..9303eadec4 100644
--- a/OpenDream.sln.DotSettings
+++ b/OpenDream.sln.DotSettings
@@ -10,6 +10,7 @@
1
1
AABB
+ RT
DM
DMF
DMI
diff --git a/OpenDreamRuntime/AtomManager.cs b/OpenDreamRuntime/AtomManager.cs
index 9187d91aa0..0a376bce57 100644
--- a/OpenDreamRuntime/AtomManager.cs
+++ b/OpenDreamRuntime/AtomManager.cs
@@ -560,9 +560,9 @@ public DreamValue GetAppearanceVar(ImmutableAppearance appearance, string varNam
/// The atom to find the appearance of.
public ImmutableAppearance MustGetAppearance(DreamObject atom) {
return atom switch {
+ DreamObjectArea area => area.Appearance,
DreamObjectTurf turf => turf.Appearance,
DreamObjectMovable movable => movable.SpriteComponent.Appearance!,
- DreamObjectArea area => area.Appearance,
DreamObjectImage image => image.IsMutableAppearance ? AppearanceSystem!.AddAppearance(image.MutableAppearance!, registerAppearance: false) : image.SpriteComponent!.Appearance!,
_ => throw new Exception($"Cannot get appearance of {atom}")
};
@@ -572,16 +572,15 @@ public ImmutableAppearance MustGetAppearance(DreamObject atom) {
/// Optionally looks up for an appearance. Does not try to create a new one when one is not found for this atom.
///
public bool TryGetAppearance(DreamObject atom, [NotNullWhen(true)] out ImmutableAppearance? appearance) {
- if (atom is DreamObjectTurf turf)
- appearance = turf.Appearance;
- else if (atom is DreamObjectMovable { SpriteComponent.Appearance: not null } movable)
- appearance = movable.SpriteComponent.Appearance;
- else if (atom is DreamObjectImage image)
- appearance = image.IsMutableAppearance ? AppearanceSystem!.AddAppearance(image.MutableAppearance!, registerAppearance: false) : image.SpriteComponent?.Appearance;
- else if (atom is DreamObjectArea area)
- appearance = area.Appearance;
- else
- appearance = null;
+ appearance = atom switch {
+ DreamObjectArea area => area.Appearance,
+ DreamObjectTurf turf => turf.Appearance,
+ DreamObjectMovable { SpriteComponent.Appearance: { } movableAppearance } => movableAppearance,
+ DreamObjectImage image => image.IsMutableAppearance
+ ? AppearanceSystem!.AddAppearance(image.MutableAppearance!, registerAppearance: false)
+ : image.SpriteComponent?.Appearance,
+ _ => null
+ };
return appearance is not null;
}
diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs
index 19794ab9b0..e3e4389248 100644
--- a/OpenDreamRuntime/Objects/DreamObject.cs
+++ b/OpenDreamRuntime/Objects/DreamObject.cs
@@ -376,10 +376,15 @@ public string GetNameUnformatted() {
///
/// Returns the name of this object with no formatting evaluated
///
- ///
public string GetRawName() {
- if (!TryGetVariable("name", out DreamValue nameVar) || !nameVar.TryGetValueAsString(out string? name))
- return ObjectDefinition.Type.ToString();
+ string name = ObjectDefinition.Type;
+
+ if (this is DreamObjectAtom) {
+ if (AtomManager.TryGetAppearance(this, out var appearance))
+ name = appearance.Name;
+ } else if (TryGetVariable("name", out DreamValue nameVar) && nameVar.TryGetValueAsString(out var nameVarStr)) {
+ name = nameVarStr;
+ }
return name;
}
diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectAtom.cs b/OpenDreamRuntime/Objects/Types/DreamObjectAtom.cs
index f50e638951..20cba60f33 100644
--- a/OpenDreamRuntime/Objects/Types/DreamObjectAtom.cs
+++ b/OpenDreamRuntime/Objects/Types/DreamObjectAtom.cs
@@ -32,10 +32,10 @@ protected override void HandleDeletion(bool possiblyThreaded) {
}
public string GetRTEntityDesc() {
- if (!TryGetVariable("desc", out DreamValue descVar) || !descVar.TryGetValueAsString(out string? desc))
- return ObjectDefinition.Type;
+ if (AtomManager.TryGetAppearance(this, out var appearance) && appearance.Desc != null)
+ return appearance.Desc;
- return desc;
+ return ObjectDefinition.Type;
}
protected override bool TryGetVar(string varName, out DreamValue value) {