feat(core): declare minecart rail network graph and junction logic interface
This commit is contained in:
1 parent
3639670fae
commit
f1d496345d
1 file changed
+103
@@ -0,0 +1,103 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include "World.h"
|
||||||
|
#include "Circuit.h"
|
||||||
|
#include "Block.h"
|
||||||
|
#include "Math.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
constexpr int poweredRailReach = 8;
|
||||||
|
|
||||||
|
enum class RailDir : uint8_t {
|
||||||
|
North, // -Z
|
||||||
|
South, // +Z
|
||||||
|
East, // +X
|
||||||
|
West, // -X
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RailShape : uint8_t {
|
||||||
|
NorthSouth,
|
||||||
|
EastWest,
|
||||||
|
AscendNorth,
|
||||||
|
AscendSouth,
|
||||||
|
AscendEast,
|
||||||
|
AscendWest,
|
||||||
|
CurveSouthEast,
|
||||||
|
CurveSouthWest,
|
||||||
|
CurveNorthWest,
|
||||||
|
CurveNorthEast,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RailStep {
|
||||||
|
Vec3i nextPos;
|
||||||
|
RailDir exitDir = RailDir::North;
|
||||||
|
bool valid = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool isRailBlock(Block b) {
|
||||||
|
return b == Block::Rail || b == Block::PoweredRail ||
|
||||||
|
b == Block::DetectorRail || b == Block::ActivatorRail;
|
||||||
|
}
|
||||||
|
|
||||||
|
RailDir opposite(RailDir dir);
|
||||||
|
Vec3i railDelta(RailDir dir);
|
||||||
|
bool isAscending(RailShape shape);
|
||||||
|
RailDir ascendUpDir(RailShape shape);
|
||||||
|
std::pair<RailDir, RailDir> railEnds(RailShape shape);
|
||||||
|
|
||||||
|
// Auto-connects a rail to its neighbours. Curves are only produced for plain
|
||||||
|
// rails (Block::Rail); powered/detector/activator rails stay straight or
|
||||||
|
// ascending. When `switched` is true a straight-capable rail that also has a
|
||||||
|
// perpendicular neighbour takes the turn instead of going straight, modelling a
|
||||||
|
// powered junction.
|
||||||
|
RailShape inferRailShape(const World& world, const Vec3i& pos, bool switched = false);
|
||||||
|
|
||||||
|
// Follows the track one cell from `pos` given an entry heading. Handles curves
|
||||||
|
// (heading rotates) and slopes (steps up onto an ascending rail or down onto a
|
||||||
|
// descending one). `valid` is false when the track dead-ends: a derail.
|
||||||
|
RailStep advanceOnRail(const World& world, const Vec3i& pos, RailDir moveDir, bool switched = false);
|
||||||
|
|
||||||
|
// Set of powered-rail cells that end up energised: every rail directly powered
|
||||||
|
// by redstone plus connected powered rails within `poweredRailReach` along the
|
||||||
|
// straight line in each direction.
|
||||||
|
std::unordered_set<Vec3i, Vec3iHash> activePoweredRails(
|
||||||
|
const World& world,
|
||||||
|
const std::vector<Vec3i>& poweredRails,
|
||||||
|
const std::function<bool(const Vec3i&)>& directlyPowered);
|
||||||
|
|
||||||
|
std::unordered_set<Vec3i, Vec3iHash> activePoweredRails(
|
||||||
|
const World& world,
|
||||||
|
const std::vector<Vec3i>& poweredRails,
|
||||||
|
const RedstoneCircuit& circuit);
|
||||||
|
|
||||||
|
// Adjacency graph over a set of rail cells. Each node links to the rail cells
|
||||||
|
// its two ends connect to, following curves and slopes. Backs cart routing:
|
||||||
|
// distance queries, one-shot track tracing and connectivity checks.
|
||||||
|
class RailGraph {
|
||||||
|
public:
|
||||||
|
void build(const World& world, const std::vector<Vec3i>& railCells, bool switched = false);
|
||||||
|
|
||||||
|
bool contains(const Vec3i& pos) const { return adjacency.find(pos) != adjacency.end(); }
|
||||||
|
std::vector<Vec3i> neighbours(const Vec3i& pos) const;
|
||||||
|
std::size_t size() const { return adjacency.size(); }
|
||||||
|
|
||||||
|
// Walks the track from `start` heading `dir`, returning the ordered cells it
|
||||||
|
// visits (including `start`) until a derail, a revisit (closed loop) or
|
||||||
|
// `maxSteps` cells.
|
||||||
|
std::vector<Vec3i> trace(const World& world, const Vec3i& start, RailDir dir, int maxSteps) const;
|
||||||
|
|
||||||
|
// Cell count of the shortest connection between two rails, or -1 when they
|
||||||
|
// are not connected within the graph.
|
||||||
|
int distance(const Vec3i& a, const Vec3i& b) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Vec3i, std::vector<Vec3i>, Vec3iHash> adjacency;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vf
|
||||||
Reference in new issue
Block a user