• The following lines are defined in YOUScript.h
#define YS_FUNCTION(fn) Variable* fn(Instance* ysi, ArgumentData* args)
#define YS_FUNCTION_CTOR(fn) void* fn(Instance* ysi, ArgumentData* args)
#define YS_FUNCTION_DTOR(fn) void fn(Instance* ysi, void* data)
  • The Userdata type number, this is the ID of the class

Use numbers higher than 100 here, numbers below the 100 are reserved for functionality to be added to YS.

Our pwitty class

class CVector{
public :
        double x;
        double y;
        double z;

Our wrappers

Constructor of the class, return a pointer

        CVector* ct = new CVector();

        ct->x = args->GetNumber(0);
        ct->y = args->GetNumber(1);
        ct->z = args->GetNumber(2);
  • Returning null here is fine too, YS will detect it and it will revert the variable to a null type

return ct; }

  • Deconstructor, data is a pointer, delete this here, and do other stuff if you want to.
  • Warning, if you dont delete your data here, then you’ll have to clean it up yourself, not deleting it would be logical for an entity system to prevent crashes like checking in the entitiy functions itself if a flag has been set
delete (CVector*)data;
  • Wrapper functions
        CVector* ct = (CVector*)args->GetUserdata(0, VECTORDATATYPE);
        ct->x = args->GetNumber(1);
        ct->y = args->GetNumber(2);
        ct->z = args->GetNumber(3);

        return null;
        CVector* ct = (CVector*)args->GetUserdata(0, VECTORDATATYPE);
        return Converter::ToVariable(ct->x); // again, returning null here is fine.

        CVector* ct = (CVector*)args->GetUserdata(0, VECTORDATATYPE);
        return Converter::ToVariable(ct->y);

        CVector* ct = (CVector*)args->GetUserdata(0, VECTORDATATYPE);
        return Converter::ToVariable(ct->z);

YS_FUNCTION(CVector__AddOperator) {
  • You can also register Operators, these work the same way as normal YSFunctions However, they always get called with 2 arguments, a + b, a is index 0, b is index 1. As example, a is an CVector class, and b is a number. you can do a + b this will make the second argument a number, and the first one a CVector However, if you do b + a, the same function also gets called. at that moment the 0 index argument will be the number and not the CVector So you’ll need to typecheck to see what a is, and what b is.
if (!args->CheckType(0, VECTORDATATYPE)) return null;
if (!args->CheckType(1, VECTORDATATYPE)) return null;

CVector* leftvalue = (CVector*)args->GetUserdata(0, VECTORDATATYPE);
CVector* rightvalue = (CVector*)args->GetUserdata(1, VECTORDATATYPE);

CVector* newvec = new CVector();
newvec->x = leftvalue->x + rightvalue->x;
newvec->y = leftvalue->y + rightvalue->y;
newvec->z = leftvalue->z + rightvalue->z;

return args->YOUScript->CreateUserdata(VECTORDATATYPE, newvec, true);
  • Register everything in the ysi, the CTor and DTor can be null, it’ll throw an error inside YS when the user tries to create a type, and it will just not call the dtor incase that’s null(watch out with leaks here!)
Userdata* vd = ysi.RegisterUserdata("CVector", VECTORDATATYPE, sizeof(CVector), CVectorCtor, CVectorDtor);
  • Add indexes for x, y and x so we can do vector.x = 15 Don’t use string as membertype unless you’re also supplying a getter and setter, using them without will cause memory leaks YS has no idea if it should delete old ones, or keep them in memory should it allocate and put a pointer back? or is it an fixed sized array? We dont know!
vd->RegisterMember("x", offsetof(CVector, x), MemberType::Double);
vd->RegisterMember("y", offsetof(CVector, y), MemberType::Double);
vd->RegisterMember("z", offsetof(CVector, z), MemberType::Double);
  • Our wrapper funcs
vd->RegisterFunction("Set", CVectorSetFunc);
vd->RegisterFunction("GetX", CVectorGetXFunc);
vd->RegisterFunction("GetY", CVectorGetYFunc);
vd->RegisterFunction("GetZ", CVectorGetZFunc);
  • Our add operator
vd->RegisterOperator(Operators::ArithmeticAdd, CVector__AddOperator);
  • And now, we can use the following code to create a new Vector in YOUScript
local vec = new Vector()