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

New AAC.. But not made in PHP

Well it's my choice! You're of course welcome to use something else, but I appreciate your feedback nonetheless
Ofc it is your choice. I have no intention of talking you out of this project.
right now the main focus is 1.2.
1.3 is the development version which is also the newest, when 1.3 is done, it will be versioned as 1.4.
You can write bad code on any language =). The performance you talk about has 0 impact, you are likely to be waiting for I/O or network latency than waiting for Python... Ruby is also slow and theres Ruby on Rails still being used!
It's language syntax that sucks, bad code has nothing to do with this. But you will be waiting for Python to finish executing and execution time is what matters. Ruby also sucks, entire code looks like pseudocode, hell PHP is also ugly as hell (fuck these $ signs) while we are on the topic of web development.
 
Last edited:
Well it's my choice! You're of course welcome to use something else, but I appreciate your feedback nonetheless. ❤️




I appreciate the info, maybe at some point I'll look into it, but right now the main focus is 1.2. ♥️

why 1.2 and not 1.3?

just asking
 
Sorry for the sudden silence, I got a bit busy in March with military stuff, then in April I caught COVID-19 and was sick for like three weeks or so.

Now that I'm banned from Discord, I'll have more time to work on this, hopefully I'll have something to show in the upcoming days. <3
 
Hello hello! So for the past few days I've been working on a new AAC, .. that is made in Python 3.8 (currently using FastAPI with Jinja 2)

That is really cool! :D
I made my bachelor thesis in Python 3 about 7 years ago (Znote AAC is 9 years old, omg...), wrote a backend json API with Flask. If I didn't already have Znote AAC today (or then), I would probably have built it using Python, and later/now in Golang. Not because of performance, but because these are great languages to learn. And that is the best reason to build anything in an open source community.
Python is super relevant today, and they have a great tools to learn AI and machine learning, which very well may be the future of all software things.

And when it comes to an OT website, no matter which language you opt for, it will not be the bottleneck. (bad code probably will). So picking a language should boil down to what you would like to learn, what you would like to code in.

I miss some sort of tiny portable mysql server (its almost as if I'm missing sqlite), so it would be easy to create tiny self contained (TFS, database, web) server stack in one easy bundle. But then again I must admit, I should probably just learn docker.

PHP is also ugly as hell (fuck these $ signs) while we are on the topic of web development.

Whaat?! I feel like a badass punching in those dollar signs yo! :cool:
But since I'm using a localized keyboard, I have to macro-bind it for efficient usage. (Else I have to press altGr-4 to instantiate a variable). xD
 
That is really cool! :D
I made my bachelor thesis in Python 3 about 7 years ago (Znote AAC is 9 years old, omg...), wrote a backend json API with Flask. If I didn't already have Znote AAC today (or then), I would probably have built it using Python, and later/now in Golang. Not because of performance, but because these are great languages to learn. And that is the best reason to build anything in an open source community.
Python is super relevant today, and they have a great tools to learn AI and machine learning, which very well may be the future of all software things.

And when it comes to an OT website, no matter which language you opt for, it will not be the bottleneck. (bad code probably will). So picking a language should boil down to what you would like to learn, what you would like to code in.

I miss some sort of tiny portable mysql server (its almost as if I'm missing sqlite), so it would be easy to create tiny self contained (TFS, database, web) server stack in one easy bundle. But then again I must admit, I should probably just learn docker.



Whaat?! I feel like a badass punching in those dollar signs yo! :cool:
But since I'm using a localized keyboard, I have to macro-bind it for efficient usage. (Else I have to press altGr-4 to instantiate a variable). xD
I really appreciate it seeing you comment on this thread, ZnoteAAC is one of my current inspirations, just because it's simply made, but very useful and performant.

Hopefully I'll be able to achieve something similar but in Python!
 
So while working on the create account portion! I noticed there's a secret field for the accounts table.

What is it for? Is it two-factor authentication or password related?
I tried reading the TFS source code, but my C++ knowledge is not the greatest, I appreciate any response.
 
So while working on the create account portion! I noticed there's a secret field for the accounts table.

What is it for? Is it two-factor authentication or password related?
I tried reading the TFS source code, but my C++ knowledge is not the greatest, I appreciate any response.
Yes, it is for two-factor authentication.

Best of luck. 👍
 
So while working on the create account portion! I noticed there's a secret field for the accounts table.

What is it for? Is it two-factor authentication or password related?
I tried reading the TFS source code, but my C++ knowledge is not the greatest, I appreciate any response.

Yep, Two-factor authentication uses a standard known as RFC 6238 to generate authentication tokens, and the secret key is stored in db as account.secret. I have an implementation of it here (setup). and here (login).
 
Last edited:
I might have disappeared for a moment, woopsie daisy.
I see now there's a TFS 1.5. with 12.86 support, using some kind of web backend for the login portion of the client.
Can someone point me to a direction as to what data the webserver needs to receive and/or send? I tried digging into ZnoteAAC briefly, but I can't see a commit where most of the work was done neither can I find a wiki on the TFS repo.

Appreciate any answers.
 
I might have disappeared for a moment, woopsie daisy.
I see now there's a TFS 1.5. with 12.86 support, using some kind of web backend for the login portion of the client.
Can someone point me to a direction as to what data the webserver needs to receive and/or send? I tried digging into ZnoteAAC briefly, but I can't see a commit where most of the work was done neither can I find a wiki on the TFS repo.

Appreciate any answers.
Everything that client needs is in:
Only 'login' action is required:
Rest is just additional information for client.

Example login request (cURL format for Postman):
Code:
curl --location --request GET 'http://127.0.0.1/login.php' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "type": "login",
    "email": "[email protected]",
    "password": "1"
}'
Expected response from server (JSON):
JSON:
{
    "playdata": {
        "worlds": [
            {
                "id": 0,
                "name": "Forgotten",
                "externaladdress": "127.0.0.1",
                "externalport": 7172,
                "externaladdressprotected": "127.0.0.1",
                "externalportprotected": 7172,
                "externaladdressunprotected": "127.0.0.1",
                "externalportunprotected": 7172,
                "previewstate": 0,
                "location": "EUR",
                "anticheatprotection": false,
                "pvptype": 0,
                "istournamentworld": false,
                "restrictedstore": false,
                "currenttournamentphase": 2
            }
        ],
        "characters": [
            {
                "worldid": 0,
                "name": "Account Manager",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "None",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Druid Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "Druid",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            }
        ]
    },
    "session": {
        "sessionkey": "[email protected]\n1",
        "lastlogintime": 0,
        "ispremium": false,
        "premiumuntil": "0",
        "status": "active",
        "returnernotification": false,
        "showrewardnews": true,
        "isreturner": true,
        "fpstracking": false,
        "optiontracking": false,
        "tournamentticketpurchasestate": 0,
        "emailcoderequest": false
    }
}
 
Last edited:
Everything that client needs is in:
Only 'login' action is required:
Rest is just additional information for client.

Example login request (cURL format for Postman):
Code:
curl --location --request GET 'http://127.0.0.1/login.php' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "type": "login",
    "email": "[email protected]",
    "password": "1"
}'
Expected response from server (JSON):
JSON:
{
    "playdata": {
        "worlds": [
            {
                "id": 0,
                "name": "Forgotten",
                "externaladdress": "127.0.0.1",
                "externalport": 7172,
                "externaladdressprotected": "127.0.0.1",
                "externalportprotected": 7172,
                "externaladdressunprotected": "127.0.0.1",
                "externalportunprotected": 7172,
                "previewstate": 0,
                "location": "EUR",
                "anticheatprotection": false,
                "pvptype": 0,
                "istournamentworld": false,
                "restrictedstore": false,
                "currenttournamentphase": 2
            }
        ],
        "characters": [
            {
                "worldid": 0,
                "name": "Account Manager",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "None",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Druid Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "Druid",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Gesior",
                "ismale": false,
                "tutorial": false,
                "level": 1,
                "vocation": "None",
                "outfitid": 136,
                "headcolor": 0,
                "torsocolor": 0,
                "legscolor": 0,
                "detailcolor": 0,
                "addonsflags": 0,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Knight Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "Knight",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Paladin Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "Paladin",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Rook Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "None",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            },
            {
                "worldid": 0,
                "name": "Sorcerer Sample",
                "ismale": false,
                "tutorial": false,
                "level": 8,
                "vocation": "Sorcerer",
                "outfitid": 128,
                "headcolor": 15,
                "torsocolor": 44,
                "legscolor": 76,
                "detailcolor": 98,
                "addonsflags": 44,
                "ishidden": 0,
                "istournamentparticipant": false,
                "ismaincharacter": true,
                "dailyrewardstate": 0,
                "remainingdailytournamentplaytime": 0
            }
        ]
    },
    "session": {
        "sessionkey": "[email protected]\n1",
        "lastlogintime": 0,
        "ispremium": false,
        "premiumuntil": "0",
        "status": "active",
        "returnernotification": false,
        "showrewardnews": true,
        "isreturner": true,
        "fpstracking": false,
        "optiontracking": false,
        "tournamentticketpurchasestate": 0,
        "emailcoderequest": false
    }
}
Ahh. Thank you tons. This is super useful.
 
Back
Top