Skip to content

Commit 86502b6

Browse files
add missed methods (mobs, inventory)
1 parent f6a9357 commit 86502b6

13 files changed

Lines changed: 732 additions & 287 deletions

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ set(NETWORK_SOURCES
104104

105105
# Core logic system
106106
set(LOGIC_CORE_SOURCES
107+
src/game/LootItem.cpp
108+
src/game/LootTable.cpp
109+
src/game/LootTableManager.cpp
110+
src/game/MobSystem.cpp
107111
src/game/LogicCore.cpp
108112
src/game/LogicWorld.cpp
109113
src/game/LogicEntity.cpp

include/game/GameLogic.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "game/PlayerManager.hpp"
1616
#include "game/InventorySystem.hpp"
1717
#include "game/LootTableManager.hpp"
18-
#include "game/MobSystem.hpp"
18+
//#include "game/MobSystem.hpp"
1919
#include "game/SkillSystem.hpp"
2020
#include "game/QuestManager.hpp"
2121
#include "game/EntityManager.hpp"

include/game/LootItem.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class LootItem {
6161
const glm::vec3& GetIconColor() const { return iconColor_; }
6262

6363
// Setters
64+
void SetId(uint64_t id) { id_ = id; }
65+
void SetName(const std::string& name) { name_ = name; }
66+
void SetRarity(LootRarity rarity = LootRarity::COMMON) { rarity_ = rarity; }
6467
void SetStackSize(int size);
6568
void SetLevelRequirement(int level);
6669
void SetIconColor(const glm::vec3& color);

include/game/LootTable.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
#pragma once
22

3-
#include <vector>
3+
#include <algorithm>
4+
#include <fstream>
45
#include <random>
6+
#include <vector>
57
#include <unordered_map>
68

9+
#include "logging/Logger.hpp"
710
#include "game/LootItem.hpp"
811

912
struct LootEntry {
10-
std::string itemId;
13+
uint64_t itemId;
14+
std::string name;
1115
float dropChance = 0.0f; // 0.0 to 1.0
1216
int minQuantity = 1;
1317
int maxQuantity = 1;

include/game/MobSystem.hpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
// MobSystem.hpp
22
#pragma once
33

4-
#include <vector>
5-
#include <unordered_map>
4+
#include <algorithm>
65
#include <chrono>
6+
#include <cmath>
77
#include <random>
8+
#include <vector>
9+
#include <unordered_map>
810

911
#include <glm/glm.hpp>
1012

11-
#include "game/WorldChunk.hpp"
12-
#include "game/LootTable.hpp"
13+
#include "logging/Logger.hpp"
14+
#include "config/ConfigManager.hpp"
1315

14-
//#include "game/NPCEntity.hpp"
15-
enum class NPCType;
16-
class NPCEntity;
16+
//#include "game/WorldChunk.hpp"
17+
//#include "game/LootTable.hpp"
18+
//#include "game/PlayerManager.hpp"
19+
//#include "game/EntityManager.hpp"
20+
//#include "game/LootTableManager.hpp"
21+
#include "game/NPCEntity.hpp"
1722

1823
// Mob spawn zone
1924
struct MobSpawnZone {
@@ -25,7 +30,7 @@ struct MobSpawnZone {
2530
int maxMobs = 10;
2631
float respawnTime = 30.0f; // seconds
2732
std::string name;
28-
std::string lootTableId; // Add loot table reference
33+
std::string lootTableId;
2934
};
3035

3136
// Mob variant (leveled version of a mob type)
@@ -35,7 +40,7 @@ struct MobVariant {
3540
float healthMultiplier = 1.0f;
3641
float damageMultiplier = 1.0f;
3742
float experienceReward = 10.0f;
38-
std::string lootTableId; // Reference to loot table
43+
std::string lootTableId;
3944
};
4045

4146
// Mob death info for rewards

include/game/NPCEntity.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
#include "game/GameEntity.hpp"
1717
#include "game/LootTableManager.hpp"
18-
#include "game/MobSystem.hpp"
18+
//#include "game/MobSystem.hpp"
1919
#include "logging/Logger.hpp"
2020
#include "config/ConfigManager.hpp"
2121

@@ -421,6 +421,8 @@ class NPCEntity : public GameEntity {
421421
float summon_cooldown_ = 0.0f;
422422

423423
// Patrol and movement
424+
float patrol_wait_timer_ = 0.0f;
425+
bool waiting_at_patrol_point_ = false;
424426
glm::vec3 spawn_position_;
425427
std::queue<glm::vec3> patrol_queue_;
426428

@@ -439,6 +441,6 @@ class NPCEntity : public GameEntity {
439441
static constexpr float DESPAWN_DELAY = 10.0f;
440442

441443
friend class NPCAISystem;
442-
friend class MobSystem;
444+
//friend class MobSystem;
443445
friend class EntityManager;
444446
};

src/game/GameLogic.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -952,18 +952,20 @@ void GameLogic::SaveGameState() {
952952
{"server_time", GetCurrentTimestamp()},
953953
{"world_seed", GetWorldConfig().seed},
954954
{"active_chunks", LogicWorld::GetInstance().GetActiveChunkCount()},
955-
{"active_npcs", 0}, // LogicEntity::GetInstance().GetActiveNPCCount() if exposed
955+
{"active_npcs", 0}, // TODO: expose from LogicEntity if needed
956956
{"world_config", {
957957
{"view_distance", GetWorldConfig().viewDistance},
958958
{"chunk_size", GetWorldConfig().chunkSize},
959959
{"terrain_scale", GetWorldConfig().terrainScale}
960960
}}
961961
};
962962

963-
auto& dbClient = CitusClient::GetInstance();
964-
dbClient.SaveGameState("current_game", gameState);
965-
966-
Logger::Debug("game state saved");
963+
// Use DbManager instead of direct CitusClient
964+
if (!DbManager::GetInstance().SaveGameState("current_game", gameState)) {
965+
Logger::Error("Failed to save game state: DbManager returned false");
966+
} else {
967+
Logger::Debug("Game state saved");
968+
}
967969
} catch (const std::exception& e) {
968970
Logger::Error("Failed to save game state: {}", e.what());
969971
}

src/game/InventorySystem.cpp

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ bool InventorySystem::AddItem(uint64_t playerId, const LootItem& item, int quant
5959

6060
// Need new slots
6161
while (quantity > 0) {
62-
if (inventory.inventorySlots.size() >= inventory.maxInventorySize) {
62+
if (inventory.inventorySlots.size() >= (uint64_t)inventory.maxInventorySize) {
6363
Logger::Error("Inventory full for player {}", playerId);
6464
SaveInventory(playerId);
6565
return false;
@@ -80,6 +80,38 @@ bool InventorySystem::AddItem(uint64_t playerId, const LootItem& item, int quant
8080
return true;
8181
}
8282

83+
bool InventorySystem::MoveItem(uint64_t playerId, int fromSlot, int toSlot) {
84+
std::lock_guard<std::mutex> lock(mutex_);
85+
86+
auto it = playerInventories_.find(playerId);
87+
if (it == playerInventories_.end())
88+
return false;
89+
90+
auto& inventory = it->second;
91+
// Validate slot indices
92+
if (fromSlot < 0 || fromSlot >= static_cast<int>(inventory.inventorySlots.size()) ||
93+
toSlot < 0 || toSlot >= static_cast<int>(inventory.inventorySlots.size()))
94+
return false;
95+
96+
if (fromSlot == toSlot)
97+
return true; // Nothing to do
98+
99+
auto& slotFrom = inventory.inventorySlots[fromSlot];
100+
auto& slotTo = inventory.inventorySlots[toSlot];
101+
102+
// Swap the contents
103+
std::swap(slotFrom.item, slotTo.item);
104+
std::swap(slotFrom.quantity, slotTo.quantity);
105+
std::swap(slotFrom.equipped, slotTo.equipped);
106+
107+
// Update position fields to match their new indices
108+
slotFrom.position = fromSlot;
109+
slotTo.position = toSlot;
110+
111+
SaveInventory(playerId);
112+
return true;
113+
}
114+
83115
bool InventorySystem::RemoveItem(uint64_t playerId, uint64_t itemId, int quantity) {
84116
std::lock_guard<std::mutex> lock(mutex_);
85117

@@ -137,7 +169,7 @@ bool InventorySystem::EquipItem(uint64_t playerId, int inventorySlot) {
137169
auto& inventory = it->second;
138170

139171
if (!ValidateSlot(playerId, inventorySlot) ||
140-
inventorySlot >= inventory.inventorySlots.size()) {
172+
(uint64_t)inventorySlot >= inventory.inventorySlots.size()) {
141173
return false;
142174
}
143175

@@ -151,7 +183,7 @@ bool InventorySystem::EquipItem(uint64_t playerId, int inventorySlot) {
151183
}
152184

153185
int equipSlot = GetEquipmentSlotForItem(*slot.item);
154-
if (equipSlot == -1 || equipSlot >= inventory.equipmentSlots.size()) {
186+
if (equipSlot == -1 || (uint64_t)equipSlot >= inventory.equipmentSlots.size()) {
155187
return false;
156188
}
157189

@@ -296,6 +328,73 @@ bool InventorySystem::AddGold(uint64_t playerId, int64_t amount) {
296328
return true;
297329
}
298330

331+
bool InventorySystem::RemoveGold(uint64_t playerId, int64_t amount) {
332+
std::lock_guard<std::mutex> lock(mutex_);
333+
334+
auto it = playerInventories_.find(playerId);
335+
if (it == playerInventories_.end()) {
336+
return false; // No inventory → cannot remove gold
337+
}
338+
339+
if (amount < 0) return false; // Cannot remove negative amount
340+
if (it->second.gold < amount) return false; // Insufficient funds
341+
342+
it->second.gold -= amount;
343+
SaveInventory(playerId);
344+
return true;
345+
}
346+
347+
bool InventorySystem::TransferGold(uint64_t fromPlayerId, uint64_t toPlayerId, int64_t amount) {
348+
if (fromPlayerId == toPlayerId || amount <= 0)
349+
return false;
350+
351+
std::lock_guard<std::mutex> lock(mutex_); // Lock once for atomicity
352+
353+
auto fromIt = playerInventories_.find(fromPlayerId);
354+
auto toIt = playerInventories_.find(toPlayerId);
355+
356+
if (fromIt == playerInventories_.end() || toIt == playerInventories_.end())
357+
return false; // Both players must have inventories
358+
359+
if (fromIt->second.gold < amount)
360+
return false; // Insufficient funds
361+
362+
// Perform transfer
363+
fromIt->second.gold -= amount;
364+
toIt->second.gold += amount;
365+
366+
// Cap at max (though gold is int64_t, addition could overflow, but unlikely)
367+
if (toIt->second.gold < 0) toIt->second.gold = INT64_MAX;
368+
369+
// Save both inventories (optional – SaveInventory already writes to DB)
370+
SaveInventory(fromPlayerId);
371+
SaveInventory(toPlayerId);
372+
return true;
373+
}
374+
375+
std::shared_ptr<LootItem> InventorySystem::GetItem(uint64_t playerId, int slot) {
376+
std::lock_guard<std::mutex> lock(mutex_);
377+
378+
auto it = playerInventories_.find(playerId);
379+
if (it == playerInventories_.end())
380+
return nullptr;
381+
382+
if (slot < 0 || slot >= static_cast<int>(it->second.inventorySlots.size()))
383+
return nullptr;
384+
385+
const auto& slotData = it->second.inventorySlots[slot];
386+
return slotData.item; // may be nullptr if slot empty
387+
}
388+
389+
std::vector<InventorySlot> InventorySystem::GetInventory(uint64_t playerId) const {
390+
std::lock_guard<std::mutex> lock(mutex_);
391+
auto it = playerInventories_.find(playerId);
392+
if (it == playerInventories_.end()) {
393+
return {};
394+
}
395+
return it->second.inventorySlots;
396+
}
397+
299398
// Helper method implementations
300399
bool InventorySystem::ValidateSlot(uint64_t playerId, int slot) const {
301400
auto it = playerInventories_.find(playerId);
@@ -318,6 +417,8 @@ int InventorySystem::GetEquipmentSlotForItem(const LootItem& item) const {
318417
}
319418

320419
bool InventorySystem::MeetsRequirements(uint64_t playerId, const LootItem& item) const {
420+
(void)playerId;
421+
(void)item;
321422
// TODO: Implement player level and other requirement checks
322423
// For now, just check level requirement
323424
// This would need access to player stats/level

src/game/LogicCore.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,68 @@ void LogicCore::HandleLogin(uint64_t sessionId, const nlohmann::json& data) {
490490
});
491491
}
492492

493+
void LogicCore::HandleChat(uint64_t sessionId, const nlohmann::json& data) {
494+
uint64_t playerId = GetPlayerIdBySession(sessionId);
495+
if (playerId == 0) {
496+
SendError(sessionId, "Player not authenticated", 401);
497+
return;
498+
}
499+
500+
if (!data.contains("message") || !data["message"].is_string()) {
501+
SendError(sessionId, "Missing or invalid message", 400);
502+
return;
503+
}
504+
505+
std::string chatMessage = data["message"];
506+
if (chatMessage.empty()) {
507+
SendError(sessionId, "Message cannot be empty", 400);
508+
return;
509+
}
510+
511+
// Optional: handle commands (starting with '/')
512+
if (chatMessage[0] == '/') {
513+
// Delegate to a command handler if desired
514+
// For now, just treat as normal chat
515+
}
516+
517+
auto player = playerManager_.GetPlayer(playerId);
518+
if (!player) {
519+
SendError(sessionId, "Player not found", 500);
520+
return;
521+
}
522+
523+
Logger::Info("Chat from player {} ({}): {}", playerId, player->GetName(), chatMessage);
524+
525+
nlohmann::json chatJson = {
526+
{"type", "chat"},
527+
{"playerId", playerId},
528+
{"playerName", player->GetName()},
529+
{"message", chatMessage},
530+
{"timestamp", GetCurrentTimestamp()}
531+
};
532+
533+
std::string channel = data.value("channel", "local");
534+
if (channel == "global") {
535+
// Broadcast to all online players
536+
auto& connMgr = ConnectionManager::GetInstance();
537+
auto sessions = connMgr.GetAllSessions();
538+
for (auto& session : sessions) {
539+
if (session && session->IsConnected()) {
540+
session->Send(chatJson);
541+
}
542+
}
543+
} else {
544+
// Default to local broadcast (nearby players)
545+
playerManager_.BroadcastToNearbyPlayers(playerId, chatJson);
546+
}
547+
548+
FirePythonEvent("player_chat", {
549+
{"playerId", playerId},
550+
{"message", chatMessage},
551+
{"channel", channel}
552+
});
553+
}
554+
493555
void LogicCore::HandleCombat(uint64_t sessionId, const nlohmann::json& data) {
494556
uint64_t playerId = GetPlayerIdBySession(sessionId);
495557
if (playerId == 0) {

src/game/LootTable.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
#include <fstream>
2-
#include <algorithm>
3-
41
#include "game/LootTable.hpp"
5-
#include "logging/Logger.hpp"
62

73
nlohmann::json LootEntry::Serialize() const {
84
return {
95
{"itemId", itemId},
6+
{"name", name},
107
{"dropChance", dropChance},
118
{"minQuantity", minQuantity},
129
{"maxQuantity", maxQuantity},
@@ -22,6 +19,7 @@ nlohmann::json LootEntry::Serialize() const {
2219

2320
void LootEntry::Deserialize(const nlohmann::json& data) {
2421
itemId = data["itemId"];
22+
name = data["name"];
2523
dropChance = data["dropChance"];
2624
minQuantity = data["minQuantity"];
2725
maxQuantity = data["maxQuantity"];

0 commit comments

Comments
 (0)