Hotfix: Conditional order comparator dropdown list was broken.
[openttd-joker.git] / src / tunnel_map.cpp
blob1d9eacbdc0f49b1628d559cccabdc42844b64be2
1 /* $Id: tunnel_map.cpp 23167 2011-11-08 19:44:41Z rubidium $ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file tunnel_map.cpp Map accessors for tunnels. */
12 #include "stdafx.h"
13 #include "tunnelbridge_map.h"
15 #include "core/pool_func.hpp"
17 #include <unordered_map>
19 #include "safeguards.h"
21 /** All tunnel portals tucked away in a pool. */
22 TunnelPool _tunnel_pool("Tunnel");
23 INSTANTIATE_POOL_METHODS(Tunnel)
25 static std::unordered_map<TileIndex, TunnelID> tunnel_tile_index_map;
26 static std::unordered_multimap<uint64, Tunnel*> tunnel_axis_height_index;
28 static uint64 GetTunnelAxisHeightCacheKey(TileIndex tile, uint8 height, bool y_axis) {
29 if (y_axis) {
30 // tunnel extends along Y axis (DIAGDIR_SE from north end), has same X values
31 return TileX(tile) | (((uint64) height) << 24) | (((uint64) 1) << 32);
32 } else {
33 // tunnel extends along X axis (DIAGDIR_SW from north end), has same Y values
34 return TileY(tile) | (((uint64) height) << 24);
38 static inline uint64 GetTunnelAxisHeightCacheKey(const Tunnel* t) {
39 return GetTunnelAxisHeightCacheKey(t->tile_n, t->height, t->tile_s - t->tile_n > MapMaxX());
42 /**
43 * Clean up a tunnel tile
45 Tunnel::~Tunnel()
47 if (CleaningPool()) return;
49 if (this->index >= TUNNEL_ID_MAP_LOOKUP) {
50 tunnel_tile_index_map.erase(this->tile_n);
51 tunnel_tile_index_map.erase(this->tile_s);
54 auto range = tunnel_axis_height_index.equal_range(GetTunnelAxisHeightCacheKey(this));
55 bool have_erased = false;
56 for (auto it = range.first; it != range.second; ++it) {
57 if (it->second == this) {
58 tunnel_axis_height_index.erase(it);
59 have_erased = true;
60 break;
63 assert(have_erased);
66 /**
67 * Update tunnel indexes
69 void Tunnel::UpdateIndexes()
71 if (this->index >= TUNNEL_ID_MAP_LOOKUP) {
72 tunnel_tile_index_map[this->tile_n] = this->index;
73 tunnel_tile_index_map[this->tile_s] = this->index;
76 tunnel_axis_height_index.emplace(GetTunnelAxisHeightCacheKey(this), this);
79 /**
80 * Tunnel pool is about to be cleaned
82 void Tunnel::PreCleanPool()
84 tunnel_tile_index_map.clear();
85 tunnel_axis_height_index.clear();
88 TunnelID GetTunnelIndexByLookup(TileIndex t)
90 auto iter = tunnel_tile_index_map.find(t);
91 assert_msg(iter != tunnel_tile_index_map.end(), "tile: 0x%X", t);
92 return iter->second;
96 /**
97 * Gets the other end of the tunnel. Where a vehicle would reappear when it
98 * enters at the given tile.
99 * @param tile the tile to search from.
100 * @return the tile of the other end of the tunnel.
102 TileIndex GetOtherTunnelEnd(TileIndex tile)
104 Tunnel * t = Tunnel::GetByTile(tile);
105 return t->tile_n == tile ? t->tile_s : t->tile_n;
108 static inline bool IsTunnelInWaySingleAxis(TileIndex tile, int z, IsTunnelInWayFlags flags, bool y_axis, TileIndexDiff tile_diff)
110 const auto tunnels = tunnel_axis_height_index.equal_range(GetTunnelAxisHeightCacheKey(tile, z, y_axis));
111 for (auto it = tunnels.first; it != tunnels.second; ++it) {
112 const Tunnel *t = it->second;
113 if (t->tile_n > tile || tile > t->tile_s) continue;
115 if (!t->is_chunnel && (flags & ITIWF_CHUNNEL_ONLY)) {
116 continue;
118 if (t->is_chunnel && (flags & ITIWF_IGNORE_CHUNNEL)) {
119 /* Only if tunnel was built over water is terraforming is allowed between portals. */
120 const TileIndexDiff delta = tile_diff * 4; // 4 tiles ramp.
121 if (tile < t->tile_n + delta || t->tile_s - delta < tile) return true;
122 continue;
125 return true;
127 return false;
131 * Is there a tunnel in the way in any direction?
132 * @param tile the tile to search from.
133 * @param z the 'z' to search on.
134 * @param chunnel_allowed True if chunnel mid-parts are allowed, used when terraforming.
135 * @return true if and only if there is a tunnel.
137 bool IsTunnelInWay(TileIndex tile, int z, IsTunnelInWayFlags flags)
139 return IsTunnelInWaySingleAxis(tile, z, flags, false, 1) || IsTunnelInWaySingleAxis(tile, z, flags, true, TileOffsByDiagDir(DIAGDIR_SE));