2024-02-25 14:46:47 +00:00
|
|
|
#pragma once
|
2023-06-20 04:33:09 +00:00
|
|
|
|
|
|
|
#include "StarSet.hpp"
|
|
|
|
#include "StarNetElementSystem.hpp"
|
|
|
|
#include "StarTileEntity.hpp"
|
|
|
|
#include "StarPlantDatabase.hpp"
|
|
|
|
#include "StarInspectableEntity.hpp"
|
2023-07-03 08:22:31 +00:00
|
|
|
#include "StarAssetPath.hpp"
|
2023-06-20 04:33:09 +00:00
|
|
|
|
|
|
|
namespace Star {
|
|
|
|
|
|
|
|
STAR_CLASS(RenderCallback);
|
|
|
|
STAR_CLASS(Plant);
|
|
|
|
|
|
|
|
STAR_EXCEPTION(PlantException, StarException);
|
|
|
|
|
|
|
|
class Plant : public virtual TileEntity {
|
|
|
|
public:
|
|
|
|
// TODO: For right now the space scan threshold is hard-coded, but should be
|
|
|
|
// configurable in the future
|
|
|
|
static float const PlantScanThreshold;
|
|
|
|
|
|
|
|
enum RotationType {
|
|
|
|
DontRotate,
|
|
|
|
RotateBranch,
|
|
|
|
RotateLeaves,
|
|
|
|
RotateCrownBranch,
|
|
|
|
RotateCrownLeaves
|
|
|
|
};
|
|
|
|
|
|
|
|
static EnumMap<RotationType> const RotationTypeNames;
|
|
|
|
|
|
|
|
enum PlantPieceKind {
|
|
|
|
None,
|
|
|
|
Stem,
|
|
|
|
Foliage
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PlantPiece {
|
|
|
|
PlantPiece();
|
2023-07-03 08:22:31 +00:00
|
|
|
AssetPath imagePath;
|
2023-06-20 04:33:09 +00:00
|
|
|
String image;
|
|
|
|
Vec2U imageSize;
|
|
|
|
Vec2F offset;
|
|
|
|
int segmentIdx;
|
|
|
|
bool structuralSegment;
|
|
|
|
PlantPieceKind kind;
|
|
|
|
RotationType rotationType;
|
|
|
|
float rotationOffset;
|
|
|
|
Set<Vec2I> spaces;
|
|
|
|
bool flip;
|
|
|
|
// no need to serialize
|
|
|
|
float zLevel;
|
|
|
|
};
|
|
|
|
|
|
|
|
Plant(TreeVariant const& config, uint64_t seed);
|
|
|
|
Plant(GrassVariant const& config, uint64_t seed);
|
|
|
|
Plant(BushVariant const& config, uint64_t seed);
|
|
|
|
Plant(Json const& diskStore);
|
|
|
|
Plant(ByteArray const& netStore);
|
|
|
|
|
|
|
|
Json diskStore() const;
|
|
|
|
ByteArray netStore() const;
|
|
|
|
|
|
|
|
EntityType entityType() const override;
|
|
|
|
|
|
|
|
void init(World* world, EntityId entityId, EntityMode mode) override;
|
|
|
|
|
|
|
|
virtual String description() const override;
|
|
|
|
|
|
|
|
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
|
|
|
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
|
|
|
|
|
|
|
void enableInterpolation(float extrapolationHint) override;
|
|
|
|
void disableInterpolation() override;
|
|
|
|
|
|
|
|
Vec2F position() const override;
|
|
|
|
RectF metaBoundBox() const override;
|
|
|
|
|
|
|
|
bool ephemeral() const override;
|
|
|
|
|
|
|
|
bool shouldDestroy() const override;
|
|
|
|
|
|
|
|
// Forces the plant to check if it has been invalidly placed in some way, and
|
|
|
|
// should die. shouldDie does not, by default, do this expensive calculation
|
|
|
|
bool checkBroken() override;
|
|
|
|
|
|
|
|
// Base tile grid position
|
|
|
|
Vec2I tilePosition() const override;
|
|
|
|
void setTilePosition(Vec2I const& tilePosition) override;
|
|
|
|
|
|
|
|
// Spaces this plant currently occupies
|
|
|
|
List<Vec2I> spaces() const override;
|
|
|
|
|
|
|
|
// Root blocks for this plant.
|
|
|
|
List<Vec2I> roots() const override;
|
|
|
|
|
2023-07-20 14:58:49 +00:00
|
|
|
void update(float dt, uint64_t currentStep) override;
|
2023-06-20 04:33:09 +00:00
|
|
|
|
|
|
|
void render(RenderCallback* renderCallback) override;
|
|
|
|
|
|
|
|
bool damageTiles(List<Vec2I> const& position, Vec2F const& sourcePosition, TileDamage const& tileDamage) override;
|
|
|
|
|
|
|
|
// Central root position
|
|
|
|
Vec2I primaryRoot() const;
|
|
|
|
// Plant hangs from the ceiling
|
|
|
|
bool ceiling() const;
|
|
|
|
|
|
|
|
List<PlantPiece> pieces() const;
|
|
|
|
RectF interactiveBoundBox() const override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Plant();
|
|
|
|
|
|
|
|
void breakAtPosition(Vec2I const& position, Vec2F const& sourcePosition);
|
|
|
|
Vec2I baseDamagePosition(List<Vec2I> const& positions) const;
|
|
|
|
bool damagable() const;
|
|
|
|
|
|
|
|
void scanSpacesAndRoots();
|
|
|
|
List<PlantPiece> spawnFolliage(String const& key, String const& type);
|
|
|
|
float branchRotation(float xPos, float rotoffset) const;
|
|
|
|
void calcBoundBox();
|
|
|
|
|
|
|
|
void readPieces(ByteArray pieces);
|
|
|
|
ByteArray writePieces() const;
|
|
|
|
|
|
|
|
void readPiecesFromJson(Json const& pieces);
|
|
|
|
Json writePiecesToJson() const;
|
|
|
|
|
|
|
|
void validatePieces();
|
|
|
|
|
|
|
|
void setupNetStates();
|
|
|
|
void getNetStates();
|
|
|
|
void setNetStates();
|
|
|
|
|
|
|
|
Vec2I m_tilePosition;
|
|
|
|
List<Vec2I> m_spaces;
|
|
|
|
List<Vec2I> m_roots;
|
|
|
|
RectI m_boundBox;
|
|
|
|
|
|
|
|
Json m_descriptions;
|
|
|
|
|
|
|
|
bool m_ephemeral;
|
|
|
|
|
|
|
|
Json m_stemDropConfig;
|
|
|
|
Json m_foliageDropConfig;
|
|
|
|
Json m_saplingDropConfig;
|
|
|
|
|
|
|
|
List<PlantPiece> m_pieces;
|
|
|
|
bool m_piecesUpdated;
|
|
|
|
|
|
|
|
bool m_ceiling;
|
|
|
|
bool m_broken;
|
|
|
|
bool m_fallsWhenDead;
|
|
|
|
|
|
|
|
float m_windTime;
|
|
|
|
float m_windLevel;
|
|
|
|
|
|
|
|
RectF m_metaBoundBox;
|
|
|
|
|
|
|
|
bool m_piecesScanned;
|
|
|
|
|
|
|
|
TileDamageParameters m_tileDamageParameters;
|
|
|
|
EntityTileDamageStatus m_tileDamageStatus;
|
|
|
|
float m_tileDamageX;
|
|
|
|
float m_tileDamageY;
|
|
|
|
bool m_tileDamageEventTrigger;
|
|
|
|
bool m_tileDamageEvent;
|
|
|
|
|
|
|
|
NetElementTopGroup m_netGroup;
|
|
|
|
NetElementBytes m_piecesNetState;
|
|
|
|
NetElementFloat m_tileDamageXNetState;
|
|
|
|
NetElementFloat m_tileDamageYNetState;
|
|
|
|
NetElementEvent m_tileDamageEventNetState;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|