#include "JsonExpression.h" #include "DimensionGenerator.h" #include "Game.h" JExpressionMemory::JExpressionMemory() : ReferenceCounter(), currentChunk(0) {} JExpressionMemory::~JExpressionMemory() { if (currentChunk) currentChunk->release(); } void JExpressionMemory::lock() { cs.lock(); } void JExpressionMemory::unlock() { cs.unlock(); } float JExpressionMemory::getNoise( Framework::Text name, float x, float y, float z) const { Noise* currentNoise = noises.z(name, name.getLength()); if (currentNoise) return (float)currentNoise->getNoise((double)x, (double)y, (double)z); return 0.f; } void JExpressionMemory::setNoise(Framework::Text name, Noise* noise) { noises.set(name, name.getLength(), noise); } void JExpressionMemory::setCurrentChunk(Chunk* chunk) { if (currentChunk) currentChunk->release(); currentChunk = chunk; } float JExpressionMemory::getFloatVariable(Framework::Text name) const { return floatVariables.get(name, name.getLength()); } void JExpressionMemory::setFloatVariable(Framework::Text name, float value) { floatVariables.set(name, name.getLength(), value); } bool JExpressionMemory::getBoolVariable(Framework::Text name) const { return boolVariables.get(name, name.getLength()); } void JExpressionMemory::setBoolVariable(Framework::Text name, bool value) { return boolVariables.set(name, name.getLength(), value); } Chunk* JExpressionMemory::zCurrentChunk() { return currentChunk; } JFloatExpression::JFloatExpression() : ReferenceCounter() {} JBoolExpression::JBoolExpression() : ReferenceCounter() {} JVariableFloatExpression::JVariableFloatExpression(Framework::Text name) : JFloatExpression(), name(name) {} float JVariableFloatExpression::getValue(JExpressionMemory* zMemory) { return zMemory->getFloatVariable(name); } JVariableBoolExpression::JVariableBoolExpression(Framework::Text name) : JBoolExpression(), name(name) {} bool JVariableBoolExpression::getValue(JExpressionMemory* zMemory) { return zMemory->getBoolVariable(name); } JConstantFloatExpression::JConstantFloatExpression(float value) : JFloatExpression(), value(value) {} float JConstantFloatExpression::getValue(JExpressionMemory* zMemory) { return value; } JConstantBoolExpression::JConstantBoolExpression(bool value) : JBoolExpression(), value(value) {} bool JConstantBoolExpression::getValue(JExpressionMemory* zMemory) { return value; } JNoiseFloatExpression::JNoiseFloatExpression(Framework::Text name, JFloatExpression* x, JFloatExpression* y, JFloatExpression* z) : JFloatExpression(), name(name), x(x), y(y), z(z) {} JNoiseFloatExpression::~JNoiseFloatExpression() { x->release(); y->release(); z->release(); } float JNoiseFloatExpression::getValue(JExpressionMemory* zMemory) { return zMemory->getNoise( name, x->getValue(zMemory), y->getValue(zMemory), z->getValue(zMemory)); } JOperatorFloatExpression::JOperatorFloatExpression( std::function accumulator, Framework::RCArray* values) : JFloatExpression(), accumulator(accumulator), values(values) {} JOperatorFloatExpression::~JOperatorFloatExpression() { values->release(); } float JOperatorFloatExpression::getValue(JExpressionMemory* zMemory) { bool first = 1; float val = 0.f; for (JFloatExpression* expression : *values) { if (first) { first = 0; val = expression->getValue(zMemory); } else { val = accumulator(val, expression->getValue(zMemory)); } } return val; } JBoolOperatorBoolExpression::JBoolOperatorBoolExpression( std::function accumulator, Framework::RCArray* values) : JBoolExpression(), accumulator(accumulator), values(values) {} JBoolOperatorBoolExpression::~JBoolOperatorBoolExpression() { values->release(); } bool JBoolOperatorBoolExpression::getValue(JExpressionMemory* zMemory) { bool first = 1; bool val = 0; for (JBoolExpression* expression : *values) { if (first) { first = 0; val = expression->getValue(zMemory); } else { val = accumulator(val, expression->getValue(zMemory)); } } return val; } JFloatOperatorBoolExpression::JFloatOperatorBoolExpression( std::function accumulator, Framework::RCArray* values) : JBoolExpression(), accumulator(accumulator), values(values) {} JFloatOperatorBoolExpression::~JFloatOperatorBoolExpression() { values->release(); } bool JFloatOperatorBoolExpression::getValue(JExpressionMemory* zMemory) { bool first = 1; bool val = 1; float last = 0.f; for (JFloatExpression* expression : *values) { float current = expression->getValue(zMemory); if (!first) val &= accumulator(last, current); first = 0; last = current; } return val; } JBlockTypeBoolExpression::JBlockTypeBoolExpression( int typeId, JFloatExpression* x, JFloatExpression* y, JFloatExpression* z) : JBoolExpression(), typeId(typeId), x(x), y(y), z(z) {} JBlockTypeBoolExpression ::~JBlockTypeBoolExpression() { x->release(); y->release(); z->release(); } bool JBlockTypeBoolExpression::getValue(JExpressionMemory* zMemory) { int x = (int)(round(this->x->getValue(zMemory))); int y = (int)(round(this->y->getValue(zMemory))); int z = (int)(round(this->z->getValue(zMemory))); if (z < 0 || z >= WORLD_HEIGHT || !zMemory->zCurrentChunk() || Game::getChunkCenter(x, y) != zMemory->zCurrentChunk()->getCenter()) { return 0; } return zMemory->zCurrentChunk()->getBlockTypeAt( Dimension::chunkCoordinates({x, y, z})) == typeId; } using namespace Framework::JSON; using namespace Framework::JSON::Validator; JFloatExpression* JExpressionParser::parseFloatExpression( Framework::JSON::JSONValue* zValue) { JSONObject* obj = zValue->asObject(); Framework::Text type = obj->zValue("type")->asString()->getString(); if (type.istGleich("variable")) { return new JVariableFloatExpression( obj->zValue("name")->asString()->getString()); } else if (type.istGleich("constant")) { return new JConstantFloatExpression( (float)obj->zValue("value")->asNumber()->getNumber()); } else if (type.istGleich("noise")) { return new JNoiseFloatExpression( obj->zValue("name")->asString()->getString(), parseFloatExpression(obj->zValue("x")), parseFloatExpression(obj->zValue("y")), parseFloatExpression(obj->zValue("z"))); } else if (type.istGleich("operator")) { Framework::RCArray* values = new Framework::RCArray(); JSONArray* valuesArray = obj->zValue("values")->asArray(); for (JSONValue* value : *valuesArray) { values->add(parseFloatExpression(value)); } Framework::Text op = obj->zValue("operator")->asString()->getString(); if (op.istGleich("+")) { return new JOperatorFloatExpression( [](float a, float b) { return a + b; }, values); } else if (op.istGleich("-")) { return new JOperatorFloatExpression( [](float a, float b) { return a - b; }, values); } else if (op.istGleich("*")) { return new JOperatorFloatExpression( [](float a, float b) { return a * b; }, values); } else if (op.istGleich("/")) { return new JOperatorFloatExpression( [](float a, float b) { return a / b; }, values); } else { values->release(); } } return 0; } Framework::JSON::Validator::JSONValidator* JExpressionParser::getFloatValidator() { JSONValidator* refs = JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type") ->addAcceptedType( JSONValidator::buildForObjectReference("jef_variable")) ->addAcceptedType( JSONValidator::buildForObjectReference("jef_constant")) ->addAcceptedType( JSONValidator::buildForObjectReference("jef_noise")) ->addAcceptedType( JSONValidator::buildForObjectReference("jef_operator")) ->finishOneOf(); JSONValidator* validator = JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type") ->addAcceptedType(JSONValidator::buildForObject() ->setObjectReferenceId("jef_variable") ->withRequiredString("type") ->whichIs("variable") ->finishString() ->withRequiredString("name") ->finishString() ->finishObject()) ->addAcceptedType(JSONValidator::buildForObject() ->setObjectReferenceId("jef_constant") ->withRequiredString("type") ->whichIs("constant") ->finishString() ->withRequiredNumber("value") ->finishNumber() ->finishObject()) ->addAcceptedType( JSONValidator::buildForObject() ->setObjectReferenceId("jef_noise") ->withRequiredString("type") ->whichIs("noise") ->finishString() ->withRequiredString("name") ->withDefault("noise") ->finishString() ->withRequiredAttribute( "x", dynamic_cast(refs->getThis())) ->withRequiredAttribute( "y", dynamic_cast(refs->getThis())) ->withRequiredAttribute( "z", dynamic_cast(refs->getThis())) ->finishObject()) ->addAcceptedType( JSONValidator::buildForObject() ->setObjectReferenceId("jef_operator") ->withRequiredString("type") ->whichIs("operator") ->finishString() ->withRequiredString("operator") ->whichIsOneOf({"+", "-", "*", "/"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray( dynamic_cast(refs->getThis())) ->finishArray() ->finishObject()) ->finishOneOf(); return validator; } JBoolExpression* JExpressionParser::parseBoolExpression( Framework::JSON::JSONValue* zValue) { JSONObject* obj = zValue->asObject(); Framework::Text type = obj->zValue("type")->asString()->getString(); if (type.istGleich("variable")) { return new JVariableBoolExpression( obj->zValue("name")->asString()->getString()); } else if (type.istGleich("constant")) { return new JConstantBoolExpression( (float)obj->zValue("value")->asBool()->getBool()); } else if (type.istGleich("blockType")) { return new JBlockTypeBoolExpression( BlockType::getTypeId( obj->zValue("blockType")->asString()->getString()), parseFloatExpression(obj->zValue("x")), parseFloatExpression(obj->zValue("y")), parseFloatExpression(obj->zValue("z"))); } else if (type.istGleich("operator")) { Framework::Text op = obj->zValue("operator")->asString()->getString(); if (op.istGleich("&&") || op.istGleich("||")) { Framework::RCArray* values = new Framework::RCArray(); JSONArray* valuesArray = obj->zValue("values")->asArray(); for (JSONValue* value : *valuesArray) { values->add(parseBoolExpression(value)); } if (op.istGleich("&&")) { return new JBoolOperatorBoolExpression( [](bool a, bool b) { return a && b; }, values); } else if (op.istGleich("||")) { return new JBoolOperatorBoolExpression( [](bool a, bool b) { return a || b; }, values); } else { values->release(); } } else { Framework::RCArray* values = new Framework::RCArray(); JSONArray* valuesArray = obj->zValue("values")->asArray(); for (JSONValue* value : *valuesArray) { values->add(parseFloatExpression(value)); } if (op.istGleich(">")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a > b; }, values); } else if (op.istGleich("<")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a < b; }, values); } else if (op.istGleich(">=")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a >= b; }, values); } else if (op.istGleich("<=")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a <= b; }, values); } else if (op.istGleich("==")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a == b; }, values); } else if (op.istGleich("!=")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return a != b; }, values); } else if (op.istGleich(">i")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return (int)a > (int)b; }, values); } else if (op.istGleich("=i")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return (int)a >= (int)b; }, values); } else if (op.istGleich("<=i")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return (int)a <= (int)b; }, values); } else if (op.istGleich("==i")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return (int)a == (int)b; }, values); } else if (op.istGleich("!=i")) { return new JFloatOperatorBoolExpression( [](float a, float b) { return (int)a != (int)b; }, values); } else { values->release(); } } } return 0; } Framework::JSON::Validator::JSONValidator* JExpressionParser::getBoolValidator() { Framework::RCArray blockTypeNames; for (int i = 0; i < StaticRegistry::INSTANCE.getCount(); i++) { if (StaticRegistry::INSTANCE.zElement(i)) { blockTypeNames.add(new Framework::Text( StaticRegistry::INSTANCE.zElement(i)->getName())); } } JSONValidator* refs = JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type") ->addAcceptedType( JSONValidator::buildForObjectReference("jeb_variable")) ->addAcceptedType( JSONValidator::buildForObjectReference("jeb_constant")) ->addAcceptedType( JSONValidator::buildForObjectReference("jeb_blockType")) ->addAcceptedType( JSONValidator::buildForObjectReference("jeb_bool_operator")) ->addAcceptedType( JSONValidator::buildForObjectReference("jeb_float_operator")) ->finishOneOf(); JSONValidator* validator = JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type") ->addAcceptedType(JSONValidator::buildForObject() ->setObjectReferenceId("jeb_variable") ->withRequiredString("type") ->whichIs("variable") ->finishString() ->withRequiredString("name") ->finishString() ->finishObject()) ->addAcceptedType(JSONValidator::buildForObject() ->setObjectReferenceId("jeb_constant") ->withRequiredString("type") ->whichIs("constant") ->finishString() ->withRequiredBool("value") ->finishBool() ->finishObject()) ->addAcceptedType( JSONValidator::buildForObject() ->setObjectReferenceId("jeb_blockType") ->withRequiredString("type") ->whichIs("blockType") ->finishString() ->withRequiredString("blockType") ->whichIsOneOf(blockTypeNames) ->finishString() ->withRequiredAttribute("x", getFloatValidator()) ->withRequiredAttribute("y", getFloatValidator()) ->withRequiredAttribute("z", getFloatValidator()) ->finishObject()) ->addAcceptedType( JSONValidator::buildForObject() ->setObjectReferenceId("jeb_bool_operator") ->withRequiredString("type") ->whichIs("operator") ->finishString() ->withRequiredString("operator") ->whichIsOneOf({"&&", "||"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray( dynamic_cast(refs->getThis())) ->finishArray() ->finishObject()) ->addAcceptedType( JSONValidator::buildForObject() ->setObjectReferenceId("jeb_float_operator") ->withRequiredString("type") ->whichIs("operator") ->finishString() ->withRequiredString("operator") ->whichIsOneOf({">", "<", ">=", "<=", "==", "!=", ">i", "=i", "<=i", "==i", "!=i"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray(getFloatValidator()) ->finishArray() ->finishObject()) ->finishOneOf(); return validator; }