SpacemanDMM icon indicating copy to clipboard operation
SpacemanDMM copied to clipboard

'Failed to resolve path' when path is a proc redefined on a child

Open Arokha opened this issue 3 years ago • 3 comments

For example:

/mob/proc/test_case()
    set name = "Test!"
    world << "/mob"

/mob/living/test_case()
    world << "/mob/living"

/mob/living/New()
    verbs += /mob/living/test_case

The linter will be unable to find /mob/living/test_case in this case. This is a problem because unlike various SS13 things where you can update the reference to just point at the top-level proc by name, verbs do NOT handle this like one might expect and can't just be changed to /mob/proc/test_case to resolve the issue.

In this case, if we change the line to verbs += /mob/proc/test_case, we receive /mob in chat, despite the fact that the proc is redefined on our type; it doesn't seem to handle it well.

The way to dance around this would be something like only having this proc-as-verb defined in one place in the type heirarchy, which then just calls a proc on src to handle the actual work.

Arokha avatar May 28 '21 16:05 Arokha

This is actually worse than it looks.

/mob/proc/test_proc()
    world << "Proc Parent"

/mob/living/test_proc()
    world << "Proc Child"

/mob/verb/test_verb()
    world << "Verb Parent"

/mob/living/test_verb()
    world << "Verb Child"

/datum/secret_verbs/proc/datum_verb()
    world << "DATUM: [type]"

/mob/living/New()
    var/e
    world << json_encode(verbs)  // ["/mob/living/test_verb", "/mob/verb/test_verb"]

    world << "# 1"
    test_proc()  // Proc Child
    call(src, "test_proc")()  // Proc Child
    call(src, /mob/proc/test_proc)()  // Proc Child
    call(src, /mob/living/test_proc)()  // Proc Child

    world << "# 2"
    verbs += .proc/test_proc
    test_proc()  // Proc Child
    call(src, "test_proc")()  // Proc Parent
    call(src, /mob/proc/test_proc)()  // Proc Parent
    call(src, /mob/living/test_proc)()  // Proc Parent

    world << "# 3"
    test_verb()  // Verb Child
    call(src, "test_verb")()  // Verb Child
    call(src, /mob/verb/test_verb)()  // Verb Child
    call(src, /mob/living/test_verb)()  // Verb Child

    world << "# 4"
    verbs -= /mob/living/test_verb
    test_verb()  // Verb Parent <- !!!
    call(src, "test_verb")()  // Verb Parent
    call(src, /mob/verb/test_verb)()  // Verb Parent
    call(src, /mob/living/test_verb)()  // Verb Parent

    world << "# 5"
    verbs -= /mob/verb/test_verb
    test_verb()  // Verb Child
    call(src, "test_verb")()  // no output, no error <- !!!
    call(src, /mob/verb/test_verb)()  // Verb Child
    call(src, /mob/living/test_verb)()  // Verb Child

    world << "# 5"
    try
        call(src, "datum_verb")()
    catch(e)
        world << "[e]"  // undefined proc or verb /mob/living/datum_verb().
    try
        call(src, /datum/secret_verbs.proc/datum_verb)()
    catch(e)
        world << "[e]"  // undefined proc or verb /mob/living/datum verb().

    world << "# 7"
    verbs += /datum/secret_verbs.proc/datum_verb
    call(src, "datum_verb")()  // DATUM: /mob/living
    call(src, /datum/secret_verbs.proc/datum_verb)()  // DATUM: /mob/living

The way to dance around this would be something like only having this proc-as-verb defined in one place in the type heirarchy, which then just calls a proc on src to handle the actual work.

I think this is the only sane option. Completely independent of dreamchecker, overriding verbs has nasty side-effects, which also might not be fixable even by DM itself without breaking the real-world use of datum verbs.

SpaceManiac avatar May 28 '21 20:05 SpaceManiac

I see, that's uh. Some of those are pretty interesting behavior. I'll just redo it using the stub verb!

Arokha avatar May 28 '21 21:05 Arokha

I having a similar problem and this bother me. My CI configuration should detect all string types like "/obj", which is designed to exclude non-existed types in code. Thought should be better to use non-string type, because DM support proc type referencing, including their overridden variants for subtypes.

/obj/foo/baz — is the proc type, which I use as argument, for example, in aeiou(X); But! I also have /obj/proc/baz , which is a proc definition. Therefore, the type I used above is a re-define with some changes for subtype - a /foo type.

Maybe, linter see them, but can't understand what are they: a proc type, or a object type. Someone suggested to scan types for proc re-defines, which could probably tell linter what he see.

quardbreak avatar Dec 09 '21 18:12 quardbreak