#include "stdafx.h" #include "api.h" #include "rmgen.h" #include "random.h" #include "map.h" #include "object.h" #include "convert.h" #include "terrain.h" #include "simpleconstraints.h" using namespace std; // Function specs JSFunctionSpec globalFunctions[] = { // {name, native, args} {"init", init, 3}, {"initFromScenario", initFromScenario, 2}, {"print", print, 1}, {"error", error, 1}, {"getTexture", getTexture, 2}, {"setTexture", setTexture, 3}, {"getHeight", getHeight, 2}, {"setHeight", setHeight, 3}, {"getMapSize", getMapSize, 0}, {"randInt", randInt, 2}, {"randFloat", randFloat, 1}, {"placeTerrain", placeTerrain, 3}, {"placeObject", placeObject, 4}, {"createArea", createArea, 3}, {"createObjectGroup", createObjectGroup, 3}, {"createTileClass", createTileClass, 0}, {"addToClass", addToClass, 0}, {"removeFromClass", removeFromClass, 0}, {0, 0, 0} }; // Helper function to validate argument types; the types string can contain the following: // i (integers), s (strings), n (numbers), . (anything); for example ValidateArgs("iin",...) // would check that arguments 1 and 2 are integers while the third is a number. void ValidateArgs(const char* types, JSContext* cx, uintN argc, jsval* argv, const char* function) { int num = strlen(types); if(argc != num) { JS_ReportError(cx, "%s: requires %d arguments but got %d", function, num, argc); } JSObject* obj; for(int i=0; igetTexture(x, y); *rval = NewJSString(texture); return JS_TRUE; } JSBool setTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("iis", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); char* texture = JS_GetStringBytes(JSVAL_TO_STRING(argv[2])); theMap->setTexture(x, y, texture); return JS_TRUE; } JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("ii", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); jsdouble height = theMap->getHeight(x, y); JS_NewDoubleValue(cx, height, rval); return JS_TRUE; } JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("iin", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); jsdouble height; JS_ValueToNumber(cx, argv[2], &height); theMap->setHeight(x, y, (float) height); return JS_TRUE; } JSBool randInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { if(argc!=1 && argc!=2) { JS_ReportError(cx, "randInt: requires 1 or 2 arguments but got %d", argc); } if(!JSVAL_IS_INT(argv[0])) { JS_ReportError(cx, "randInt: argument 1 must be an integer"); } if(argc==2 && !JSVAL_IS_INT(argv[1])) { JS_ReportError(cx, "randInt: argument 2 must be an integer"); } int minVal = argc==1 ? 0 : JSVAL_TO_INT(argv[0]); int maxVal = argc==1 ? JSVAL_TO_INT(argv[0]) : JSVAL_TO_INT(argv[1])-1; if(maxVal < minVal) { JS_ReportError(cx, argc==1 ? "randInt: argument must be positive" : "randInt: argument 2 must be greater than or equal to argument 1"); } int r = RandInt(minVal, maxVal); *rval = INT_TO_JSVAL(r); return JS_TRUE; } JSBool randFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { if(argc!=0 && argc!=2) { JS_ReportError(cx, "randFloat: requires 0 or 2 arguments but got %d", argc); } jsdouble r; if(argc==0) { r = RandFloat(); } else { if(!JSVAL_IS_NUMBER(argv[0])) { JS_ReportError(cx, "randFloat: argument 1 must be a number"); } if(!JSVAL_IS_NUMBER(argv[1])) { JS_ReportError(cx, "randFloat: argument 2 must be a number"); } jsdouble minVal, maxVal; JS_ValueToNumber(cx, argv[0], &minVal); JS_ValueToNumber(cx, argv[1], &maxVal); if(maxVal < minVal) { JS_ReportError(cx, "randFloat: argument 2 must be greater than or equal to argument 1"); } r = RandFloat(minVal, maxVal); } JS_NewDoubleValue(cx, r, rval); return JS_TRUE; } JSBool placeObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("sinnn", cx, argc, argv, __FUNCTION__); string type = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); int player = JSVAL_TO_INT(argv[1]); jsdouble x, y, orientation; JS_ValueToNumber(cx, argv[2], &x); JS_ValueToNumber(cx, argv[3], &y); JS_ValueToNumber(cx, argv[4], &orientation); theMap->addObject(new Object(type, player, x,y, orientation)); return JS_TRUE; } JSBool placeTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("ii*", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); Terrain* terrain = ParseTerrain(cx, argv[2]); if(!terrain) { JS_ReportError(cx, "placeTerrain: invalid terrain argument"); } theMap->placeTerrain(x, y, terrain); return JS_TRUE; } JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); if(argc != 2 && argc != 3) { JS_ReportError(cx, "createArea: expected 2 or 3 arguments but got %d", argc); } AreaPlacer* placer; AreaPainter* painter; Constraint* constr; if(!(placer = ParseAreaPlacer(cx, argv[0]))) { JS_ReportError(cx, "createArea: argument 1 must be a valid area placer"); } if(!(painter = ParseAreaPainter(cx, argv[1]))) { JS_ReportError(cx, "createArea: argument 2 must be a valid area painter"); } if(argc == 3) { if(!(constr = ParseConstraint(cx, argv[2]))) { JS_ReportError(cx, "createArea: argument 3 must be a valid constraint"); } } else { constr = new NullConstraint(); } Area* area = theMap->createArea(placer, painter, constr); delete placer; delete painter; delete constr; if(!area) { *rval = INT_TO_JSVAL(0); } else { *rval = INT_TO_JSVAL(theMap->areas.size()); } return JS_TRUE; } JSBool createObjectGroup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); if(argc != 2 && argc != 3) { JS_ReportError(cx, "createObjectGroup: expected 1 or 2 arguments but got %d", argc); } ObjectGroupPlacer* placer; Constraint* constr; if(!(placer = ParseObjectGroupPlacer(cx, argv[0]))) { JS_ReportError(cx, "createObjectGroup: argument 1 must be a valid object group placer"); } if(!JSVAL_IS_INT(argv[1])) { JS_ReportError(cx, "createObjectGroup: argument 2 must be a valid player number"); } if(argc == 3) { if(!(constr = ParseConstraint(cx, argv[2]))) { JS_ReportError(cx, "createObjectGroup: argument 3 must be a valid constraint"); } } else { constr = new NullConstraint(); } int player = JSVAL_TO_INT(argv[1]); bool ret = theMap->createObjectGroup(placer, player, constr); delete placer; delete constr; *rval = BOOLEAN_TO_JSVAL(ret); return JS_TRUE; } JSBool createTileClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); if(argc != 0) { JS_ReportError(cx, "createTileClass: expected 0 arguments but got %d", argc); } int id = theMap->createTileClass(); *rval = INT_TO_JSVAL(id); return JS_TRUE; } JSBool addToClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("iii", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); int classIndex = JSVAL_TO_INT(argv[2]) - 1; if(!theMap->validClass(classIndex) || !theMap->validT(x, y)) { JS_ReportError(cx, "addToClass: Invalid arguments for addToClass(x, y, class)"); } theMap->tileClasses[classIndex]->add(x, y); return JS_TRUE; } JSBool removeFromClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); ValidateArgs("iii", cx, argc, argv, __FUNCTION__); int x = JSVAL_TO_INT(argv[0]); int y = JSVAL_TO_INT(argv[1]); int classIndex = JSVAL_TO_INT(argv[2]) - 1; if(!theMap->validClass(classIndex) || !theMap->validT(x, y)) { JS_ReportError(cx, "addToClass: Invalid arguments for removeFromClass(x, y, class)"); } theMap->tileClasses[classIndex]->remove(x, y); return JS_TRUE; } JSBool getMapSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CheckInit(true, cx, __FUNCTION__); if(argc != 0) { JS_ReportError(cx, "getMapSize: expected 0 arguments but got %d", argc); } *rval = INT_TO_JSVAL(theMap->size); return JS_TRUE; }