JSON ile oyuncu bilgilerini depolamak

isthambul1453

Yasaklanmış Üye
Cezalı
Mesaj
354
Çözümler
3
Beğeni
255
Puan
764
Ticaret Puanı
0
kullanılan filesi soracaklar 3 envanterli Hard filesi kullandım anlatıma geçelim :)

db ye data adında klasör açılır ve gerekli chmod izinler verilir

db/data/accounts.json içeriği;
{
"accounts": [
{
"id": 1,
"login": "test",
"passwd": "testpass",
"social_id": "0000",
"bEmpire": 1,
"players": [
{
"id": 10,
"name": "TestChar",
"job": 0,
"level": 1,
"playtime": 0,
"st": 1,
"ht": 1,
"dx": 1,
"iq": 1,
"part_main": 0,
"part_hair": 0,
"x": 0,
"y": 0,
"skill_group": 0,
"change_name": 0
}
],
"status": "OK"
}
]
}

common kısmında oluştur Serverside/Server/common/json.hpp(json.rar)
Clientmanagerlogin.cpp aç arat


ekle altına

#include "JsonStorage.h"

arat

TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));

pkTab->id = r.id;
trim_and_lower(r.login, pkTab->login, sizeof(pkTab->login));
strlcpy(pkTab->passwd, r.passwd, sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, r.social_id, sizeof(pkTab->social_id));
strlcpy(pkTab->status, "OK", sizeof(pkTab->status));

ClientHandleInfo * info = new ClientHandleInfo(dwHandle);
info->pAccountTable = pkTab;
strlcpy(info->ip, p->szIP, sizeof(info->ip));

sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index WHERE id=%u", r.id);
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
değiştir

TAccountTable * pkTab = JsonStorage::instance().GetAccountByLogin(szLogin);
if (!pkTab)
{
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}

sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, p->szIP);

CLoginData * pLogin = GetLoginDataByLogin(pkTab->login);
if (pLogin)
memcpy(&pLogin->GetAccountRef(), pkTab, sizeof(TAccountTable));

if (!InsertLogonAccount(pkTab->login, pkPeer->GetHandle(), p->szIP))
{
TPacketDGLoginAlready ptog;
strlcpy(ptog.szLogin, pkTab->login, sizeof(ptog.szLogin));
pkPeer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, dwHandle, sizeof(ptog));
pkPeer->Encode(&ptog, sizeof(ptog));
}
else
{
pkPeer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, dwHandle, sizeof(TAccountTable));
pkPeer->Encode(pkTab, sizeof(TAccountTable));
}

JsonStorage.cpp
#include "stdafx.h"
#include "JsonStorage.h"
#include <fstream>
using json = nlohmann::json;

JsonStorage& JsonStorage::instance()
{
static JsonStorage s;
return s;
}

bool JsonStorage::Load(const std::string& file)
{
std::ifstream ifs(file.c_str());
if (!ifs.is_open())
return false;
json j;
ifs >> j;
for (const auto& acc : j["accounts"])
{
TAccountTable tab;
memset(&tab, 0, sizeof(TAccountTable));
tab.id = acc.value("id", 0);
std::string login = acc.value("login", "");
strlcpy(tab.login, login.c_str(), sizeof(tab.login));
std::string passwd = acc.value("passwd", "");
strlcpy(tab.passwd, passwd.c_str(), sizeof(tab.passwd));
std::string social = acc.value("social_id", "");
strlcpy(tab.social_id, social.c_str(), sizeof(tab.social_id));
tab.bEmpire = acc.value("bEmpire", 0);
strlcpy(tab.status, acc.value("status", "OK").c_str(), sizeof(tab.status));
size_t idx = 0;
for (const auto& pl : acc["players"])
{
if (idx >= PLAYER_PER_ACCOUNT)
break;
TSimplePlayer& sp = tab.players[idx];
sp.dwID = pl.value("id", 0);
std::string name = pl.value("name", "");
strlcpy(sp.szName, name.c_str(), sizeof(sp.szName));
sp.byJob = pl.value("job", 0);
sp.byLevel = pl.value("level", 0);
sp.dwPlayMinutes = pl.value("playtime", 0);
sp.byST = pl.value("st", 0);
sp.byHT = pl.value("ht", 0);
sp.byDX = pl.value("dx", 0);
sp.byIQ = pl.value("iq", 0);
sp.wMainPart = pl.value("part_main", 0);
sp.wHairPart = pl.value("part_hair", 0);
sp.x = pl.value("x", 0);
sp.y = pl.value("y", 0);
sp.skill_group = pl.value("skill_group", 0);
sp.bChangeName = pl.value("change_name", 0);
++idx;
}
m_accounts[login] = tab;
}
return true;
}

TAccountTable* JsonStorage::GetAccountByLogin(const std::string& login)
{
auto it = m_accounts.find(login);
if (it == m_accounts.end())
return NULL;
return &it->second;
}

JsonStorage.h
#ifndef JSON_STORAGE_H
#define JSON_STORAGE_H
#include <unordered_map>
#include <string>
#include "../../common/json.hpp"
#include "../../common/tables.h"
class JsonStorage {
public:
static JsonStorage& instance();
bool Load(const std::string& file);
TAccountTable* GetAccountByLogin(const std::string& login);
private:
std::unordered_map<std::string, TAccountTable> m_accounts;
};
#endif

Main.cpp aç arat

#include "ItemIDRangeManager.h"

alta geç ekle

#include "JsonStorage.h"

arat

int iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_PLAYER, "localhost", 0, "player", "root", "aKc~tG!M3?5MF5#Y"))
{
sys_log(0, " OK");
break;
}

sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success PLAYER\n");

iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_ACCOUNT, "localhost", 0, "account", "root", "aKc~tG!M3?5MF5#Y"))
{
sys_log(0, " OK");
break;
}

sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success ACCOUNT\n");

iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_COMMON, "localhost", 0, "common", "root", "aKc~tG!M3?5MF5#Y"))
{
sys_log(0, " OK");
break;
}

sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success COMMON\n");

iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_HOTBACKUP, "localhost", 0, "hotbackup", "root", "aKc~tG!M3?5MF5#Y"))
{
sys_log(0, " OK");
break;
}

sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
}
while (iRetry--);
fprintf(stderr, "Success HOTBACKUP\n");

bununla değiştir

if (!JsonStorage::instance().Load("data/accounts.json"))
{
sys_err("cannot load accounts.json");
return false;
}

Makefile açıp sıraya ekle

CC = g++

OBJDIR = obj
$(shell if [ ! -d $(OBJDIR) ]; then mkdir $(OBJDIR); fi)

CFLAGS = -g -Wall -O2 -pipe -fno-rtti -fno-exceptions -pthread -D_THREAD_SAFE -mtune=i686

INCDIR = -I../../boost -I../../libmysql/7.x-5.1.35
LIBDIR = -L../../libthecore/lib -L../../libsql -L../../libpoly -L../../libgame/lib -L/usr/local/lib/mysql -L../../libmysql/7.x-5.1.35
LIBS = -lthecore -lmysqlclient -lsql -lpoly -lgame -lm -lz

TARGET = ../db

SRCS = NetBase.cpp Peer.cpp PeerBase.cpp Main.cpp Lock.cpp DBManager.cpp \
Cache.cpp LoginData.cpp ClientManager.cpp ClientManagerPlayer.cpp ClientManagerLogin.cpp \
ClientManagerBoot.cpp ClientManagerParty.cpp ClientManagerGuild.cpp GuildManager.cpp HB.cpp \
PrivManager.cpp MoneyLog.cpp ItemAwardManager.cpp ClientManagerEventFlag.cpp Marriage.cpp \
BlockCountry.cpp ItemIDRangeManager.cpp ClientManagerHorseName.cpp version.cpp \
BlockCountry.cpp ItemIDRangeManager.cpp ClientManagerHorseName.cpp JsonStorage.cpp version.cpp \
ProtoReader.cpp CsvReader.cpp

OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o)

default: $(TARGET)

$(TARGET): $(OBJS)
@echo linking
@$(CC) $(CFLAGS) $(LIBDIR) $(OBJS) $(LIBS) -o $(TARGET)
@touch version.cpp

$(OBJDIR)/%.o: %.cpp
@echo compile $<
@$(CC) $(CFLAGS) $(INCDIR) -c $< -o $@

$(OBJDIR)/version.o: version.cpp
@$(CC) $(CFLAGS) -D__USER__=\"$(USER)\" -D__HOSTNAME__=\"$(HOSTNAME)\" -D__PWD__=\"$(PWD)\" -c $< -o $@
@echo compile $<

$(OBJDIR):
@mkdir $(OBJDIR)

clean:
@rm -f $(OBJS) ../db
 

Dosya Eklentileri

bir kaç farklı versiyonu daha elimde olacaktı onlarıda bulabilirsem konuya dahil ederim gün içinde
 
Version 2
ClientManagerLogin.cpp aç ve ekle

Kod:
Genişlet Daralt Kopyala
#ifdef USE_JSON_DB
#include "JSONDB.h"
#endif

arat

Kod:
Genişlet Daralt Kopyala
    sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
    char szQuery[QUERY_MAX_LEN];
    snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index WHERE id=%u", r.id);
    CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);

değiştir

Kod:
Genişlet Daralt Kopyala
#ifdef USE_JSON_DB
        if (JSONDB_FindAccount(pkTab->login, *pkTab))
        {
                pkPeer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, dwHandle, sizeof(TAccountTable));
                pkPeer->Encode(pkTab, sizeof(TAccountTable));
                delete info;
        }
        else
        {
                pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
                delete info;
        }
        delete pkTab;
        return;
#else
        sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
        char szQuery[QUERY_MAX_LEN];
        snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index WHERE id=%u", r.id);
        CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
#endif

db/src/JSONDB.cpp

C++:
Genişlet Daralt Kopyala
#include "JSONDB.h"
#include <fstream>
#include <nlohmann/json.hpp>
#include <algorithm>
#include <cstring>

static nlohmann::json g_json;

bool JSONDB_Load(const std::string& path)
{
    std::ifstream f(path);
    if (!f.is_open())
        return false;
    f >> g_json;
    return true;
}

bool JSONDB_Save(const std::string& path)
{
    std::ofstream f(path);
    if (!f.is_open())
        return false;
    f << g_json.dump(4);
    return true;
}

bool JSONDB_FindAccount(const std::string& login, TAccountTable& out)
{
    if (!g_json.is_object() || !g_json.contains("accounts"))
        return false;
    auto& arr = g_json["accounts"];
    for (auto& acc : arr)
    {
        if (acc["login"].get<std::string>() == login)
        {
            memset(&out, 0, sizeof(TAccountTable));
            strlcpy(out.login, login.c_str(), sizeof(out.login));
            if (acc.contains("passwd"))
                strlcpy(out.passwd, acc["passwd"].get<std::string>().c_str(), sizeof(out.passwd));
            if (acc.contains("id"))
                out.id = acc["id"].get<int>();
            if (acc.contains("social_id"))
                strlcpy(out.social_id, acc["social_id"].get<std::string>().c_str(), sizeof(out.social_id));
            if (acc.contains("status"))
                strlcpy(out.status, acc["status"].get<std::string>().c_str(), sizeof(out.status));
            if (acc.contains("empire"))
                out.bEmpire = acc["empire"].get<int>();
            return true;
        }
    }
    return false;
}

JSONDB.h

C++:
Genişlet Daralt Kopyala
#ifndef JSONDB_H
#define JSONDB_H

#include <string>
#include "tables.h"

bool JSONDB_Load(const std::string& path);
bool JSONDB_Save(const std::string& path);
bool JSONDB_FindAccount(const std::string& login, TAccountTable& out);

#endif // JSONDB_H

Main.cpp aç ve includelara dahil et

Kod:
Genişlet Daralt Kopyala
#ifdef USE_JSON_DB
#include "JSONDB.h"
#endif

bul

C++:
Genişlet Daralt Kopyala
    CClientManager::instance().SetPlayerIDStart(1);

üstüne ekle

C++:
Genişlet Daralt Kopyala
#ifdef USE_JSON_DB
    if(!JSONDB_Load("../../players.json"))
        return false;
#else

Start kısmını bu şekilde modifiye et

Son hali bu şekilde görünmeli:
Genişlet Daralt Kopyala
int Start()
{
    fprintf(stderr, "Real Server\n");

    g_log = 1;
    fprintf(stderr, "Log On");

    log_set_expiration_days(3);
    thecore_init(50, emptybeat); // 50 = client heart beat
    signal_timer_enable(60);
#ifdef USE_JSON_DB
    if(!JSONDB_Load("../../players.json"))
        return false;
#else

    CClientManager::instance().SetPlayerIDStart(1);

    int iRetry = 5;
    do
    {
        if (CDBManager::instance().Connect(SQL_PLAYER, "localhost", 0, "player", "root", "aKc~tG!M3?5MF5#Y"))
        {
            sys_log(0, "   OK");
            break;
        }

        sys_log(0, "   failed, retrying in 5 seconds");
        fprintf(stderr, "   failed, retrying in 5 seconds");
        sleep(5);
    } while (iRetry--);
    fprintf(stderr, "Success PLAYER\n");

    iRetry = 5;
    do
    {
        if (CDBManager::instance().Connect(SQL_ACCOUNT, "localhost", 0, "account", "root", "aKc~tG!M3?5MF5#Y"))
        {
            sys_log(0, "   OK");
            break;

            sys_log(0, "   OK");
            break;
        }

        sys_log(0, "   failed, retrying in 5 seconds");
        fprintf(stderr, "   failed, retrying in 5 seconds");
        sleep(5);
    } while (iRetry--);
    fprintf(stderr, "Success COMMON\n");

    iRetry = 5;
    do
    {
        if (CDBManager::instance().Connect(SQL_HOTBACKUP, "localhost", 0, "hotbackup", "root", "aKc~tG!M3?5MF5#Y"))
        {
            sys_log(0, "   OK");
            break;
        }

        sys_log(0, "   failed, retrying in 5 seconds");
        fprintf(stderr, "   failed, retrying in 5 seconds");
        sleep(5);
    }
    while (iRetry--);
    fprintf(stderr, "Success HOTBACKUP\n");
#endif



Makefile kısmı

Makefile:
Genişlet Daralt Kopyala
CC = g++

OBJDIR = obj
$(shell if [ ! -d $(OBJDIR) ]; then mkdir $(OBJDIR); fi)

CFLAGS = -g -Wall -O2 -pipe -fno-rtti -fno-exceptions -pthread -D_THREAD_SAFE -mtune=i686
CFLAGS = -g -Wall -O2 -pipe -fno-rtti -fno-exceptions -pthread -D_THREAD_SAFE -mtune=i686[B] -DUSE_JSON_DB[/B]

INCDIR = -I../../boost -I../../libmysql/7.x-5.1.35
INCDIR = -I../../common -I../../../Extern/include/boost -I../../../Extern/include -I../../boost -I../../libmysql/7.x-5.1.35
LIBDIR = -L../../libthecore/lib -L../../libsql -L../../libpoly -L../../libgame/lib -L/usr/local/lib/mysql -L../../libmysql/7.x-5.1.35
LIBS = -lthecore -lmysqlclient -lsql -lpoly -lgame -lm -lz

TARGET = ../db

SRCS =    NetBase.cpp Peer.cpp PeerBase.cpp Main.cpp Lock.cpp DBManager.cpp \
        Cache.cpp LoginData.cpp ClientManager.cpp ClientManagerPlayer.cpp ClientManagerLogin.cpp \
        ClientManagerBoot.cpp ClientManagerParty.cpp ClientManagerGuild.cpp GuildManager.cpp HB.cpp \
        PrivManager.cpp MoneyLog.cpp ItemAwardManager.cpp ClientManagerEventFlag.cpp Marriage.cpp \
        BlockCountry.cpp ItemIDRangeManager.cpp ClientManagerHorseName.cpp version.cpp \
        ProtoReader.cpp CsvReader.cpp
        ProtoReader.cpp CsvReader.cpp [B]JSONDB.cpp[/B]

OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o)

default: $(TARGET)

$(TARGET): $(OBJS)
    @echo linking
    @$(CC) $(CFLAGS) $(LIBDIR) $(OBJS) $(LIBS) -o $(TARGET)
    @touch version.cpp

$(OBJDIR)/%.o: %.cpp
    @echo compile $<
    @$(CC) $(CFLAGS) $(INCDIR) -c $< -o $@

$(OBJDIR)/version.o: version.cpp
    @$(CC) $(CFLAGS) -D__USER__=\"$(USER)\" -D__HOSTNAME__=\"$(HOSTNAME)\" -D__PWD__=\"$(PWD)\" -c $< -o $@
    @echo compile $<

$(OBJDIR):
    @mkdir $(OBJDIR)

clean:
    @rm -f $(OBJS) ../db

dep:

players.json içeriği

JSON:
Genişlet Daralt Kopyala
{
  "accounts": [
    {
      "id": 1,
      "login": "test",
      "passwd": "pass",
      "social_id": "0000",
      "status": "OK",
      "empire": 1
    }
  ]
}

aç service.h definesini ekle

Kod:
Genişlet Daralt Kopyala
USE_JSON_DB
 
Uyarı: Bu konu açıldığından bu yana baya zaman geçmiş.
Muhtemelen daha fazla tartışma gerekli değildir ki bu durumda yeni bir konu başlatmayı öneririz. Eğer yine de cevabınızın gerekli olduğunu düşünüyorsanız buna rağmen cevap verebilirsiniz.
Geri
Üst