Skip to content

Jhobean/Source-X

 
 

Repository files navigation

SphereServer X

Ultima Online game server, developed in C++.

GitHub License     GitHub Repo size     GitHub Stars
Coverity Scan Build Status     GitHub Issues

Join the SphereServer Discord channel!
Discord Shield

Getting Started tutorial

If you're new to the Sphere server and want to set up your first shard, this is your go-to guide!

Releases

Core

Branch: Master
(most stable pre-releases)
Branch: Dev
(most recent, potentially unstable)
GitHub last commit on Master branch   Changelog GitHub last commit on Dev branch   Changelog
Nightly builds: Nightly builds:
Build status: Windows x86_64 Build status: Windows x86 Build status: Windows x86_64 Build status: Windows x86
Build status: Linux x86_64 Build status: Linux x86 Build status: Linux x86_64 Build status: Linux x86
Build status: macOS x86_64 Build status: macOS ARM Build status: macOS x86_64 Build status: macOS ARM

Click the badges or follow the links:

ScriptPack

The official script pack is fully compatible with X new syntax, has all the new X features and preserves legacy/classic systems, which can be activated back in place of the new ones.
It is currently being revamped to add original OSI features.
Beware, it's still not 100% complete!

Resources

Coming from a different SphereServer version?

  • From 0.56d? Here a list of major scripting changes!
  • From an older 0.55 or 0.56 version? This might help resuming major changes until 0.56d.

Why the fork?

This branch started in 2016 from a slow and radical rework of SphereServer 0.56d, while trying to preserve script compatibility with the starting branch. Though, something has changed script-wise, so we suggest to take a look here. Most notable changes (right now) are:

  • Bug fixes and heavy changing of some internal behaviours, with the aim to achieve truly better speed and stability;
  • Support for x86_64 (64 bits) and ARM architectures, Mac OSX builds, Clang and GCC Linux builds, MinGW compiler for Windows;
  • CMake is now the standard way to generate updated build and project files;
  • Switched from MySQL 5.x to MariaDB client;
  • Added (and still adding) comments to the code to make it more understandable;
  • Reorganization of directories and files, avoiding big files with thousands of lines;
  • Code refactoring, updating to most recent programming standards and to the conventions described below.

Running

Required libraries (Windows)

  • libmariadb.dll (MariaDB Client v10.* package), found in lib/bin/*cpu_architecture*/mariadb/libmariadb.dll

Required libraries (Linux)

  • MariaDB Client library. Get it from the following sources.
    • From MariaDB website
      See https://mariadb.com/docs/skysql/connect/clients/mariadb-client/
    • Ubuntu and Debian repositories
      Ubuntu: Enable "universe" repository: sudo add-apt-repository universe
      Install MariaDB client: sudo apt-get install mariadb-client or sudo apt-get install libmariadb3 (depends on the OS version)
    • CentOS - Red Hat Enterprise Linux - Fedora repositories
      Then install MariaDB client via yum (CentOS or RH) or dnf (Fedora): mariadb-connector-c

Required libraries (MacOS)

  • Install MariaDB Client library via brew install mariadb-connector-c

Building the server from the source

Generating the project files

Only recent compilers are supported, since Sphere uses C++20 features: the newer the compiler, the better. Oldest compiler versions supporting C++20: Visual Studio 2019 version 16.11, GCC 8, MinGW distributions using GCC 8, Clang version 10.
No pre-built project files are included. You need to build Visual Studio solution (.sln), Makefiles or Ninja Build files (or project files for other IDE or build systems) with CMake.
Below there is a small guide.
You can use CMake GUI (graphical interface) or its CLI (command line interface).
To pass a flag to using the CLI, just prepend -D to the name of the variable, then assign the value with the equal sign, eg: -DFOO=TRUE.

Before starting: does CMake give you an error? Ensure that you have Git installed, and if you are on Windows ensure also that the Git executable was added to the PATH environmental variable (you'll need to add it manually if you are using Git Desktop, here's a quick guide).

  • Select a Generator
    Tells CMake which kind of project file to generate (Visual Studio, makefile, ninja build file...)

    • GUI: it's the first thing CMake will ask you (well, after Sphere source directory)
    • CLI: use -G flag, example: -G "Visual Studio 17 2022" or -G Ninja.
  • Select a Toolchain
    When generating project files, the easiest way is to use the provided OS-specific CMake toolchain file to automatically pass the right options to the selected compiler.
    You can find them in the cmake/toolchains/ folder.
    If you don't specify a toolchain, CMake will pick the native one as default.
    How to set a toolchain:

    • Via CMake GUI: when configuring for the first time the project, choose "Specify toolchain file for cross-compiling", then on the next step you'll be allowed to select the toolchain file.
    • Via CMake CLI (command line interface): pass the parameter -DCMAKE_TOOLCHAIN_FILE="..."
  • Build Configuration (type)
    When using Makefiles or Ninja, you can specify a build type by setting (also this via GUI or CLI) CMAKE_BUILD_TYPE="build", where build is Nightly, Debug or Release. If the build type was not set, by default the makefiles for all three build types are generated.
    Debug build is expected to be slow, and it's to be used, you guessed it, for debugging purposes (best coupled with a debugger or with sanitizers enabled, more on them right below), so don't use it for a live shard!

Other useful CMake flags:

  • You can add other compiler flags with the custom variables C_FLAGS_EXTRA, CXX_FLAGS_EXTRA, CMAKE_EXE_LINKER_FLAGS_EXTRA.
  • Enable Sanitizers: USE_ASAN[=ON], USE_UBSAN, USE_LSAN, etc. If you are using Address Sanitizer, Undefined Behaviour Sanitizer, Leak Sanitizer on Windows, it might be useful to redirect stderr to stdout to correctly show the output: SphereSvrX64_nightly > Sphere_ASan_log.txt 2>&1. Remember to set up Sanitizers settings by setting the respective shell variables. To ease this, there are some batch/shell scripts doing that for you inside utilities/.
  • CROSSCOMPILING_ARCH: set this to TRUE to tell the compiler you are building binary files for a different architecture (not from x86_64 to x86, but for example from x86 to ARM).

Example to build makefiles on Linux for a 64 bits Nightly version, inside the "build" directory (run the command inside the project's root folder):

mkdir build
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/Linux-GNU-x86_64.cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Nightly" -B ./build -S ./

Compiling

Installing the required packages on Linux

Building will require more packages than the ones needed to run Sphere.

  • Ubuntu and Debian
    Install these additional packages:

    • Build tools (other than the compiler): sudo apt-get install git cmake.
    • MariaDB client: sudo apt-get install libmariadb-dev and libmariadb3 or mariadb-client (depends on the OS version)
      If you are on a 64 bits architecture, but you want to compile (or execute) a 32 bits binary, you will need to install MariaDB packages adding the postfix :i386 to each package name.
  • CentOS - Red Hat Enterprise Linux - Fedora Install these additional packages via yum (CentOS or RH) or dnf (Fedora).

    • Build tools (other than the compiler): git cmake glibc-devel
    • MariaDB client: mariadb-connector-c mariadb-connector-c-devel
      If you are on a 64 bits architecture, but you want to compile (or execute) a 32 bits binary, you will need to install MariaDB packages adding the postfix .i686 to each package name.

Compiling on Linux

Just run cmake --build . in the build directory (the one where you have asked CMake to create its files).

Debian package

Debian package is an installation package for Linux Debian and its derivates (Ubuntu, Linux Mint, etc.) and intended to be run as a service. Folder structure is as follows:

  • Binary is located in /usr/bin/ directory (use which sphereserver to locate it).
  • Configuration files (ini) are in /etc/sphereserver/ directory.
  • Log files are stored in /var/log/sphereserver/ directory.
  • Everything else is in /opt/sphereserver/.

These paths are automatically replaced in sphere.ini during installation.

Build

Building deb package is pretty straightforward. The requirements are the same, as you would compile code by hand. One extra requirement is debhelper package (sudo apt install debhelper).

Step by step building:

  1. Clone repository.
  2. Change directory to wherever you cloned repository and then go to packaging directory.
  3. Since we are in nightly, there is no actual SemVer changelog that we can include, and we have to use workaround to generate one. By running cat debian/data/changelog | sed -e "s/@version@/$(git rev-list --count HEAD)/" -e "s/@date@/$(date -R)/" > debian/changelog you will generate one. This command takes deb changelog template (in debian/data/changelog) and replaces version and date variables with git revision and current date.
  4. Build package by running dpkg-buildpackage -us -uc -b (arguments are -b = build, -us and -uc = don't sign built files with OpenPGP key). This will compile sources and create debian package, which will be stored in the root of the project directory (i.e. /home/dev/source-x/). The cmake is predefined to build a Linux x86_64 Nightly version of SphereServer. All build commands and switches are defined in debian/rules file.

Installation

When you download or build the package, you have to make it executable sudo chmod +x FILENAME.deb. Then you can install the package by running sudo apt install FILENAME.deb. The installation process will download required dependencies, show you some info about SphereServer being in nightly version, create an owner game account (admin/admin), create dedicated linux user sphereserver, directory structure and service files for you.

After installation, you will have to provide mul files and scripts to /opt/sphereserver/mul/ and/opt/sphereserver/scripts/ folder and AGREE=1 in sphere.ini.

When you are finished with configuration, you can enable/start services by running sudo systemctl enable sphereserver and sudo systemctl start sphereserver. To check, if service is running, type systemctl status sphereserver, check the journal (journalctl -u sphereserver) or sphere logs.

Updating

Updating is the same as installation, download / build package, run sudo chmod +x FILENAME.deb and sudo apt install FILENAME.deb. If any changes happened in ini files and are in conflict with your settings, you will be asked to review them.

Removal

To remove sphereserver, run sudo apt remove sphereserver and sudo apt remove sphereserver --purge. All files related to sphereserver will be deleted.

Coding Notes (add as you wish to standardize the coding for new contributors)

  • Make sure you can compile and run the program before pushing a commit.
  • Rebasing instead of pulling the project is a better practice to avoid unnecessary "merge branch master" commits.
  • Removing/Changing/Adding anything that was working in one way for years should be followed by an ini setting if the changes cannot be replicated from script to keep some backwards compatibility.
  • Comment your code, add information about its logic. It's very important since it helps others to understand your work.
  • Be sure to use Sphere's custom datatypes and the string formatting macros described in src/common/datatypes.h.
  • When casting numeric data types, always prefer C-style casts, like (int), to C++ static_cast<int>(). It's way more concise.
  • Be wary that in SphereScript unsigned values does not exist, all numbers are considered signed, and that 64 bits integers meant to be printed to or retrieved by scripts should always be signed.
  • Don't use "long" except if you know why do you actually need it. Always prefer "int" or "llong". Use fixed width variables only for values that need to fit a limited range.
  • For strings, use pointers:
    to "char" for strings that should always have ASCII encoding;
    to "tchar" for strings that may be ASCII or Unicode, depending on compilation settings (more info in "datatypes.h");
    to "wchar" for string that should always have Unicode encoding.

Naming Conventions

These are meant to be applied to new code and, if there's some old code not following them, it would be nice to update it.

  • Pointer variables should have as first prefix "p".
  • Unsigned variables should have as first (or second to "p") prefix "u".
  • Boolean variables should have the prefix "f" (it stands for flag).
  • Classes need to have the first letter uppercase and the prefix "C".
  • Private or protected methods (functions) and members (variables) of a class or struct need to have the prefix "_". This is a new convention, the old one used the "m_" prefix for the members.
  • Constants (static const class members, to be preferred to preprocessor macros) should have the prefix "k".
  • After the prefix, the descriptive name should begin with an upper letter.

Variables meant to hold numerical values:

  • For char, short, int, long, llong, use the prefix: "i" (stands for integer).
  • For byte, word and dword use respectively the prefixes: "b", "w", "dw". Do not add the unsigned prefix.
  • For float and double, use the prefix: "r" (stands for real number).

Variables meant to hold characters (also strings):

  • For char, wchar, tchar use respectively the prefixes "c", "wc", "tc".
  • When handling strings, "lpstr", "lpcstr", "lpwstr", "lpcwstr", "lptstr", "lpctstr" data types are preferred aliases.
    You'll find a lot of "psz" prefixes for strings: the reason is that in the past Sphere coders wanted to be consistent with Microsoft's Hungarian Notation.
    The correct and up-to-date notation is "pc" for lpstr/lpcstr (which are respectively charand const char), "pwc" (wcharand const wchar), "ptc" for lptstr/lpctstr (tcharand const tchar).
    Use the "s" or "ps" (if pointer) when using CString or std::string. Always prefer CString over std::string, unless in your case there are obvious advantages for using the latter.

Examples:

  • Class or Struct: "CChar".
  • Class internal variable, signed integer: "_iAmount".
  • Tchar pointer: "ptcName".
  • Dword: "dwUID".

Coding Style Conventions

  • Indent with spaces of size 4.

  • Use the Allman indentation style:
    while (x == y)
    {
        something();
        somethingelse();
    }

  • Even if a single statement follows the if/else/while... clauses, use the brackets:
    if (fTrue)
    {
        g_Log.EventWarn("True!\n");
    }

Licensing

Copyright 2025 SphereServer development team.

Licensed under the Apache License, Version 2.0 (the "License").
You may not use any file of this project except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 62.6%
  • C++ 36.4%
  • CMake 1.0%
  • Shell 0.0%
  • Makefile 0.0%
  • Batchfile 0.0%