There's a reason why there's a HUGE team behind any game project or reverse engineering project xD
A huge amount of data is always stored in a database, and it doesn't really matter what kind of database it is as long you are making the correct relationship between them. (RDBMS - MySQL, SQL Server, etc). When you are thinking about getting and setting the data, you must think of how the relation between object is (what objects are related and constraint by other object).
Data => Database, as always (MySQL, SQL Server, etc.).
Classes, structures: Objects like Account, Character, Guild, Party.
What you need in those classes and structures? Answer is attributes, like specific things associated with that class. (Car => wheels, brand, model, color, engine, etc).
A fast example of classes in C++ that I've made:
C++:
class Account
{
string username;
string password; // Hashed/encrypted
std::list<Character*> character_list; // List of characters associated with this accounts
...
// Everything related to account can go in here.
}
class Items
{
int item_unique_id;
string item_name;
int inv_posX;
int inv_posY;
int sizeX;
int sizeY;
bool accountBound;
bool characterBound;
int damage;
int defence;
int magic_damage;
int magic_defense;
int critical_dmg;
int magic_critical_dmg;
int accuracy;
int reqStr;
int reqDex;
int reqVit;
int reqInt;
...
// The list can go on.
}
class Inventory
{
std::list<Items*> inventory_items;
...
//Other methods to get the items, search for them, add, delete, etc.
}
class Character
{
int character_id;
string character_name;
Inventory * character_inventory;
...
//Everything related to character is here.
}
Now, related to Opcodes and packets:
First, you need to receive the packets and make sure you are decrypting them correctly, also make sure you are encrypting them correctly before sending them to the client.
Most of the things can be solved using OOP (Object Oriented Programming - my suggestion is to learn it if you don't know it - learning while doing the project is the best learning method which is gonna give you faster results) which is making the life much much much more easier when developing a server emulator.
C++:
struct Packet
{
byte *head; // opcode
byte *data; // packet data
u16 size; // the size of packet sent by client (not the one received in the socket)
...
// Any packet related methods in this structure
}
The game logic is based on what you know about the game + your findings in your reverse engineering process + intuitive actions in the client.
You need to make a function for each one of the opcode (the game logic), then you upgrade them as you go with what you need to complete the game logic functionality.
The first opcodes probably are for login:
Recv login packet -> Decrypt it -> Get the opcode and handle it -> Pass the Packet object as parameter for the login function (Login(&Packet)) -> Retrieve from the DB the username and password or the data necessarily to be checked on login -> Check the data retrieved from DB with the data from the packet to be correct -> If the data is correct send a new packet to the client telling that the login was successful and the client can continue, then the next packet will be send from the client, and this process repeats.
This is just a small portion of what I can actually write about this subject, but I will stop here cause I think you can get the idea from these examples.
My advice is to learn OOP. It's gonna be helpful. Don't hurry with anything. Take your time and make your best architecture and design by observing what you find in the reversed client. Just write down how things should follow one another in the game logic and document anything you find.