JSON ile oyuncu bilgilerini depolamak

isthambul1453

Premium Üye
Premium Üye
Üye
Mesaj
78
Beğeni
54
Puan
331
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

Linkleri görebilmek için giriş yap veya kayıt ol.


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
 
Geri
Üst