1
\$\begingroup\$

I've searched for it, but I couldn't find any question about this.

I'm working on a game where PvP fights are possible. The game is written in PHP/MySQL.

What I want to implement is to save all the actions of users in the fight (hits, misses, critical hits etc.).

However, I couldn't decide how and where to keep them. As an array, xml file, in json format; in a log file, in the database or in a separate cookie? Which way is the best practice?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

If you're using MySQL as your persistence layer, I don't see any reason why you wouldn't keep your combat logs there.

The amount of sense that your listed options make goes about like this:

  • Array: 0% (array in what? "array" is a data structure, not a persistence mechanism)
  • XML file: 50%
  • JSON file: 30%
  • Log file: 20% (have fun finding the records you want again)
  • Database: 100%
  • Cookie: -1000% (!?!?)
\$\endgroup\$
9
  • \$\begingroup\$ Thank you for quick response. I'm also thinking about keeping it in the database, but what I intend to ask is the way to keep it. I mean, whether keep them in single rows in the database or storing it in a serialized array or json format? \$\endgroup\$
    – Chris Ford
    May 29, 2012 at 22:28
  • \$\begingroup\$ More details are needed, like can you attack more than one person? What makes a battle a finished battle? If you are just going against one enemy at a time, you could save each new battle as a new row in your database. From there it depends what you want to save, you will probably will need a second database to keep records of your attacks, and then a third to link them up. I can do a small diagram if you give me the details at the top \$\endgroup\$
    – bitbitbot
    May 29, 2012 at 22:50
  • 1
    \$\begingroup\$ @ChrisFord JSON is a data exchange format, as is, for example, XML. Sure you can persistently save your strings of battle messages in JSON or XML format, but that makes zero sense if you want to save them to a database, as it pretty much invalidates the point of a relational data base. And "a serialized array" still makes no sense, for starters because an array IS a serialized object to begin with. Long story short: if you store data in a relational DB, you store only the raw data. Any relations between your data are stored as separate fields, not as some huge data blob. \$\endgroup\$
    – Hackworth
    May 29, 2012 at 22:54
  • \$\begingroup\$ @bitbitbot You will attack only one player; simple PvP system. When one of the player's health is below 0, the battle will end. Actually, what I want to ask is about performance, because there will be 500+ online players who will play at the same time. \$\endgroup\$
    – Chris Ford
    May 29, 2012 at 22:54
  • \$\begingroup\$ @ChrisFord: Hackworth is mostly right, except about "serialized array" (Hackworth, by that term he means the string result of passing an array through PHP serialize()). Basically, if the only purpose your storage of this combat will ever have is to visually display it like in your example link, then you could maybe store it as some kind of data blob (filesystem is better for those than DB; still kinda disgusting). But since you'll eventually want to do things like generate statistics on your combats, you should work up DB tables that actually usefully represent the combat events. \$\endgroup\$
    – chaos
    May 29, 2012 at 23:02
1
\$\begingroup\$

Where to keep that kind of data is obvious: use a database. How to keep it depends on a number of factors. Here are some use cases that come to mind:

Scenario 1: You only have to be able to reprint rendered combat messages

In this case, you could actually save strings in your database:

table combatmessages
    id
    combat_id
    combatant_id
    message

You can think of message as a cached version of an already rendered combat message. If reprinting rendered combat messages is all you want, this allows you to skip the rendering process, which makes data retrieval and processing very fast. The downside is that reprinting combat messages is really ALL you can do. (Unless you want to process the message, which would be insane.) Also, you have to store each message twice, for it reads differently for the two players involved in a battle.

Scenario 2: You want to access battle actions to calculate things

In this case, the structure of your database will be more complicated, for it has to represent combat action data, not just some lousy string. On the plus side, you can actually do interesting stuff with it. The design of your database will depend on what kind of stuff you want to do, and on how complex your battles are. If you are only talking about 500 or so players playing at the same time, I'd suggest to err on the side of flexibility and just store every bit of information that you can.

In order to store battle actions and events like the ones you posted, a table structure like this might suffice:

table battle
    id
    combatant1_id
    combatant2_id
    winner_id
    combatant1_startHP (in order to be able to calculate remaining HPs in messages)
    combatant2_startHP

table battlelog
    id
    battle_id
    turn (if your combat system makes use of turns)
    subject_id (null if there is no actor or receiver of this battle message, 
                e.g. if it's a global message to both combatants)
    action_id (or action enum ('attack','backstab','missile'), if there is only 
               a limited, predefined set of possible actions. 
               null if the record stores an event that is not the direct result of an action)
    target_id (null if there is no target)
    resultHit enum('miss', 'hit', 'critical hit', null)
    resultDamage int
    resultWound bool (or enum if there are several types of wounds)
    resultSkillImprovement_skill_id
    resultSkillImprovement_points int

Note that storing combat data instead of rendered battle messages is also necessary if you want to be able to render battle messages in different ways, for example by using different message templates in different contexts. Another advantage is that you don't have to save battle messages twice anymore; one battlelog record provides enough information to render battlelog messages for both players.

Note also that this design is a trade-off between a simple table structure and easy data storage/retrieval on the one hand and high data efficiency and level of normalization on the other. If your game knows 200 different results of battle events, then storing 199 null values in each battlelog record would no longer be the preferred route to take.

\$\endgroup\$
1
  • \$\begingroup\$ I like this analysis of the two approaches. I do just want to note that the "action_enum" concept sounds a little... ...short sighted, and should probably be avoided. I think that at first it's obvious there will only be X limited, predefined set of possible actions... ...until that day you add X+1, and then add X+2. As it is said, with computers there is only 0, 1, Infinity. \$\endgroup\$
    – Kzqai
    Aug 18, 2015 at 13:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .