osb/source/game/interfaces/StarTileEntity.hpp
Kae dc77061840 hopefully fix #33
in OpenStarbound, players can place blocks with their own collision type. this can cause objects to override the collision type if the object has material spaces and a previous attempt at accounting for this led to that bug: giving object collision its own field in the server tile should fix this
2024-03-09 12:18:22 +11:00

97 lines
3.3 KiB
C++

#pragma once
#include "StarEntity.hpp"
#include "StarTileDamage.hpp"
#include "StarInteractiveEntity.hpp"
#include "StarCollisionBlock.hpp"
namespace Star {
STAR_CLASS(TileEntity);
struct MaterialSpace {
MaterialSpace();
MaterialSpace(Vec2I space, MaterialId material);
bool operator==(MaterialSpace const& rhs) const;
Vec2I space;
MaterialId material;
};
DataStream& operator<<(DataStream& ds, MaterialSpace const& materialSpace);
DataStream& operator>>(DataStream& ds, MaterialSpace& materialSpace);
// Entities that derive from TileEntity are those that can be placed in the
// tile grid, and occupy tile spaces, possibly affecting collision.
class TileEntity : public virtual InteractiveEntity {
public:
TileEntity();
// position() here is simply the tilePosition (but Vec2F)
virtual Vec2F position() const override;
// The base tile position of this object.
virtual Vec2I tilePosition() const = 0;
virtual void setTilePosition(Vec2I const& pos) = 0;
// TileEntities occupy the given spaces in tile space. This is relative to
// the current base position, and may include negative positions. A 1x1
// object would occupy just (0, 0).
virtual List<Vec2I> spaces() const;
// Blocks that should be marked as "root", so that they are non-destroyable
// until this entity is destroyable. Should be outside of spaces(), and
// after placement should remain static for the lifetime of the entity.
virtual List<Vec2I> roots() const;
// TileEntities may register some of their occupied spaces with metamaterials
// to generate collidable regions
virtual List<MaterialSpace> materialSpaces() const;
// Returns whether the entity was destroyed
virtual bool damageTiles(List<Vec2I> const& positions, Vec2F const& sourcePosition, TileDamage const& tileDamage);
// Forces the tile entity to do an immediate check if it has been invalidly
// placed in some way. The tile entity may do this check on its own, but
// less often.
virtual bool checkBroken() = 0;
// If the entity accepts interaction through right clicking, by default,
// returns false.
virtual bool isInteractive() const override;
// By default, does nothing. Will be called only on the server.
virtual InteractAction interact(InteractRequest const& request) override;
// Specific subset spaces that are interactive, by default, just returns
// spaces()
virtual List<Vec2I> interactiveSpaces() const;
virtual List<QuestArcDescriptor> offeredQuests() const override;
virtual StringSet turnInQuests() const override;
virtual Vec2F questIndicatorPosition() const override;
protected:
// Checks whether any of a given spaces list (relative to current tile
// position) is occupied by a real material. (Does not include tile
// entities).
bool anySpacesOccupied(List<Vec2I> const& relativeSpaces) const;
// Checks that *all* spaces are occupied by a real material.
bool allSpacesOccupied(List<Vec2I> const& relativeSpaces) const;
float spacesLiquidFillLevel(List<Vec2I> const& relativeSpaces) const;
};
inline MaterialSpace::MaterialSpace()
: material(NullMaterialId) {}
inline MaterialSpace::MaterialSpace(Vec2I space, MaterialId material)
: space(space), material(material) {}
inline bool MaterialSpace::operator==(MaterialSpace const& rhs) const {
return space == rhs.space
&& material == rhs.material;
}
}