32 # include <sys/cdefs.h>
34 #include <tbb/blocked_range.h>
35 #include <tbb/concurrent_vector.h>
36 #include <tbb/parallel_for.h>
37 #include <tbb/combinable.h>
39 #include "eng3d/binary_image.hpp"
40 #include "eng3d/log.hpp"
41 #include "eng3d/serializer.hpp"
42 #include "eng3d/state.hpp"
43 #include "eng3d/utils.hpp"
44 #include "eng3d/string.hpp"
67 static const T& find_or_throw(
const std::string_view ref_name) {
69 const auto result = std::find_if(list.begin(), list.end(), [ref_name](
const auto& o) {
70 return !strcmp(o.ref_name.c_str(), ref_name.data());
73 if(result == list.end())
114 lua_register(
lua.
state,
"set_nation_ideology", [](lua_State*
L) {
115 auto& nation = g_world.nations.at(lua_tonumber(L, 1));
116 const auto& ideology = g_world.ideologies.at(lua_tonumber(L, 2));
117 nation.ideology_id = ideology.get_id();
118 nation.subideology_id = SubideologyId(0);
119 const std::string subideology_ref_name = luaL_checkstring(L, 3);
120 for(const auto& subideology : ideology.subideologies) {
121 if(subideology.ref_name.get_string() == subideology_ref_name) {
122 nation.subideology_id = subideology.get_id();
123 nation.current_policy.economic = subideology.economic;
124 nation.current_policy.political = subideology.political;
133 lua_register(lua.state,
"nation_make_puppet", [](lua_State*
L) {
134 const auto& nation = g_world.nations.at(lua_tonumber(L, 1));
135 auto& other_nation = g_world.nations.at(lua_tonumber(L, 2));
136 other_nation.make_puppet(nation);
137 auto& relation = g_world.get_relation(nation, other_nation);
138 relation.alliance = 0.45f;
139 relation.relation = 0.f;
142 lua_register(lua.state,
"nation_make_customs_union", [](lua_State*
L) {
143 auto& nation = g_world.nations.at(lua_tonumber(L, 1));
144 auto& other_nation = g_world.nations.at(lua_tonumber(L, 2));
145 auto& relation = g_world.get_relation(nation, other_nation);
146 relation.alliance = 1.f;
147 relation.relation = 0.f;
150 lua_register(lua.state,
"set_nation_flag", [](lua_State*
L) {
151 auto& nation = g_world.nations.at(lua_tonumber(L, 1));
152 nation.flags[luaL_checkstring(L, 2)] = lua_tonumber(L, 3);
155 lua_register(lua.state,
"get_nation_flag", [](lua_State*
L) {
156 auto& nation = g_world.nations.at(lua_tonumber(L, 1));
157 lua_pushnumber(L, nation.flags[luaL_checkstring(L, 2)]);
176 lua_register(lua.state,
"get_province_pops_size", [](lua_State*
L) {
177 const auto& province = g_world.provinces.at(lua_tonumber(L, 1));
178 lua_pushnumber(L, province.pops.size());
181 lua_register(lua.state,
"get_province_pop", [](lua_State*
L) {
182 const auto& province = g_world.provinces.at(lua_tonumber(L, 1));
183 const auto& pop = province.pops.at(lua_tonumber(L, 2));
184 lua_pushnumber(L, pop.size);
185 lua_pushnumber(L, pop.budget);
186 lua_pushnumber(L, pop.literacy);
187 lua_pushnumber(L, pop.life_needs_met);
188 lua_pushnumber(L, 1.f);
189 lua_pushnumber(L, 1.f);
190 lua_pushnumber(L, (size_t)pop.type_id);
191 lua_pushnumber(L, IdeologyId(0));
192 lua_pushnumber(L, pop.militancy);
195 lua_register(lua.state,
"set_province_pop", [](lua_State*
L) {
196 auto& province = g_world.provinces.at(lua_tonumber(L, 1));
197 auto& pop = province.pops.at(lua_tonumber(L, 2));
198 pop.size = lua_tonumber(L, 3);
199 pop.budget = lua_tonumber(L, 4);
200 pop.literacy = lua_tonumber(L, 5);
201 pop.life_needs_met = lua_tonumber(L, 6);
204 pop.type_id = PopTypeId(lua_tonumber(L, 9));
205 pop.militancy = lua_tonumber(L, 10);
209 lua_register(lua.state,
"get_province_buildings_size", [](lua_State*
L) {
210 const auto& province = g_world.provinces.at(lua_tonumber(L, 1));
211 lua_pushnumber(L, province.buildings.size());
214 lua_register(lua.state,
"get_province_building", [](lua_State*
L) {
215 const auto& province = g_world.provinces.at(lua_tonumber(L, 1));
216 const auto& building = province.buildings.at(lua_tonumber(L, 2));
217 lua_pushnumber(L, building.level);
218 lua_pushnumber(L, building.production_scale);
219 lua_pushnumber(L, building.workers);
222 lua_register(lua.state,
"set_province_building", [](lua_State*
L) {
223 auto& province = g_world.provinces.at(lua_tonumber(L, 1));
224 auto& building = province.buildings.at(lua_tonumber(L, 2));
225 building.level = lua_tonumber(L, 3);
226 building.production_scale = lua_tonumber(L, 4);
227 building.workers = lua_tonumber(L, 5);
258 lua_register(lua.state,
"add_ideology", [](lua_State*
L) {
259 if(g_world.needs_to_sync)
260 luaL_error(L,
"MP-Sync in this function is not supported");
263 ideology.ref_name = luaL_checkstring(
L, 1);
264 ideology.name = luaL_checkstring(
L, 2);
265 ideology.color = (std::byteswap<std::uint32_t>(
static_cast<int>(lua_tonumber(
L, 3))) >> 8) | 0xff000000;
267 lua_pushnumber(
L,
g_world.ideologies.size() - 1);
270 lua_register(lua.state,
"add_ideology_subideology", [](lua_State*
L) {
271 if(g_world.needs_to_sync)
272 luaL_error(L,
"MP-Sync in this function is not supported");
274 auto& ideology = g_world.ideologies.at(lua_tonumber(L, 1));
275 Ideology::Subideology subideology{};
276 subideology.ref_name = luaL_checkstring(
L, 2);
277 subideology.name = luaL_checkstring(
L, 3);
278 subideology.economic.distributism = lua_tonumber(
L, 4);
279 subideology.economic.mercantilist = lua_tonumber(
L, 5);
280 subideology.economic.capitalism = lua_tonumber(
L, 6);
281 subideology.political.individualism = lua_tonumber(
L, 7);
282 subideology.political.state_power = lua_tonumber(
L, 8);
283 subideology.political.equalitarianism = lua_tonumber(
L, 9);
284 subideology.political.secular = lua_tonumber(
L, 10);
285 subideology.political.pluralism = lua_tonumber(
L, 11);
287 subideology.cached_id =
SubideologyId(ideology.subideologies.size());
288 ideology.subideologies.push_back(subideology);
291 lua_register(lua.state,
"get_ideology", [](lua_State*
L) {
292 const auto& ideology = find_or_throw<Ideology>(luaL_checkstring(L, 1));
293 lua_pushnumber(L, (size_t)g_world.get_id(ideology));
294 lua_pushstring(L, ideology.name.c_str());
295 lua_pushnumber(L, std::byteswap<std::uint32_t>((ideology.color & 0x00ffffff) << 8));
298 lua_register(lua.state,
"get_ideology_by_id", [](lua_State*
L) {
299 const auto& ideology = g_world.ideologies.at(lua_tonumber(L, 1));
300 lua_pushstring(L, ideology.ref_name.c_str());
301 lua_pushstring(L, ideology.name.c_str());
302 lua_pushnumber(L, std::byteswap<std::uint32_t>((ideology.color & 0x00ffffff) << 8));
306 lua_register(lua.state,
"get_day", [](lua_State*
L) {
307 lua_pushnumber(L, g_world.get_day());
310 lua_register(lua.state,
"get_month", [](lua_State*
L) {
311 lua_pushnumber(L, g_world.get_month());
314 lua_register(lua.state,
"get_year", [](lua_State*
L) {
315 lua_pushnumber(L, g_world.get_year());
318 lua_register(lua.state,
"set_date", [](lua_State*
L) {
319 const int year = lua_tonumber(L, 1) * 12 * 30;
320 const int month = lua_tonumber(L, 2) * 30;
321 const int day = lua_tonumber(L, 3);
322 g_world.time = year + month + day;
334 lua_pushboolean(lua.state,
true);
335 lua_setglobal(lua.state,
"EVENT_CONDITIONS_MET");
336 lua_pushboolean(lua.state,
false);
337 lua_setglobal(lua.state,
"EVENT_CONDITIONS_UNMET");
339 lua_pushboolean(lua.state,
true);
340 lua_setglobal(lua.state,
"EVENT_DO_MANY_TIMES");
341 lua_pushboolean(lua.state,
false);
342 lua_setglobal(lua.state,
"EVENT_DO_ONE_TIME");
346 lua_setglobal(lua.state,
"TECH_STRATEGIC");
348 lua_setglobal(lua.state,
"TECH_MILITARY");
350 lua_setglobal(lua.state,
"TECH_NAVY");
352 lua_setglobal(lua.state,
"TECH_SOCIAL");
354 lua_setglobal(lua.state,
"TECH_ECONOMIC");
356 lua_setglobal(lua.state,
"TECH_POLITICS");
359 #define POLICY_CAPITALIST 1
361 lua_setglobal(lua.state,
"POLICY_CAPITALIST");
362 lua_register(lua.state,
"relative_nation_policy_stance", [](lua_State*
L) {
363 auto& nation = g_world.nations.at(lua_tonumber(L, 1));
364 float val = lua_tonumber(L, 3);
366 auto& policy = nation.current_policy;
367 switch((int)lua_tonumber(L, 2)) {
368 case POLICY_CAPITALIST:
369 ret_val = policy.economic.capitalism = glm::clamp(policy.economic.capitalism + val, -1.f, 1.f);
374 lua_pushnumber(
L, ret_val);
382 lua_getglobal(lua.state,
"package");
383 lua_getfield(lua.state, -1,
"path");
384 std::string curr_path = lua_tostring(lua.state, -1);
388 for(
const auto& path : paths) {
390 curr_path.append(
";" + path +
"/lua/?.lua");
392 lua_pop(lua.state, 1);
393 lua_pushstring(lua.state, curr_path.c_str());
394 lua_setfield(lua.state, -2,
"path");
395 lua_pop(lua.state, 1);
398 static void lua_exec_all_of(
World& world,
const std::vector<std::string> files,
const std::string& dir =
"lua") {
399 std::string files_buf =
"require(\"classes/base\")\n\n";
400 for(
const auto& file : files) {
402 for(
const auto& path : paths) {
403 #ifdef E3D_TARGET_WINDOWS
405 for(
auto& c : path->get_abs_path())
406 if(c ==
'\\') m_path +=
"\\\\";
409 std::string m_path = path->get_abs_path();
411 files_buf +=
"print(\"" + m_path +
"\")\nassert(loadfile(\"" + m_path +
"\"))()\n";
415 if(luaL_loadstring(world.
lua.
state, files_buf.c_str()) != LUA_OK || lua_pcall(world.
lua.
state, 0, 0, 0) != LUA_OK)
424 }
catch(
const std::exception& e) {
428 lua_exec_all_of(*
this, std::vector<std::string> {
429 "terrain_types",
"good_types",
"ideologies",
"languages",
430 "building_types",
"technology",
"religions",
"pop_types",
431 "industry_types",
"unit_types",
"boat_types",
432 "nations",
"provinces",
"init"
435 auto div = std::make_unique<Eng3D::BinaryImage>(
Eng3D::State::get_instance().package_man.get_unique(
"map/provinces.png")->get_abs_path());
437 height = div->height;
438 tiles = std::make_unique<ProvinceId[]>(width * height);
445 std::vector<ProvinceId> province_color_table(0xffffff + 1,
ProvinceId(0));
446 for(
const auto& province : provinces)
447 province_color_table[province.color & 0xffffff] = this->get_id(province);
449 const auto* raw_buffer = div->buffer.get();
450 tbb::parallel_for(
static_cast<size_t>(0), height, [
this, &province_color_table, raw_buffer](
const auto j) {
451 const auto off = j * width;
452 for(
size_t i = 0; i < width; i++)
453 tiles[off + i] = province_color_table[raw_buffer[off + i] & 0xffffff];
457 std::set<uint32_t> colors_found;
458 std::set<uint32_t> colors_used;
459 for(
size_t i = 0; i < width * height; i++) {
460 const auto province_id = province_color_table[raw_buffer[i] & 0xffffff];
462 colors_found.insert(raw_buffer[i]);
463 colors_used.insert(raw_buffer[i] & 0xffffff);
465 if(!colors_found.empty()) {
466 std::unique_ptr<FILE, int(*)(FILE*)> province_fp(fopen(
"uprovinces.lua",
"w+t"), fclose);
467 if(province_fp !=
nullptr) {
468 for(
const auto& color_raw : colors_found) {
469 uint32_t color = color_raw << 8;
470 fprintf(province_fp.get(),
"province=Province:new{ref_name=\"province_%06x\",name=translate(\"Unknown\"),color=0x%06x,terrain=tt_sea,rgo_size={}}\n",
static_cast<unsigned int>(std::byteswap<std::uint32_t>(color)),
static_cast<unsigned int>(std::byteswap<std::uint32_t>(color)));
471 fprintf(province_fp.get(),
"province:register()\n");
475 std::unique_ptr<FILE, int(*)(FILE*)> color_fp(fopen(
"ucolors.txt",
"w+t"), fclose);
476 if(color_fp !=
nullptr) {
477 for(
size_t i = 0; i < province_color_table.size(); i++) {
478 if((i % 128 == 0) && (province_color_table[i] ==
ProvinceId(0))) {
479 const uint32_t color = i << 8;
480 fprintf(color_fp.get(),
"%06lx\n",
static_cast<unsigned long int>(std::byteswap<std::uint32_t>(color)));
490 Eng3D::Log::error(
"world",
"There are unregistered provinces, please register them!");
493 std::string provinces_ref_names =
"";
494 for(
auto& province : provinces)
495 if(!colors_used.contains(province.color & 0xffffff))
496 provinces_ref_names +=
"'" + std::string{province.ref_name.get_string()} +
"'";
498 if(!provinces_ref_names.empty()) {
499 std::string
error =
"Province " + provinces_ref_names +
" is registered but missing on province.png, please add it!";
510 for(
auto& province : provinces) {
511 province.box_area.right = province.box_area.bottom = 0.f;
512 province.box_area.left = width;
513 province.box_area.top = height;
516 for(
size_t i = 0; i < width; i++) {
517 for(
size_t j = 0; j < height; j++) {
518 auto& province = provinces[this->tiles[i + j * width]];
519 province.box_area.left = glm::min(province.box_area.left,
static_cast<float>(i));
520 province.box_area.right = glm::max(province.box_area.right,
static_cast<float>(i));
521 province.box_area.bottom = glm::max(province.box_area.bottom,
static_cast<float>(j));
522 province.box_area.top = glm::min(province.box_area.top,
static_cast<float>(j));
528 for(
auto& province : provinces) {
529 province.box_area.right = glm::min(width,
static_cast<size_t>(province.box_area.right));
530 province.box_area.bottom = glm::min(height,
static_cast<size_t>(province.box_area.bottom));
535 for(
size_t i = 0; i < width * height; i++) {
536 auto& province = this->provinces[this->tiles[i]];
537 if(i > this->width) {
538 auto other_tile = this->tiles[i - this->width];
539 province.neighbour_ids.push_back(other_tile);
541 if(i < (this->width * this->height) - this->width) {
542 auto other_tile = this->tiles[i + this->width];
543 province.neighbour_ids.push_back(other_tile);
546 auto other_tile = this->tiles[i - 1];
547 province.neighbour_ids.push_back(other_tile);
549 if(i < (this->width * this->height) - 1) {
550 auto other_tile = this->tiles[i + 1];
551 province.neighbour_ids.push_back(other_tile);
556 for(
auto& province : this->provinces) {
557 auto last = std::unique(province.neighbour_ids.begin(), province.neighbour_ids.end());
558 province.neighbour_ids.erase(last, province.neighbour_ids.end());
559 std::erase(province.neighbour_ids, province);
563 for(
auto& province : this->provinces) {
564 std::sort(province.neighbour_ids.begin(), province.neighbour_ids.end());
565 auto last = std::unique(province.neighbour_ids.begin(), province.neighbour_ids.end());
566 province.neighbour_ids.erase(last, province.neighbour_ids.end());
568 unit_manager.init(*
this);
574 this->relations.resize(this->nations.size() * this->nations.size());
577 for(
auto& nation : this->nations) {
578 if(!nation.exists())
continue;
580 nation.auto_relocate_capital();
587 ar.to_file(
"world.cch");
591 const std::vector<std::string> mod_files = {
594 lua_exec_all_of(*
this, mod_files,
"lua/init");
602 static inline void unit_do_tick(
World& world,
Unit& unit) {
609 auto& province = world.provinces[unit.
province_id()];
617 bool can_move =
true, can_take =
false;
618 if(unit_target.controller_id != unit.
owner_id) {
621 can_take = relation.has_war;
626 if(unit_moved && can_take) {
628 if(unit.
owner_id != unit_target.owner_id) {
631 if(relation.is_allied())
632 world.nations[unit_target.owner_id].control_province(unit_target);
634 world.nations[unit.
owner_id].control_province(unit_target);
636 world.nations[unit.
owner_id].control_province(unit_target);
643 static inline void unit_do_battle_tick(
World& world,
Unit& unit) {
647 auto& province = world.provinces[unit.
province_id()];
648 if(province.battle.active) {
651 bool will_attack =
false;
652 for(
const auto attacker_id : province.battle.attacker_nations_ids) {
658 if(relation.is_allied()) {
665 auto& nation_ids = province.battle.attacker_nations_ids;
666 if(std::find(nation_ids.begin(), nation_ids.end(), unit.
owner_id) == nation_ids.end())
667 nation_ids.push_back(unit.
owner_id);
669 auto& nation_ids = province.battle.defender_nations_ids;
670 if(std::find(nation_ids.begin(), nation_ids.end(), unit.
owner_id) == nation_ids.end())
671 nation_ids.push_back(unit.
owner_id);
673 province.battle.unit_ids.push_back(unit.
get_id());
679 std::vector<UnitId> enemy_unit_ids;
680 for(
const auto other_unit_id : unit_ids) {
684 if(unit.
owner_id == other_unit.owner_id)
688 if(!relation.has_war)
690 enemy_unit_ids.push_back(other_unit_id);
694 if(!enemy_unit_ids.empty()) {
696 province.battle.active =
true;
701 province.battle.unit_ids.push_back(unit);
702 province.battle.attacker_nations_ids.push_back(unit.
owner_id);
704 std::vector<NationId> v;
705 for(
const auto enemy_unit_id : enemy_unit_ids) {
707 enemy_unit.on_battle =
true;
708 enemy_unit.stop_movement();
709 province.battle.unit_ids.push_back(enemy_unit);
710 v.push_back(enemy_unit.owner_id);
712 std::sort(v.begin(), v.end());
713 v.erase(std::unique(v.begin(), v.end()), v.end());
714 province.battle.defender_nations_ids = v;
721 std::vector<UnitId> unit_ids;
722 for(
auto& province : world.provinces)
723 if(province.battle.active)
724 for(
const auto unit_id : province.battle.unit_ids)
725 unit_ids.push_back(unit_id);
726 std::sort(unit_ids.begin(), unit_ids.end());
727 assert(std::adjacent_find(unit_ids.begin(), unit_ids.end()) == unit_ids.end());
730 void World::fire_special_event(
const std::string_view event_ref_name,
const std::string_view nation_ref_name,
const std::string_view other_nation_ref_name) {
731 auto event_it = std::find_if(this->events.begin(), this->events.end(), [&](
const auto& e) {
732 return e.ref_name.get_string() == event_ref_name;
734 if(event_it == this->events.end())
737 auto nation_it = std::find_if(this->nations.begin(), this->nations.end(), [&](
const auto& e) {
738 return e.ref_name.get_string() == nation_ref_name;
740 if(nation_it == this->nations.end())
741 CXX_THROW(std::runtime_error,
translate_format(
"Can't find the first nation %s for firing special event %s", nation_ref_name.data(), event_ref_name.data()));
743 auto other_nation_it = std::find_if(this->nations.begin(), this->nations.end(), [&](
const auto& e) {
744 return e.ref_name.get_string() == other_nation_ref_name;
746 if(other_nation_it == this->nations.end())
747 CXX_THROW(std::runtime_error,
translate_format(
"Can't find the second nation %s for firing special event %s", nation_ref_name.data(), event_ref_name.data()));
749 bool discard =
false;
773 for(
auto& nation : nations)
774 nation.research[nation.focus_tech_id] += nation.get_research_points();
779 for(
const auto& treaty : treaties) {
780 if(!treaty.in_effect())
continue;
784 for(
auto& clause : treaty.clauses) {
785 assert(clause !=
nullptr);
788 if(!dyn_clause->in_effect())
continue;
792 if(!dyn_clause->in_effect())
continue;
796 if(!dyn_clause->in_effect())
continue;
800 if(!dyn_clause->in_effect())
continue;
804 if(!dyn_clause->in_effect())
continue;
808 if(!dyn_clause->in_effect())
continue;
813 auto& relation = this->
get_relation(treaty.sender_id, treaty.receiver_id);
814 if(relation.has_war) {
818 relation.has_war =
false;
826 unit_do_tick(*
this, unit);
829 unit_do_battle_tick(*
this, unit);
835 std::vector<UnitId> clear_units;
836 for(
auto& province : provinces) {
837 if(province.battle.active) {
839 const auto attacker_unit_ids = province.battle.get_attacker_unit_ids();
840 const auto defender_unit_ids = province.battle.get_defender_unit_ids();
843 std::vector<UnitId> v;
844 std::set_intersection(attacker_unit_ids.begin(), attacker_unit_ids.end(), defender_unit_ids.begin(), defender_unit_ids.end(), std::back_inserter(v));
848 if(defender_unit_ids.empty() || attacker_unit_ids.empty()) {
849 if(!attacker_unit_ids.empty() && defender_unit_ids.empty()) {
851 this->nations[units[attacker_unit_ids[0]].owner_id].control_province(province);
852 }
else if(attacker_unit_ids.empty() && !defender_unit_ids.empty()) {
854 this->nations[units[defender_unit_ids[0]].owner_id].control_province(province);
857 for(
const auto unit_id : attacker_unit_ids) {
858 auto& unit = units[unit_id];
859 this->nations[unit.
owner_id].prestige += unit.
base / 10000.f;
863 for(
const auto unit_id : defender_unit_ids) {
864 auto& unit = units[unit_id];
865 this->nations[unit.
owner_id].prestige += unit.
base / 10000.f;
868 province.battle.active =
false;
872 for(
auto attacker_id : attacker_unit_ids) {
873 auto& attacker = units[attacker_id];
874 for(
auto defender_id : defender_unit_ids) {
875 auto& defender = units[defender_id];
876 province.battle.defender_casualties += attacker.attack(defender);
877 if(defender.size > 1.f)
878 province.battle.attacker_casualties += defender.attack(attacker);
883 for(
size_t i = 0; i < province.battle.unit_ids.size(); ) {
884 const auto unit_id = province.battle.unit_ids[i];
885 auto& unit = units[unit_id];
886 assert(unit_id == unit.
get_id());
887 if(unit.
size < 1.f) {
889 assert(std::find(clear_units.begin(), clear_units.end(), unit_id) == clear_units.end());
890 clear_units.push_back(unit_id);
891 province.battle.unit_ids.erase(province.battle.unit_ids.begin() + i);
901 for(
const auto unit_id : clear_units) {
903 this->nations[unit.
owner_id].prestige -= unit.
base / 1000.f;
909 for(
auto& province : provinces) {
911 auto& owner_nation = nations[province.owner_id];
912 const auto militancy = province.average_militancy();
913 if (0 && militancy > 0.5f) {
914 bool has_found_revolt_nation =
false;
915 for(
const auto nuclei_id : province.nuclei) {
916 auto& revolt_nation = nations[nuclei_id];
917 if(revolt_nation == owner_nation)
continue;
918 if(revolt_nation.owned_provinces.empty()) {
919 revolt_nation.declare_war(owner_nation);
920 revolt_nation.control_province(province);
922 for(
const auto unit_id : unit_ids) {
924 if(unit.
owner_id == province.controller_id)
927 has_found_revolt_nation =
true;
932 if (!has_found_revolt_nation) {
933 for(
auto& revolt_nation : nations) {
934 if(revolt_nation == owner_nation)
continue;
935 if(revolt_nation.owned_provinces.empty()) {
936 revolt_nation.declare_war(owner_nation);
937 revolt_nation.control_province(province);
939 for(
const auto unit_id : unit_ids) {
941 if(unit.
owner_id == province.controller_id)
944 has_found_revolt_nation =
true;
977 packet.data(ar.get_buffer(), ar.size());
std::vector< std::shared_ptr< Eng3D::IO::Asset::Base > > get_multiple(const Eng3D::IO::Path &path)
Obtains multiple assets iff they share a common path (useful for concating files that might clash,...
std::vector< std::string > get_paths(void) const
Obtain all the paths that are currently under the management of a package, that is return the absolut...
void broadcast(const Eng3D::Networking::Packet &packet)
This will broadcast the given packet to all clients currently on the server.
static State & get_instance()
Eng3D::IO::PackageManager package_man
static StringManager & get_instance()
Roughly a batallion, consisting of approximately 500 soldiers each.
void set_owner(const Nation &nation)
ProvinceId get_target_province_id() const
ProvinceId province_id() const
bool has_target_province() const
bool update_movement(UnitManager &unit_manager)
Eng3D::Freelist< Unit > units
void remove_unit(UnitId unit)
std::vector< UnitId > get_province_units(ProvinceId province_id) const
bool needs_to_sync
Used to signal the lua scripts of invalid operations (eg. adding a country midgame)
Nation::Relation & get_relation(NationId a, NationId b)
Economy::EconomyState economy_state
void fire_special_event(const std::string_view event_ref_name, const std::string_view nation_ref_name, const std::string_view other_nation_ref_name)
ProvinceManager province_manager
static World & get_instance()
constexpr static unsigned int ticks_per_month
void do_emigration(World &world)
void do_tick(World &world)
void do_tick(World &world, EconomyState &economy_state)
void deserialize(Eng3D::Deser::Archive &ar, T &obj)
void serialize(Eng3D::Deser::Archive &ar, const T &obj)
std::string translate(const std::string_view str)
void error(const std::string_view category, const std::string_view msg)
void debug(const std::string_view category, const std::string_view msg)
std::string string_format(const std::string_view format, Args &&... args)
String formatter.
std::string translate_format(const std::string_view format, Args &&... args)
String formatter, with translation.
int province_add_unit(lua_State *L)
int add_event(lua_State *L)
int add_decision(lua_State *L)
int get_religion_by_id(lua_State *L)
int get_terrain_type(lua_State *L)
int set_nation_relation(lua_State *L)
int ui_call_builtin(lua_State *L)
int get_pop_type_by_id(lua_State *L)
int add_province_pop(lua_State *L)
int get_province_nuclei(lua_State *L)
int add_province_owner(lua_State *L)
int get_religion(lua_State *L)
int get_terrain_type_by_id(lua_State *L)
int update_province(lua_State *L)
int add_req_technology_to_industry_type(lua_State *L)
int get_good(lua_State *L)
int add_event_receivers(lua_State *L)
int add_good(lua_State *L)
int get_province_by_id(lua_State *L)
int get_technology(lua_State *L)
int add_technology(lua_State *L)
int add_req_good_unit_type(lua_State *L)
int add_accepted_religion(lua_State *L)
int set_nation_primary_language(lua_State *L)
int add_pop_type(lua_State *L)
int get_province_owner(lua_State *L)
int get_province_neighbours(lua_State *L)
int set_province_religion(lua_State *L)
int add_input_to_industry_type(lua_State *L)
int add_terrain_type(lua_State *L)
int get_nation_relation(lua_State *L)
int nation_declare_war_no_cb(lua_State *L)
int add_nation_client_hint(lua_State *L)
int add_req_tech_to_tech(lua_State *L)
int add_output_to_industry_type(lua_State *L)
int add_province_nucleus(lua_State *L)
int add_unit_type(lua_State *L)
int get_all_nations(lua_State *L)
int switch_nation_soul(lua_State *L)
int get_nation(lua_State *L)
int add_accepted_language(lua_State *L)
int update_province_building(lua_State *L)
int get_provinces_with_nucleus_by_nation(lua_State *L)
int get_event(lua_State *L)
int get_province_controller(lua_State *L)
int get_provinces_owned_by_nation(lua_State *L)
int set_province_language(lua_State *L)
int nation_declare_unjustified_war(lua_State *L)
int add_building_type(lua_State *L)
void fire_event(lua_State *L, Nation &nation, Event &event, bool &is_multi, const std::string_view extra)
int get_pop_type(lua_State *L)
int get_province(lua_State *L)
int get_language(lua_State *L)
int add_language(lua_State *L)
int give_hard_province_to(lua_State *L)
int get_building_type(lua_State *L)
int get_language_by_id(lua_State *L)
int add_nation(lua_State *L)
int add_province(lua_State *L)
int add_req_good_to_industry_type(lua_State *L)
int get_unit_type(lua_State *L)
int rename_province(lua_State *L)
int give_province_to(lua_State *L)
int update_event(lua_State *L)
int get_nation_by_id(lua_State *L)
int set_nation_capital(lua_State *L)
void check_events(lua_State *L)
int add_religion(lua_State *L)
void parallel_for(T range, F &&func)
static Eng3D::Networking::Packet form_packet(const std::vector< Nation > &list)
static Eng3D::Networking::Packet form_packet(const std::vector< Province > &list)
static Eng3D::Networking::Packet form_packet(const Eng3D::Freelist< Unit > &units)
Base class that serves as archiver, stores (in memory) the data required for serialization/deserializ...
void from_file(const ::std::string &path)
void for_each(const F &lambda) const
void stop(const std::string &name)
void start(const std::string &name)
constexpr bool is_invalid() const
Checks if the current id is invalid.
constexpr Id get_id() const
bool has_landpass() const
#define CXX_THROW(class,...)
#define POLICY_CAPITALIST