feat(core): declare crop growth and farmland hydration interface
This commit is contained in:
1 parent
125ee956b2
commit
23c73ff8ff
1 file changed
+106
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "World.h"
|
||||
#include "Math.h"
|
||||
|
||||
namespace vf {
|
||||
|
||||
enum class CropType : uint8_t {
|
||||
None = 0,
|
||||
Wheat = 1,
|
||||
Carrot = 2,
|
||||
Potato = 3,
|
||||
PumpkinStem = 4,
|
||||
MelonStem = 5,
|
||||
SugarCane = 6,
|
||||
Cactus = 7,
|
||||
Sapling = 8,
|
||||
Vine = 9,
|
||||
};
|
||||
|
||||
const char* cropTypeName(CropType type);
|
||||
int cropMaxStage(CropType type);
|
||||
|
||||
struct CropState {
|
||||
CropType type = CropType::None;
|
||||
int stage = 0;
|
||||
int maxStage = 0;
|
||||
|
||||
bool mature() const { return stage >= maxStage; }
|
||||
};
|
||||
|
||||
struct HarvestDrop {
|
||||
Block item;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct FarmingConfig {
|
||||
int hydrationRadius = 4;
|
||||
int minGrowthLight = 9;
|
||||
// Growth attempt succeeds when rng % denominator < points; dry farmland
|
||||
// scores 1 point, moist farmland 3, so hydration roughly triples the rate.
|
||||
uint32_t growthDenominator = 6;
|
||||
uint32_t saplingDenominator = 8;
|
||||
uint32_t verticalDenominator = 6;
|
||||
int caneMaxHeight = 3;
|
||||
int cactusMaxHeight = 3;
|
||||
int vineMaxLength = 4;
|
||||
int treeTrunkMin = 4;
|
||||
int treeTrunkMax = 6;
|
||||
// Bonemeal shoves a crop this many stages forward per application.
|
||||
int bonemealMinStages = 2;
|
||||
int bonemealMaxStages = 5;
|
||||
// Odds (in 100ths) a bonemealed sapling grows into a tree at once.
|
||||
uint32_t bonemealSaplingChance = 45;
|
||||
};
|
||||
|
||||
// Deterministic crop simulation with its own position->state registry, kept
|
||||
// separate from the block-tick scheduler. Ground crops (wheat, carrot, potato)
|
||||
// advance on random ticks gated by sky light and accelerated by farmland
|
||||
// hydration; stems mature and set fruit on a free neighbour; sugar cane grows
|
||||
// beside water and cactus only where it has no solid neighbours; a mature
|
||||
// sapling stamps a tree. Harvesting removes the crop and yields drops. A given
|
||||
// seed and tick order always produce the same growth history.
|
||||
class Farming {
|
||||
public:
|
||||
explicit Farming(uint32_t seed = 1u, const FarmingConfig& config = {});
|
||||
|
||||
void plant(World& world, const Vec3i& pos, CropType type);
|
||||
bool randomTick(World& world, const Vec3i& pos, int skyLight);
|
||||
int growStep(World& world, int skyLight);
|
||||
|
||||
bool applyBonemeal(World& world, const Vec3i& pos);
|
||||
bool trample(World& world, const Vec3i& farmland);
|
||||
|
||||
std::vector<HarvestDrop> harvest(World& world, const Vec3i& pos);
|
||||
|
||||
bool isHydrated(const World& world, const Vec3i& farmland) const;
|
||||
|
||||
const CropState* stateAt(const Vec3i& pos) const;
|
||||
std::size_t trackedCount() const { return crops.size(); }
|
||||
|
||||
const FarmingConfig& settings() const { return config; }
|
||||
|
||||
private:
|
||||
enum class GrowthResult { None, Advanced, Removed };
|
||||
|
||||
uint32_t nextRandom();
|
||||
bool rollGrowth(uint32_t denominator, int points);
|
||||
|
||||
GrowthResult growGroundCrop(World& world, const Vec3i& pos, CropState& state, int skyLight);
|
||||
GrowthResult growStem(World& world, const Vec3i& pos, CropState& state, int skyLight);
|
||||
GrowthResult growColumn(World& world, const Vec3i& pos, CropState& state, bool cane);
|
||||
GrowthResult growVine(World& world, const Vec3i& pos, CropState& state);
|
||||
GrowthResult growSapling(World& world, const Vec3i& pos, CropState& state, int skyLight);
|
||||
|
||||
void stampTree(World& world, const Vec3i& base);
|
||||
|
||||
FarmingConfig config;
|
||||
uint32_t rngState;
|
||||
std::unordered_map<Vec3i, CropState, Vec3iHash> crops;
|
||||
};
|
||||
|
||||
} // namespace vf
|
||||
Reference in new issue
Block a user