fix issue where items were accepted by a belt from opposite travel direction

This commit is contained in:
2026-07-14 20:15:39 +02:00
parent 4b149d97a7
commit af8a2224c0
5 changed files with 249 additions and 80 deletions

View File

@@ -27,6 +27,56 @@ QPoint BeltSystem::adjacentTile(QPoint tile, Rotation dir)
return tile;
}
Rotation BeltSystem::oppositeRotation(Rotation dir)
{
switch (dir)
{
case Rotation::North: return Rotation::South;
case Rotation::East: return Rotation::West;
case Rotation::South: return Rotation::North;
case Rotation::West: return Rotation::East;
}
return dir;
}
bool BeltSystem::entersThroughOutputEdge(QPoint tile, Rotation travelDir) const
{
// An item travelling in travelDir crosses into the tile through the edge
// opposite that direction. If that entry edge is one of the tile's output
// edges, the tile must refuse the item (REQ-MAT-ACCEPT-DIR).
const Rotation entryEdge = oppositeRotation(travelDir);
const std::map<std::pair<int, int>, BeltTile>::const_iterator beltIt =
m_belts.find(key(tile));
if (beltIt != m_belts.end())
{
return entryEdge == beltIt->second.direction;
}
const std::map<std::pair<int, int>, SplitterTile>::const_iterator splIt =
m_splitters.find(key(tile));
if (splIt != m_splitters.end())
{
return entryEdge == splIt->second.outputA || entryEdge == splIt->second.outputB;
}
const std::map<std::pair<int, int>, TunnelEntryTile>::const_iterator teIt =
m_tunnelEntries.find(key(tile));
if (teIt != m_tunnelEntries.end())
{
return entryEdge == teIt->second.direction;
}
const std::map<std::pair<int, int>, TunnelExitTile>::const_iterator txIt =
m_tunnelExits.find(key(tile));
if (txIt != m_tunnelExits.end())
{
return entryEdge == txIt->second.direction;
}
return false;
}
QPointF BeltSystem::slotWorldPos(QPoint tile, Rotation dir, double progress)
{
// Map progress [0, 1] along the belt direction to a fractional tile-unit position.
@@ -202,6 +252,12 @@ void BeltSystem::reevaluateTunnelPairing()
bool BeltSystem::tryPutItem(QPoint tile, Item item, Rotation fromDir)
{
// Refuse items that would enter through the tile's output edge (REQ-MAT-ACCEPT-DIR).
if (entersThroughOutputEdge(tile, fromDir))
{
return false;
}
const std::map<std::pair<int, int>, BeltTile>::iterator bIt = m_belts.find(key(tile));
if (bIt != m_belts.end())
{
@@ -579,6 +635,13 @@ void BeltSystem::moveItemsToNextTile()
const QPoint here = QPoint(it->first.first, it->first.second);
const QPoint next = adjacentTile(here, bt.direction);
// Refuse to hand off into a downstream tile's output edge (REQ-MAT-ACCEPT-DIR);
// the item stays blocked at progress 1.0.
if (entersThroughOutputEdge(next, bt.direction))
{
continue;
}
const std::map<std::pair<int, int>, BeltTile>::iterator nextBelt = m_belts.find(key(next));
const std::map<std::pair<int, int>, SplitterTile>::iterator nextSplitter = m_splitters.find(key(next));
@@ -804,6 +867,12 @@ bool BeltSystem::tryPlaceOnBelt(QPoint tile, Item item)
bool BeltSystem::tryPushToTile(QPoint dest, Item item, Rotation fromDir)
{
// Refuse items that would enter through the tile's output edge (REQ-MAT-ACCEPT-DIR).
if (entersThroughOutputEdge(dest, fromDir))
{
return false;
}
if (tryPlaceOnBelt(dest, item))
{
return true;