Let's modernize this fucking codebase. ECS and interfaces how?
Created by: PJB3005
Ok. How has nobody coded an ECS and interfaces yet?
Interfaces
Pretty simple stuff, you define a contract for what a type does but leave the implementation up to the type. If you don't implement the contract correctly it won't even compile. BYOND doesn't support this natively because of course, but we can at least replicate a bare bones system. Issue is I'm not entirely sure whether it's feasible to do performantly and neatly at the same time.
Current idea I've got so far is the following:
// How this works is that implementing an interface defines a proc on the type equal to the interface name.
// Then we can do a really damn cheap lookup.
#define hasinterface(object, interface) hascall(object, "[#interface]")
// Need a generic name for reasons of being clean.
#define IINTERACTABLE IInteractable
// This, when correctly used, defines the proc checked by hasinterface.
// The proc tries calling the interface methods and will fail compile if any are undefined.
// Should be extendable to vars too *whoop*
// No non clumsy way to automate this sadly.
// This proc should NEVER be called directly!
#define IMPLEMENTS_IINTERACTABLE proc/IINTERACTABLE { \
attackby(); \
attack_hand(); \
}
// Define a generic interface type for casting and documentation purposes.
// Actually irrelevant to the correct functioning of the above macros and defines.
/IINTERACTABLE/proc/attack_hand(var/mob/user)
/IINTERACTABLE/proc/attackby(var/obj/item/W, var/mob/user)
// Example
/obj/thing
name = "thing"
...
// Define that we implement the interface.
IMPLEMENTS_IINTERACTABLE
// Implement the procs.
/obj/thing/proc/attackby(var/obj/item/W, var/mob/user)
world << "Ouch!"
/obj/thing/proc/attack_hand(var/mob/user)
world << "Honk!"
// Example usage.
/client/Click(var/atom/object)
if (hasinterface(object, IINTERACTABLE))
var/interface/IINTERACTABLE/I = object
I.attack_hand(mob)
This method has a lot of boilerplate to defining interfaces but should hopefully be very boiler plate free for implementing them. Other solution I've seen can't be checked at compile time and aren't as fast to check whether the object implements an interface.
ECS
TODO: need brainstorming can't decide on a syntax yet.