• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 0.X build and run 0.4 in docker container

fitorey

New Member
Joined
Mar 9, 2025
Messages
8
Reaction score
2
i don't know how to make 0.4 able to build on debian 12 / new ubuntus
the only one who manage to do it in pass was @Gesior.pl

idk a lot about docker, but is this possible to make build and run a server 0.4 on docker with this sources for example:
???

i mean until it becomes compatible with new ubuntus/debians
 
I think you might be able to compile if you do this:

  • change OTSYS_TIME:
C++:
inline int64_t OTSYS_TIME()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    return static_cast<int64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}

  • at every file that complains about boost you add the define below above the include <boost...>. In your case I think it would be on /home/fito/Documents/otserver/3777/src/otpch.h:35 file
    C++:
    #define BOOST_BIND_GLOBAL_PLACEHOLDERS

Paste new errors here.
 
I think you might be able to compile if you do this:

  • change OTSYS_TIME:
C++:
inline int64_t OTSYS_TIME()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    return static_cast<int64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}

  • at every file that complains about boost you add the define below above the include <boost...>. In your case I think it would be on /home/fito/Documents/otserver/3777/src/otpch.h:35 file
    C++:
    #define BOOST_BIND_GLOBAL_PLACEHOLDERS

Paste new errors here.

LOL even better if i could build and run on new debians/ubuntus...

So just to confirm i have to change:

otpch.h
Code:
////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////
#ifdef __OTPCH__
#error "Precompiled header should be included only once."
#endif
#define __OTPCH__
#if defined WINDOWS
#include <winerror.h>
#endif
//libxml
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/threads.h>
//boost
#include <boost/config.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/regex.hpp>
#include <boost/tokenizer.hpp>
//otserv
#include "thing.h"

to:
Code:
////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////
#ifdef __OTPCH__
#error "Precompiled header should be included only once."
#endif
#define __OTPCH__
#if defined WINDOWS
#include <winerror.h>
#endif
//libxml
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/threads.h>
//boost
#include <boost/config.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/regex.hpp>
#include <boost/tokenizer.hpp>
// godoyxd suggestion to build on debian 12
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
//otserv
#include "thing.h"

and i also have to change file otsystem.h
from:
Code:
inline int64_t OTSYS_TIME()
{
    timeb t;
    ftime(&t);
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}

to:
Code:
// godoyxd suggestion to build on debian 12
inline int64_t OTSYS_TIME()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return static_cast<int64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
}
 
I compiled this one GitHub - otland/tfs-old-svn at r3777 (https://github.com/otland/tfs-old-svn/tree/r3777) on ubuntu 24.04.
It might have bugs, but at least it compiles and can be executed.

bash commands (you can create a Dockerifle with them)
Code:
apt-get update && apt-get -y full-upgrade

apt-get install -y git cmake build-essential libluajit-5.1-dev libmariadb-dev-compat libboost-date-time-dev libboost-system-dev libboost-iostreams-dev libpugixml-dev libcrypto++-dev libfmt-dev zlib1g-dev libxml2-dev python3 python3.12-venv ninja-build pkg-config libgmp3-dev libsqlite3-dev autoconf libboost-all-dev libboost-thread-dev lua-sql-sqlite3-dev lua-sql-sqlite3 lua5.1 liblua5.1-0 liblua5.1-0-dev

./configure --enable-sqlite --enable-mysql --enable-root-permission --enable-server-diag

./build.sh


You can clone the tfs-old-svn above and change to r3777 tag, then apply the patch below with "git apply <name of the file>"
changes.patch:
Code:
diff --git a/chat.cpp b/chat.cpp
index c6a69cbc..63eb7931 100644
--- a/chat.cpp
+++ b/chat.cpp
@@ -1141,7 +1141,7 @@ ChatChannel* Chat::getChannel(Player* player, uint16_t channelId)
     std::clog << "Chat::getChannel - getChannel id " << channelId << std::endl;
     #endif
     if(!player || player->isRemoved())
-        return false;
+        return NULL;
 
     if(channelId == CHANNEL_GUILD)
     {
diff --git a/configure.ac b/configure.ac
index 83209ade..00097d5c 100755
--- a/configure.ac
+++ b/configure.ac
@@ -199,7 +199,7 @@ AC_CHECK_LIB(boost_filesystem-gcc-mt, main, , [
 AC_CHECK_HEADERS([boost/asio.hpp], , [AC_MSG_ERROR("boost::asio header not found.")])
 
 # check for boost::unordered_set
-AC_CHECK_HEADERS([boost/tr1/unordered_set.hpp], , [AC_MSG_ERROR("boost::unordered_set header not found.")])
+#AC_CHECK_HEADERS([boost/tr1/unordered_set.hpp], , [AC_MSG_ERROR("boost::unordered_set header not found.")])
 
 # check for Crypto++
 AC_CHECK_HEADERS([cryptopp/sha.h cryptopp/md5.h cryptopp/adler32.h cryptopp/hex.h cryptopp/base64.h cryptopp/hmac.h cryptopp/cryptlib.h], , [AC_MSG_ERROR("Required Crypto++ headers not found.")])
diff --git a/connection.h b/connection.h
index 42874baf..c83938c5 100644
--- a/connection.h
+++ b/connection.h
@@ -90,8 +90,8 @@ class ConnectionManager
 class Connection : public boost::enable_shared_from_this<Connection>, boost::noncopyable
 {
     public:
-        enum {writeTimeout = 30};
-        enum {readTimeout = 30};
+        static constexpr int writeTimeout = 30;
+        static constexpr int readTimeout = 30;
 
         enum ConnectionState_t
         {
diff --git a/game.cpp b/game.cpp
index dee2cf0e..fc6a50e6 100644
--- a/game.cpp
+++ b/game.cpp
@@ -15,6 +15,7 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ////////////////////////////////////////////////////////////////////////
 #include "otpch.h"
+#include "tools.h"
 #include "game.h"
 
 #include "configmanager.h"
@@ -1722,7 +1723,7 @@ Item* Game::findItemOfType(Cylinder* cylinder, uint16_t itemId,
     bool depthSearch /*= true*/, int32_t subType /*= -1*/)
 {
     if(!cylinder)
-        return false;
+        return NULL;
 
     std::list<Container*> listContainer;
     Container* tmpContainer = NULL;
@@ -5345,7 +5346,7 @@ Position Game::getClosestFreeTile(Creature* creature, Position pos, bool extende
         relList.push_back(PositionPair(2, 0));
     }
 
-    std::random_shuffle(relList.begin() + 1, relList.end());
+    std::shuffle(relList.begin() + 1, relList.end(), getRandomGenerator());
     if(Player* player = creature->getPlayer())
     {
         for(PairVector::iterator it = relList.begin(); it != relList.end(); ++it)
diff --git a/game.h b/game.h
index 5d3bd7d7..64b6bd1f 100644
--- a/game.h
+++ b/game.h
@@ -669,7 +669,7 @@ class Game
         int32_t lastMotdId;
         uint32_t playersRecord;
         uint32_t checkLightEvent, checkCreatureEvent, checkDecayEvent, saveEvent;
-        bool globalSaveMessage[2];
+        bool globalSaveMessage[3];
 
         RefreshTiles refreshTiles;
         Trash trash;
diff --git a/house.h b/house.h
index 86dc0ac7..64630901 100644
--- a/house.h
+++ b/house.h
@@ -20,7 +20,7 @@
 #include "otsystem.h"
 
 #include <boost/regex.hpp>
-#include <boost/tr1/unordered_set.hpp>
+#include <unordered_set>
 
 #include "position.h"
 #include "housetile.h"
@@ -73,7 +73,7 @@ class AccessList
         void getList(std::string& _list) const;
 
     private:
-        typedef std::tr1::unordered_set<uint32_t> PlayerList;
+        typedef std::unordered_set<uint32_t> PlayerList;
         typedef std::list<std::pair<uint32_t, int32_t> > GuildList;
         typedef std::list<std::string> ExpressionList;
         typedef std::list<std::pair<boost::regex, bool> > RegexList;
diff --git a/item.cpp b/item.cpp
index 45522aad..1aba4d3b 100644
--- a/item.cpp
+++ b/item.cpp
@@ -629,6 +629,7 @@ Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream)
 
             if(ret)
                 break;
+            [[fallthrough]];
         }
 
         default:
diff --git a/luascript.cpp b/luascript.cpp
index ffb0cc00..d049bc20 100644
--- a/luascript.cpp
+++ b/luascript.cpp
@@ -738,7 +738,7 @@ bool LuaInterface::loadDirectory(const std::string& dir, Npc* npc/* = NULL*/)
     StringVec files;
     for(boost::filesystem::directory_iterator it(dir), end; it != end; ++it)
     {
-        std::string s = it->leaf();
+        std::string s = it->path().filename().string();
         if(!boost::filesystem::is_directory(it->status()) && (s.size() > 4 ? s.substr(s.size() - 4) : "") == ".lua")
             files.push_back(s);
     }
@@ -9183,9 +9183,9 @@ int32_t LuaInterface::luaGetTownName(lua_State* L)
 int32_t LuaInterface::luaGetTownTemplePosition(lua_State* L)
 {
     //getTownTemplePosition(townId)
-    bool displayError = true;
+    //bool displayError = true;
     if(lua_gettop(L) >= 2)
-        displayError = popNumber(L);
+        popNumber(L);
 
     uint32_t townId = popNumber(L);
     if(Town* town = Towns::getInstance()->getTown(townId))
diff --git a/manager.cpp b/manager.cpp
index 63959420..dafaf0bb 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -252,6 +252,7 @@ void ProtocolManager::parsePacket(NetworkMessage& msg)
                 output->put<char>(MP_MSG_FAILURE);
                 output->putString("Player not found");
             }
+            break;
         }
 
         case MP_MSG_CHAT_REQUEST:
diff --git a/map.cpp b/map.cpp
index 6a486453..195c2d21 100644
--- a/map.cpp
+++ b/map.cpp
@@ -20,6 +20,7 @@
 #include <boost/config.hpp>
 #include <boost/bind.hpp>
 
+#include "tools.h"
 #include "iomap.h"
 #include "map.h"
 #include "tile.h"
@@ -202,7 +203,7 @@ bool Map::placeCreature(const Position& centerPos, Creature* creature, bool exte
         relList.push_back(PositionPair(0, -2));
         relList.push_back(PositionPair(0, 2));
         relList.push_back(PositionPair(2, 0));
-        std::random_shuffle(relList.begin(), relList.end());
+        std::shuffle(relList.begin(), relList.end(), getRandomGenerator());
     }
 
     relList.push_back(PositionPair(-1, -1));
@@ -213,7 +214,7 @@ bool Map::placeCreature(const Position& centerPos, Creature* creature, bool exte
     relList.push_back(PositionPair(1, -1));
     relList.push_back(PositionPair(1, 0));
     relList.push_back(PositionPair(1, 1));
-    std::random_shuffle(relList.begin() + shufflePos, relList.end());
+    std::shuffle(relList.begin() + shufflePos, relList.end(), getRandomGenerator());
 
     uint32_t radius = 1;
     Position tryPos;
diff --git a/map.h b/map.h
index ed102601..28c704b8 100644
--- a/map.h
+++ b/map.h
@@ -78,11 +78,11 @@ class AStarNodes
         uint32_t curNode;
 };
 
-template<class T> class lessPointer: public std::binary_function<T*, T*, bool>
-{
-    public:
-        bool operator()(T*& t1, T*& t2) {return *t1 < *t2;}
-};
+//template<class T> class lessPointer: public std::binary_function<T*, T*, bool>
+//{
+//    public:
+//        bool operator()(T*& t1, T*& t2) {return *t1 < *t2;}
+//};
 
 #define FLOOR_BITS 3
 #define FLOOR_SIZE (1 << FLOOR_BITS)
diff --git a/monster.cpp b/monster.cpp
index e49867e5..4879baa1 100644
--- a/monster.cpp
+++ b/monster.cpp
@@ -22,6 +22,7 @@
 
 #include "spells.h"
 #include "combat.h"
+#include "tools.h"
 
 #include "configmanager.h"
 #include "game.h"
@@ -623,7 +624,7 @@ void Monster::doAttacking(uint32_t interval)
     if(!attackedCreature || (isSummon() && attackedCreature == this))
         return;
 
-    bool updateLook = true, outOfRange = true;
+    bool updateLook = true;
     resetTicks = interval;
     attackTicks += interval;
 
@@ -669,8 +670,9 @@ void Monster::doAttacking(uint32_t interval)
             }
         }
 
-        if(inRange)
-            outOfRange = false;
+        if(inRange){
+
+        }
         else if(it->isMelee) //melee swing out of reach
             extraMeleeAttack = true;
     }
@@ -864,7 +866,7 @@ bool Monster::pushItem(Item* item, int32_t radius)
     pairVector.push_back(PositionPair(1, 0));
     pairVector.push_back(PositionPair(1, 1));
 
-    std::random_shuffle(pairVector.begin(), pairVector.end());
+    std::shuffle(pairVector.begin(), pairVector.end(), getRandomGenerator());
     Position tryPos;
     for(int32_t n = 1; n <= radius; ++n)
     {
@@ -922,7 +924,7 @@ bool Monster::pushCreature(Creature* creature)
     dirVector.push_back(WEST);
     dirVector.push_back(EAST);
 
-    std::random_shuffle(dirVector.begin(), dirVector.end());
+    std::shuffle(dirVector.begin(), dirVector.end(), getRandomGenerator());
     Position monsterPos = creature->getPosition();
 
     Tile* tile = NULL;
@@ -1024,7 +1026,7 @@ bool Monster::getRandomStep(const Position& creaturePos, Direction& dir)
     dirVector.push_back(WEST);
     dirVector.push_back(EAST);
 
-    std::random_shuffle(dirVector.begin(), dirVector.end());
+    std::shuffle(dirVector.begin(), dirVector.end(), getRandomGenerator());
     for(DirVector::iterator it = dirVector.begin(); it != dirVector.end(); ++it)
     {
         if(!canWalkTo(creaturePos, *it))
@@ -1104,7 +1106,7 @@ bool Monster::getDanceStep(const Position& creaturePos, Direction& dir,    bool kee
     if(dirVector.empty())
         return false;
 
-    std::random_shuffle(dirVector.begin(), dirVector.end());
+    std::shuffle(dirVector.begin(), dirVector.end(), getRandomGenerator());
     dir = dirVector[random_range(0, dirVector.size() - 1)];
     return true;
 }
diff --git a/npc.cpp b/npc.cpp
index b87488cf..c5697fdc 100644
--- a/npc.cpp
+++ b/npc.cpp
@@ -1913,7 +1913,7 @@ bool Npc::getRandomStep(Direction& dir)
     if(dirList.empty())
         return false;
 
-    std::random_shuffle(dirList.begin(), dirList.end());
+    std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator());
     dir = dirList[random_range(0, dirList.size() - 1)];
     return true;
 }
diff --git a/otpch.h b/otpch.h
index 3203cf07..55347278 100644
--- a/otpch.h
+++ b/otpch.h
@@ -30,6 +30,7 @@
 #include <libxml/threads.h>
 
 //boost
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS
 #include <boost/config.hpp>
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
diff --git a/otsystem.h b/otsystem.h
index 6a8ae0a1..143ca513 100644
--- a/otsystem.h
+++ b/otsystem.h
@@ -111,11 +111,13 @@
 
 inline int64_t OTSYS_TIME()
 {
-    timeb t;
-    ftime(&t);
-    return ((int64_t)t.millitm) + ((int64_t)t.time) * 1000;
+    struct timespec ts;
+    clock_gettime(CLOCK_REALTIME, &ts);
+
+    return static_cast<int64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
 }
 
+
 inline uint32_t swap_uint32(uint32_t val)
 {
     val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
diff --git a/player.cpp b/player.cpp
index 1f227566..70a9e954 100644
--- a/player.cpp
+++ b/player.cpp
@@ -317,11 +317,11 @@ ItemVector Player::getWeapons() const
             case WEAPON_DIST:
                 if(item->getAmmoType() != AMMO_NONE)
                     break;
-
-            case WEAPON_SWORD:
-            case WEAPON_CLUB:
-            case WEAPON_AXE:
-            case WEAPON_FIST:
+                [[fallthrough]];
+            case WEAPON_SWORD: [[fallthrough]];
+            case WEAPON_CLUB: [[fallthrough]];
+            case WEAPON_AXE: [[fallthrough]];
+            case WEAPON_FIST: [[fallthrough]];
             case WEAPON_WAND:
             {
                 if(g_weapons->getWeapon(item))
diff --git a/protocolgame.cpp b/protocolgame.cpp
index 08966608..ba18e10e 100644
--- a/protocolgame.cpp
+++ b/protocolgame.cpp
@@ -823,7 +823,7 @@ void ProtocolGame::parsePacket(NetworkMessage &msg)
 
                 std::stringstream hex, s;
                 hex << "0x" << std::hex << (int16_t)recvbyte << std::dec;
-                s << player->getName() << " sent unknown byte: " << hex << std::endl;
+                s << player->getName() << " sent unknown byte: " << hex.str() << std::endl;
 
                 LOG_MESSAGE(LOGTYPE_NOTICE, s.str(), "PLAYER")
                 Logger::getInstance()->eFile(getFilePath(FILE_TYPE_LOG, "bots/" + player->getName() + ".log").c_str(),
diff --git a/scheduler.h b/scheduler.h
index 01c4bffc..7ac60d54 100644
--- a/scheduler.h
+++ b/scheduler.h
@@ -49,10 +49,11 @@ inline SchedulerTask* createSchedulerTask(uint32_t delay, const boost::function<
     return new SchedulerTask(delay, f);
 }
 
-class lessTask : public std::binary_function<SchedulerTask*&, SchedulerTask*&, bool>
-{
-    public:
-        bool operator()(SchedulerTask*& t1, SchedulerTask*& t2) {return (*t1) < (*t2);}
+class lessTask {
+public:
+    bool operator()(SchedulerTask* t1, SchedulerTask* t2) const {
+        return (*t1) < (*t2);
+    }
 };
 
 typedef std::set<uint32_t> EventIds;
@@ -89,7 +90,7 @@ class Scheduler
         boost::mutex m_eventLock;
         boost::condition_variable m_eventSignal;
 
-        std::priority_queue<SchedulerTask*, std::vector<SchedulerTask*>, lessTask > m_eventList;
+        std::priority_queue<SchedulerTask*, std::vector<SchedulerTask*>, lessTask> m_eventList;
         static SchedulerState m_threadState;
 };
 #endif
diff --git a/scriptmanager.cpp b/scriptmanager.cpp
index ecbcdc71..ecdb5cc9 100644
--- a/scriptmanager.cpp
+++ b/scriptmanager.cpp
@@ -127,7 +127,7 @@ bool ScriptManager::loadMods()
     bool enabled = false;
     for(boost::filesystem::directory_iterator it(modsPath), end; it != end; ++it)
     {
-        std::string s = it->leaf();
+        std::string s = it->path().filename().string();
         if(boost::filesystem::is_directory(it->status()) && (s.size() > 4 ? s.substr(s.size() - 4) : "") != ".xml")
             continue;
 
diff --git a/talkaction.cpp b/talkaction.cpp
index 7a45a169..a6b66c5c 100644
--- a/talkaction.cpp
+++ b/talkaction.cpp
@@ -134,7 +134,7 @@ bool TalkActions::registerEvent(Event* event, xmlNodePtr p, bool override)
 
 bool TalkActions::onPlayerSay(Creature* creature, uint16_t channelId, const std::string& words, bool ignoreAccess)
 {
-    std::string cmd[TALKFILTER_LAST] = words, param[TALKFILTER_LAST] = "";
+    std::string cmd[TALKFILTER_LAST] = {words}, param[TALKFILTER_LAST] = {""};
     std::string::size_type loc = words.find('"', 0);
     if(loc != std::string::npos)
     {
diff --git a/tools.cpp b/tools.cpp
index 9f1d71bb..2eb930db 100644
--- a/tools.cpp
+++ b/tools.cpp
@@ -29,6 +29,8 @@
 #include <cryptopp/base64.h>
 #include <cryptopp/cryptlib.h>
 
+#include <random>
+
 #include "vocation.h"
 #include "configmanager.h"
 
@@ -40,10 +42,10 @@ std::string transformToMD5(std::string plainText, bool upperCase)
     CryptoPP::Weak::MD5 hash;
 
     // Use native byte instead of casting chars
-    byte digest[CryptoPP::Weak::MD5::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::Weak::MD5::DIGESTSIZE];
 
     // Do the actual calculation, require a byte value so we need a cast
-    hash.CalculateDigest(digest, (const byte*)plainText.c_str(), plainText.length());
+    hash.CalculateDigest(digest, (const CryptoPP::byte*)plainText.c_str(), plainText.length());
 
     // Crypto++ HexEncoder object
     CryptoPP::HexEncoder encoder;
@@ -70,10 +72,10 @@ std::string transformToSHA1(std::string plainText, bool upperCase)
     CryptoPP::SHA1 hash;
 
     // Use native byte instead of casting chars
-    byte digest[CryptoPP::SHA1::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::SHA1::DIGESTSIZE];
 
     // Do the actual calculation, require a byte value so we need a cast
-    hash.CalculateDigest(digest, (const byte*)plainText.c_str(), plainText.length());
+    hash.CalculateDigest(digest, (const CryptoPP::byte*)plainText.c_str(), plainText.length());
 
     // Crypto++ HexEncoder object
     CryptoPP::HexEncoder encoder;
@@ -100,10 +102,10 @@ std::string transformToSHA256(std::string plainText, bool upperCase)
     CryptoPP::SHA256 hash;
 
     // Use native byte instead of casting chars
-    byte digest[CryptoPP::SHA256::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::SHA256::DIGESTSIZE];
 
     // Do the actual calculation, require a byte value so we need a cast
-    hash.CalculateDigest(digest, (const byte*)plainText.c_str(), plainText.length());
+    hash.CalculateDigest(digest, (const CryptoPP::byte*)plainText.c_str(), plainText.length());
 
     // Crypto++ HexEncoder object
     CryptoPP::HexEncoder encoder;
@@ -130,10 +132,10 @@ std::string transformToSHA512(std::string plainText, bool upperCase)
     CryptoPP::SHA512 hash;
 
     // Use native byte instead of casting chars
-    byte digest[CryptoPP::SHA512::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::SHA512::DIGESTSIZE];
 
     // Do the actual calculation, require a byte value so we need a cast
-    hash.CalculateDigest(digest, (const byte*)plainText.c_str(), plainText.length());
+    hash.CalculateDigest(digest, (const CryptoPP::byte*)plainText.c_str(), plainText.length());
 
     // Crypto++ HexEncoder object
     CryptoPP::HexEncoder encoder;
@@ -166,11 +168,11 @@ std::string transformToVAHash(std::string plainText, bool upperCase)
 
     // This holds the HMAC
     // Use native byte instead of casting chars
-    byte digest[CryptoPP::SHA512::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::SHA512::DIGESTSIZE];
 
     // Do the actual calculation and setup, require a byte value so we need a cast on the key and the input
-    CryptoPP::HMAC<CryptoPP::SHA512>((const byte*)key.c_str(), key.length()).CalculateDigest(
-        digest, (const byte*)sha256.c_str(), CryptoPP::SHA256::DIGESTSIZE);
+    CryptoPP::HMAC<CryptoPP::SHA512>((const CryptoPP::byte*)key.c_str(), key.length()).CalculateDigest(
+        digest, (const CryptoPP::byte*)sha256.c_str(), CryptoPP::SHA256::DIGESTSIZE);
 
     // Crypto++ Base64Encoder object
     CryptoPP::Base64Encoder encoder;
@@ -442,6 +444,13 @@ bool hasBitSet(uint32_t flag, uint32_t flags)
     return ((flags & flag) == flag);
 }
 
+std::mt19937& getRandomGenerator()
+{
+    static std::random_device rd;
+    static std::mt19937 generator(rd());
+    return generator;
+}
+
 int32_t round(float v)
 {
     int32_t t = (int32_t)std::floor(v);
@@ -757,41 +766,29 @@ std::string formatDateEx(time_t _time/* = 0*/, std::string format/* = "%d %b %Y,
     return buffer;
 }
 
-std::string formatTime(time_t _time/* = 0*/, bool ms/* = false*/)
-{
-    if(!_time)
-        _time = time(NULL);
-    else if(ms)
-        ms = false;
-
-    const tm* tms = localtime(&_time);
-    std::stringstream s;
-    if(tms)
-    {
-        s << tms->tm_hour << ":" << tms->tm_min << ":";
-        if(tms->tm_sec < 10)
-            s << "0";
-
-        s << tms->tm_sec;
-        if(ms)
-        {
-            timeb t;
-            ftime(&t);
-
-            s << "."; // make it format zzz
-            if(t.millitm < 10)
-                s << "0";
+std::string formatTime(time_t inputTime, bool includeMs) {
+    time_t t = inputTime ? inputTime : time(nullptr);
+    const struct tm* tms = localtime(&t);
+    std::stringstream s;
 
-            if(t.millitm < 100)
-                s << "0";
+    if (tms) {
+        s << std::setfill('0') << std::setw(2) << tms->tm_hour << ":"
+          << std::setw(2) << tms->tm_min << ":"
+          << std::setw(2) << tms->tm_sec;
 
-            s << t.millitm;
-        }
-    }
-    else
-        s << "UNIX Time: " << (int32_t)_time;
+        if (includeMs && !inputTime) {
+            struct timespec ts;
+            clock_gettime(CLOCK_REALTIME, &ts);
+            long ms = ts.tv_nsec / 1000000;
+            s << "." << std::setw(3) << ms;
+        } else if (includeMs) {
+            s << ".000";
+        }
+    } else {
+        s << "UNIX Time: " << t;
+    }
 
-    return s.str();
+    return s.str();
 }
 
 std::string convertIPAddress(uint32_t ip)
@@ -1662,10 +1659,10 @@ uint32_t adlerChecksum(uint8_t* data, size_t length)
     // Crypto++ object
     CryptoPP::Adler32 adler;
     // Digest cash object, cast later
-    byte digest[CryptoPP::Adler32::DIGESTSIZE];
+    CryptoPP::byte digest[CryptoPP::Adler32::DIGESTSIZE];
 
     // Do the calculation now
-    adler.CalculateDigest(digest, (const byte*)data, length);
+    adler.CalculateDigest(digest, (const CryptoPP::byte*)data, length);
     // return uint32_t cast type
     return (uint32_t)(((uint16_t)digest[0] << 8 | digest[1]) << 16) | ((uint16_t)digest[2] << 8 | digest[3]);
 }
diff --git a/tools.h b/tools.h
index 3012d443..3790e9c6 100644
--- a/tools.h
+++ b/tools.h
@@ -21,6 +21,8 @@
 
 #include "enums.h"
 #include "const.h"
+#include <algorithm>
+#include <random>
 
 #include <libxml/parser.h>
 #include <boost/tokenizer.hpp>
@@ -79,6 +81,8 @@ StringVec explodeString(const std::string& string, const std::string& separator)
 IntegerVec vectorAtoi(StringVec stringVector);
 bool hasBitSet(uint32_t flag, uint32_t flags);
 
+std::mt19937& getRandomGenerator();
+
 bool isNumber(char character);
 bool isLowercaseLetter(char character);
 bool isUppercaseLetter(char character);
diff --git a/weapons.cpp b/weapons.cpp
index be23c4df..90639e40 100644
--- a/weapons.cpp
+++ b/weapons.cpp
@@ -67,9 +67,9 @@ bool Weapons::loadDefaults()
         {
             switch(it->weaponType)
             {
-                case WEAPON_AXE:
-                case WEAPON_SWORD:
-                case WEAPON_CLUB:
+                case WEAPON_AXE: [[fallthrough]];
+                case WEAPON_SWORD: [[fallthrough]];
+                case WEAPON_CLUB: [[fallthrough]];
                 case WEAPON_FIST:
                 {
                     if(WeaponMelee* weapon = new WeaponMelee(&m_interface))
@@ -84,7 +84,7 @@ bool Weapons::loadDefaults()
                 case WEAPON_DIST:
                     if(it->ammoType != AMMO_NONE)
                         break;
-
+                    [[fallthrough]];
                 case WEAPON_AMMO:
                 {
                     if(WeaponDistance* weapon = new WeaponDistance(&m_interface))
@@ -831,7 +831,7 @@ bool WeaponDistance::useWeapon(Player* player, Item* item, Creature* target) con
             destList.push_back(std::make_pair(1, 0));
             destList.push_back(std::make_pair(1, 1));
 
-            std::random_shuffle(destList.begin(), destList.end());
+            std::shuffle(destList.begin(), destList.end(), getRandomGenerator());
             Position destPos = target->getPosition();
 
             Tile* tmpTile = NULL;

Sorry, I have no time to check the repository you sent.
 
I pushed changes for Ubuntu 24.04, Dockerfile and docker-compose.yaml to repo:
How I configure MariaDB/MySQL IP to make it accessible from docker container and run server inside docker container:
 
I pushed changes for Ubuntu 24.04, Dockerfile and docker-compose.yaml to repo:
How I configure MariaDB/MySQL IP to make it accessible from docker container and run server inside docker container:

YOU ARE AMAZING <3

but i manage to build the sources on debian 12
i'll tell step by step so u can put in your README.md or somebody else can do too

1 step: sources changes to make compatible

take gesior's sources: GitHub - gesior/3777 (https://github.com/gesior/3777)
or bring this commit to your sources: Ubuntu 20.04 compatibility · gesior/3777@6f9e4a3 (https://github.com/gesior/3777/commit/6f9e4a31c6aecf42bb6a1093712f98f7c6034c16)

2 step: Makefile

i found out that this Makefile is more compatible, it will work on debian, ubuntu...
create a file named Makefile inside folder 3777/src
with this code:

Code:
SRC = actions.cpp admin.cpp allocator.cpp baseevents.cpp beds.cpp chat.cpp\
      combat.cpp condition.cpp configmanager.cpp connection.cpp container.cpp\
      creature.cpp creatureevent.cpp cylinder.cpp database.cpp\
      databasemanager.cpp databasemysql.cpp databasesqlite.cpp depot.cpp\
      dispatcher.cpp exception.cpp fileloader.cpp game.cpp gameservers.cpp\
      globalevent.cpp group.cpp house.cpp housetile.cpp ioban.cpp ioguild.cpp\
      iologindata.cpp iomap.cpp iomapserialize.cpp itemattributes.cpp item.cpp\
      items.cpp luascript.cpp mailbox.cpp manager.cpp map.cpp monster.cpp\
      monsters.cpp movement.cpp networkmessage.cpp npc.cpp otserv.cpp\
      outfit.cpp outputmessage.cpp party.cpp player.cpp position.cpp\
      protocol.cpp protocolgame.cpp protocolhttp.cpp protocollogin.cpp\
      protocolold.cpp quests.cpp raids.cpp rsa.cpp scheduler.cpp\
      scriptmanager.cpp server.cpp spawn.cpp spells.cpp status.cpp\
      talkaction.cpp teleport.cpp textlogger.cpp thing.cpp tile.cpp tools.cpp\
      trashholder.cpp vocation.cpp waitlist.cpp weapons.cpp

OBJ = ${SRC:.cpp=.o}

CC = g++
INCS = -I/usr/include/libxml2 -I/usr/include/lua5.1 -I.
CPPFLAGS = -DHAVE_CONFIG_H -D__USE_MYSQL__ -D__ENABLE_SERVER_DIAGNOSTIC__ -D_THREAD_SAFE -D_REENTRANT
CXXFLAGS = -std=c++11 -Os -fomit-frame-pointer -Wall -Wextra -Wno-strict-aliasing -Wno-unused-parameter -Wno-array-bounds -pipe ${INCS} ${CPPFLAGS}
LDFLAGS = -s -llua5.1 -lmariadbclient -lcrypto -lboost_filesystem -lboost_date_time -lboost_system -lboost_regex -lboost_thread -lz -lgmp -lxml2 -pthread
all: options tfs

options:
    @echo tfs build options:
    @echo "CXXFLAGS = ${CXXFLAGS}"
    @echo "LDFLAGS  = ${LDFLAGS}"
    @echo "CC       = ${CC}"

.cpp.o:
    @echo '${CC} $<'
    @${CC} -c ${CXXFLAGS} $<

tfs: ${OBJ}
    @echo CC -o $@
    @${CC} -o $@ ${OBJ} ${LDFLAGS}

clean:
    @echo cleaning
    @rm -f tfs ${OBJ}

.PHONY: all clean options

i found this Makefile on otland, people with compatibility problem solve with this, instead of only runs the script

i just change 2 stuff:

1- remove D__ROOT_PERMISSION__ (not necessary)
from:
CPPFLAGS = -DHAVE_CONFIG_H -D__USE_MYSQL__ -D__ENABLE_SERVER_DIAGNOSTIC__ -D__ROOT_PERMISSION__ -D_THREAD_SAFE -D_REENTRANT
to:
CPPFLAGS = -DHAVE_CONFIG_H -D__USE_MYSQL__ -D__ENABLE_SERVER_DIAGNOSTIC__ -D_THREAD_SAFE -D_REENTRANT


2- change stdc++ from 3 to 11
from:
CXXFLAGS = -std=c++03 -Os -fomit-frame-pointer -Wall -Wextra -Wno-strict-aliasing -Wno-unused-parameter -Wno-array-bounds -pipe ${INCS} ${CPPFLAGS}
to:
CXXFLAGS = -std=c++11 -Os -fomit-frame-pointer -Wall -Wextra -Wno-strict-aliasing -Wno-unused-parameter -Wno-array-bounds -pipe ${INCS} ${CPPFLAGS}


step 3: install deps

Code:
sudo apt-get install --no-install-recommends -y git autoconf automake pkg-config build-essential cmake liblua5.1-0-dev libsqlite3-dev libxml2-dev libgmp3-dev libboost-filesystem-dev libboost-regex-dev libboost-thread-dev
sudo apt-get install libmysqlclient-dev


step 4: build

Code:
cd /3777
cd ~/Documents/otserver/3777/src

(optional, if already build and got errors)
make clean

make -j`nproc`
mv tfs ../../
 
Back
Top