2005-05-16 09:30:39 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "api.h"
|
|
|
|
#include "rmgen.h"
|
|
|
|
#include "random.h"
|
2005-05-23 04:52:37 +02:00
|
|
|
#include "map.h"
|
|
|
|
#include "entity.h"
|
|
|
|
#include "objparse.h"
|
2005-05-16 09:30:39 +02:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
// Function specs
|
|
|
|
|
|
|
|
JSFunctionSpec globalFunctions[] = {
|
|
|
|
// {name, native, args}
|
|
|
|
{"init", init, 3},
|
|
|
|
{"print", print, 1},
|
|
|
|
{"error", error, 1},
|
|
|
|
{"getTerrain", getTerrain, 2},
|
|
|
|
{"setTerrain", setTerrain, 3},
|
|
|
|
{"getHeight", getHeight, 2},
|
|
|
|
{"setHeight", setHeight, 3},
|
|
|
|
{"randInt", randInt, 1},
|
|
|
|
{"randFloat", randFloat, 0},
|
2005-05-23 04:52:37 +02:00
|
|
|
{"addEntity", addEntity, 5},
|
|
|
|
{"createArea", createArea, 3},
|
2005-05-16 09:30:39 +02:00
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
2005-05-23 04:52:37 +02:00
|
|
|
// 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: expected %d arguments but got %d", function, num, argc);
|
|
|
|
}
|
|
|
|
JSObject* obj;
|
|
|
|
for(int i=0; i<num; i++) {
|
|
|
|
switch(types[i]) {
|
|
|
|
case 'i':
|
|
|
|
if(!JSVAL_IS_INT(argv[i])) {
|
|
|
|
JS_ReportError(cx, "%s: argument %d must be an integer", function, i+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if(!JSVAL_IS_STRING(argv[i])) {
|
|
|
|
JS_ReportError(cx, "%s: argument %d must be an integer", function, i+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
if(!JSVAL_IS_NUMBER(argv[i])) {
|
|
|
|
JS_ReportError(cx, "%s: argument %d must be an integer", function, i+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
if(!JSVAL_IS_OBJECT(argv[i])) {
|
|
|
|
JS_ReportError(cx, "%s: argument %d must be an array", function, i+1);
|
|
|
|
}
|
|
|
|
obj = JSVAL_TO_OBJECT(argv[i]);
|
|
|
|
if(!JS_IsArrayObject(cx, obj)) {
|
|
|
|
JS_ReportError(cx, "%s: argument %d must be an array", function, i+1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr << "Internal Error: Invalid type passed to ValidateArgs: " << types[i] << "." << endl;
|
|
|
|
Shutdown(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-16 09:30:39 +02:00
|
|
|
// JS API implementation
|
|
|
|
|
|
|
|
JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("*", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
|
|
|
|
cout << JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("*", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
|
|
|
|
JS_ReportError(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("isn", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
if(theMap != 0) {
|
|
|
|
JS_ReportError(cx, "init: cannot be called twice");
|
|
|
|
}
|
|
|
|
|
|
|
|
int size = JSVAL_TO_INT(argv[0]);
|
|
|
|
char* baseTerrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]));
|
|
|
|
jsdouble baseHeight;
|
|
|
|
JS_ValueToNumber(cx, argv[2], &baseHeight);
|
|
|
|
|
|
|
|
theMap = new Map(size, baseTerrain, (float) baseHeight);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("ii", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "getTerrain: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = JSVAL_TO_INT(argv[0]);
|
|
|
|
int y = JSVAL_TO_INT(argv[1]);
|
|
|
|
string terrain = theMap->getTerrain(x, y);
|
|
|
|
*rval = NewJSString(terrain);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("iis", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "setTerrain: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = JSVAL_TO_INT(argv[0]);
|
|
|
|
int y = JSVAL_TO_INT(argv[1]);
|
|
|
|
char* terrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[2]));
|
|
|
|
theMap->setTerrain(x, y, terrain);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("ii", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "getHeight: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("iin", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "setHeight: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("i", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
|
|
|
|
int x = JSVAL_TO_INT(argv[0]);
|
|
|
|
if(x<=0) {
|
|
|
|
JS_ReportError(cx, "randInt: argument must be positive");
|
|
|
|
}
|
|
|
|
int r = RandInt(x);
|
|
|
|
*rval = INT_TO_JSVAL(r);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool randFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
2005-05-23 04:52:37 +02:00
|
|
|
ValidateArgs("", cx, argc, argv, __FUNCTION__);
|
2005-05-16 09:30:39 +02:00
|
|
|
|
|
|
|
jsdouble r = RandFloat();
|
|
|
|
JS_NewDoubleValue(cx, r, rval);
|
2005-05-23 04:52:37 +02:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool addEntity(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
ValidateArgs("sinnn", cx, argc, argv, __FUNCTION__);
|
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "addEntity: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
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[5], &orientation);
|
|
|
|
|
|
|
|
theMap->addEntity(new Entity(type, player, x,0,y, orientation));
|
|
|
|
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
|
|
{
|
|
|
|
ValidateArgs("***", cx, argc, argv, __FUNCTION__);
|
|
|
|
if(theMap == 0) {
|
|
|
|
JS_ReportError(cx, "createArea: cannot be called before init()");
|
|
|
|
}
|
|
|
|
|
|
|
|
AreaPlacer* placer;
|
|
|
|
AreaPainter* painter;
|
|
|
|
Constraint* constr;
|
|
|
|
|
|
|
|
if(!(placer = ParsePlacer(cx, argv[0]))) {
|
|
|
|
JS_ReportError(cx, "createArea: argument 1 must be an area placer definition");
|
|
|
|
}
|
|
|
|
if(!(painter = ParsePainter(cx, argv[1]))) {
|
|
|
|
JS_ReportError(cx, "createArea: argument 1 must be an area painter definition");
|
|
|
|
}
|
|
|
|
if(!(constr = ParseConstraint(cx, argv[2]))) {
|
|
|
|
JS_ReportError(cx, "createArea: argument 1 must be a constraint definition");
|
|
|
|
}
|
|
|
|
|
|
|
|
Area* r = theMap->createArea(placer, painter, constr);
|
|
|
|
|
2005-05-16 09:30:39 +02:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|