123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- #include "Entity.h"
- #include "Dimension.h"
- #include "Game.h"
- #include "BlockType.h"
- #include "ItemSkill.h"
- #include "PlaceBlockUpdate.h"
- #include "EntityRemovedUpdate.h"
- ActionTarget::ActionTarget(Vec3<int> blockPos, Direction blockSide)
- : blockPos(blockPos),
- targetBlockSide(blockSide),
- entityId(-1)
- {}
- ActionTarget::ActionTarget(int entityId)
- : entityId(entityId)
- {}
- bool ActionTarget::isBlock(Framework::Vec3<int> blockPos, Direction blockSide) const
- {
- return this->entityId == -1 && this->blockPos == blockPos && this->targetBlockSide == targetBlockSide;
- }
- bool ActionTarget::isEntity(int entityId) const
- {
- return this->entityId == entityId;
- }
- void ActionTarget::applyItemSkillOnTarget(Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
- {
- if (entityId >= 0)
- {
- // TODO: get entity from game and apply skill
- }
- else
- {
- Block* block = Game::INSTANCE->zRealBlockInstance(blockPos, zActor->getCurrentDimensionId());
- if (block)
- zItemSkill->use(zActor, zUsedItem, block);
- }
- }
- void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
- {
- // TODO: check stamina of actor
- Block* block = zItem->zPlacedBlockType()->createBlockAt(blockPos + getDirection(targetBlockSide), zItem);
- if (block)
- {
- if (Game::INSTANCE->requestWorldUpdate(new PlaceBlockUpdate(block, block->getPos(), zActor->getCurrentDimensionId())))
- {
- zItem->onPlaced();
- // TODO: decrese stamina of actor
- }
- }
- }
- void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
- {
- if (zTarget)
- {
- if (zTarget->entityId >= 0)
- {
- char b = 1;
- zWriter->schreibe(&b, 1);
- zWriter->schreibe((char*)&zTarget->entityId, 4);
- }
- else
- {
- char b = 2;
- zWriter->schreibe(&b, 1);
- zWriter->schreibe((char*)&zTarget->blockPos.x, 4);
- zWriter->schreibe((char*)&zTarget->blockPos.y, 4);
- zWriter->schreibe((char*)&zTarget->blockPos.z, 4);
- zWriter->schreibe((char*)&zTarget->targetBlockSide, 4);
- }
- }
- else
- {
- char b = 0;
- zWriter->schreibe(&b, 1);
- }
- }
- ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
- {
- char b;
- zReader->lese(&b, 1);
- if (b == 1)
- {
- int id;
- zReader->lese((char*)&id, 4);
- return new ActionTarget(id);
- }
- else if (b == 2)
- {
- Framework::Vec3<int> pos;
- Direction side;
- zReader->lese((char*)&pos.x, 4);
- zReader->lese((char*)&pos.y, 4);
- zReader->lese((char*)&pos.z, 4);
- zReader->lese((char*)&side, 4);
- return new ActionTarget(pos, side);
- }
- return 0;
- }
- Entity::Entity(const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId)
- : Inventory(location, true),
- speed(0, 0, 0),
- faceDir(1, 0, 0),
- target(0),
- zEntityType(zType),
- currentDimensionId(dimensionId),
- removed(0),
- gravityMultiplier(1.f),
- needUpdate(0),
- id(entityId)
- {}
- void Entity::onDeath()
- {
- removed = 1;
- Game::INSTANCE->requestWorldUpdate(new EntityRemovedUpdate(id, currentDimensionId, location));
- }
- void Entity::useItem(const ItemType* zType, Item* zItem)
- {
- if (zItem && zItem->isEatable())
- { // TODO: eat item
- zItem->applyFoodEffects(this);
- }
- else if (zItem && zItem->isPlaceable())
- { // TODO: place item
- if (target)
- target->placeBlock(this, zItem);
- }
- else if (!zItem || zItem->isUsable())
- { // use item skill
- if (target)
- {
- ItemSkill* selected = 0;
- for (ItemSkill* skill : skills)
- {
- if (skill->zSkillType() == zType)
- {
- selected = skill;
- break;
- }
- }
- if (!selected)
- {
- selected = zType->createDefaultItemSkill();
- skills.add(selected);
- }
- target->applyItemSkillOnTarget(this, selected, zItem);
- }
- }
- }
- void Entity::prepareTick(const Dimension* zDimension)
- {
- Vec3<float> headPosition = location + faceOffset;
- int px = (int)floor(headPosition.x);
- int py = (int)floor(headPosition.y);
- int pz = (int)floor(headPosition.z);
- faceDir.normalize();
- Direction dir = BOTTOM;
- while (true)
- {
- if (getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz }, zDimension->getDimensionId()))->isInteractable())
- {
- if (!target || !target->isBlock({ px, py, pz }, dir))
- {
- delete target;
- target = new ActionTarget({ px, py, pz }, dir);
- needUpdate = 1;
- }
- break;
- }
- // collision to neighbor of current block
- if (faceDir.x > 0)
- {
- float xt = ((float)px + 1.f - headPosition.x) / faceDir.x;
- Vec3<float> tmp = headPosition + faceDir * xt;
- if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- dir = WEST;
- px++;
- continue;
- }
- }
- if (faceDir.x < 0)
- {
- float xt = ((float)px - headPosition.x) / faceDir.x;
- Vec3<float> tmp = headPosition + faceDir * xt;
- if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- dir = EAST;
- px--;
- continue;
- }
- }
- if (faceDir.y > 0)
- {
- float yt = ((float)py + 1.f - headPosition.y) / faceDir.y;
- Vec3<float> tmp = headPosition + faceDir * yt;
- if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- dir = NORTH;
- py++;
- continue;
- }
- }
- if (faceDir.y < 0)
- {
- float yt = ((float)py - headPosition.y) / faceDir.y;
- Vec3<float> tmp = headPosition + faceDir * yt;
- if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- dir = SOUTH;
- py--;
- continue;
- }
- }
- if (faceDir.z > 0)
- {
- float zt = ((float)pz + 1.f - headPosition.z) / faceDir.z;
- Vec3<float> tmp = headPosition + faceDir * zt;
- if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f)
- {
- dir = BOTTOM;
- pz++;
- continue;
- }
- }
- if (faceDir.z < 0)
- {
- float zt = ((float)pz - headPosition.z) / faceDir.z;
- Vec3<float> tmp = headPosition + faceDir * zt;
- if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1)
- {
- dir = TOP;
- pz--;
- continue;
- }
- }
- if (target)
- {
- delete target;
- target = 0;
- needUpdate = 1;
- }
- break;
- }
- }
- void Entity::tick(const Dimension* zDimension)
- {
- Vec3<float> oldPos = location;
- // current block cooredinates
- int px = (int)floor(location.x);
- int py = (int)floor(location.y);
- int pz = (int)floor(location.z);
- // falling down
- speed.z -= (zDimension->getGravity() * gravityMultiplier) / 30.f;
- // movement in current tick
- Vec3<float> frameSpeed = speed / 30.f;
- // loop through all collided blocks
- bool needCollisionCheck = 1;
- while (needCollisionCheck)
- {
- needCollisionCheck = 0;
- // collision to neighbor of current block
- if (speed.x > 0)
- {
- float xt = ((float)px + 1.f - oldPos.x) / frameSpeed.x;
- Vec3<float> tmp = oldPos + frameSpeed * xt;
- if (xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.x = frameSpeed.x * (xt - 0.1f);
- speed.x = 0;
- }
- else
- px++;
- needCollisionCheck = 1;
- continue;
- }
- }
- if (speed.x < 0)
- {
- float xt = ((float)px - oldPos.x) / frameSpeed.x;
- Vec3<float> tmp = oldPos + frameSpeed * xt;
- if (xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.x = frameSpeed.x * (xt - 0.1f);
- speed.x = 0;
- }
- else
- px--;
- needCollisionCheck = 1;
- continue;
- }
- }
- if (speed.y > 0)
- {
- float yt = ((float)py + 1.f - oldPos.y) / frameSpeed.y;
- Vec3<float> tmp = oldPos + frameSpeed * yt;
- if (yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.y = frameSpeed.y * (yt - 0.1f);
- speed.y = 0;
- }
- else
- py++;
- needCollisionCheck = 1;
- continue;
- }
- }
- if (speed.y < 0)
- {
- float yt = ((float)py - oldPos.y) / frameSpeed.y;
- Vec3<float> tmp = oldPos + frameSpeed * yt;
- if (yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.y = frameSpeed.y * (yt - 0.1f);
- speed.y = 0;
- }
- else
- py--;
- needCollisionCheck = 1;
- continue;
- }
- }
- if (speed.z > 0)
- {
- float zt = ((float)pz + 1.f - oldPos.z) / frameSpeed.z;
- Vec3<float> tmp = oldPos + frameSpeed * zt;
- if (zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.z = frameSpeed.z * (zt - 0.1f);
- speed.z = 0;
- }
- else
- pz++;
- needCollisionCheck = 1;
- continue;
- }
- }
- if (speed.z < 0)
- {
- float zt = ((float)pz - oldPos.z) / frameSpeed.z;
- Vec3<float> tmp = oldPos + frameSpeed * zt;
- if (zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1)
- {
- if (!getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId()))->isPassable())
- {
- frameSpeed.z = frameSpeed.z * (zt - 0.1f);
- onFall(speed.z);
- speed.z = 0;
- }
- else
- pz--;
- needCollisionCheck = 1;
- continue;
- }
- }
- }
- location += frameSpeed;
- if (oldPos != location || needUpdate)
- {
- NetworkResponse changeMsg;
- changeMsg.adressEntity(this);
- char msg[13];
- msg[0] = 0; // position changed
- *(float*)(msg + 1) = this->location.x;
- *(float*)(msg + 5) = this->location.y;
- *(float*)(msg + 9) = this->location.z;
- changeMsg.setMessage(msg, 13, 0);
- Game::INSTANCE->distributeResponse(&changeMsg);
- }
- }
- void Entity::api(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
- {
- char type;
- zRequest->lese(&type, 1);
- switch (type)
- {
- case 100: // request inventory
- {
- char idLen;
- zRequest->lese(&idLen, 1);
- char* id = new char[idLen + 1];
- zRequest->lese(id, idLen);
- id[(int)idLen] = 0;
- zResponse->adressGui(id);
- delete[] id;
- char filterLen;
- zRequest->lese(&filterLen, 1);
- char* filter = new char[filterLen + 1];
- zRequest->lese(filter, filterLen);
- filter[(int)filterLen] = 0;
- InMemoryBuffer buffer;
- int count = 0;
- for (ItemSlot* slot : *this)
- {
- if (slot->getName().istGleich(filter))
- {
- count++;
- int id = slot->getId();
- buffer.schreibe((char*)&id, 4);
- int itemCount = slot->getNumberOfItems();
- buffer.schreibe((char*)&itemCount, 4);
- if (itemCount > 0)
- {
- float f = slot->zStack()->zItem()->getDamage();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getMaxDamage();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getDurability();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getMaxDurability();
- buffer.schreibe((char*)&f, 4);
- int id = slot->zStack()->zItem()->zItemType()->getId();
- buffer.schreibe((char*)&id, 4);
- }
- }
- }
- delete[] filter;
- char* msg = new char[5 + buffer.getSize()];
- msg[0] = 0;
- *(int*)(msg + 1) = count;
- buffer.lese(msg + 5, (int)buffer.getSize());
- zResponse->setMessage(msg, 5 + (int)buffer.getSize(), 1);
- break;
- }
- }
- }
- void Entity::onFall(float collisionSpeed)
- {
- if (collisionSpeed > 5)
- {
- // TODO: take damage
- }
- }
- void Entity::setPosition(Framework::Vec3<float> pos)
- {
- location = pos;
- }
- float Entity::getMaxHP() const
- {
- return maxHP;
- }
- float Entity::getCurrentHP() const
- {
- return currentHP;
- }
- float Entity::getStamina() const
- {
- return stamina;
- }
- float Entity::getMaxStamina() const
- {
- return maxStamina;
- }
- float Entity::getHunger() const
- {
- return hunger;
- }
- float Entity::getMaxHunger() const
- {
- return maxHunger;
- }
- float Entity::getThirst() const
- {
- return thirst;
- }
- float Entity::getMaxThirst() const
- {
- return maxThirst;
- }
- Framework::Vec3<float> Entity::getSpeed() const
- {
- return speed;
- }
- Framework::Vec3<float> Entity::getFaceDir() const
- {
- return faceDir;
- }
- Framework::Vec3<float> Entity::getPosition() const
- {
- return location;
- }
- float Entity::getGravityMultiplier() const
- {
- return gravityMultiplier;
- }
- int Entity::getCurrentDimensionId() const
- {
- return currentDimensionId;
- }
- bool Entity::isRemoved() const
- {
- return removed;
- }
- const EntityType* Entity::zType() const
- {
- return zEntityType;
- }
- const ActionTarget* Entity::zTarget() const
- {
- return target;
- }
- int Entity::getId() const
- {
- return id;
- }
- bool Entity::hasDefaultModel() const
- {
- return 1;
- }
- ModelInfo Entity::getSpecialModel() const
- {
- return ModelInfo("", "", 0);
- }
|