Maintain item list

This commit is contained in:
2025-12-08 03:37:14 +03:00
parent 33fc237793
commit 81a78990ce
4 changed files with 263 additions and 8 deletions

View File

@@ -2,11 +2,17 @@ project(gamedata)
set(CMAKE_CXX_STANDARD 17)
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG)
find_package(Bullet REQUIRED)
find_package(nlohmann_json REQUIRED)
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp
GUIModule.cpp LuaData.cpp WorldMapModule.cpp BoatModule.cpp EventTriggerModule.cpp
CharacterAnimationModule.cpp PhysicsModule.cpp EventModule.cpp CharacterManagerModule.cpp
VehicleManagerModule.cpp AppModule.cpp SmartObject.cpp SlotsModule.cpp goap.cpp)
target_link_libraries(GameData PUBLIC lua flecs::flecs_static OgreMain OgreBites
target_link_libraries(GameData PUBLIC
lua
flecs::flecs_static
nlohmann_json::nlohmann_json
OgreMain
OgreBites
OgrePaging OgreTerrain OgreOverlay
PRIVATE sceneloader world-build physics editor)
target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${BULLET_INCLUDE_DIR} ../luaaa)

View File

@@ -700,6 +700,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
bool locationSelected = false;
float strength = 0.0f;
int size = 0;
long slot_x, slot_y;
void updateWorldTexture()
{
// Get the hardware pixel buffer
@@ -748,16 +749,33 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
ECS::get<Terrain>().mTerrainGroup->update(true);
}
void setCameraPos()
void setCursorPos(Ogre::Vector3 &cursorPosition,
Ogre::Quaternion &orientation)
{
Ogre::Vector3 worldPos =
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
worldPos.x = TerrainModule::get_world_x(selected_x);
worldPos.z = TerrainModule::get_world_y(selected_y);
worldPos.y = TerrainModule::get_height(
ECS::get<Terrain>().mTerrainGroup, worldPos);
ECS::get<EditorGizmo>().sceneNode->_setDerivedPosition(
worldPos);
cursorPosition = worldPos;
orientation = ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
}
void setCameraPos()
{
Ogre::Vector3 cursorPos;
Ogre::Quaternion cursorOrientation;
setCursorPos(cursorPos, cursorOrientation);
Ogre::Vector3 cameraPos =
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
cameraPos.x = worldPos.x;
cameraPos.z = worldPos.z;
Ogre::Vector3 cameraOffset =
cursorOrientation * Ogre::Vector3::UNIT_Z * 30.0f;
cameraPos.x = cursorPos.x;
cameraPos.z = cursorPos.z;
cameraPos += cameraOffset;
cameraPos.y =
TerrainModule::get_height(
ECS::get<Terrain>().mTerrainGroup, cameraPos) +
@@ -765,9 +783,14 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
if (cameraPos.y < 0.0f)
cameraPos.y = 10.0f;
ECS::get<Camera>().mCameraPivot->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraPivot->_setDerivedOrientation(
cursorOrientation);
cameraPos =
ECS::get<Camera>().mCameraGoal->_getDerivedPosition();
ECS::get<Camera>().mCameraNode->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraNode->_setDerivedOrientation(
ECS::get<Camera>()
.mCameraGoal->_getDerivedOrientation());
updateHeightmap();
}
void worldMapView()
@@ -784,10 +807,10 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
OgreAssert(TerrainModule::get_world_y(worldMap->getHeight() /
2) == 0.0f,
"get_world_y");
if (ECS::get<Camera>().mCameraPivot) {
if (ECS::get<EditorGizmo>().sceneNode) {
Ogre::Vector3 worldPos =
ECS::get<Camera>()
.mCameraPivot->_getDerivedPosition();
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
selected_x = TerrainModule::get_img_x(worldPos.x);
selected_y = TerrainModule::get_img_y(worldPos.z);
locationSelected = true;
@@ -797,6 +820,10 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
OgreAssert(selected_y >= 0 &&
selected_y < worldMap->getHeight(),
"mix height");
ECS::get<Terrain>()
.mTerrainGroup
->convertWorldPositionToTerrainSlot(
worldPos, &slot_x, &slot_y);
}
ImGui::SetNextWindowSizeConstraints(ImVec2(512 + 20, 512 + 20),
ImVec2(768, 768));
@@ -856,6 +883,18 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
ImDrawList *draw_list = ImGui::GetWindowDrawList();
draw_list->AddCircleFilled(ImVec2(top_x + pos_x, top_y + pos_y),
1.0f, IM_COL32(0, 255, 0, 255));
{
std::list<Ogre::Vector3> positions;
TerrainModule::getItemPositions(&positions);
for (auto pos : positions) {
int item_x = TerrainModule::get_img_x(pos.x);
int item_y = TerrainModule::get_img_y(pos.z);
draw_list->AddCircleFilled(
ImVec2(top_x + item_x, top_y + item_y),
3.0f, IM_COL32(255, 255, 0, 255));
std::cout << pos << std::endl;
}
}
if (locationSelected)
draw_list->AddCircleFilled(
ImVec2(top_x + selected_x, top_y + selected_y),
@@ -877,6 +916,13 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
ImGui::Text(
"Selected height: %f",
worldMapImage.getColourAt(selected_x, selected_y, 0).r);
{
Ogre::Vector3 position =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
ImGui::Text("Cursor position %f %f %f", position.x,
position.y, position.z);
}
if (ImGui::Button("Update terrain")) {
ECS::get<Terrain>().mTerrainGroup->update(true);
}
@@ -948,6 +994,17 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
setLevel = true;
setLevelValue = 0.646f;
}
if (ImGui::Button("Harbour")) {
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
TerrainModule::createItem(itemPosition, itemOrientation,
"harbour");
TerrainModule::saveItems();
}
if (riseLower) {
int actualSize = 1 + size * 2;
int i, j;

View File

@@ -9,6 +9,7 @@
#include <OgrePage.h>
#include <OgreTerrainPaging.h>
#include <OgreFileSystemLayer.h>
#include <nlohmann/json.hpp>
#include "GameData.h"
#include "Components.h"
@@ -465,6 +466,15 @@ struct TerrainPrivate {
Ogre::Timer mSunUpdate;
};
struct TerrainSlotParent {
std::pair<long, long> slot;
};
struct TerrainItem {
Ogre::Vector3 position;
Ogre::Quaternion orientation;
Ogre::String properties;
};
TerrainModule::TerrainModule(flecs::world &ecs)
{
struct CanSetPlayerPosition {};
@@ -472,6 +482,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
ecs.component<CanSetPlayerPosition>().add(flecs::Singleton);
ecs.component<Terrain>().add(flecs::Singleton);
ecs.component<TerrainPrivate>().add(flecs::Singleton);
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<PlacementObjects>();
ecs.component<TerrainReady>().add(flecs::Singleton);
ecs.import <CharacterModule>();
@@ -726,6 +738,12 @@ TerrainModule::TerrainModule(flecs::world &ecs)
player.modified<CharacterLocation>();
ECS::get().remove<CanSetPlayerPosition>();
});
ecs.observer<const Terrain>("LoadTerrainItems")
.event(flecs::OnSet)
.each([](const Terrain &terrain) {
if (terrain.mTerrainGroup)
loadItems();
});
}
float TerrainModule::get_height(Ogre::TerrainGroup *group,
const Ogre::Vector3 &position)
@@ -765,4 +783,167 @@ void TerrainModule::save_heightmap()
{
HeightData::get_singleton()->save_heightmap();
}
flecs::entity TerrainModule::createItem(const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation,
const Ogre::String &type)
{
long x, y;
ECS::get<Terrain>().mTerrainGroup->convertWorldPositionToTerrainSlot(
position, &x, &y);
std::pair<long, long> pos{ x, y };
flecs::entity slot =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&](const TerrainSlotParent &slot) -> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
slot = ECS::get().entity().add<TerrainSlotParent>();
flecs::entity item = ECS::get().entity().child_of(slot);
nlohmann::json jproperties;
jproperties["type"] = type;
item.set<TerrainItem>({ position, orientation, jproperties.dump() });
return item;
}
void TerrainModule::setItemProperties(flecs::entity id, Ogre::String properties)
{
OgreAssert(id.is_valid(), "bad id");
id.get_mut<TerrainItem>().properties = properties;
id.modified<TerrainItem>();
}
const Ogre::String &TerrainModule::getItemProperties(flecs::entity id)
{
OgreAssert(id.is_valid(), "bad id");
return id.get<TerrainItem>().properties;
}
static void to_json(nlohmann::json &j, const Ogre::Vector3 &position)
{
j["x"] = position.x;
j["y"] = position.y;
j["z"] = position.z;
}
static void to_json(nlohmann::json &j, const Ogre::Quaternion &orientation)
{
j["w"] = orientation.w;
j["x"] = orientation.x;
j["y"] = orientation.y;
j["z"] = orientation.z;
}
static void from_json(const nlohmann::json &j, Ogre::Vector3 &position)
{
position.x = j["x"].get<float>();
position.y = j["y"].get<float>();
position.z = j["z"].get<float>();
}
static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation)
{
orientation.w = j["w"].get<float>();
orientation.x = j["x"].get<float>();
orientation.y = j["y"].get<float>();
orientation.z = j["z"].get<float>();
}
void TerrainModule::saveItems()
{
Ogre::String path = "resources/buildings/items.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list")) {
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("items.list");
Ogre::FileInfoListPtr fileInfoList(
Ogre::ResourceGroupManager::getSingleton()
.findResourceFileInfo(group, "items.list"));
OgreAssert(fileInfoList->size() == 1,
"worpd_map.png should be there and only once");
path = fileInfoList->at(0).archive->getName() + "/" +
"items.list";
Ogre::FileSystemLayer::removeFile(path);
}
std::fstream fout(path.c_str(), std::ios::out);
nlohmann::json jitemlist;
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
nlohmann::json jitem;
to_json(jitem["position"], item.position);
to_json(jitem["orientation"], item.orientation);
to_json(jitem["properties"], item.properties);
jitemlist.push_back(jitem);
});
fout << jitemlist.dump();
fout.close();
}
void TerrainModule::loadItems()
{
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list"))
return;
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("items.list");
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
"items.list", group);
Ogre::String json = stream->getAsString();
nlohmann::json jlist = nlohmann::json::parse(json);
ECS::get().delete_with<TerrainItem>();
ECS::get().delete_with<TerrainSlotParent>();
for (const auto &v : jlist) {
Ogre::Vector3 position;
Ogre::Quaternion orientation;
Ogre::String properties;
from_json(v["position"], position);
from_json(v["orientation"], orientation);
properties = v["properties"].get<Ogre::String>();
long x, y;
ECS::get<Terrain>()
.mTerrainGroup->convertWorldPositionToTerrainSlot(
position, &x, &y);
std::pair<long, long> pos{ x, y };
flecs::entity slot =
ECS::get()
.query_builder<const TerrainSlotParent>()
.build()
.find([&](const TerrainSlotParent &slot)
-> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
slot = ECS::get().entity().add<TerrainSlotParent>();
flecs::entity item = ECS::get().entity().child_of(slot);
item.set<TerrainItem>({ position, orientation, properties });
std::cout << "position: " << item.id() << " " << position
<< std::endl;
}
}
void TerrainModule::getItemPositionPerSlot(long x, long y,
std::list<Ogre::Vector3> *positions)
{
std::pair<long, long> pos{ x, y };
if (!positions)
return;
flecs::entity slot =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&](const TerrainSlotParent &slot) -> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
return;
ECS::get()
.query_builder<const TerrainItem>()
.with(flecs::ChildOf, slot)
.build()
.each([&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
std::cout << e.id() << " " << item.position
<< std::endl;
});
}
void TerrainModule::getItemPositions(std::list<Ogre::Vector3> *positions)
{
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
std::cout << e.id() << " " << item.position
<< std::endl;
});
}
}

View File

@@ -41,6 +41,17 @@ struct TerrainModule {
static int get_img_y(float world_z);
static void update_heightmap(const Ogre::Image &heightmap);
static void save_heightmap();
static flecs::entity createItem(const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation,
const Ogre::String &type);
static void setItemProperties(flecs::entity id,
Ogre::String properties);
static const Ogre::String &getItemProperties(flecs::entity id);
static void saveItems();
static void loadItems();
static void getItemPositionPerSlot(long x, long y,
std::list<Ogre::Vector3> *positions);
static void getItemPositions(std::list<Ogre::Vector3> *positions);
};
struct TerrainReady {};
}