Jump to content

[M2Dev] Advanced Files To Build Your Server: Src & Server Files & Client [x64 / DX9Ex / CMake / Python3.14 / FreeType / XChaCha20-Poly1305]


Recommended Posts

  • Honorable Member

New PRs merged to main.

Contributor list updated in the main topic (whoever I found on the forum).

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

I don't know if I'm doing something wrong, but I've set-up free-bsd 13.5 VM according to a tutorial I've found, set-up the database per the m2dev-server-main/sql/Readme.txt, now when I run python install.py, it goes through, a channels folder is created, but upon running python start.py I get a bunch of FileNotFoundError for each channel and channel core example

> Starting CH1:
        > channel1_core1
> Failed to start channel1_core1: [Errno 2] No such file or directory: './channel1_core1'
Traceback (most recent call last):
  File "/root/server/start.py", line 28, in try_start
    proc = start_process(exe)
           ^^^^^^^^^^^^^^^^^^
  File "/root/server/start.py", line 23, in start_process
    return subprocess.Popen([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/lib/python3.11/subprocess.py", line 1955, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: './channel1_core1'

So then I tried compiling the source server files instead (on free-bsd) where "cmake -S . -B build" went through without problems but running "make -j4" on the build folder produced errors, that after fixing produced new errors for example 

/root/devserver/src/libpoly/main.cpp:18:20: error: use of undeclared identifier 'getpid'
   18 |         srandom(time(0) + getpid());
      |           
/root/devserver/src/db/version.cpp:11:36: error: use of undeclared identifier '__P4_VERSION__'
   11 |                 fprintf(fp, "db revision: %s\n", __P4_VERSION__);
      |                
/root/devserver/src/game/auth_brazil.cpp:31:5: error: unknown type name 'MD5_CTX'
   31 |     MD5_CTX md5;
      |     ^

Am I missing something obvious here, or doing something wrong?

  • Honorable Member
3 hours ago, vaoba said:

I don't know if I'm doing something wrong, but I've set-up free-bsd 13.5 VM according to a tutorial I've found, set-up the database per the m2dev-server-main/sql/Readme.txt, now when I run python install.py, it goes through, a channels folder is created, but upon running python start.py I get a bunch of FileNotFoundError for each channel and channel core example

> Starting CH1:
        > channel1_core1
> Failed to start channel1_core1: [Errno 2] No such file or directory: './channel1_core1'
Traceback (most recent call last):
  File "/root/server/start.py", line 28, in try_start
    proc = start_process(exe)
           ^^^^^^^^^^^^^^^^^^
  File "/root/server/start.py", line 23, in start_process
    return subprocess.Popen([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/lib/python3.11/subprocess.py", line 1955, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: './channel1_core1'

So then I tried compiling the source server files instead (on free-bsd) where "cmake -S . -B build" went through without problems but running "make -j4" on the build folder produced errors, that after fixing produced new errors for example 

/root/devserver/src/libpoly/main.cpp:18:20: error: use of undeclared identifier 'getpid'
   18 |         srandom(time(0) + getpid());
      |           
/root/devserver/src/db/version.cpp:11:36: error: use of undeclared identifier '__P4_VERSION__'
   11 |                 fprintf(fp, "db revision: %s\n", __P4_VERSION__);
      |                
/root/devserver/src/game/auth_brazil.cpp:31:5: error: unknown type name 'MD5_CTX'
   31 |     MD5_CTX md5;
      |     ^

Am I missing something obvious here, or doing something wrong?

Build it with: cmake --build build --parallel 4
This way cmake will use the build system it generated the files for.


The 2 cmake commands work the following way:
Generate build files for the cmake project specified after -S into the folder specified after -B: cmake -S . -B build 
Build the actual project in the folder specified after --build with the number of threads specified after --parallel: cmake --build build --parallel 4

 

2 hours ago, BlackList said:

Could you guys share full commit where you updated to x64 for Server and Client?

No, that was not my intention. I release things for people who likes to develop or wants to learn.
I do not do that kind of releases so people just take it and use it for their servers. If you don't even wanna spend your time on going through well documented commit logs, why would anyone else do it for you?

Edited by Distraught
  • Metin2 Dev 1
  • Good 1
  • muscle 2
  • Love 1

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Honorable Member

I created a public Trello board for the development of these files.
If you find any bugs or you want to send feature requests, please write it to this topic, so we can add it to the respective list.
Here you can track what has been added and how we're progressing with things: https://trello.com/b/nbSvG4HP/m2dev-files

Edited by Distraught

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

Hey everyone,

First off, a huge thanks to everyone for all your work on this project! I'm new to the scene and really excited to learn how everything works under the hood.

I've set up a fresh FreeBSD 14 on VPS and have been trying to get a metin2 server running. Here are the steps I've taken so far:

Installed all the necessary packages on FreeBSD.

Cloned both the server and source code repositories.

Successfully built the source.

Copied the compiled db and game files into the server's share/bin/ directory.

Ran the install.sh script to set up the channels.

Launched the server using start.sh.

Unfortunately, it seems like something isn't right. When I check the syslog for both the auth and channel1 processes, I see the same connection error repeating:

Code snippet

Sep 5 00:09:02 :: SYSTEM: Trying to connect to :9000 SYSERR: Sep 5 00:09:02 :: socket_connect: socket_connect(): can not connect to :9000

Here are the active ports (the ip is fake):

.png

I'm a bit stuck and would really appreciate your help.

Thanks in advance for any pointers! ❤️

 

I'm trying to use 40k client with your server files. But i have this error in aut/syslog

SYSERR: Sep 5 22:50:36 :: Process: SEQUENCE da816f00 mismatch 0x4e != 0xaf header 111 

Any clue ? I tried to use your client but it does not execute

Thanks for your help

Edited by yasu
  • Metin2 Dev 1
  • Bot
On 9/4/2025 at 12:16 AM, Distraught said:

Build it with: cmake --build build --parallel 4
This way cmake will use the build system it generated the files for.


The 2 cmake commands work the following way:
Generate build files for the cmake project specified after -S into the folder specified after -B: cmake -S . -B build 
Build the actual project in the folder specified after --build with the number of threads specified after --parallel: cmake --build build --parallel 4

 

No, that was not my intention. I release things for people who likes to develop or wants to learn.
I do not do that kind of releases so people just take it and use it for their servers. If you don't even wanna spend your time on going through well documented commit logs, why would anyone else do it for you?

I’m willing to learn and also invest the time to understand things. My goal is to update my project to x64 as well, but I don’t know where to start or what to look out for. It would already help a lot if there’s some kind of documentation to understand it.

english_banner.gif

  • Honorable Member

New PRs from @ Koray merged.

client-src:

  • enabled detailed packet logs for easier debugging

server-src:

  • refactor some code to prevent possible crashes and bugs
  • enabled detailed packet logs for easier debugging
  • disable build libpoly entrypoint
  • add git derived version info
  • remove FreeBSD specific MD5 includes 
  • refactor arena iteration in AddArena
  • remove OS_FREEBSD preventation from xmd5
  • add missing ch data
  • add Github actions workflow for FreeBSD build
  • Metin2 Dev 4

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Active+ Member

i will continue to improve it. if i encounter any errors, i will let you know. if i can solve them, i will let you know with the solution. thx again for your contribution.

 

spacer.png

  • Love 1

hasanmacit

  • Active+ Member

Didn't have the chance to test it since my VM is still building for server testing and compiling but I had the chance to go through the binary and get rid of all the build warnings (except vendors).

You can check it out here:

This is the hidden content, please

 

Again, I have not tested it, I am not a professional and I am very open to suggestions, feedback and improvements.

This update makes the codebase compatible with:

  • The latest Windows 10 SDK Platform version
  • C++ 20 (was C++ 17)
  • C 17 (⚠️ was Legacy)
  • Metin2 Dev 53
  • Good 5
  • Love 1
  • Love 23
  • Active+ Member

Decided to add a nice asset to the mix:

DumpProto for this project is here. Buildable for x32 and x64 envs, no includes/libs or vcpkg required!

Compatible with the latest Windows 10 SDK, C++ 20 and C 17.

Uses an exact LZO 2.10 copy from the binary source (vendor folder).

Please read warnings in README before using.

Feel free to provide feedback and improvements!

This is the hidden content, please

 

The DumpProto project is now integrated and built along with the Client Source

 

 

Edited by Mind Rapist
  • Metin2 Dev 30
  • Good 4
  • Love 9
  • Honorable Member

I think you should do a PR instead of forking it, because it won't receive the updates we add later.

We use C++17 with a reason. Last time a checked, C++20 wasn't consistent between all compilers, (like jthread implementation missing on clang), so I decided to stuck with C++17 as that's the last like fully implemented standard on the 3 main compilers (msvc, clang and gcc).

Maybe I'll check it again in the future to see, if there are any changes in this matter.

Edited by Distraught

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Active+ Member
19 hours ago, Distraught said:

I think you should do a PR instead of forking it, because it won't receive the updates we add later.

We use C++17 with a reason. Last time a checked, C++20 wasn't consistent between all compilers, (like jthread implementation missing on clang), so I decided to stuck with C++17 as that's the last like fully implemented standard on the 3 main compilers (msvc, clang and gcc).

Maybe I'll check it again in the future to see, if there are any changes in this matter.

Thanks for the advice! TBH I'm not very familiar with Github yet so I forked but I will probably look into PRing and if I make any more updates I'll probably post a PR version.

Newbie here, is this a good starting point for learing how to make a metin2 server? I focused on webdesign, how hard would you scale the difficulty on making my own server?

  • Love 1
  • Active+ Member

For anyone who would be interested in moving all server-related compiled sources (or choose one to many of them), I have this python script:

Spoiler
#!/usr/bin/env python3
# File: dist2loc.py

import argparse
import os
import shutil
import sys

# --- Configuration ---
# You can define your root directories here. Use a full, absolute path.



# Define the root directory for your game server's destination files.
# For example: '/usr/home/game'
GAME_ROOT_DIR = "/usr/home/game" # Change this line to your desired path (e.g., GAME_ROOT_DIR = "/usr/game". Do NOT include "/share" folder or/and beyond)

# Define the root directory where your source code and build output are located.
# For example: '/usr/home/src'
SOURCE_ROOT_DIR = "/usr/home" # Change this line to your desired path (e.g., SOURCE_ROOT_DIR = "/usr/game/gamesrc". Do NOT include "/src", "/vendor" or any of the root folders or/and beyond them)

# --- Derived Paths (Do not change below this line) ---
# Source directory for compiled binaries
SOURCE_DIR = os.path.join(SOURCE_ROOT_DIR, 'src', 'build', 'bin')

# Destination directories are based on the GAME_ROOT_DIR
GAME_DEST_DIR = os.path.join(GAME_ROOT_DIR, 'share', 'bin')
DB_DEST_DIR = os.path.join(GAME_ROOT_DIR, 'share', 'bin')
LOCALE_DIR = os.path.join(GAME_ROOT_DIR, 'share', 'locale')

# --- Argument Parsing ---
def parse_arguments():
	"""
	Parses command-line arguments to determine which files to copy.
	"""
	parser = argparse.ArgumentParser(
		description="Automate the deployment of game, db, and qc binaries.",
		epilog="Example: python3 deploy_game_binaries.py --all"
	)

	# Mutually exclusive group for the flags
	group = parser.add_mutually_exclusive_group()
	group.add_argument(
		'--all',
		action='store_true',
		help="Transfer all three files: game, db, and qc."
	)
	group.add_argument(
		'--files',
		nargs='+',
		choices=['game', 'db', 'qc'],
		help="Specify which files to transfer (e.g., game db qc)."
	)

	args = parser.parse_args()

	# If --all is used, set all individual files to be transferred.
	if args.all:
		args.files = ['game', 'db', 'qc']
	elif args.files is None:
		parser.print_help()
		sys.exit(1)

	return args

# --- Core Functions ---
def set_permissions(path: str, permission_code: int) -> None:
	"""
	Sets the specified permission code on a given file.
	"""
	try:
		os.chmod(path, permission_code)
		print(f"  - Set permissions to {oct(permission_code)[2:]} on: {path}")
	except OSError as e:
		print(f"  - ERROR: Failed to set permissions on {path}: {e}")

def find_qc_destinations():
	"""
	Searches all locale subdirectories for a 'quest' folder that contains
	a 'questlib.lua' file.
	Returns a list of all valid quest folder paths.
	"""
	destinations = []
	# Make sure LOCALE_DIR exists before walking it
	if not os.path.isdir(LOCALE_DIR):
		print(f"Warning: Locale directory not found at '{LOCALE_DIR}'. No 'qc' destinations will be found.")
		return destinations
	for root, dirs, files in os.walk(LOCALE_DIR):
		# Check if the current directory is named 'quest'
		if os.path.basename(root) == 'quest':
			# Check if questlib.lua exists in this 'quest' folder
			if 'questlib.lua' in files:
				destinations.append(root)
	return destinations

def copy_file(source, destination):
	"""
	Copies a single file from source to destination, handling errors.
	"""
	try:
		shutil.copy2(source, destination)
		print(f"  - Copied '{os.path.basename(source)}' to '{destination}'")
		return True
	except FileNotFoundError:
		print(f"  - ERROR: File not found at '{source}'. Skipping.")
	except Exception as e:
		print(f"  - ERROR: Failed to copy '{os.path.basename(source)}'. Reason: {e}")
	return False

def main():
	"""
	Main function to orchestrate the deployment process.
	"""
	args = parse_arguments()

	# 777 in octal
	permission_code = 0o777

	print("\nStarting game binary deployment...")
	print(f"Source directory: {SOURCE_DIR}\n")

	# Mapping of file names to their source and destination paths
	file_map = {
		'game': (os.path.join(SOURCE_DIR, 'game'), GAME_DEST_DIR),
		'db': (os.path.join(SOURCE_DIR, 'db'), DB_DEST_DIR),
		'qc': (os.path.join(SOURCE_DIR, 'qc'), None) # Destination for 'qc' is dynamic
	}

	# Files to set permissions on after they are copied
	permissions_targets = []

	# Handle 'qc' separately to copy to multiple destinations
	if 'qc' in args.files:
		qc_dest_dirs = find_qc_destinations()
		if not qc_dest_dirs:
			print("ERROR: No 'quest' folders containing 'questlib.lua' found in any locale. Skipping 'qc' transfer.")

		else:
			print("Processing 'qc'...")
			for dest_dir in qc_dest_dirs:
				dest_file = os.path.join(dest_dir, os.path.basename(file_map['qc'][0]))
				if copy_file(file_map['qc'][0], dest_dir):
					permissions_targets.append(dest_file)
		args.files.remove('qc') # Remove to avoid processing again

	# Perform the copy operations for the remaining files
	for file_to_copy in args.files:
		source_path, dest_path = file_map.get(file_to_copy)
		dest_file = os.path.join(dest_path, os.path.basename(source_path))

		print(f"Processing '{file_to_copy}'...")
		if copy_file(source_path, dest_path):
			permissions_targets.append(dest_file)

	print("\nSetting permissions...")
	for target in permissions_targets:
		set_permissions(target, permission_code)

	print("\nDeployment and permissions complete.")

if __name__ == "__main__":
	main()

 

Remember to change root and destination folders prefix at the beginning of the file to match your own (detailed instructions found as comments in the file).

 

  • Works from any directory.
  • Targets all files in /build/bin directory or a selection of them.
  • All 3 files: 
    Quote

    python3 ./dist2loc.py --all

  • Selection (1 or 2 files, order-irrelevant):
    Quote

    python3 ./dist2loc.py --files game db

  • Files game and db are designed to be copied in GAME_ROOT_DIR/share/bin.
  • QC file is designed to be copied in all directories inside GAME_ROOT_DIR/share/locale/[folder_name]/quest that contain a questlib.lua file in them. You will never have to edit the script when changing locales. If you keep multiple locale folders inside /locale as a backup or for any reasons that contain /quest/questlib.lua, these folders will get a copy of the new QC as well.

UPDATE: The file now automatically gives 0777 permissions for game and db copied files

Edited by Mind Rapist
  • Metin2 Dev 1
  • Honorable Member

[UPDATE] DirectX 9 upgraded to DirectX 9 Ex thanks to @ Koray

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Honorable Member

[UPDATE]

New virtual filesystem is available!
The new system uses zstd for compression and Camellia (via cryptopp) for encryption.
From now on, there is only one file, which contains indexes and pack data too (*.pck).
A PackMaker project has been added to the build, please run cmake again.
You can modify encryption keys in PackLib/config.h
A default PackMaker build has been added to the client too (delete all files in the pack folder and run python pack.py --all in the assets folder).

Edited by Distraught
  • Metin2 Dev 2

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Active+ Member
On 9/5/2025 at 3:38 AM, yasu said:

Hey everyone,

First off, a huge thanks to everyone for all your work on this project! I'm new to the scene and really excited to learn how everything works under the hood.

I've set up a fresh FreeBSD 14 on VPS and have been trying to get a metin2 server running. Here are the steps I've taken so far:

Installed all the necessary packages on FreeBSD.

Cloned both the server and source code repositories.

Successfully built the source.

Copied the compiled db and game files into the server's share/bin/ directory.

Ran the install.sh script to set up the channels.

Launched the server using start.sh.

Unfortunately, it seems like something isn't right. When I check the syslog for both the auth and channel1 processes, I see the same connection error repeating:

Code snippet

Sep 5 00:09:02 :: SYSTEM: Trying to connect to :9000 SYSERR: Sep 5 00:09:02 :: socket_connect: socket_connect(): can not connect to :9000

Here are the active ports (the ip is fake):

.png

I'm a bit stuck and would really appreciate your help.

Thanks in advance for any pointers! ❤️

 

I'm trying to use 40k client with your server files. But i have this error in aut/syslog

SYSERR: Sep 5 22:50:36 :: Process: SEQUENCE da816f00 mismatch 0x4e != 0xaf header 111 

Any clue ? I tried to use your client but it does not execute

Thanks for your help

Same issue with the server. I managed to build a machine and tried to test the server in the same way.

Port 9000 causes AsyncSQL errors in syslog for all tables in channels/db.

Port 15000 works for db but causes this in channel/auth syserr:

SYSERR: Sep 20 19:13:56 :: pid_init: 
Start of pid: 1254

SYSERR: Sep 20 19:13:56 :: socket_connect: socket_connect(): can not connect to :15000
SYSERR: Sep 20 19:13:56 :: main: Failed to Load ClientPackageCryptInfo File(package/)
SYSERR: Sep 20 19:13:59 :: socket_connect: socket_connect(): can not connect to :15000
SYSERR: Sep 20 19:14:02 :: socket_connect: socket_connect(): can not connect to :15000
SYSERR: Sep 20 19:14:05 :: socket_connect: socket_connect(): can not connect to :15000
SYSERR: Sep 20 19:14:08 :: socket_connect: socket_connect(): can not connect to :15000
SYSERR: Sep 20 19:14:11 :: socket_connect: socket_connect(): can not connect to :15000

Using FreeBSD 14.3 and MariaDB 11.8. DB user and password confirmed to work as well as DB port. I did not change anything in the source or in any config files (only the ip in client root)

Excuse me, newbie to cmake. How can I import the project into VS 2022 and also build-debug it properly?
The client source throws me an error about missing a Python library.
Thanks.

  • Love 1
  • Active+ Member
2 hours ago, kyotax said:

Thanks<3, can someone make a video Tutorial

As soon as I can make it work I will be posting a download link for a VDI file so you guys can download and get started right away.

does not work on freebsd 14.3 amd64 ?

I have a VPS bought, I compiled the sources and it doesn't start the game, only db, I haven't changed anything at all.

  • Honorable Member
12 hours ago, Mind Rapist said:

As soon as I can make it work I will be posting a download link for a VDI file so you guys can download and get started right away.

Please do not! If I wanted to add a VM image, I would have done it. But it breaks the whole purpose. It's really straightforward and the files are always updated, if you put them on a VDI, they won't be able to get the latest updates.
Also, if someone can't do a git clone or a FreeBSD install, than it's completely pointless for them to use these files.

 

  

16 hours ago, twbro54l said:

Excuse me, newbie to cmake. How can I import the project into VS 2022 and also build-debug it properly?
The client source throws me an error about missing a Python library.
Thanks.

It's literally written down in the topic. Read it again.

 

[UPDATE]

 - After careful consideration and checking the compiler implementation statuses, I decided to move the client and server sources to C++20 standard.
- logging changed to spdlog

Edited by Distraught
  • Love 5

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.