Basic CityMania extension structure and road layout counter

This commit is contained in:
dP
2020-06-10 01:34:38 +03:00
parent 5ff4fa4bc0
commit f8095884a3
18 changed files with 409 additions and 1 deletions

View File

@@ -1348,6 +1348,13 @@
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread.h" />
<ClInclude Include="..\src\citymania\cm_event.hpp" />
<ClInclude Include="..\src\citymania\cm_game.hpp" />
<ClCompile Include="..\src\citymania\cm_game.cpp" />
<ClInclude Include="..\src\citymania\cm_main.hpp" />
<ClCompile Include="..\src\citymania\cm_main.cpp" />
<ClInclude Include="..\src\citymania\cm_type.hpp" />
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -100,6 +100,9 @@
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="CityMania">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\airport.cpp">
@@ -3132,6 +3135,27 @@
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_event.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_game.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_game.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_main.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_main.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_type.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp">
<Filter>CityMania</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -1348,6 +1348,13 @@
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread.h" />
<ClInclude Include="..\src\citymania\cm_event.hpp" />
<ClInclude Include="..\src\citymania\cm_game.hpp" />
<ClCompile Include="..\src\citymania\cm_game.cpp" />
<ClInclude Include="..\src\citymania\cm_main.hpp" />
<ClCompile Include="..\src\citymania\cm_main.cpp" />
<ClInclude Include="..\src\citymania\cm_type.hpp" />
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -100,6 +100,9 @@
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="CityMania">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\airport.cpp">
@@ -3132,6 +3135,27 @@
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_event.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_game.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_game.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_main.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_main.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_type.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp">
<Filter>CityMania</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -1348,6 +1348,13 @@
<ClCompile Include="..\src\os\windows\string_uniscribe.cpp" />
<ClCompile Include="..\src\os\windows\win32.cpp" />
<ClInclude Include="..\src\thread.h" />
<ClInclude Include="..\src\citymania\cm_event.hpp" />
<ClInclude Include="..\src\citymania\cm_game.hpp" />
<ClCompile Include="..\src\citymania\cm_game.cpp" />
<ClInclude Include="..\src\citymania\cm_main.hpp" />
<ClCompile Include="..\src\citymania\cm_main.cpp" />
<ClInclude Include="..\src\citymania\cm_type.hpp" />
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -100,6 +100,9 @@
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="CityMania">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\airport.cpp">
@@ -3132,6 +3135,27 @@
<ClInclude Include="..\src\thread.h">
<Filter>Threading</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_event.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\cm_game.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_game.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_main.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClCompile Include="..\src\citymania\cm_main.cpp">
<Filter>CityMania</Filter>
</ClCompile>
<ClInclude Include="..\src\citymania\cm_type.hpp">
<Filter>CityMania</Filter>
</ClInclude>
<ClInclude Include="..\src\citymania\extensions\cmext_town.hpp">
<Filter>CityMania</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\media\openttd.ico" />

View File

@@ -1191,3 +1191,12 @@ sound/null_s.cpp
# Threading
thread.h
# CityMania
citymania/cm_event.hpp
citymania/cm_game.hpp
citymania/cm_game.cpp
citymania/cm_main.hpp
citymania/cm_main.cpp
citymania/cm_type.hpp
citymania/extensions/cmext_town.hpp

123
src/citymania/cm_event.hpp Normal file
View File

@@ -0,0 +1,123 @@
#ifndef CM_EVENT_HPP
#define CM_EVENT_HPP
#include "cm_type.hpp"
#include "../cargo_type.h"
#include "../company_type.h"
#include "../economy_type.h"
#include "../station_type.h"
#include "../town_type.h"
#include <functional>
#include <map>
#include <typeindex>
#include <typeinfo>
namespace citymania {
namespace event {
struct NewMonth {
};
struct TownGrowthTick {
Town *town;
bool growth_result;
uint16 prev_houses;
};
struct CompanyEvent {
Company *company;
};
struct CargoAccepted {
Company *company;
CargoID cargo_type;
uint amount;
const Station *station;
Money profit;
SourceType src_type;
SourceID src;
};
struct CompanyMoneyChanged {
Company *company;
Money delta;
};
struct CompanyLoanChanged {
Company *company;
Money delta;
};
struct CompanyBalanceChanged {
Company *company;
Money delta;
};
class TypeDispatcherBase {
public:
virtual ~TypeDispatcherBase() {}
};
template<typename T>
class TypeDispatcher: public TypeDispatcherBase {
public:
typedef std::function<void(const T &)> Handler;
TypeDispatcher() { }
virtual ~TypeDispatcher() {}
void listen(Handler &handler) {
this->new_handlers.push_back(handler);
}
void emit(const T &event) {
if (!this->new_handlers.empty()) {
this->handlers.insert(this->handlers.end(), this->new_handlers.begin(), this->new_handlers.end());
this->new_handlers.clear();
}
for (auto &h : this->handlers) {
h(event);
}
}
protected:
std::vector<Handler> handlers;
std::vector<Handler> new_handlers;
};
class Dispatcher {
protected:
std::map<std::type_index, up<TypeDispatcherBase>> dispacthers;
template<typename T>
TypeDispatcher<T> &get_dispatcher() {
auto p = this->dispacthers.find(typeid(T));
if (p == this->dispacthers.end()) {
auto x = make_up<TypeDispatcher<T>>();
p = this->dispacthers.emplace_hint(p, typeid(T), std::move(x));
}
return *(static_cast<TypeDispatcher<T> *>((*p).second.get()));
}
public:
template<typename T>
void listen(std::function<void(const T &)> handler) {
this->get_dispatcher<T>().listen(handler);
}
template<typename T>
void emit(const T &event) {
this->get_dispatcher<T>().emit(event);
}
};
} // namespace event
} // namespace citymania
#endif

31
src/citymania/cm_game.cpp Normal file
View File

@@ -0,0 +1,31 @@
#include "../stdafx.h"
#include "cm_game.hpp"
#include "../safeguards.h"
namespace citymania {
Game::Game() {
this->events.listen<event::NewMonth>([] (const event::NewMonth &) {
for (Town *t : Town::Iterate()) {
t->cm.hs_last_month = t->cm.hs_total - t->cm.hs_total_prev;
t->cm.hs_total_prev = t->cm.hs_total;
t->cm.cs_last_month = t->cm.cs_total - t->cm.cs_total_prev;
t->cm.cs_total_prev = t->cm.cs_total;
t->cm.hr_last_month = t->cm.hr_total - t->cm.hr_total_prev;
t->cm.hr_total_prev = t->cm.hr_total;
}
});
this->events.listen<event::TownGrowthTick>([this] (const event::TownGrowthTick &event) {
if (event.growth_result) {
if (event.town->cache.num_houses <= event.prev_houses) {
event.town->cm.hs_total++;
}
} else {
event.town->cm.cs_total++;
}
});
}
} // namespace citymania

19
src/citymania/cm_game.hpp Normal file
View File

@@ -0,0 +1,19 @@
#ifndef CMEXT_GAME_HPP
#define CMEXT_GAME_HPP
#include "../town.h"
#include "cm_event.hpp"
namespace citymania {
class Game {
public:
event::Dispatcher events;
Game();
};
} // namespace citymania
#endif

20
src/citymania/cm_main.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include "../stdafx.h"
#include "cm_main.hpp"
#include "../safeguards.h"
namespace citymania {
up<Game> _game = nullptr;
void ResetGame() {
_game = make_up<Game>();
}
void SwitchToMode(SwitchMode new_mode) {
ResetGame();
}
} // namespace citymania

20
src/citymania/cm_main.hpp Normal file
View File

@@ -0,0 +1,20 @@
#ifndef CMEXT_MAIN_HPP
#define CMEXT_MAIN_HPP
#include "cm_type.hpp"
#include "cm_game.hpp"
namespace citymania {
extern up<Game> _game;
void SwitchToMode(SwitchMode new_mode);
template <typename T>
void Emit(const T &event) {
_game->events.emit<T>(event);
}
} // namespace citymania
#endif

53
src/citymania/cm_type.hpp Normal file
View File

@@ -0,0 +1,53 @@
#ifndef CMEXT_TYPE_HPP
#define CMEXT_TYPE_HPP
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
/* C++14 implementation of make_unique */
namespace std {
template<class T> struct _Unique_if {
typedef unique_ptr<T> _Single_object;
};
template<class T> struct _Unique_if<T[]> {
typedef unique_ptr<T[]> _Unknown_bound;
};
template<class T, size_t N> struct _Unique_if<T[N]> {
typedef void _Known_bound;
};
template<class T, class... Args>
typename _Unique_if<T>::_Single_object
make_unique(Args&&... args) {
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template<class T>
typename _Unique_if<T>::_Unknown_bound
make_unique(size_t n) {
typedef typename remove_extent<T>::type U;
return unique_ptr<T>(new U[n]());
}
template<class T, class... Args>
typename _Unique_if<T>::_Known_bound
make_unique(Args&&...) = delete;
} // namespace std
namespace citymania {
// Make smart pointers easier to type
template<class T> using up=std::unique_ptr<T>;
template<class T> using sp=std::shared_ptr<T>;
template<class T> using wp=std::weak_ptr<T>;
template<typename T> const auto make_up = std::make_unique<T>;
template<typename T> const auto make_sp = std::make_shared<T>;
} // namespace citymania
#endif

View File

@@ -0,0 +1,25 @@
#ifndef CMEXT_TOWN_HPP
#define CMEXT_TOWN_HPP
namespace citymania {
namespace ext {
class Town {
public:
uint32 hs_total = 0; ///< number of skipped house buildings (HS) in total
uint32 hs_total_prev = 0; ///< number of skipped house buildings (HS) in total at the end of last month
uint32 hs_last_month = 0; ///< number of skipped house buildings (HS) during last month
uint32 cs_total = 0; ///< number of skipped growth cycles (CS) in total
uint32 cs_total_prev = 0; ///< number of skipped growth cycles (CS) in total at the end of last month
uint32 cs_last_month = 0; ///< number of skipped growth cycles (CS) during last month
uint32 hr_total = 0; ///< number of houses removed by the server (HR) in total
uint32 hr_total_prev = 0; ///< number of houses removed by the server (HR) in total at the end of last month
uint32 hr_last_month = 0; ///< number of houses removed by the server (HR) during last month
};
} // namespace citymania
} // namespace citymania
#endif

View File

@@ -20,6 +20,8 @@
#include "saveload/saveload.h"
#include "newgrf_profiling.h"
#include "citymania/cm_main.hpp"
#include "safeguards.h"
Year _cur_year; ///< Current year, starting at 0
@@ -238,6 +240,7 @@ static void OnNewMonth()
IndustryMonthlyLoop();
SubsidyMonthlyLoop();
StationMonthlyLoop();
citymania::Emit(citymania::event::NewMonth());
if (_network_server) NetworkServerMonthlyLoop();
}

View File

@@ -68,6 +68,8 @@
#include "linkgraph/linkgraphschedule.h"
#include "citymania/cm_main.hpp"
#include <stdarg.h>
#include <system_error>
@@ -1042,6 +1044,7 @@ bool SafeLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft,
void SwitchToMode(SwitchMode new_mode)
{
citymania::SwitchToMode(new_mode);
/* If we are saving something, the network stays in his current state */
if (new_mode != SM_SAVE_GAME) {
/* If the network is active, make it not-active */

View File

@@ -18,6 +18,8 @@
#include "tilematrix_type.hpp"
#include <list>
#include "citymania/extensions/cmext_town.hpp"
template <typename T>
struct BuildingCounts {
T id_count[NUM_HOUSES];
@@ -104,6 +106,8 @@ struct Town : TownPool::PoolItem<&_town_pool> {
std::list<PersistentStorage *> psa_list;
citymania::ext::Town cm;
/**
* Creates a new town.
* @param tile center tile of the town

View File

@@ -52,6 +52,8 @@
#include "table/strings.h"
#include "table/town_land.h"
#include "citymania/cm_main.hpp"
#include "safeguards.h"
TownID _new_town_id;
@@ -871,7 +873,10 @@ static void TownTickHandler(Town *t)
if (HasBit(t->flags, TOWN_IS_GROWING)) {
int i = (int)t->grow_counter - 1;
if (i < 0) {
if (GrowTown(t)) {
uint16 prev_houses = t->cache.num_houses;
bool growth_res = GrowTown(t);
citymania::Emit((citymania::event::TownGrowthTick){t, growth_res, prev_houses});
if (growth_res) {
i = t->growth_rate;
} else {
/* If growth failed wait a bit before retrying */