#include "GrowingPlant.h" #include "Game.h" GrowthState::GrowthState(float percentage, ModelInfo* model) : ReferenceCounter(), percentage(percentage), model(model) {} GrowthState::~GrowthState() { model->release(); } float GrowthState::getPercentage() const { return percentage; } ModelInfo* GrowthState::zModel() const { return model; } GrowingPlantBlock::GrowingPlantBlock(int typeId, Framework::Vec3 pos, int dimensionId, int maxTicks, Framework::Text name, int blockTypeAfterGrowth) : Block(typeId, pos, dimensionId, 0), seblingTicks(0), seblingTicksMax(maxTicks), name(name), states(), blockTypeAfterGrowth(blockTypeAfterGrowth), plantSpawned(0), lastSendState(-1) { tickSource = 1; } bool GrowingPlantBlock::onTick(TickQueue* zQueue, int numTicks, bool& blocked) { float beforePercentage = seblingTicks / (float)seblingTicksMax; seblingTicks += (float)numTicks; if ((int)(seblingTicks / (float)seblingTicksMax * 100.f) != (int)(beforePercentage * 100.f)) { Game::INSTANCE->blockTargetChanged(this); } int index = 0; int currentIndex = 0; for (GrowthState* state : states) { if (state->getPercentage() <= seblingTicks / (float)seblingTicksMax) { currentIndex = index; } else { break; } index++; } if (lastSendState != currentIndex) { updateModel(states.z(currentIndex)->zModel()); lastSendState = currentIndex; } return 1; } void GrowingPlantBlock::onPostTick() { if (seblingTicks >= (float)seblingTicksMax && !plantSpawned) { plantSpawned = 1; Game::INSTANCE->doLater([this]() { Game::INSTANCE->zDimension(getDimensionId()) ->placeBlock(getPos(), blockTypeAfterGrowth); }); } } void GrowingPlantBlock::sendModelInfo(NetworkMessage* zMessage) { GrowthState* current = 0; for (GrowthState* state : states) { if (state->getPercentage() <= seblingTicks / (float)seblingTicksMax) { current = state; } } if (current) { zMessage->addressBlock(this); InMemoryBuffer buffer; current->zModel()->writeTo(&buffer); char* msg = new char[(int)buffer.getSize() + 1]; msg[0] = 1; // hmodel change buffer.lese(msg + 1, (int)buffer.getSize()); zMessage->setMessage(msg, (int)buffer.getSize() + 1); } } Framework::Text GrowingPlantBlock::getTargetUIML() { return Text("") + name + "\n" + "Growth: " + Text((int)(seblingTicks / (float)seblingTicksMax * 100.f)) + "%"; } GrowingPlantBlock* GrowingPlantBlock::addGrowthState(GrowthState* state) { int index = 0; for (GrowthState* s : states) { if (s->getPercentage() > state->getPercentage()) { states.add(state, index); return this; } index++; } states.add(state); return this; } GrowingPlantBlockType::GrowingPlantBlockType(ModelInfo* model, Framework::Text name, Framework::Text blockTypeNameAfterGrowth, const char* readableName, int ticksNeeded, int mapColor, float hardness, Framework::RCArray groupNames) : BlockType( 0, model, true, 10, false, name, true, mapColor, groupNames, hardness), transparent(1), passable(1), speedModifier(0.3f), interactable(1), states(), blockTypeNameAfterGrowth(blockTypeNameAfterGrowth), readableName(readableName), ticksNeeded(ticksNeeded) {} void GrowingPlantBlockType::createSuperBlock(Block* zBlock, Item* zItem) const { GrowingPlantBlock* block = dynamic_cast(zBlock); block->transparent = transparent; block->passable = passable; block->hardness = getHardness(); block->speedModifier = speedModifier; block->interactable = interactable; BlockType::createSuperBlock(zBlock, zItem); } void GrowingPlantBlockType::loadSuperBlock( Block* zBlock, Framework::StreamReader* zReader, int dimensionId) const { BlockType::loadSuperBlock(zBlock, zReader, dimensionId); GrowingPlantBlock* block = dynamic_cast(zBlock); zReader->lese((char*)&block->seblingTicks, 4); } void GrowingPlantBlockType::saveSuperBlock( Block* zBlock, Framework::StreamWriter* zWriter) const { BlockType::saveSuperBlock(zBlock, zWriter); GrowingPlantBlock* block = dynamic_cast(zBlock); zWriter->schreibe((char*)&block->seblingTicks, 4); } Item* GrowingPlantBlockType::createItem() const { return 0; } Block* GrowingPlantBlockType::createBlock( Framework::Vec3 position, int dimensionId) const { GrowingPlantBlock* block = new GrowingPlantBlock(getId(), position, dimensionId, ticksNeeded, readableName, blockTypeIdAfterGrowth); for (GrowthState* state : states) { block->addGrowthState(dynamic_cast(state->getThis())); } return block; } GrowingPlantBlockType* GrowingPlantBlockType::addGrowthState( float growthPercentage, ModelInfo* model) { states.add(new GrowthState(growthPercentage, model)); return this; } Framework::Text GrowingPlantBlockType::getBlockTypeNameAfterGrowth() const { return blockTypeNameAfterGrowth; } const char* GrowingPlantBlockType::getReadableName() const { return readableName; } int GrowingPlantBlockType::getTicksNeeded() const { return ticksNeeded; } const Framework::RCArray& GrowingPlantBlockType::getStates() const { return states; } ItemType* GrowingPlantBlockType::createItemType() const { return 0; } GrowingPlantBlockTypeFactory::GrowingPlantBlockTypeFactory() : SubTypeFactory() {} GrowingPlantBlockType* GrowingPlantBlockTypeFactory::fromJson( Framework::JSON::JSONObject* zJson) const { Framework::RCArray groupNames; for (Framework::JSON::JSONValue* value : *zJson->zValue("groupNames")->asArray()) { groupNames.add(new Framework::Text(value->asString()->getString())); } GrowingPlantBlockType* result = new GrowingPlantBlockType( Game::INSTANCE->zTypeRegistry()->fromJson( zJson->zValue("model")), zJson->zValue("name")->asString()->getString(), zJson->zValue("blockTypeAfterGrowth")->asString()->getString(), zJson->zValue("readableName")->asString()->getString(), (int)zJson->zValue("ticksNeeded")->asNumber()->getNumber(), (int)zJson->zValue("mapColor")->asString()->getString(), (float)zJson->zValue("hardness")->asNumber()->getNumber(), groupNames); for (Framework::JSON::JSONValue* state : *zJson->zValue("states")->asArray()) { result->addGrowthState((float)state->asObject() ->zValue("percentage") ->asNumber() ->getNumber(), Game::INSTANCE->zTypeRegistry()->fromJson( state->asObject()->zValue("model"))); } return result; } Framework::JSON::JSONObject* GrowingPlantBlockTypeFactory::toJson( GrowingPlantBlockType* zObject) const { Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); result->addValue("readableName", new Framework::JSON::JSONString(zObject->getReadableName())); result->addValue( "model", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModel())); result->addValue( "name", new Framework::JSON::JSONString(zObject->getName())); result->addValue( "hardness", new Framework::JSON::JSONNumber(zObject->getHardness())); result->addValue( "mapColor", new Framework::JSON::JSONString(zObject->getMapColor())); result->addValue("blockTypeAfterGrowth", new Framework::JSON::JSONString( zObject->getBlockTypeNameAfterGrowth())); result->addValue("ticksNeeded", new Framework::JSON::JSONNumber((double)zObject->getTicksNeeded())); Framework::JSON::JSONArray* states = new Framework::JSON::JSONArray(); for (GrowthState* state : zObject->getStates()) { Framework::JSON::JSONObject* stateObj = new Framework::JSON::JSONObject(); stateObj->addValue( "model", Game::INSTANCE->zTypeRegistry()->toJson(state->zModel())); stateObj->addValue("percentage", new Framework::JSON::JSONNumber(state->getPercentage())); states->addValue(stateObj); } result->addValue("states", states); Framework::JSON::JSONArray* groupNames = new Framework::JSON::JSONArray(); for (Framework::Text* groupName : zObject->getGroupNames()) { groupNames->addValue(new Framework::JSON::JSONString(*groupName)); } result->addValue("groupNames", groupNames); return result; } Framework::JSON::Validator::JSONValidator* GrowingPlantBlockTypeFactory::getValidator( Framework::JSON::Validator::ObjectValidationBuilder< Framework::JSON::Validator::JSONValidator>* builder) const { return builder ->withRequiredAttribute( "model", Game::INSTANCE->zTypeRegistry()->getValidator()) ->withRequiredString("name") ->finishString() ->withRequiredNumber("hardness") ->withDefault(1.0) ->finishNumber() ->withRequiredString("mapColor") ->finishString() ->withRequiredString("readableName") ->finishString() ->withRequiredNumber("ticksNeeded") ->finishNumber() ->withRequiredString("blockTypeAfterGrowth") ->finishString() ->withRequiredArray("states") ->addAcceptedObjectInArray() ->withRequiredNumber("percentage") ->whichIsGreaterOrEqual(0.0) ->whichIsLessOrEqual(1.0) ->finishNumber() ->withRequiredAttribute( "model", Game::INSTANCE->zTypeRegistry()->getValidator()) ->finishObject() ->finishArray() ->withRequiredArray("groupNames") ->withDefault(new Framework::JSON::JSONArray()) ->addAcceptedStringInArray() ->finishString() ->finishArray() ->finishObject(); } Framework::Text GrowingPlantBlockTypeFactory::getTypeToken() const { return "growingPlant"; }