Skip to content

Commit 3b005d9

Browse files
authored
Merge pull request #1 from Seltraeh/claude/beautiful-greider
Real unit stats, item inventory, and mission seeding from bravefrontier_data using claude automation on the data mined missions, units, and items from deathmax's captures of Brave Frontier and additional TODO/ file optimizations
2 parents 6d821c5 + f083a46 commit 3b005d9

25 files changed

+862
-137
lines changed

.claude/launch.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": "0.0.1",
3+
"configurations": [
4+
{
5+
"name": "GimuServer (Debug)",
6+
"runtimeExecutable": "cmd",
7+
"runtimeArgs": ["/c", "cd /d A:\\BF\\BF_WorkingDir\\server\\deploy && A:\\BF\\BF_WorkingDir\\beautiful-greider-build\\standalone_frontend\\Debug\\gimuserverw.exe"],
8+
"port": 9960
9+
},
10+
{
11+
"name": "GimuServer (Release)",
12+
"runtimeExecutable": "cmd",
13+
"runtimeArgs": ["/c", "cd /d A:\\BF\\BF_WorkingDir\\server\\deploy && A:\\BF\\BF_WorkingDir\\server\\standalone_frontend\\Release\\gimuserverw.exe"],
14+
"port": 9960
15+
}
16+
]
17+
}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,3 +486,7 @@ vcpkg_installed/
486486
.vscode
487487
generated/
488488
.cmake/
489+
490+
# Claude Code local session data (permissions, worktree state)
491+
.claude/settings.local.json
492+
.claude/worktrees/

gimuserver/core/BfCrypt.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
#pragma once
22

3+
// BfCrypt — AES-based encryption/decryption for the Brave Frontier GME protocol.
4+
//
5+
// CryptSREE - Encodes a JSON value into the SREE (account API) wire format.
6+
// CryptGME - Encrypts a JSON response body with the handler-specific AES key
7+
// before sending it back to the game client.
8+
// DecryptGME - Decrypts an inbound GME request body that was encrypted by the
9+
// client using the same handler-specific AES key.
10+
311
#include <json/value.h>
412

513
namespace BfCrypt

gimuserver/core/System.cpp

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ void System::ParseSystemConfig(const Json::Value& v)
3838
m_dbPath = v["gme_sqlite_path"].asString();
3939
m_sessionTimeout = size_t(v["session_timeout"].asUInt64());
4040

41-
m_mstConfig.LoadAllTables(v["mst_root"].asString());
41+
const auto mstRoot = v["mst_root"].asString();
42+
m_mstConfig.LoadAllTables(mstRoot);
43+
m_unitMst.LoadFromJson(mstRoot + "/unit_master.json");
4244
}
4345

4446
void System::RunMigrations(drogon::orm::DbClientPtr p)
@@ -76,7 +78,8 @@ void System::DevValidateAndSeedUnits(drogon::orm::DbClientPtr db)
7678
#if !DEV_SKIP_TUTORIAL
7779
return;
7880
#else
79-
const size_t expectedCount = ALL_UNIT_IDS.size();
81+
const auto& unitIds = m_unitMst.GetAllUnitIds();
82+
const size_t expectedCount = unitIds.size();
8083

8184
LOG_INFO << "System::DevValidateAndSeedUnits: checking existing users "
8285
<< "(expecting " << expectedCount << " units each)";
@@ -110,7 +113,7 @@ void System::DevValidateAndSeedUnits(drogon::orm::DbClientPtr db)
110113
LOG_INFO << "System::DevValidateAndSeedUnits: user " << userId
111114
<< " has " << have << "/" << expectedCount << " units - seeding.";
112115

113-
for (const auto& unitId : ALL_UNIT_IDS)
116+
for (const auto& unitId : unitIds)
114117
{
115118
try
116119
{
@@ -135,4 +138,70 @@ void System::DevValidateAndSeedUnits(drogon::orm::DbClientPtr db)
135138
#endif
136139
}
137140

141+
void System::DevValidateAndSeedItems(drogon::orm::DbClientPtr db)
142+
{
143+
#if !DEV_SKIP_TUTORIAL
144+
return;
145+
#else
146+
const auto& seedItems = m_mstConfig.GetSeedItems();
147+
if (seedItems.empty())
148+
return;
149+
150+
LOG_INFO << "System::DevValidateAndSeedItems: checking existing users "
151+
<< "(expecting " << seedItems.size() << " item types each)";
152+
153+
try
154+
{
155+
auto users = db->execSqlSync("SELECT id FROM users;");
156+
157+
if (users.empty())
158+
{
159+
LOG_INFO << "System::DevValidateAndSeedItems: no existing users, nothing to do.";
160+
return;
161+
}
162+
163+
for (const auto& row : users)
164+
{
165+
const std::string userId = row["id"].as<std::string>();
166+
167+
auto countResult = db->execSqlSync(
168+
"SELECT COUNT(*) FROM user_items WHERE user_id = $1;", userId);
169+
170+
const size_t have = countResult[0][0].as<size_t>();
171+
172+
if (have >= seedItems.size())
173+
{
174+
LOG_DEBUG << "System::DevValidateAndSeedItems: user " << userId
175+
<< " already has " << have << " item types, skipping.";
176+
continue;
177+
}
178+
179+
LOG_INFO << "System::DevValidateAndSeedItems: user " << userId
180+
<< " has " << have << "/" << seedItems.size() << " item types - seeding.";
181+
182+
for (const auto& item : seedItems)
183+
{
184+
try
185+
{
186+
db->execSqlSync(
187+
"INSERT OR IGNORE INTO user_items (user_id, item_id, quantity) VALUES ($1, $2, $3);",
188+
userId, item.id, item.quantity);
189+
}
190+
catch (const drogon::orm::DrogonDbException& e)
191+
{
192+
LOG_WARN << "System::DevValidateAndSeedItems: failed to insert item "
193+
<< item.id << " for " << userId << ": " << e.base().what();
194+
}
195+
}
196+
197+
LOG_INFO << "System::DevValidateAndSeedItems: finished seeding user " << userId;
198+
}
199+
}
200+
catch (const drogon::orm::DrogonDbException& e)
201+
{
202+
LOG_ERROR << "System::DevValidateAndSeedItems: DB error: " << e.base().what();
203+
}
204+
#endif
205+
}
206+
138207
System System::m_sys;

gimuserver/core/System.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string>
44
#include <drogon/orm/DbClient.h>
55
#include <gimuserver/system/MstConfig.hpp>
6+
#include <gimuserver/system/UnitMstConfig.hpp>
67
#include <gimuserver/system/ServerConfig.hpp>
78
#include <gimuserver/system/LogConfig.hpp>
89
#include <gimuserver/db/MigrationManager.hpp>
@@ -15,6 +16,7 @@ class System final
1516
void LoadSystemConfig(const std::string& path);
1617
void RunMigrations(drogon::orm::DbClientPtr ptr);
1718
void DevValidateAndSeedUnits(drogon::orm::DbClientPtr ptr);
19+
void DevValidateAndSeedItems(drogon::orm::DbClientPtr ptr);
1820

1921
// Queries the users table for the first real account and caches the ID.
2022
// Called once at startup after RunMigrations. GmeController reads this
@@ -32,6 +34,7 @@ class System final
3234
const auto& GetSessionTimeout() const { return m_sessionTimeout; }
3335
// "mst"
3436
const auto& MstConfig() const { return m_mstConfig; }
37+
const auto& Units() const { return m_unitMst; }
3538
// "server"
3639
const auto& ServerConfig() { return m_serverCfg; }
3740
// "log"
@@ -47,6 +50,7 @@ class System final
4750

4851
::ServerConfig m_serverCfg;
4952
::MstConfig m_mstConfig;
53+
::UnitMstConfig m_unitMst;
5054
::LogConfig m_logCfg;
5155
MigrationManager m_mg;
5256

gimuserver/core/Utils.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
#pragma once
22

3+
// Utils — miscellaneous helper functions used across the server.
4+
//
5+
// DumpInfoToDrogon - Logs HTTP request details through Drogon's logging system.
6+
// GetDrogonBindHostname - Returns the HTTPS bind address configured in config.json.
7+
// GetDrogonHttpBindHostname - Returns the plain HTTP bind address.
8+
// RandomUserID - Generates a random user ID string for new accounts.
9+
// RandomAccountID - Generates a random account ID string for new accounts.
10+
// AppendJsonReqToFile - Writes a decoded request body to the request log directory.
11+
// AppendJsonResToFile - Writes a response body to the response log directory.
12+
// AddMissingDlcFile - Records a 404'd DLC asset path to dlc_error_file.
13+
314
#include <drogon/HttpRequest.h>
415
#include <drogon/Session.h>
516
#include <gme/GmeTypes.hpp>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
#include "MigrationManager.hpp"
22
#include "migrations/CreateDefaultTables.hpp"
33
#include "migrations/CreateUserUnitsTable.hpp"
4+
#include "migrations/AddTutorialEndFlag.hpp"
5+
#include "migrations/CreateDailyTaskTables.hpp"
6+
#include "migrations/CreateUserItemsTable.hpp"
47

58
#define ADD(x) m_migs.push_back(std::make_shared<Migrations::##x>());
69

710
void MigrationManager::Register()
811
{
912
ADD(CreateDefaultTables);
1013
ADD(CreateUserUnitsTable);
14+
ADD(AddTutorialEndFlag);
15+
ADD(CreateDailyTaskTables);
16+
ADD(CreateUserItemsTable);
1117
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "../IMigration.hpp"
4+
#include "../DbMacro.hpp"
5+
6+
MIGRATION_NS_BEGIN
7+
8+
// Adds the tutorial_end_flag column to the users table so that tutorial
9+
// completion state can be persisted per-user rather than forced by the
10+
// compile-time DEV_SKIP_TUTORIAL flag.
11+
//
12+
// DEFAULT 0 means all existing users have tutorial_end_flag=0 (incomplete).
13+
// The tutorial-completion handler should UPDATE it to 1 after the player
14+
// picks their starter unit.
15+
struct AddTutorialEndFlag : public IMigration
16+
{
17+
void execute(drogon::orm::DbClientPtr db) override
18+
{
19+
db->execSqlSync(
20+
"ALTER TABLE users ADD COLUMN tutorial_end_flag INTEGER NOT NULL DEFAULT 0;"
21+
);
22+
}
23+
24+
const char* getName() const override { return "10032025_AddTutorialEndFlag"; }
25+
};
26+
27+
MIGRATION_NS_END
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include "../IMigration.hpp"
4+
#include "../DbMacro.hpp"
5+
6+
MIGRATION_NS_BEGIN
7+
8+
// Creates two tables for the daily task system:
9+
//
10+
// user_daily_task_claims
11+
// Tracks how many times a user has claimed a specific daily prize (keyed by
12+
// the task_id from dailytask.json / DailyTaskPrizeMst). currentClaimCount
13+
// in the DailyTaskPrizeMst response should be populated from this table.
14+
//
15+
// user_daily_task_progress
16+
// Tracks a user's progress toward each daily task type (e.g., "AV" = Arena
17+
// Victories, "VV" = Vortex runs, "CM" = Crafts). reset_date stores the Unix
18+
// timestamp of the day boundary when progress was last reset so progress can
19+
// be zeroed on a new day without deleting rows.
20+
struct CreateDailyTaskTables : public IMigration
21+
{
22+
void execute(drogon::orm::DbClientPtr db) override
23+
{
24+
// Prize claim counts per user
25+
db->execSqlSync(R"(
26+
CREATE TABLE IF NOT EXISTS user_daily_task_claims (
27+
user_id TEXT NOT NULL,
28+
task_id INTEGER NOT NULL,
29+
claim_count INTEGER NOT NULL DEFAULT 0,
30+
PRIMARY KEY (user_id, task_id)
31+
);
32+
)");
33+
34+
// Per-day progress counters per user
35+
db->execSqlSync(R"(
36+
CREATE TABLE IF NOT EXISTS user_daily_task_progress (
37+
user_id TEXT NOT NULL,
38+
task_type_key TEXT NOT NULL,
39+
progress INTEGER NOT NULL DEFAULT 0,
40+
reset_date INTEGER NOT NULL DEFAULT 0,
41+
PRIMARY KEY (user_id, task_type_key)
42+
);
43+
)");
44+
}
45+
46+
const char* getName() const override { return "10032025_CreateDailyTaskTables"; }
47+
};
48+
49+
MIGRATION_NS_END
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include "../IMigration.hpp"
4+
#include "../DbMacro.hpp"
5+
6+
MIGRATION_NS_BEGIN
7+
8+
struct CreateUserItemsTable : public IMigration
9+
{
10+
void execute(drogon::orm::DbClientPtr db) override
11+
{
12+
db->execSqlSync(R"(
13+
CREATE TABLE IF NOT EXISTS user_items (
14+
user_id TEXT NOT NULL,
15+
item_id INTEGER NOT NULL,
16+
quantity INTEGER NOT NULL DEFAULT 1,
17+
PRIMARY KEY (user_id, item_id)
18+
);
19+
)");
20+
}
21+
22+
const char* getName() const override { return "11032025_CreateUserItemsTable"; }
23+
};
24+
25+
MIGRATION_NS_END

0 commit comments

Comments
 (0)