add terrain features

such as islands, peaks, etc

will be detected and assigned to places
This commit is contained in:
Crypto City 2022-07-01 13:20:53 +00:00
parent 6d5529d323
commit e62d9478de
24 changed files with 284 additions and 19 deletions

View File

@ -9,10 +9,14 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
TBTextField: text: "You can create more complex shapes by creating several areas sharing the same name."
TBTextField: text: "Holes may be made by creating an area with an empty name."
TBEditField: multiline: 1, readonly: 1, gravity: "left right", adapt-to-content: 1, skin: 0, is-focusable: 0
text: "Place name"
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
TBTextField: text: "Terrain type:"
TBTextField: id: "terrain-feature"
TBButton: id: "help", text: "?"
TBEditField: id: "name", gravity: "all", placeholder: "Give this place a name", multiline: 0
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
TBTextField: text: "Place name:"
TBEditField: id: "name", gravity: "all", placeholder: "Give this place a name", multiline: 0, autofocus: 1
TBLayout: axis: x
TBTextField: text: "Naming a place this size needs"

View File

@ -223,6 +223,7 @@ elements
padding 10
travel-to-place-row
padding 10
TBButton.tradelink

View File

@ -2,3 +2,7 @@ WindowInfo
TBLayout: axis: y, size: "available", distribution: "gravity", skin: "travel-to-place-row"
TBTextField: id: "name"
TBToggleContainer: id: "feature-container", toggle: "expanded", value: 0
TBLayout: axis: x
TBTextField: id: "feature", gravity: "left right"
TBTextField: id: "distance"

View File

@ -1224,6 +1224,7 @@ typedef struct mdb_cc_place_data_t
uint32_t y0;
uint32_t x1;
uint32_t y1;
uint32_t terrain_feature;
std::string name;
uint32_t priority;
@ -1234,6 +1235,7 @@ typedef struct mdb_cc_place_data_t
FIELD(y0)
FIELD(x1)
FIELD(y1)
VARINT_FIELD(terrain_feature)
TEXT_FIELD(name)
VARINT_FIELD(priority)
END_SERIALIZE()
@ -11657,6 +11659,7 @@ void BlockchainLMDB::add_cc_place(const cc::place_t &place)
pd.y0 = place.y0;
pd.x1 = place.x1;
pd.y1 = place.y1;
pd.terrain_feature = place.terrain_feature;
pd.name = place.name;
pd.priority = priority;
@ -11719,6 +11722,7 @@ bool BlockchainLMDB::for_all_cc_places(uint32_t city, const std::function<bool(c
place.y0 = pd.y0;
place.x1 = pd.x1;
place.y1 = pd.y1;
place.terrain_feature = pd.terrain_feature;
place.name = std::move(pd.name);
place.priority = pd.priority;

View File

@ -111,6 +111,7 @@ set(cc_sources
cc_special_events.cpp
cc_temperature.cpp
cc_terrain.cc
cc_terrain_features.cc
cc_whisper.cc
cc.cpp
fixed.cc
@ -199,6 +200,7 @@ set(cc_headers
cc_special_events.h
cc_temperature.h
cc_terrain.h
cc_terrain_features.h
cc.h)
set(cc_private_headers

View File

@ -33,6 +33,7 @@
#include "cc/cc_influence.h"
#include "cc/cc_badge.h"
#include "cc/cc_place.h"
#include "cc/cc_terrain_features.h"
#include "cc_command_handler_helpers.h"
#include "cc_command_handler_name_place.h"
@ -168,7 +169,11 @@ bool cc_command_handler_name_place::execute(cryptonote::BlockchainDB &db, const
CHECK_AND_ASSERT_MES(cc::decrease_item_count(db, ITEM_RUNESTONE, num_runestones), false, "Item count anomaly");
}
db.add_cc_place(make_place(name_place));
cc::place_t place = make_place(name_place);
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(name_place.city, cd.seed);
place.terrain_feature = cc::classify_terrain_feature(state, place.x0, place.y0, place.x1, place.y1);
db.add_cc_place(place);
events.add_full(cmd, name_place.cc_account, 0, 0, ITEM_NONE, 0, 0, tx_fee) << "Mamed '" + name_place.name + "' in " << cd.name;
return true;

View File

@ -17,6 +17,7 @@ struct place_t
uint32_t y0;
uint32_t x1;
uint32_t y1;
uint32_t terrain_feature;
std::string name;
uint32_t priority;
@ -24,7 +25,7 @@ struct place_t
{
return id == other.id && height == other.height && city == other.city && namer == other.namer
&& x0 == other.x0 && y0 == other.y0 && x1 == other.x1 && y1 == other.y1
&& name == other.name && priority == other.priority;
&& terrain_feature == other.terrain_feature && name == other.name && priority == other.priority;
}
};

View File

@ -0,0 +1,125 @@
#include <stdint.h>
#include <vector>
#include "cc/cc.h"
#include "sqrtint.h"
#include "cc_terrain_features.h"
namespace cc
{
const char *terrain_feature_names[] =
{
"none",
"open sea",
"sand bank",
"beach",
"peak",
"island",
"lake",
"plain",
};
terrain_feature_t classify_terrain_feature(const std::shared_ptr<cc_potential_state_t> &state, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1)
{
const uint32_t w = x1 - x0 + 1;
const uint32_t h = y1 - y0 + 1;
const int32_t maxwh = std::max(w, h);
std::vector<uint16_t> height(w * h);
uint32_t offset = 0;
for (uint32_t y = y0; y <= y1; ++y)
for (uint32_t x = x0; x <= x1; ++x)
height[offset++] = cc::get_cc_height(state, x, y);
// open sea
bool above_water = false;
uint16_t min_height = 0xffff;
uint16_t max_height = 0;
for (uint16_t h: height)
{
min_height = std::min(min_height, h);
max_height = std::max(max_height, h);
if (h >= BASE_WATER_LEVEL)
above_water = true;
}
if (!above_water)
return terrain_feature_open_sea;
// island or sand bank
bool water = true;
for (uint32_t y = y0; y <= y1; ++y)
{
if (height[(y - y0) * w] >= BASE_WATER_LEVEL || height[(y - y0) * w + x1 - x0] >= BASE_WATER_LEVEL)
{
water = false;
break;
}
}
if (water) for (uint32_t x = x0; x <= x1; ++x)
{
if (height[x - x0] >= BASE_WATER_LEVEL || height[(y1 - y0) * w + x - x0] >= BASE_WATER_LEVEL)
{
water = false;
break;
}
}
if (water) // already not open sea
{
if (max_height < SAND_LEVEL)
return terrain_feature_sand_bank;
else
return terrain_feature_island;
}
// lake
bool land = true;
for (uint32_t y = y0; y <= y1; ++y)
{
if (height[(y - y0) * w] <= BASE_WATER_LEVEL || height[(y - y0) * w + x1 - x0] <= BASE_WATER_LEVEL)
{
land = false;
break;
}
}
if (land) for (uint32_t x = x0; x <= x1; ++x)
{
if (height[x - x0] <= BASE_WATER_LEVEL || height[(y1 - y0) * w + x - x0] <= BASE_WATER_LEVEL)
{
land = false;
break;
}
}
if (land && min_height < BASE_WATER_LEVEL)
return terrain_feature_lake;
// beach
uint32_t beach_height = 0;
for (uint16_t h: height)
if (h > BASE_WATER_LEVEL && h <= SAND_LEVEL)
++beach_height;
if (beach_height >= w * h * 30 / 100)
return terrain_feature_beach;
// peak
uint16_t max_border_height = 0;
const uint32_t peak_border_w = w / 10;
const uint32_t peak_border_h = h / 10;
for (uint32_t y = y0; y <= y1; ++y)
for (uint32_t x = x0; x <= x1; ++x)
if (y < y0 + peak_border_h || y > y1 - peak_border_h || x < x0 + peak_border_w || x > x1 - peak_border_w)
max_border_height = std::max(max_border_height, height[(y - y0) * w + x - x0]);
const uint16_t d_peak_height = max_height - max_border_height;
const uint64_t peak_rating = 100 * d_peak_height * sqrtint(sqrtint(maxwh * 65536ull * 65536ull)) / (768 * HEIGHT_UNITS_PER_BLOCK * maxwh);
if (peak_rating >= 20)
return terrain_feature_peak;
// plain
const uint16_t dheight = max_height - min_height;
if (min_height > SAND_LEVEL && dheight < maxwh * HEIGHT_UNITS_PER_BLOCK / 12)
return terrain_feature_plain;
return terrain_feature_none;
}
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "cc/cc_potential.h"
namespace cc
{
enum terrain_feature_t
{
terrain_feature_none = 0,
terrain_feature_open_sea,
terrain_feature_sand_bank,
terrain_feature_beach,
terrain_feature_peak,
terrain_feature_island,
terrain_feature_lake,
terrain_feature_plain,
};
extern const char *terrain_feature_names[];
terrain_feature_t classify_terrain_feature(const std::shared_ptr<cc_potential_state_t> &state, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1);
}

View File

@ -382,6 +382,7 @@ struct cc_snapshot
uint32_t y0;
uint32_t x1;
uint32_t y1;
uint32_t terrain_feature;
std::string name;
uint32_t priority;
@ -394,6 +395,7 @@ struct cc_snapshot
KV_SERIALIZE(y0)
KV_SERIALIZE(x1)
KV_SERIALIZE(y1)
KV_SERIALIZE(terrain_feature)
KV_SERIALIZE(name)
KV_SERIALIZE(priority)
END_KV_SERIALIZE_MAP()
@ -407,6 +409,7 @@ struct cc_snapshot
FIELD(y0)
FIELD(x1)
FIELD(y1)
VARINT_FIELD(terrain_feature)
FIELD(name)
VARINT_FIELD(priority)
END_SERIALIZE()

View File

@ -1068,6 +1068,7 @@ bool GameState::process_name_place(const cryptonote::cc_command_name_place_t &cm
eventData[NewPlaceName::P_X1] = cmd.x1;
eventData[NewPlaceName::P_Y1] = cmd.y1;
eventData[NewPlaceName::P_NAME] = cmd.name.c_str();
eventData[NewPlaceName::P_TERRAIN_FEATURE] = 0;
eventData[NewPlaceName::P_PRIORITY] = 0;
SendEvent(E_CRYPTOCITY_NEW_PLACE_NAME, eventData);
return true;
@ -1632,6 +1633,7 @@ bool GameState::reset(const cryptonote::cc_snapshot *snapshot)
eventData[NewPlaceName::P_X1] = p.x1;
eventData[NewPlaceName::P_Y1] = p.y1;
eventData[NewPlaceName::P_NAME] = p.name.c_str();
eventData[NewPlaceName::P_TERRAIN_FEATURE] = p.terrain_feature;
eventData[NewPlaceName::P_PRIORITY] = p.priority;
SendEvent(E_CRYPTOCITY_NEW_PLACE_NAME, eventData);
}

View File

@ -77,6 +77,7 @@ URHO3D_EVENT(E_CRYPTOCITY_NEW_PLACE_NAME, NewPlaceName)
URHO3D_PARAM(P_Y0, Y0);
URHO3D_PARAM(P_X1, X1);
URHO3D_PARAM(P_Y1, Y1);
URHO3D_PARAM(P_TERRAIN_FEATURE, TerrainFeature);
URHO3D_PARAM(P_NAME, Name);
URHO3D_PARAM(P_PRIORITY, Priority);
}

View File

@ -64,6 +64,7 @@
#include "cc/cc_influence.h"
#include "cc/cc_potential.h"
#include "cc/cc_temperature.h"
#include "cc/cc_terrain_features.h"
#include "selection.h"
#include "selection-info.h"
#include "game-util.h"
@ -1911,6 +1912,7 @@ void CryptoCityUrho3D::UpdateTargetting()
selection_tooltip->SetTop(true);
SubscribeToEvent(selection_tooltip, E_TB_WINDOW_DEAD, [this](StringHash eventType, VariantMap& eventData){ selection_tooltip = NULL; cached_potential.clear(); });
}
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
std::string s = std::to_string(sel_w) + " x " + std::to_string(sel_h);
bool error = sel_w > 256 || sel_h > 256;
if (!error)
@ -1929,7 +1931,6 @@ void CryptoCityUrho3D::UpdateTargetting()
if (flags.empty())
{
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
uint32_t ox, oy;
uint64_t cost = 0;
cc::get_city_origin(gameState.cityState.id, ox, oy);
@ -2077,8 +2078,13 @@ void CryptoCityUrho3D::UpdateTargetting()
s += "\nUnderwater area: " + std::string(buf);
}
}
if (error)
s = "<color #f04040>" + s + "</color>";
}
if (error)
s = "<color #f04040>" + s + "</color>";
if (HasSelectionInfo(selection_info_terrain_feature))
{
const cc::terrain_feature_t feature = cc::classify_terrain_feature(state, selection.x0, selection.y0, selection.x1, selection.y1);
s += "\nTerrain feature: " + std::string(cc::terrain_feature_names[feature]);
}
selection_tooltip->SetText(s.c_str());
}
@ -7342,7 +7348,13 @@ void CryptoCityUrho3D::HandleNewPlaceName(StringHash eventType, VariantMap& even
if (gameState.ignore_player(namer))
return;
map.add_place(id, height, gameState.cityState.id, namer, x0, y0, x1, y1, name.CString(), priority);
uint32_t terrain_feature = eventData[NewPlaceName::P_TERRAIN_FEATURE].GetInt();
if (!eventData.Contains(NewPlaceName::P_TERRAIN_FEATURE))
{
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
terrain_feature = cc::classify_terrain_feature(state, x0, y0, x1, y1);
}
map.add_place(id, height, gameState.cityState.id, namer, x0, y0, x1, y1, terrain_feature, name.CString(), priority);
cityMesh->RebuildNamedAreas();
}

View File

@ -534,7 +534,7 @@ void Map::remove_flag(const std::shared_ptr<Flag> &flag)
flags.erase(flag->id);
}
void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const std::string &name, uint32_t priority)
void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t terrain_feature, const std::string &name, uint32_t priority)
{
if (priority == 0)
priority = ++highest_place_priority;
@ -549,6 +549,7 @@ void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer,
place->y0 = y0;
place->x1 = x1;
place->y1 = y1;
place->terrain_feature = terrain_feature;
place->name = name;
place->priority = priority;
qplaces.insert(place);

View File

@ -215,7 +215,7 @@ public:
void set_flag_palette(uint32_t id, const std::vector<uint16_t> &new_palette);
void resize_flag(const std::shared_ptr<Flag> &flag, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const uint8_t potential[NUM_POTENTIALS], uint16_t base_height, uint32_t elevation_bonus, uint32_t average_slope, int32_t average_slope_modifier, uint32_t south_facing, uint32_t bridge_score, const uint32_t underwater_area[2]);
void remove_flag(const std::shared_ptr<Flag> &flag);
void add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const std::string &name, uint32_t priority);
void add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t terrain_feature, const std::string &name, uint32_t priority);
void get_places(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, std::set<std::shared_ptr<cc::place_t>> &res) const;
void get_all_places(std::set<std::shared_ptr<cc::place_t>> &res) const;
bool get_place(uint32_t x, uint32_t y, std::string &name, const std::function<bool(uint32_t)> &allow_namer = NULL) const;

View File

@ -22,6 +22,7 @@ static const char *text[] =
"Influences",
"Bridge score",
"Underwater area",
"Terrain feature",
};
const char *get_selection_info_text(selection_info_t si)

View File

@ -22,6 +22,7 @@ enum selection_info_t
selection_info_influences,
selection_info_bridge_score,
selection_info_underwater_area,
selection_info_terrain_feature,
num_selection_info
};

View File

@ -8,6 +8,7 @@
#include "cryptonote_config.h"
#include "cc/cc_config.h"
#include "cc/cc.h"
#include "cc/cc_terrain_features.h"
#include "UTBRendererBatcher.h"
#include "game-util.h"
#include "game-state.h"
@ -32,6 +33,11 @@ UINamePlaceDialog::UINamePlaceDialog(Context *ctx, const GameState *game, uint32
nameWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("name"));
runestonesNeededWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("runestones-needed"));
runestonesOwnedWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("runestones-owned"));
terrainFeatureWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("terrain-feature"));
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(game->cityState.id, game->cityState.seed);
const cc::terrain_feature_t feature = cc::classify_terrain_feature(state, x0, y0, x1, y1);
terrainFeatureWidget->SetText(cc::terrain_feature_names[feature]);
SubscribeToEvent(this, E_TB_WIDGET_EVENT, URHO3D_HANDLER(UINamePlaceDialog, HandleTBMessage));
SubscribeToEvent(this, E_TB_WINDOW_CLOSED, URHO3D_HANDLER(UINamePlaceDialog, HandleClose));
@ -73,6 +79,18 @@ void UINamePlaceDialog::HandleNameChanged(StringHash eventType, VariantMap& even
refresh = true;
}
void UINamePlaceDialog::HandleHelp(StringHash eventType, VariantMap& eventData)
{
new MessageBox(context_,
"Terrain features are automatically detected, and so have particular rules.\n"
"While most are obvious from the name, some rules need spelling out:\n"
" - islands MUST have the entirety of their edge be water - no exception\n"
" - lakes MUST have the entirety of their edge be on land - no exception\n"
" - the entire 10% outer bands inside the area around a peak must be substantially lower than the peak itself\n",
"Info"
);
}
void UINamePlaceDialog::HandleCancel(StringHash eventType, VariantMap& eventData)
{
VariantMap& newEventData = GetEventDataMap();
@ -117,6 +135,7 @@ void UINamePlaceDialog::HandleTBMessage(StringHash eventType, VariantMap& eventD
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[P_WIDGET_EVENT].GetVoidPtr();
if (ev->type == EVENT_TYPE_CLICK)
{
CONNECT("help", HandleHelp);
CONNECT("ok", HandleOK);
CONNECT("cancel", HandleCancel);
}

View File

@ -36,6 +36,7 @@ public:
private:
void HandleNameChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleHelp(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleOK(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleCancel(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleTBMessage(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
@ -55,6 +56,7 @@ private:
tb::TBEditField *nameWidget;
tb::TBTextField *runestonesNeededWidget;
tb::TBTextField *runestonesOwnedWidget;
tb::TBTextField *terrainFeatureWidget;
std::string last_refresh_stop_hash;
bool refresh;

View File

@ -9,6 +9,7 @@
#include <tb/tb_font_renderer.h>
#include "cc/cc.h"
#include "cc/cc_influence.h"
#include "cc/cc_terrain_features.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "game-wallet.h"
#include "game-state.h"
@ -30,8 +31,55 @@ UITravelToPlaceDialog::PlaceWidget::PlaceWidget(PlaceItem *item, PlaceSource *so
g_widgets_reader->LoadFile(GetContentRoot(), "cc/travel-to-place-row.tb.txt");
const tb::TBFontDescription fd = g_font_manager->GetDefaultFontDescription();
TBTextField *nameWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("name"));
nameWidget->SetText(item->place->name);
tb::TBFontDescription fd_large = fd;
fd_large.SetSize(fd.GetSize() * 4 / 3);
nameWidget->SetFontDescription(fd_large);
if (item->place->terrain_feature != cc::terrain_feature_none)
{
TBToggleContainer *featureContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("feature-container"));
featureContainer->SetValue(1);
TBTextField *featureWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("feature"));
featureWidget->SetText(cc::terrain_feature_names[item->place->terrain_feature]);
}
TBTextField *distanceWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("distance"));
uint32_t distance = cc::get_distance(item->place->x0, item->place->y0, item->place->x1, item->place->y1, item->x, item->y);
std::string s;
if (distance < 5)
{
s = "right here";
}
else
{
s = std::to_string(distance) + " feet away ";
const uint32_t midx = item->place->x0 + (item->place->x1 - item->place->x0) / 2;
const uint32_t midy = item->place->y0 + (item->place->y1 - item->place->y0) / 2;
float angle = 180.0f * atan2f((int32_t)(midy - item->y), (int32_t)(midx - item->x)) / M_PI;
if (fabsf(angle) < 11.25f)
s += "E";
else if (fabsf(angle) < 33.75f)
s += angle > 0.0f ? "WNE" : "WSE";
else if (fabsf(angle) < 56.25f)
s += angle > 0.0f ? "NE" : "SE";
else if (fabsf(angle) < 78.75f)
s += angle > 0.0f ? "NNE" : "SSE";
else if (fabsf(angle) < 101.25f)
s += "N";
else if (fabsf(angle) < 123.75f)
s += angle > 0.0f ? "NNW" : "SSW";
else if (fabsf(angle) < 146.25f)
s += angle > 0.0f ? "NW" : "SW";
else if (fabsf(angle) < 168.75f)
s += angle > 0.0f ? "WNW" : "WSW";
else
s += "W";
}
distanceWidget->SetText(s.c_str());
}
WIDGET_HIT_STATUS UITravelToPlaceDialog::PlaceWidget::GetHitStatus(int x, int y)
@ -39,9 +87,11 @@ WIDGET_HIT_STATUS UITravelToPlaceDialog::PlaceWidget::GetHitStatus(int x, int y)
return x >= 0 && y >= 0 && x < GetRect().w && y < GetRect().h ? tb::WIDGET_HIT_STATUS_HIT_NO_CHILDREN : tb::WIDGET_HIT_STATUS_NO_HIT;
}
UITravelToPlaceDialog::PlaceItem::PlaceItem(const std::shared_ptr<cc::place_t> &place):
UITravelToPlaceDialog::PlaceItem::PlaceItem(const std::shared_ptr<cc::place_t> &place, uint32_t x, uint32_t y):
TBGenericStringItem(place->name),
place(place)
place(place),
x(x),
y(y)
{
}
@ -132,7 +182,7 @@ void UITravelToPlaceDialog::UpdatePlacesList(const std::shared_ptr<GameWallet> &
{
if (game->ignore_player(e->namer))
continue;
PlaceItem *item = new PlaceItem(e);
PlaceItem *item = new PlaceItem(e, x, y);
item->tag.SetInt(e->id);
if (e->id == select_place_id)
sel = builder.GetNumItems();

View File

@ -48,10 +48,12 @@ private:
class PlaceItem: public tb::TBGenericStringItem
{
public:
PlaceItem(const std::shared_ptr<cc::place_t> &place);
PlaceItem(const std::shared_ptr<cc::place_t> &place, uint32_t x, uint32_t y);
std::shared_ptr<cc::place_t> place;
uint32_t x;
uint32_t y;
bool operator==(const PlaceItem &item) const { return place == item.place; }
bool operator==(const PlaceItem &item) const { return place == item.place && x == item.x && y == item.y; }
};
class PlaceSource: public tb::TBSelectItemSourceList<PlaceItem>

View File

@ -4388,7 +4388,7 @@ namespace cryptonote
return true;
});
db.for_all_cc_places(city, [&snapshot](const cc::place_t &p) {
snapshot.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.name, p.priority});
snapshot.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, p.name, p.priority});
return true;
});
@ -6407,7 +6407,7 @@ namespace cryptonote
if (!db.for_all_cc_places(req.city, [&req, &res](const cc::place_t &p) {
uint32_t ix0, iy0, ix1, iy1;
if (cc::intersection(p.x0, p.y0, p.x1, p.y1, req.x0, req.y0, req.x1, req.y1, ix0, iy0, ix1, iy1))
res.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.name, p.priority});
res.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, p.name, p.priority});
return true;
}))
{

View File

@ -5667,6 +5667,7 @@ namespace cryptonote
uint32_t y0;
uint32_t x1;
uint32_t y1;
uint32_t terrain_feature;
std::string name;
uint32_t priority;
@ -5679,6 +5680,7 @@ namespace cryptonote
KV_SERIALIZE(y0)
KV_SERIALIZE(x1)
KV_SERIALIZE(y1)
KV_SERIALIZE(terrain_feature)
KV_SERIALIZE(name)
KV_SERIALIZE(priority)
END_KV_SERIALIZE_MAP()

View File

@ -1390,7 +1390,7 @@ bool wallet2::get_cc_places(uint32_t city, uint32_t x0, uint32_t y0, uint32_t x1
places.reserve(res.places.size());
for (auto &p: res.places)
{
places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, std::move(p.name)});
places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, std::move(p.name)});
}
return true;