#include "JsonExpression.h" #include "Dimension.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(); } Noise* JExpressionMemory::zNoiseP(Framework::Text name) { return noises.z(name, name.getLength()); } 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::getFloatVariableP(const Framework::Text& name) { if (!floatVariables.contains(name, name.getLength())) { floatVariables.set(name, name.getLength(), 0.f); } return floatVariables.getP(name, name.getLength()); } bool* JExpressionMemory::getBoolVariableP(const Framework::Text& name) { if (!boolVariables.contains(name, name.getLength())) { boolVariables.set(name, name.getLength(), 0); } return boolVariables.getP(name, name.getLength()); } Chunk** JExpressionMemory::zzCurrentChunk() { return ¤tChunk; } JFloatExpression::JFloatExpression() : ReferenceCounter(), compiled(0) {} float JFloatExpression::getValue() { return compiled(); } FloatFunc JFloatExpression::compile(JExpressionMemory* zMemory) { if (compiled) { if (zMemory != memory) { throw "Cannot compile the same expression for different memories"; } return compiled; } memory = zMemory; return compiled = buildAssembly(zMemory).compileToFunction(); } JBoolExpression::JBoolExpression() : ReferenceCounter(), compiled(0) {} bool JBoolExpression::getValue() { return compiled(); } BoolFunc JBoolExpression::compile(JExpressionMemory* zMemory) { if (compiled) { if (zMemory != memory) { throw "Cannot compile the same expression for different " "memories"; } return compiled; } memory = zMemory; return compiled = buildAssembly(zMemory).compileToFunction(); } JVariableFloatExpression::JVariableFloatExpression() : JFloatExpression() {} Framework::Assembly::AssemblyBlock& JVariableFloatExpression::buildAssembly( JExpressionMemory* zMemory) { codeBlock.addLoadValue( zMemory->getFloatVariableP(name), Framework::Assembly::MM0); return codeBlock; } void JVariableFloatExpression::setName(Framework::Text name) { this->name = name; } Framework::Text JVariableFloatExpression::getName() const { return name; } JVariableFloatExpressionFactory::JVariableFloatExpressionFactory() : SubTypeFactory() {} JVariableFloatExpression* JVariableFloatExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JVariableFloatExpression* result = new JVariableFloatExpression(); result->setName(zJson->zValue("name")->asString()->getString()); return result; } Framework::JSON::JSONObject* JVariableFloatExpressionFactory::toJsonObject( JVariableFloatExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "name", new Framework::JSON::JSONString(zObject->getName())); return result; } JSONObjectValidationBuilder* JVariableFloatExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("name")->finishString(); } const char* JVariableFloatExpressionFactory::getTypeToken() const { return "variable"; } JVariableBoolExpression::JVariableBoolExpression() : JBoolExpression() {} Framework::Assembly::AssemblyBlock& JVariableBoolExpression::buildAssembly( JExpressionMemory* zMemory) { codeBlock.addLoadValue( (char*)zMemory->getBoolVariableP(name), Framework::Assembly::RAX); return codeBlock; } void JVariableBoolExpression::setName(Framework::Text name) { this->name = name; } Framework::Text JVariableBoolExpression::getName() const { return name; } JVariableBoolExpressionFactory::JVariableBoolExpressionFactory() : SubTypeFactory() {} JVariableBoolExpression* JVariableBoolExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JVariableBoolExpression* result = new JVariableBoolExpression(); result->setName(zJson->zValue("name")->asString()->getString()); return result; } Framework::JSON::JSONObject* JVariableBoolExpressionFactory::toJsonObject( JVariableBoolExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "name", new Framework::JSON::JSONString(zObject->getName())); return result; } JSONObjectValidationBuilder* JVariableBoolExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("name")->finishString(); } const char* JVariableBoolExpressionFactory::getTypeToken() const { return "variable"; } JConstantFloatExpression::JConstantFloatExpression() : JFloatExpression(), value(0) {} Framework::Assembly::AssemblyBlock& JConstantFloatExpression::buildAssembly( JExpressionMemory* zMemory) { codeBlock.addLoadValue(&value, Framework::Assembly::MM0); return codeBlock; } void JConstantFloatExpression::setValue(float value) { this->value = value; } float JConstantFloatExpression::getValue() const { return value; } JConstantFloatExpressionFactory::JConstantFloatExpressionFactory() : SubTypeFactory() {} JConstantFloatExpression* JConstantFloatExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JConstantFloatExpression* result = new JConstantFloatExpression(); result->setValue((float)zJson->zValue("value")->asNumber()->getNumber()); return result; } Framework::JSON::JSONObject* JConstantFloatExpressionFactory::toJsonObject( JConstantFloatExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "value", new Framework::JSON::JSONNumber(zObject->getValue())); return result; } JSONObjectValidationBuilder* JConstantFloatExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredNumber("value")->finishNumber(); } const char* JConstantFloatExpressionFactory::getTypeToken() const { return "constant"; } JConstantBoolExpression::JConstantBoolExpression() : JBoolExpression() {} Framework::Assembly::AssemblyBlock& JConstantBoolExpression::buildAssembly( JExpressionMemory* zMemory) { codeBlock.addMoveValue(Framework::Assembly::RAX, (char)(value ? 1 : 0)); return codeBlock; } void JConstantBoolExpression::setValue(bool value) { this->value = value; } bool JConstantBoolExpression::getValue() const { return value; } JConstantBoolExpressionFactory::JConstantBoolExpressionFactory() : SubTypeFactory() {} JConstantBoolExpression* JConstantBoolExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JConstantBoolExpression* result = new JConstantBoolExpression(); result->setValue(zJson->zValue("value")->asBool()->getBool()); return result; } Framework::JSON::JSONObject* JConstantBoolExpressionFactory::toJsonObject( JConstantBoolExpression* zObject) const { Framework::JSON::JSONObject* zResult = new Framework::JSON::JSONObject(); zResult->addValue( "value", new Framework::JSON::JSONBool(zObject->getValue())); return zResult; } JSONObjectValidationBuilder* JConstantBoolExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredBool("value")->finishBool(); } const char* JConstantBoolExpressionFactory::getTypeToken() const { return "constant"; } JNoiseFloatExpression::JNoiseFloatExpression() : JFloatExpression(), x(0), y(0), z(0) {} JNoiseFloatExpression::~JNoiseFloatExpression() { if (x) x->release(); if (y) y->release(); if (z) z->release(); } Framework::Assembly::AssemblyBlock& JNoiseFloatExpression::buildAssembly( JExpressionMemory* zMemory) { Noise* noise = zMemory->zNoiseP(name); if (!noise) { Framework::Logging::error() << "no noise with name '" << name.getText() << "' found, behavior is undefined\n"; return codeBlock; } Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory); Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory); Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory); Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0; if (xBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM1)) { xBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM1); xTarget = Framework::Assembly::MM1; } Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0; if (yBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM2)) { yBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM2); yTarget = Framework::Assembly::MM2; } Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0; if (zBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM3)) { zBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM3); zTarget = Framework::Assembly::MM3; } codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget); if (zTarget != Framework::Assembly::MM3) { codeBlock.addMoveValue(Framework::Assembly::MM3, zTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } codeBlock.addBlock(&yBlock, {}, {Framework::Assembly::MM3}, {Framework::Assembly::SINGLE_FLOAT}, 0, &yTarget); if (yTarget != Framework::Assembly::MM2) { codeBlock.addMoveValue(Framework::Assembly::MM2, yTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } codeBlock.addBlock(&xBlock, {}, {Framework::Assembly::MM2, Framework::Assembly::MM3}, {Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::SINGLE_FLOAT}, 0, &xTarget); if (xTarget != Framework::Assembly::MM1) { codeBlock.addMoveValue(Framework::Assembly::MM1, xTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } codeBlock.addLoadAddress(noise, Framework::Assembly::RCX); codeBlock.addMemberCall( &Noise::getNoise, Framework::Assembly::FLOAT_VALUE, {Framework::Assembly::RCX}, {Framework::Assembly::MM1, Framework::Assembly::MM2, Framework::Assembly::MM3}); return codeBlock; } void JNoiseFloatExpression::setName(Framework::Text name) { this->name = name; } Framework::Text JNoiseFloatExpression::getName() const { return name; } void JNoiseFloatExpression::setX(JFloatExpression* x) { if (this->x) this->x->release(); this->x = x; } JFloatExpression* JNoiseFloatExpression::zX() const { return x; } void JNoiseFloatExpression::setY(JFloatExpression* y) { if (this->y) this->y->release(); this->y = y; } JFloatExpression* JNoiseFloatExpression::zY() const { return y; } void JNoiseFloatExpression::setZ(JFloatExpression* z) { if (this->z) this->z->release(); this->z = z; } JFloatExpression* JNoiseFloatExpression::zZ() const { return z; } JNoiseFloatExpressionFactory::JNoiseFloatExpressionFactory() : SubTypeFactory() {} JNoiseFloatExpression* JNoiseFloatExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JNoiseFloatExpression* result = new JNoiseFloatExpression(); result->setName(zJson->zValue("name")->asString()->getString()); result->setX(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("x"))); result->setY(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("y"))); result->setZ(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("z"))); return result; } Framework::JSON::JSONObject* JNoiseFloatExpressionFactory::toJsonObject( JNoiseFloatExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "name", new Framework::JSON::JSONString(zObject->getName())); result->addValue( "x", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zX())); result->addValue( "y", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zY())); result->addValue( "z", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zZ())); return result; } JSONObjectValidationBuilder* JNoiseFloatExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("name") ->finishString() ->withRequiredAttribute("x", Game::INSTANCE->zTypeRegistry()->getValidator()) ->withRequiredAttribute("y", Game::INSTANCE->zTypeRegistry()->getValidator()) ->withRequiredAttribute("z", Game::INSTANCE->zTypeRegistry()->getValidator()); } const char* JNoiseFloatExpressionFactory::getTypeToken() const { return "noise"; } JOperatorFloatExpression::JOperatorFloatExpression() : JFloatExpression() {} Framework::Assembly::AssemblyBlock& JOperatorFloatExpression::buildAssembly( JExpressionMemory* zMemory) { bool first = 1; if (!values.getEintragAnzahl()) { codeBlock.addMoveValue(Framework::Assembly::MM0, 0.f); } for (JFloatExpression* expression : values) { if (first) { first = 0; codeBlock.addBlock( &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0); } else { Framework::Assembly::AssemblyBlock& exprBlock = expression->buildAssembly(zMemory); if (exprBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM1)) { exprBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM1); } else { exprBlock.addMoveValue(Framework::Assembly::MM1, Framework::Assembly::MM0, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } codeBlock.addBlock(&exprBlock, {}, {Framework::Assembly::MM0}, {Framework::Assembly::SINGLE_FLOAT}, 0, 0); if (op.istGleich("+")) { codeBlock.addAddition(Framework::Assembly::MM0, Framework::Assembly::MM1, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } else if (op.istGleich("-")) { codeBlock.addSubtraction(Framework::Assembly::MM0, Framework::Assembly::MM1, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } else if (op.istGleich("*")) { codeBlock.addMultiplication(Framework::Assembly::MM0, Framework::Assembly::MM1, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } else if (op.istGleich("/")) { codeBlock.addDivision(Framework::Assembly::MM0, Framework::Assembly::MM1, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } } } return codeBlock; } void JOperatorFloatExpression::setOperator(Framework::Text op) { this->op = op; } Framework::Text JOperatorFloatExpression::getOperator() { return op; } void JOperatorFloatExpression::addValue(JFloatExpression* value) { values.add(value); } const Framework::RCArray& JOperatorFloatExpression::getValues() const { return values; } JOperatorFloatExpressionFactory::JOperatorFloatExpressionFactory() : SubTypeFactory() {} JOperatorFloatExpression* JOperatorFloatExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JOperatorFloatExpression* result = new JOperatorFloatExpression(); result->setOperator(zJson->zValue("operator")->asString()->getString()); for (Framework::JSON::JSONValue* value : *zJson->zValue("values")->asArray()) { result->addValue( Game::INSTANCE->zTypeRegistry()->fromJson(value)); } return result; } Framework::JSON::JSONObject* JOperatorFloatExpressionFactory::toJsonObject( JOperatorFloatExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "operator", new Framework::JSON::JSONString(zObject->getOperator())); Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray(); for (JFloatExpression* expression : zObject->getValues()) { values->addValue( Game::INSTANCE->zTypeRegistry()->toJson( expression)); } result->addValue("values", values); return result; } JSONObjectValidationBuilder* JOperatorFloatExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("operator") ->whichIsOneOf({"+", "-", "*", "/"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray( Game::INSTANCE->zTypeRegistry()->getValidator()) ->finishArray(); } const char* JOperatorFloatExpressionFactory::getTypeToken() const { return "operator"; } JBoolOperatorBoolExpression::JBoolOperatorBoolExpression() : JBoolExpression() {} Framework::Assembly::AssemblyBlock& JBoolOperatorBoolExpression::buildAssembly( JExpressionMemory* zMemory) { bool first = 1; if (!values.getEintragAnzahl()) { codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0); } for (JBoolExpression* expression : values) { if (first) { first = 0; codeBlock.addBlock( &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0); } else { Framework::Assembly::AssemblyBlock& exprBlock = expression->buildAssembly(zMemory); if (exprBlock.isReplacementPossible( Framework::Assembly::RAX, Framework::Assembly::RCX)) { exprBlock.replaceRegister( Framework::Assembly::RAX, Framework::Assembly::RCX); } else { exprBlock.addMoveValue(Framework::Assembly::RCX, Framework::Assembly::RAX, Framework::Assembly::LOWER8); } codeBlock.addBlock( &exprBlock, {Framework::Assembly::RAX}, {}, {}, 0, 0); if (op.istGleich("&&")) { codeBlock.addAnd(Framework::Assembly::RAX, Framework::Assembly::RCX, Framework::Assembly::LOWER8); } else if (op.istGleich("||")) { codeBlock.addOr(Framework::Assembly::RAX, Framework::Assembly::RCX, Framework::Assembly::LOWER8); } } } return codeBlock; } void JBoolOperatorBoolExpression::setOperator(Framework::Text op) { this->op = op; } Framework::Text JBoolOperatorBoolExpression::getOperator() { return op; } void JBoolOperatorBoolExpression::addValue(JBoolExpression* value) { values.add(value); } const Framework::RCArray& JBoolOperatorBoolExpression::getValues() const { return values; } JBoolOperatorBoolExpressionFactory::JBoolOperatorBoolExpressionFactory() : SubTypeFactory() {} JBoolOperatorBoolExpression* JBoolOperatorBoolExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JBoolOperatorBoolExpression* result = new JBoolOperatorBoolExpression(); for (Framework::JSON::JSONValue* value : *zJson->zValue("values")->asArray()) { result->addValue( Game::INSTANCE->zTypeRegistry()->fromJson(value)); } result->setOperator(zJson->zValue("operator")->asString()->getString()); return result; } Framework::JSON::JSONObject* JBoolOperatorBoolExpressionFactory::toJsonObject( JBoolOperatorBoolExpression* zObject) const { Framework::JSON::JSONObject* zResult = new Framework::JSON::JSONObject(); Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray(); for (JBoolExpression* expression : zObject->getValues()) { values->addValue( Game::INSTANCE->zTypeRegistry()->toJson( expression)); } zResult->addValue("values", values); zResult->addValue( "operator", new Framework::JSON::JSONString(zObject->getOperator())); return zResult; } JSONObjectValidationBuilder* JBoolOperatorBoolExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("operator") ->whichIsOneOf({"&&", "||"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray( Game::INSTANCE->zTypeRegistry()->getValidator()) ->finishArray(); } const char* JBoolOperatorBoolExpressionFactory::getTypeToken() const { return "operator"; } JFloatOperatorBoolExpression::JFloatOperatorBoolExpression() : JBoolExpression() {} Framework::Assembly::AssemblyBlock& JFloatOperatorBoolExpression::buildAssembly( JExpressionMemory* zMemory) { bool first = 1; Framework::Assembly::FPRegister lastResultSorage = Framework::Assembly::MM0; for (JFloatExpression* expression : values) { if (first) { first = 0; codeBlock.addBlock( &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0); } else { Framework::Assembly::FPRegister currentResultSorage = lastResultSorage == Framework::Assembly::MM0 ? Framework::Assembly::MM1 : Framework::Assembly::MM0; Framework::Assembly::AssemblyBlock& exprBlock = expression->buildAssembly(zMemory); if (currentResultSorage != Framework::Assembly::MM0) { if (exprBlock.isReplacementPossible( Framework::Assembly::MM0, currentResultSorage)) { exprBlock.replaceRegister( Framework::Assembly::MM0, currentResultSorage); } else { exprBlock.addMoveValue(currentResultSorage, Framework::Assembly::MM0, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::X); } } codeBlock.addBlock(&exprBlock, {}, {lastResultSorage}, {Framework::Assembly::SINGLE_FLOAT}, 0, 0); Framework::Assembly::Operation jumpOp = Framework::Assembly::NOP; bool needConversion = false; if (op.istGleich(">")) { jumpOp = Framework::Assembly::JBE; // jump if below or equal } else if (op.istGleich("<")) { jumpOp = Framework::Assembly::JNB; // jump if not below } else if (op.istGleich(">=")) { jumpOp = Framework::Assembly::JB; // jump if below } else if (op.istGleich("<=")) { jumpOp = Framework::Assembly::JA; // jump if above } else if (op.istGleich("==")) { jumpOp = Framework::Assembly::JNE; // jump if not equal } else if (op.istGleich("!=")) { jumpOp = Framework::Assembly::JE; // jump if equal } else { needConversion = true; if (op.istGleich(">i")) { jumpOp = Framework::Assembly::JLE; // jump if less or equal } else if (op.istGleich("=i")) { jumpOp = Framework::Assembly::JL; // jump if less } else if (op.istGleich("<=i")) { jumpOp = Framework::Assembly::JG; // jump if greater } else if (op.istGleich("==i")) { jumpOp = Framework::Assembly::JNE; // jump if not equal } else if (op.istGleich("!=i")) { jumpOp = Framework::Assembly::JE; // jump if equal } } if (needConversion) { codeBlock.addConversion(Framework::Assembly::RAX, lastResultSorage, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::LOWER32); codeBlock.addConversion(Framework::Assembly::RCX, currentResultSorage, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::LOWER32); codeBlock.addCompare(Framework::Assembly::RAX, Framework::Assembly::RCX, Framework::Assembly::LOWER32); } else { codeBlock.addCompare(lastResultSorage, currentResultSorage, Framework::Assembly::SINGLE_FLOAT); } codeBlock.addJump(jumpOp, "end_false"); lastResultSorage = currentResultSorage; } } codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1); codeBlock.addJump(Framework::Assembly::JMP, "end"); codeBlock.defineJumpTarget("end_false"); codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0); codeBlock.defineJumpTarget("end"); return codeBlock; } void JFloatOperatorBoolExpression::setOperator(Framework::Text op) { this->op = op; } Framework::Text JFloatOperatorBoolExpression::getOperator() { return op; } void JFloatOperatorBoolExpression::addValue(JFloatExpression* value) { values.add(value); } const Framework::RCArray& JFloatOperatorBoolExpression::getValues() const { return values; } JFloatOperatorBoolExpressionFactory::JFloatOperatorBoolExpressionFactory() : SubTypeFactory() {} JFloatOperatorBoolExpression* JFloatOperatorBoolExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JFloatOperatorBoolExpression* result = new JFloatOperatorBoolExpression(); result->setOperator(zJson->zValue("operator")->asString()->getString()); for (Framework::JSON::JSONValue* value : *zJson->zValue("values")->asArray()) { result->addValue( Game::INSTANCE->zTypeRegistry()->fromJson(value)); } return result; } Framework::JSON::JSONObject* JFloatOperatorBoolExpressionFactory::toJsonObject( JFloatOperatorBoolExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue( "operator", new Framework::JSON::JSONString(zObject->getOperator())); Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray(); for (JFloatExpression* expression : zObject->getValues()) { values->addValue( Game::INSTANCE->zTypeRegistry()->toJson( expression)); } result->addValue("values", values); return result; } JSONObjectValidationBuilder* JFloatOperatorBoolExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder->withRequiredString("operator") ->whichIsOneOf({">", "<", ">=", "<=", "==", "!=", "i", ">=i", "<=i", "==i", "!=i"}) ->finishString() ->withRequiredArray("values") ->addAcceptedTypeInArray( Game::INSTANCE->zTypeRegistry()->getValidator()) ->finishArray(); } const char* JFloatOperatorBoolExpressionFactory::getTypeToken() const { return "comparsion"; } JBlockTypeBoolExpression::JBlockTypeBoolExpression() : JBoolExpression(), typeId(0), x(0), y(0), z(0) {} JBlockTypeBoolExpression ::~JBlockTypeBoolExpression() { if (x) x->release(); if (y) y->release(); if (z) z->release(); } bool JBlockTypeBoolExpression::isValidPosition( int x, int y, Chunk* currentChunk) { return currentChunk && Game::getChunkCenter(x, y) == currentChunk->getCenter(); } Framework::Assembly::AssemblyBlock& JBlockTypeBoolExpression::buildAssembly( JExpressionMemory* zMemory) { Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory); Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory); Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory); Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0; if (xBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM1)) { xBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM1); xTarget = Framework::Assembly::MM1; } Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0; if (yBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM2)) { yBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM2); yTarget = Framework::Assembly::MM2; } Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0; if (zBlock.isReplacementPossible( Framework::Assembly::MM0, Framework::Assembly::MM3)) { zBlock.replaceRegister( Framework::Assembly::MM0, Framework::Assembly::MM3); zTarget = Framework::Assembly::MM3; } codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget); codeBlock.addConversion(Framework::Assembly::R9, zTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::LOWER32, 1); codeBlock.addTest(Framework::Assembly::R9, Framework::Assembly::R9, Framework::Assembly::LOWER32); codeBlock.addJump(Framework::Assembly::JL, "end_false"); codeBlock.addCompare(Framework::Assembly::R9, WORLD_HEIGHT); codeBlock.addJump(Framework::Assembly::JGE, "end_false"); codeBlock.addBlock(&yBlock, {Framework::Assembly::R9}, {}, {}, 0, &yTarget); codeBlock.addConversion(Framework::Assembly::R8, yTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::LOWER32, 1); codeBlock.addBlock(&xBlock, {Framework::Assembly::R8, Framework::Assembly::R9}, {}, {}, 0, &xTarget); codeBlock.addConversion(Framework::Assembly::RDX, xTarget, Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::LOWER32, 1); codeBlock.addLoadAddress(this, Framework::Assembly::RCX); codeBlock.addPush(Framework::Assembly::RDX, Framework::Assembly::LOWER32); codeBlock.addPush(Framework::Assembly::R8, Framework::Assembly::LOWER32); codeBlock.addPush(Framework::Assembly::R9, Framework::Assembly::LOWER32); codeBlock.addLoadValue( (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::R9); codeBlock .addMemberCall( &JBlockTypeBoolExpression::isValidPosition, Framework::Assembly::INT_VALUE, {Framework::Assembly::R9}, {}); codeBlock.addPop(Framework::Assembly::R9, Framework::Assembly::LOWER32); codeBlock.addPop(Framework::Assembly::R8, Framework::Assembly::LOWER32); codeBlock.addPop(Framework::Assembly::RDX, Framework::Assembly::LOWER32); codeBlock.addTest(Framework::Assembly::RAX, Framework::Assembly::RAX, Framework::Assembly::LOWER8); codeBlock.addJump(Framework::Assembly::JZ, "end"); codeBlock.addLoadValue( (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::RCX); codeBlock.addMemberCall( &Chunk::getBlockTypeAtWC, Framework::Assembly::INT_VALUE, {Framework::Assembly::RCX, Framework::Assembly::RDX, Framework::Assembly::R8, Framework::Assembly::R9}, {}); codeBlock.addCompare(Framework::Assembly::RAX, Framework::Assembly::RCX, Framework::Assembly::LOWER32); codeBlock.addJump(Framework::Assembly::JNE, "end_false"); codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1); codeBlock.addJump(Framework::Assembly::JMP, "end"); codeBlock.defineJumpTarget("end_false"); codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0); codeBlock.defineJumpTarget("end"); return codeBlock; } void JBlockTypeBoolExpression::setTypeId(int typeId) { this->typeId = typeId; } int JBlockTypeBoolExpression::getTypeId() const { return typeId; } void JBlockTypeBoolExpression::setX(JFloatExpression* x) { if (this->x) this->x->release(); this->x = x; } JFloatExpression* JBlockTypeBoolExpression::zX() const { return x; } void JBlockTypeBoolExpression::setY(JFloatExpression* y) { if (this->y) this->y->release(); this->y = y; } JFloatExpression* JBlockTypeBoolExpression::zY() const { return y; } void JBlockTypeBoolExpression::setZ(JFloatExpression* z) { if (this->z) this->z->release(); this->z = z; } JFloatExpression* JBlockTypeBoolExpression::zZ() const { return z; } JBlockTypeBoolExpressionFactory::JBlockTypeBoolExpressionFactory() : SubTypeFactory() {} JBlockTypeBoolExpression* JBlockTypeBoolExpressionFactory::fromJson( Framework::JSON::JSONObject* zJson) const { JBlockTypeBoolExpression* result = new JBlockTypeBoolExpression(); result->setTypeId(Game::INSTANCE->getBlockTypeId( zJson->zValue("blockType")->asString()->getString())); result->setX(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("x"))); result->setY(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("y"))); result->setZ(Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("z"))); return result; } Framework::JSON::JSONObject* JBlockTypeBoolExpressionFactory::toJsonObject( JBlockTypeBoolExpression* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue("blockType", new Framework::JSON::JSONString( Game::INSTANCE->zBlockType(zObject->getTypeId())->getName())); result->addValue( "x", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zX())); result->addValue( "y", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zY())); result->addValue( "z", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zZ())); return result; } JSONObjectValidationBuilder* JBlockTypeBoolExpressionFactory::addToValidator( JSONObjectValidationBuilder* builder) const { return builder ->withRequiredAttribute("blockType", Game::INSTANCE->zTypeRegistry()->getValidator( BlockTypeNameFactory::TYPE_ID)) ->withRequiredAttribute("x", Game::INSTANCE->zTypeRegistry()->getValidator()) ->withRequiredAttribute("y", Game::INSTANCE->zTypeRegistry()->getValidator()) ->withRequiredAttribute("z", Game::INSTANCE->zTypeRegistry()->getValidator()); } const char* JBlockTypeBoolExpressionFactory::getTypeToken() const { return "blockType"; }