Four cores brought to one shape. TERRAIN. src/shared/terrain in all four behind the TerrainInfo seam, and no src/game/vmap anywhere: one baked tile carries ground, liquid, area and collision together. The seam is load-bearing -- the moment the engine learns what a zone is, it can no longer live in shared. A hull has surfaces stacked at one (x, y), so the query is a Column, not a height. SPATIAL. An object no longer owns coordinates: it HAS a Geometry::Placement, read through Where() and mutated through Place(). A placement carries the FRAME it is in, and a cross-frame answer fails closed -- so "same map AND in range" cannot be written wrong, because it is one question. Ground height, line of sight and the free-spot sweep were never geometry and became free functions beside it. MOVEMENT. A generator states an INTENT -- where the mover wants to be -- and a driver realises it. The two were one thing before, so every generator knew how movement is executed and none could be reasoned about alone. An intent resolves in the mover's OWN frame, so chase, follow and a random walk on a deck are computed in deck coordinates without the caller knowing there is a deck, and the pathfinder is handed the map it routes on rather than assuming the world's. TRANSPORTS. The vessel IS a map. A ship's hull is baked as its own map with its own terrain, so a passenger stands on real ground rather than on an offset, and deck-local is the only coordinate system aboard. The server's estimate of a hull's world position is used for one thing only -- finding observers ashore -- and never composed into anything. SD3. The scripts moved onto Where()/Place() and the free functions beside them, so the old coordinate-owning API is not compiled at all in an SD3 build. What remains of the compatibility layer exists for Eluna alone. dep, realmd and SD3 all point at merged upstream. EXTRACTORS. One baker per core, from the client to the caches the server reads, with a Windows GUI in front of it: checkboxes per component, folder and file pickers, a live log. It drives the console tool through its command line and links none of it. Cataclysm's split ADT and its MPQ patch chain are read properly; every core's output is scored against the world database's own ground spawns, 97-99% within two yards. ALSO. Off-thread logging and one startup console. The src/proto network seam, enforced at build time -- game links proto, proto reaches neither game nor the database. C++17 throughout, ACE and G3D gone. One test harness, socket tests behind their own switch. Layout, CI and ignore rules identical across the four. Built with both script engines on GCC, Clang and MSVC. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
5.4 KiB
Coding standards
It is highly recommended to use a single coding style for the whole project source code. Exceptions are allowed for external libraries used in the project, but it is generally advisable all contributors to use this style.
Tab Size
First of all, we use spaces. Tabs are four-character width. That is, no 8-space tabs, no 2-space tabs. Four. Unfortunately there's no such thing as 'standard tab width', and 4-space indenting looks best from our point of view, besides MSVC' editor has this setting by default.
Line length
Then, please use 80-character wide lines. If your line is way longer than that, please split it. If it's just a little longer, so be it. The continuation text, if you're splitting text inside the brackets, should be indented to the position after the opening bracket:
printf("This is a example of how we split lines longer than %d characters\n"
"into several so that they won't exceed this limit.\n",
max_sourcecode_width);
If you have long strings, you can split them as shown above, just remember that C/C++ compilers will glue together several strings that come without any special characters between them into one.
Brackets
Now we use symmetric bracket placement, closing bracket under the opening bracket:
if (something)
{
...;
}
else
{
...;
}
switch (x)
{
case 1:
{
printf("X is one!\n");
break;
}
case 2:
{
printf("X is two!\n");
break;
}
}
for (int i = 1; i < 3; ++i)
{
printf("I is %i!\n", i);
}
Every bracketed block moves its contents by one tab to the right. Labels (but not case selectors or 'public:/private:/protected' C++ keywords) are placed at the leftmost indentation position for the current block, that is, in the same position where enclosing brackets are.
Also use brackets around a single statement because it helps clarify usage to newer coders, like:
if (...)
{
if (...)
{
...;
}
}
else
{
...;
}
Also, please place one space before opening parenthesis. Before, but not after
(the if ( blah ) style is a no-no!).
Inline functions
Inline functions must use the same symmetric bracket placement as any other function, even when the body contains only a single statement.
bool isArena() const
{
return m_IsArena;
}
Do not write function, method, constructor, or destructor bodies on the same line as the declaration.
Incorrect:
~GroupReference() { unlink(); }
GroupReference const* next() const { return (GroupReference const*)Reference<Group, Player>::next(); }
Correct:
~GroupReference()
{
unlink();
}
GroupReference const* next() const
{
return (GroupReference const*)Reference<Group, Player>::next();
}
Class declaration and constructors
Here is an example:
class Class : public Parent
{
public:
Class() : Parent(0),
m_field(1)
{
func();
}
void func() {}
private:
int m_field;
};
Please follow the following rules for classes:
- space before and after : in class parents list and constructor body
- next line and indent for class field initialization list
- indent for public:/private:/protected: section with additional indent for section content
- function bodies must start on the next line, even for short in-class definitions
Code documentation with Doxygen
Now, please use DoxyGen-type comments. This is a bit similar to JavaDoc comments
and to other automatic code documentation generation tools. One-line documentation
should be placed in /// (three slashes) comments if the comment is above the
function/member, if you want the comment on the same line you should use ///<
instead, multi-line comments should be put in a /** ... */ block (slash-two-stars).
Here's a example that shows most useful keywords that you can use in a comment block:
/**
* This function does something very useful. If used with care, this function
* has the potential to make your programs really really useful.
*
* \arg \c x
* The x argument specifies a integer that is transformed into something useful.
* \arg \c y
* This argument, if not NULL, is a pointer to a free memory area where this
* function will put something really really useful.
* \return
* A useful value, or NULL if error.
*
* Here is a example that you can paste into your code so that it saves you a
* lot of typing:
*
* \verb atim (Remove the space)
* for (int x = 0; x < 100; ++x)
* printf("DoSomethingUseful%d = %s\n", i,
* DoSomethingUseful(i, &ScratchPad));
* \endve rbatim (Remove the space)
*
* Paragraphs are split from each other by inserting a empty line. Also some HTML
* tags are supported, like <ol> [<li>...] </ol> and <ul> [<li>...] </ul> for
* ordered (numbered) and unordered (dotted) lists respectively.
*/
char *DoSomethingUseful(int x, void *y);
/// This is a one-line comment
void Something();
Use normal comments like // and /* ... */ only if you want to make a comment
that should not go into the automatically annotated code (like:
/* shit ... this does not work */).