• 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!

OTClient for Web Browsers

dunno if something like that is even possible on cam files, never tried cam files loading.
I may be mistaken, but I believed you worked with clients and that this might interest you. The purpose is not for players to watch their cams directly through the browser, but for an admin to monitor flagged cams directly in his or her browser instead of downloading cams, but perhaps there are better ways.

I apologize for tagging you; I thought you might find this relevant
first
sudo apt update
sudo apt install ffmpeg
PHP:
<?php
// Define the directory where your .cam files are stored
$cam_folder = "path/to/cams";  // Replace with your folder path
$converted_folder = "path/to/converted";  // Folder where .mp4 files will be saved

// Ensure the converted folder exists
if (!is_dir($converted_folder)) {
    mkdir($converted_folder, 0777, true);  // Create the folder if it doesn't exist
}

// Function to get all .cam files from the directory
function get_cam_files($folder) {
    $files = [];
    if (is_dir($folder)) {
        if ($handle = opendir($folder)) {
            while (false !== ($file = readdir($handle))) {
                // Only add .cam files
                if (pathinfo($file, PATHINFO_EXTENSION) == 'cam') {
                    $files[] = $file;
                }
            }
            closedir($handle);
        }
    }
    return $files;
}

// Function to convert .cam file to .mp4 using FFmpeg
function convert_cam_to_mp4($input_file, $output_file) {
    // Command to convert .cam to .mp4 (adjust depending on actual .cam format compatibility with FFmpeg)
    $command = "ffmpeg -i " . escapeshellarg($input_file) . " " . escapeshellarg($output_file) . " 2>&1";
   
    // Execute the command and capture the output and status
    exec($command, $output, $status);

    // Check if conversion was successful
    if ($status === 0) {
        return true;
    } else {
        // If there was an error, log or print the output for debugging
        error_log("Error converting file: " . implode("\n", $output));
        return false;
    }
}

// Get all .cam files in the folder
$cam_files = get_cam_files($cam_folder);

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Converted CAM Video Files</title>
    <style>
        video {
            width: 600px;
            height: auto;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <h1>Converted CAM Video Files</h1>
   
    <?php if (empty($cam_files)): ?>
        <p>No CAM files found in the directory.</p>
    <?php else: ?>
        <?php foreach ($cam_files as $cam_file): ?>
            <?php
            // Define the input and output file paths
            $input_file = $cam_folder . '/' . $cam_file;
            $output_file = $converted_folder . '/' . pathinfo($cam_file, PATHINFO_FILENAME) . '.mp4';
           
            // Check if the converted file already exists
            if (!file_exists($output_file)) {
                // Convert the file if it doesn't exist
                $conversion_successful = convert_cam_to_mp4($input_file, $output_file);
                if (!$conversion_successful) {
                    echo "<p>Error converting {$cam_file}</p>";
                    continue;
                }
            }
            ?>

            <div>
                <h3><?php echo htmlspecialchars($cam_file); ?> (Converted)</h3>
                <!-- Embed video player for the converted .mp4 file -->
                <video controls>
                    <source src="<?php echo htmlspecialchars($output_file); ?>" type="video/mp4">
                    Your browser does not support the video tag.
                </video>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
   
</body>
</html>
 
dunno if something like that is even possible on cam files, never tried cam files loading.

first
sudo apt update
sudo apt install ffmpeg
PHP:
<?php
// Define the directory where your .cam files are stored
$cam_folder = "path/to/cams";  // Replace with your folder path
$converted_folder = "path/to/converted";  // Folder where .mp4 files will be saved

// Ensure the converted folder exists
if (!is_dir($converted_folder)) {
    mkdir($converted_folder, 0777, true);  // Create the folder if it doesn't exist
}

// Function to get all .cam files from the directory
function get_cam_files($folder) {
    $files = [];
    if (is_dir($folder)) {
        if ($handle = opendir($folder)) {
            while (false !== ($file = readdir($handle))) {
                // Only add .cam files
                if (pathinfo($file, PATHINFO_EXTENSION) == 'cam') {
                    $files[] = $file;
                }
            }
            closedir($handle);
        }
    }
    return $files;
}

// Function to convert .cam file to .mp4 using FFmpeg
function convert_cam_to_mp4($input_file, $output_file) {
    // Command to convert .cam to .mp4 (adjust depending on actual .cam format compatibility with FFmpeg)
    $command = "ffmpeg -i " . escapeshellarg($input_file) . " " . escapeshellarg($output_file) . " 2>&1";
  
    // Execute the command and capture the output and status
    exec($command, $output, $status);

    // Check if conversion was successful
    if ($status === 0) {
        return true;
    } else {
        // If there was an error, log or print the output for debugging
        error_log("Error converting file: " . implode("\n", $output));
        return false;
    }
}

// Get all .cam files in the folder
$cam_files = get_cam_files($cam_folder);

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Converted CAM Video Files</title>
    <style>
        video {
            width: 600px;
            height: auto;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <h1>Converted CAM Video Files</h1>
  
    <?php if (empty($cam_files)): ?>
        <p>No CAM files found in the directory.</p>
    <?php else: ?>
        <?php foreach ($cam_files as $cam_file): ?>
            <?php
            // Define the input and output file paths
            $input_file = $cam_folder . '/' . $cam_file;
            $output_file = $converted_folder . '/' . pathinfo($cam_file, PATHINFO_FILENAME) . '.mp4';
          
            // Check if the converted file already exists
            if (!file_exists($output_file)) {
                // Convert the file if it doesn't exist
                $conversion_successful = convert_cam_to_mp4($input_file, $output_file);
                if (!$conversion_successful) {
                    echo "<p>Error converting {$cam_file}</p>";
                    continue;
                }
            }
            ?>

            <div>
                <h3><?php echo htmlspecialchars($cam_file); ?> (Converted)</h3>
                <!-- Embed video player for the converted .mp4 file -->
                <video controls>
                    <source src="<?php echo htmlspecialchars($output_file); ?>" type="video/mp4">
                    Your browser does not support the video tag.
                </video>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
  
</body>
</html>
That's gold. Thank you for making my day so much better. Well, I should thank ChatGPT too I guess...
 
That's gold. Thank you for making my day so much better. Well, I should thank ChatGPT too I guess...
dunno if something like that is even possible on cam files, never tried cam files loading.

dunno which part of my message you find hard to understand :D
 
admin to monitor flagged cams directly in his or her browser instead of downloading cams
That's right, but I assume that the administrator of a given server has a client for that server to watch the recordings anyway (and doesn't have to download them, at least in my case), so the ability to do the same in the browser can only be a nice addition :)

However, I think that players using this client to play will definitely be delighted, because they don't have to download anything or wonder if their antivirus will let it through <3
 
Meh this directx and etc support for windows.
Windows? Probably useful for most OTSes. OTS users are used to installing/running .exe to play OTSes.
DirectX? I don't think so, in every client (real Tibia, any OTC) it looks worse. Maybe it uses a bit less CPU/GPU (for sure CPU, I did not benchmark GPU), but it looks like it's lagging even with 1000+ FPS.
Everything except Windows uses OpenGL/Vulcan. OpenGL client looks more smooth on Windows than DirectX. Probably DX support in OTC can be dropped and no one will care about it.
dunno if something like that is even possible on cam files, never tried cam files loading.
It is. OTC .cam files are in OTCv8. They can be easily added to Mehah and loaded on website with same URL loading feature it uses to load client data .zip (ex. ?gameData=https://x.com/client.zip and add to it &cam=https://x.com/cam123.cam to load cam).
dunno which part of my message you find hard to understand
It's funny, because it's AI hallucination. Just look at these code comments, it's like 'AI code example' - too many comments, which does not document important parts of code (like real programmer code comments).
.cam files are not movies - .cam files are network packets dumps. ffmpeg is movie format processing tool and it has no idea what to do with .cam files (only OTCv8/Tibia Client does).
 
I moved all sub-domains, websockify and OTS to same machine.

nginx config:
arm.skalski.pro (OTS website):
  • port 80 (HTTP): redirects to port 443
  • port 443 (HTTPS): opens OTS website (PHP/website files)
web.skalski.pro (for Web Browser OTClient):
  • port 80 (HTTP): redirects to port 443
  • port 443 (HTTPS/WSS): offloads SSL, passes connection to port 6172
  • port 444 (WSS/extra for login): offloads SSL, passes connection to port 6171


websockify
config (2 commands running on 2 `screen`s):
  • port 6171: offloads WebSocket protocol, passes connection to port 7171 (websockify -v localhost:6171 localhost:7171)
  • port 6172: offloads WebSocket protocol, passes connection to port 7172 (websockify -v localhost:6172 localhost:7172)

OTS config - normal:
  • port 7171: listens for logins to account (list characters)
  • port 7172: listens for connections to game server

@OT Archive
I've replaced https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive.zip (old files threw error) with https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive_2024_10_16.zip files. You can redirect URL without version to this file.
New versions I will put in file with date in name and if they work fine, I will replace otclient-otarchive.zip with latest working version.
 
hey @Gesior.pl, can you share the conf file?
In files included are my configs from /etc/nginx/sites-enabled/ with added .txt extension (OTLand upload requirement).

I made them using these configs:
- website:
Code:
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name arm.skalski.pro;
   
    root /var/www/thais;

    index index.php index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
    }
}
- web sockets (just 1 server with port 80 for certbot):
Code:
server {
    listen 80;
    listen [::]:80;

    server_name web.skalski.pro;

    location / {
        proxy_pass http://localhost:6172;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
It's important that only one file in /etc/nginx/sites-enabled/ has default_server set next to given port ex. 80 listen 80 default_server; - you can run nginx -t to check, if there are errors in nginx config.
Then I ran certbot --nginx ( Certbot Instructions (https://certbot.eff.org/instructions?ws=nginx&os=snap) ) to generate SSL certs and edited web sockets nginx config. I've copied 443 port config (generated by certbot - with SSL config) and replaced ports: 443 -> 444 and 6172 -> 6171.

Then I ran 2 screen s and ran on them (first apt install websockify):
  • websockify -v localhost:6171 localhost:7171
  • websockify -v localhost:6172 localhost:7172

In OTC you must set login port to 444. 443 is set somewhere (probably in C++). Ex. in my init.lua of OTC it's set to:
Code:
Servers_init = {
    ["web.skalski.pro"] = {
        ["port"] = 444,
        ["protocol"] = 860,
        ["httpLogin"] = false
    },

}
In modules/client_entergame/characterlist.lua you must edit:
LUA:
    g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort,
                      charInfo.characterName, G.authenticatorToken, G.sessionKey)
to (set your websocket proxy nginx domain):
LUA:
    g_game.loginWorld(G.account, G.password, charInfo.worldName, "web.skalski.pro", charInfo.worldPort,
                      charInfo.characterName, G.authenticatorToken, G.sessionKey)
Don't forget to use OTArchive/otclient 'browser' branch when you prepare .zip with OTC files:

If you want to host .zip with OTC files data (ex. like my https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive.zip for https://webclient.otarchive.com/?version=01c750d&gameData=https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive.zip you have to edit in web server config:
Code:
    location / {
        try_files $uri $uri/ =404;
    }
to:
Code:
    location / {
        add_header Access-Control-Allow-Origin *;
        try_files $uri $uri/ =404;
    }
Make sure that in your URL there is version=01c750d ex. https://webclient.otarchive.com/?version=01c750d&gameData=YOUR_URL (it's temporary fix)
 

Attachments

Latest commits from main made keyboard walking very smooth for me, it's feeling great with ping 150+.
@Gesior.pl could you update your data pack when you have the time, please?
I think this version is great to have a first contact with the web client.
 
could you update your data pack when you have the time, please?
Updated https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive.zip to newest data/modules from https://github.com/OTArchive/otclient
Old files are available on https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive_2024_10_16.zip
New files are also available on https://downloads-oracle.ots.me/data/MehahWeb860/otclient-otarchive_2024_11_18.zip

Walking looks pretty smooth. To play use this link (if you visited it before, press Update to download newest .zip):
(login/password: ppp/ppp)
 
I just can't believe the OT community has come this far. I remember the early days of OT development, what a mess it used to be. Been through it all. But this is something different. Not even CipSoft with their ~100 employees could ever build something like this. Absolutely incredible.
 
Latest commits breaks building for browsers, I've pushed some quick fixes to my repo. You can use it while I work on properly supporting latest changes (improved UIGraph).
Main repo should be all good (no UIGraph for browsers, for now).

Updated data, modules and init.lua files are necessary.

New builds uploaded to the modular version.
 
Back
Top