26

Re: Are leagues "community business"?

i did not say that he ain´t doing a good job, just that the temporary hud is perfectly fine and it came to my ears (or better, eyes) that there is something new planed. that´s why i wrote that sad

27 (edited by lamefun 2014-11-18 13:38:04)

Re: Are leagues "community business"?

There are several more important problems in my opinion:

* Client-side only localization, English-only website, no language auto-detection.
* Lack of client-side scripting and data downloading blocks almost all complex modding (Star Wars - never released, Nodes - died, Aviator - died). This leads to stagnation.
* "Standard Maps" check box and slow map downloading.
* Lack of weapon lag compensation.

Anyway, I'm probably going to try to write a replacement engine for Teeworlds with ZIP packages and JuaJIT scripting. If all goes well, I'll start a thread when it loads its first ZIP package and runs its first script.

28

Re: Are leagues "community business"?

lamefun wrote:

There are several more important problems in my opinion:

* Client-side only localization, English-only website, no language auto-detection.
* Lack of client-side scripting and data downloading blocks almost all complex modding (Star Wars - never released, Nodes - died, Aviator - died). This leads to stagnation.
* "Standard Maps" check box and slow map downloading.
* Lack of weapon lag compensation.

Anyway, I'm probably going to try to write a replacement engine for Teeworlds with ZIP packages and JuaJIT scripting. If all goes well, I'll start a thread when it loads its first ZIP package and runs its first script.

Zip for what? The maps uses ZLib compression... the problem with the download speed its that uses UDP protocol... and need rewrite all TCP concept (Lost packets, congestion, errors, order, ...) for me the best way its open a TCP comunnication when send .map...

29 (edited by lamefun 2014-11-18 17:57:12)

Re: Are leagues "community business"?

Downloadable packages of course, that can contain images, scripts, etc. ie.

teeworlds.zip
- package.json { "name": "teeworlds", "version": "0.8.0-alpha.1", "dependencies": { "teeworlds-data": "0.8" } }
- scripts/game/main.js
- scripts/menu/main.js

teeworlds-data.zip
- package.json { "name": "teeworlds-data", "version": "0.8.0-alpha.1" }
- tilesets/grass.png
- tilesets/snow.png
- music/menu.ogg
- maps/dm1.map

So mods can use custom images, sounds and even their own custom file types. Mods will get to access the files from JavaScript like:

var file = engine.vfs.open('/packages/teeworlds/1.0/tilesets/grass.png');
var data = file.readAsBytes();

And I'm probably going to have to use JavaScript anyway. As much as I didn't want to embed the large v8 library with rapid API changes...

http://repo.or.cz/w/luajit-2.0.git

I can see commits from May in the shortlog. Not good... The official programming language of planet Earth wins yet again!

And it's a big if whether I'll actually manage to do this.

30

Re: Are leagues "community business"?

Looks to me as if you were considering rewriting teeworlds entirely except for graphics and sound.
Very ambitious.

Developper of teeworlds-stats.info

31

Re: Are leagues "community business"?

I agree with Alucard that the game kind of reached its peak. If you want to change this ( could turn out better , could also turn out worse ) you'll have to do drastic adjustments as was stated all over this topic. The problem is this will again take a whole lot of time and effort without guarantee of succes.

Visit our clan: =Eagle= !

32

Re: Are leagues "community business"?

Never mind. I'm fed up with C++ and programming.

33

Re: Are leagues "community business"?

Sorry, I am in hurry.
Here is my specification in a way, how I think it would work.



Specification for Teeworlds Account Management System (TAMS)

1. Introduction
Teeworlds development follows the KISS-Principle. With its current release state it is becoming
a "nearly perfect" game (Landil, Magnet). The current development reached an as-is state that is
acceptable. Past tasks are finished and Teeworlds offers a solid basis, having all needed features
implemented. On this basis is much space further ideas left to maximize game experience and extend
features. Today, Teeworlds is a simple and nice game, but lacks of players and supported competitive game
methods. A first step to overcome this problem is TAMS.
TAMS should add a way to to authorize a client as player. While using known methods (like identication
with name and passphrase), it can be extended with more valuable functions like clan-support, friends-
support, global chat-support and server-sided data-storage. On the other hand, given identity grants
better server- and match-finding methods and adds new ways to organize competitive game.
Regarding to KISS, used functions and algorithms should keep as simple as possible. Thought many new
features can simplify the game usage and grand a better game experience, an account should not be
required to join a server and play. As Teeworlds source code is open, the authentication service must
be seperated from the existing server code. Otherwise it could be altered and abused.

https://dl.dropboxusercontent.com/u/33670843/Teeworlds/Diagram1.png

2. Functions
Following functions will be needed to fulfill the requirements. For better systematization they are
structured as Authentication Service, Client and Server.

2.1 Authentication Service (AS)
  // AS1 //    CreateAccount()
        Simple function to create a user account with following properties:
            - AccountName, the name for the account the player wants
            - Passphrase, used for authentication
            - Clan_ID, clan the player is member in
            - Countryflag, visualizing where he is from
            - Gamemode, preferred gamemode of the player
            - Ip_Address, current address he is connected with
            - Timestamp, when he logged in last
            - AuthKey, generated by AS (Session key)
        Those data should be stored in a database and be linked with other proper datasets.
        Returns 0 (error) or 1 (success).
       
  // AS2 //    DeleteAccount()
        Deletes the existing account and all related information about it.
        Should require identication first.
        Returns 0 (error) or 1 (success).

  // AS3 //    EditAccount()
        Function to edit values of an account, like passphrase, clan, countryflag.
        Should require identication first.
        Returns 0 (error) or 1 (success).
   
  // AS4 //    AuthClient()
        Function to authenticate a client.
        1. Client sends accountname and passphrase to this function.
        2. AS checks if match:
            true: AS generates a temporary valid AuthKey for the client and logs the Timestamp
        Returns AuthKey  (success) or 0 (error)
       
  // AS5 //    LogoutClient()
        Function to log out a client.
        Returns 0 (error) or 1 (success).
       
  // AS6 //    AuthValidate()
        Validates an sent AuthKey for an account, to prove his identity.
        1. Clients sends his AuthKey to the server, where he wants to get identicated.
        2. Server sends the received AuthKey with the clients AccountName to this function
            AuthValidate
        3. AS checks if match:
        Returns 0 (error) or 1 (success)
       
2.2 Client
  // C1 //    CreateAccount()
        Uses // AS1 // to create an account at AS.
        Parameters:
            - AccountName
            - Passphrase
            - Clan
            - Countryflag
            - Gamemode
        Shows the return of // AS1 // to the user.
       
  // C2 //    DeleteAccount()
        Uses // AS2 // to delete an existing account of AS.
        Parameters:
            - AccountName
            - Passphrase
        User should have to identify first.
        Shows the return of // AS2 // to the user.
       
  // C3 //    EditAccount()
        Uses // AS3 // to edit the account data of the account of AS.
        Editable parameters:
            - AccountName
            - Passphrase
            - Clan
            - Countryflag
            - Gamemode
        Shows the return of // AS3 // to the user.
       
  // C4 //    AuthAS()
        Sends authentication values to // AS4 // to identify.
        Parameters:
            - Accountname
            - Passphrase
        Sends the return of // AS4 // (= AuthKey) to // S1 //.
        Shows the return of // S1 // to the user.
       
2.3 Server
  // S1 //    AuthClient()
        Called by // C4 //.
        Sends received data (AccountName, Passphrase) to // AS4 //.
        Validation success: Calls SendValidation with AccountName.
        Returns // AS4 // return (0 = error, 1 = success).
       
  // S2 //    SendValidation()
        Sends the succeeded authentication to all clients connected to the server.
        Clients should be able to put this information to use, e.g. in the scoreboard.
       
3. Further features
With the system as descriped above, it is possible to implement server independent features.
Here some ideas:

3.1 Friend list
The current friend list is based on nicknames. If a player with the nickname on your friend list
plays on a server, the server browser will mark it. On the other hand, when playing on server with a
friend on it, the score board will show it. Some functions can work with the data.

TAMS could release the friend list of the servers. When binding the friend list to accounts of AS,
you will be able to get information about the client without the need to join the same server as he did.
Information like who is online, who just went online, who goes offline, and which server someone is
joining can keenly change the way you communicate and play with friends.

Following functions need to be altered or added:
// AS 4 //    AuthClient()
        Function to authenticate a client.
        1. Client sends accountname and passphrase to this function.
        2. AS checks if match:
            true: AS generates a temporary valid AuthKey for the client and logs the Timestamp
                + AS logs the IP address of the client
                + Calls // AS 4.1 // SendLoginNotification()
        Returns AuthKey (success) or 0 (error)
                + a list of all online friends.

+ // AS 4.1 // SendLoginNotification()
        Uses // C 4.1 // to send a login notification to all (online) friends of the
        authenticated client.

+ // AS 4.2 // ReceiveLogoutNotification()
        Receives // C 4.2 // and calls // AS 4.3 //.

+ // AS 4.3 // SendLogoutNotification()
        Uses // C 4.3 // to send a logout notification to all (online) friends of
        the authenticated client, that is going offline.

+ // C 4.1 // ReceiveLoginNotification()
        Receives a login notification, if a friend goes online.
        Displays it to the user.

+ // C 4.2 // SendLogoutNotification()
        Sends a logout notification to AS.
        Should be called when the application is going to exit.

+ // C 4.3 // ReceiveLogoutNotification()
        Receives a logout notification, if a friend went offline.
        Displays it to the user.


3.2 Global chat
The friend list function as described in 3.1 stores all IP addresses of authenticated clients.
Knowing the IP addresses gives the possibility for a global chat. As the client receives a notification
which friend went online (authenticated) and is online. The client can send chat messages to AS, who
forwards them to the addressed client.

Following functions need to be added:
+ // C 5 //    SendChatMessage()
        Uses // AS 7 // to send a chat message to a friend.
        Parameters:
            - Friend (AccountName)
            - ChatMessage

+ // C 6 //    ReceiveChatMessage()
        Receives a chat message.
        Displays the message in a chat window.

+ // AS 7 // ForwardChatMessage()
        Uses // C 6 // to forwards a chat message of // C 5 // to the friend (AccountName)
        Returns 0 (error) or 1 (success).


3.3 Match history
A match history would require "trusted servers" to prevent the system being abused. After the match is
finished, the server will send the results to AS.

Following functions need to be added:
// S 3 //    SendMatchResults()
        Uses // AS 8 // to send the results to AS.
        Paramters:
            - timestamp
            - result
            - length
            - Player-Stats:
                - Accountname
                - Score
                - Kills
                - Deaths
                - ...

// AS 8 //    ReceiveMatchResults()
        Receives the match results...
        Stores them in a proper way.
           
        Match            Match_Player
        +----------+        +----------------+
        | M_ID     |-------| M_ID            |
        | time      |         | AccountID    |
        | result    |         | Score           |
        | length   |         | Kills              |
        +----------+        | Deaths         |
                                +-----------------+


3.4 Achievements
The stored match history gives comprehensive possibilities for reportings and achievements.

https://dl.dropboxusercontent.com/u/336 … m_Rev1.txt

34

Re: Are leagues "community business"?

Counrryflag should be set by the system by defining the IP's location. Clan should only be set if the creator of the clan allows it.

Move along, nothing to see here, really.

35

Re: Are leagues "community business"?

Just gonna throw out some stuff that has been talked about before. Feel free to disregard everything if you want smile

Account system
Me and minus have talked a lot about an account system and design for it years ago. The absolute simplest thing you could do it to hook up the this forum to it and off you go. However, neither of us are a fan of centralized services and therefore rejected this idea. This is a bit of the reason for the design of the master servers as well so anyone can setup a master server as well. A better design would be to use some discovery-system so we don't have to hold the standard master servers. The less control we have, the less we have to get involved with tricky player disputes.

The design we were fiddling with for an account system looked more like email and XMPP (we even talked about just using XMPP). This will allow anyone to setup an account server and get their unique id in the user@server.com fashion. This is the system I would like to see if I ever saw one in Teeworlds but no one had time to sit down and actually write it. Loads of security concerns here as well.

I've been thinking if you could go the other way with the whole thing, making players more anonymous to each other. Strip away skins (random on join), no names and no chat. Blizzard have been trying this out a bit with hearthstone to get rid of a lot of issues. Would be a nice experiment to have as an option on the servers.

Matchmaking
Doing matches with queues etc have a lot of problems with what servers to use and how to validate the result. Trusted servers etc but it requires a lot of administrative work. One of the core things in Teeworlds was that I should be able to drop dead the next day and it should just continue. Running trusted servers etc is a huge burden and the increased impact of cheating is not going to be favorable.

Client side scripting
Client side scripting has been on the wall several times as well. My ressys branch is a step in that direction. It allows the client to fetch all kinds of different resources from disc, game server and http server in the background. All it needed to start is the actual exe file. Then next step would be to allow client-side scripting to control some rendering. This is a whopper of a security concern as allowing anything close to Turing complete to be sent from the server to the client is a never ending nightmare of possibilities to screw the client over. I fiddles with a custom language and vm which would be sufficient to do simple flow control to do the rendering of the snapshot without the halting problem. The code for this was less then 600 lines with python and c code. Very easy to verify that it wouldn't do anything weird.

Achievement
There were early design of "achievement" (called badges) that people would get after each match, but those would only just show on the scoreboard when the match was done and then forgotten forever.

My misstake
Also, I say that one of the biggest engineering mistakes I've done with Teeworlds were to add translations. Adds a lot of developer-developer interaction and synchronization for very very little benefit. Better would be to make the UI more understandable in other ways with graphics.


/rant

Cheers!

36

Re: Are leagues "community business"?

matricks wrote:

Achievement
There were early design of "achievement" (called badges) that people would get after each match, but those would only just show on the scoreboard when the match was done and then forgotten forever.

My misstake
Also, I say that one of the biggest engineering mistakes I've done with Teeworlds were to add translations. Adds a lot of developer-developer interaction and synchronization for very very little benefit. Better would be to make the UI more understandable in other ways with graphics.
!

If you are in need for some achievement graphics in your neighbourhood, who you gonna call? wink

I supported the language support from the early beginning ... and it was wrong. One of the worst decisions regarding teeworlds I think.

Antoine de Saint Exupéry: It seems that perfection is reached not when there is nothing left to add, but when there is nothing left to take away.
Besides -  I am the gfx guy!

37

Re: Are leagues "community business"?

an account system would clear the issue with the achievements, which means that they would stay. IF this is going to work with an acc system, please note the following line:
- either enable an "ranked game" option, or create a lvl system where the number of frags will be valued as exp. points... or simply make both

everything has it´s pro´s and con´s but it is worth a shot since it opens more options than before. using the account from the forum as an in game account would surely bring it´s benefits too. Here is a solution to a concern that might have gotten through your mind while reading the line before this:
- the account option HAS to be an option of choice by the player, which means, if some1 new jsut discovered teeworlds for himself and he starts to play, it would be wrong to force him to create an account. Instead of forcing him to do that, there can be either a pop-up window, a hint bubble or a blinking tab in the upper corner which is suggesting to create an account which also explains the benefits of it (don´t forget to add the "don´t ask again" otpion if it´s a bubble or pop-up). With some amazing writing skillz, the new guy will be convinced to create a new account, which means that he will also register here and that he will have an automatically created account in game.

since i am lacking in time atm, i´ll add some stuff later regarding:
- "ranked game"
- why forum account = in game account

ps. don´t blame yourselves for the language support, it was a kind gesture towards the players wink

38

Re: Are leagues "community business"?

If we combine the ingame account with a forum account, then the game gets dependent from the forum (server).
If we don't, then players could build there own account system and modify it in the way they want it.

@matricks Matchmaking
I see your point there, that the teeworlds dev team gets essential if we are going for official account systems. On the other hand we shouldn't disregard the option to leave account systems to the community. I am pretty much sure, that we will have soon popular account "networks" build up by them. A client option to pick a account server completes it, and the teeworlds dev team is dispensable again!

39

Re: Are leagues "community business"?

TAMS is imho the best thing that can happen to teeworlds. Guys i know its a lot of hard Work and there will be a lot of problems by starting this up. But Teeworlds needs it.

40

Re: Are leagues "community business"?

One question I have about the account system, why is it needed? Finding what servers friends are playing on? Server administration?

41

Re: Are leagues "community business"?

@matricks: Players do need something to fight for, atm teeworlds really lacks of organization; there are mostly just some random ctf5 games at midlevel, only highlevel is more organized. An accountsystem would offer stats and global rankings probably even an official clansystem, which might lead to clan-tournaments. Like this there were goals to fight for and that is what players like (see ddnet with its point and ranksystem).

Luck is allowed

42

Re: Are leagues "community business"?

Imho Teeworlds with its current version 0.6.3 is NOT capable for further features like achievements, match making, match history, rankings, leagues...

Yes, TAMS isn't needed to play Teeworlds. But this is a benefit, because this way you don't need an account (Q.E.D.).
But on the other hand, as HMH pointed out, TAMS enables various features that can maximize the gaming experience (most important goal for a game imo).

I really do not know how keen you, our devs, are discussing this/ such a system. But please don't hesitate to publish any criticm or ideas here! Currently we are rather talking around it, not about it.

43

Re: Are leagues "community business"?

Generally, account system will offer a lot of things. Starting from collecting your stats, to obtain achievements etc.. You can make division system, searching for players (friend list as someone said before) , filter servers via skill, better warning/ban system etc.
Btw. i think "reservation" of nickname isn't needed... just identified player by account.

And yes, account system will give us a lot of things and problems. But still very usable smile

44

Re: Are leagues "community business"?

I have a hard time collecting my thoughts on paper about this subject but I'm going to try.

There is a huge fork in the road when it comes to the account system. There are a couple of ways to go on and doing it and they all have merits and problems. One option is just to skip it and not do it at all. There are two main roads here, the central way and the decentralized way. Have a central account system that people have their accounts on a server that the team manages and takes care of. The other one is to allow people to setup their own account server (like how email, xmpp etc). A really lightweight version is just to do a player identification system using crypto keys and this doesn't require any extra servers at all.

I really dislike the central way because it puts burden on a team to carry that system and is not the spirit of openness. Everything (including masterservers to some degree, wish it was better) in Teeworlds were designed so that the whole development team could disappear tomorrow and the game will continue to work.

I've tried to gather a bit of information through out the discussions to see what people actually want.

Statistics and achievements - This doesn't require an account system and can be done locally by the client.

Better bans - This requires a central account system in order to be efficient at all and still ban evasion is still gonna be a problem due to duplicate accounts etc. Having mods looking into player disputes is going to be a time consuming hassle like no other with lacking evidence.

Better friend list - Doesn't require an account system. Can be done with a player identification.

Division, skill ranking system, matchmaking, match history - This is such a huge can of worms I don't even know where to start. How do you measure someones skill? It requires a rethought about the drop-in/out system that Teeworlds have at the moment in order to solve I think. This will be even more trouble some with different gametypes and add the issue with modded servers and we are going to have a real soup. You could do a per server skill ranking perhaps but that again does not require an account system, just player identification


At the end of the day, I don't really think an account system will offer that much. A player identification system is something that could more useful.

45

Re: Are leagues "community business"?

Could you please explain a "player identification system" further?
I would define it as a server that authenticates the player. (What would be similiar to TAMS)

matricks wrote:

Statistics and achievements - This doesn't require an account system and can be done locally by the client.

Yes, we can. But they neither could be shared (or be "public visible"), nor could they be verificated. I agree that a client-only solution would be possible and probably a good beginning.

matricks wrote:

Better bans - This requires a central account system in order to be efficient at all and still ban evasion is still gonna be a problem due to duplicate accounts etc. Having mods looking into player disputes is going to be a time consuming hassle like no other with lacking evidence.

If it is done decentralized, server admins could build up a "banned player" database to share with each other. Yes, it wouldn't be as efficient as a centralized system, but I wouldn't agree that it is required to be "efficient at all".
Duplicate accounts are a problem most likely all f2p games have to fight with, but it would at least help to ban a specific account with its statistics, achievements and "fame".
I agree that we don't have the manpower for mods.

matricks wrote:

Better friend list - Doesn't require an account system. Can be done with a player identification.

Dunno how you want to implement a global friend system (with chat possibility etc) without a server sharing information like IP.

matricks wrote:

Division, skill ranking system, matchmaking, match history - This is such a huge can of worms I don't even know where to start. How do you measure someones skill? It requires a rethought about the drop-in/out system that Teeworlds have at the moment in order to solve I think.

Discussing about ranking algorithms would be a next (future) step. I was thinking about some kind of ELO rating (short: Win against a high rated player = many points; win against an even rated player = some points; lose against a higher rated player = lose a few points; etc).
I could imagine using such a skill system TAMS-wide, giving the possibility for linked server rankings.

46

Re: Are leagues "community business"?

Slayer *gV* wrote:
matricks wrote:

Statistics and achievements - This doesn't require an account system and can be done locally by the client.

Yes, we can. But they neither could be shared (or be "public visible"), nor could they be verificated. I agree that a client-only solution would be possible and probably a good beginning.

I guess verifyable systems would need trusted servers – another thing the team would need to do, it would also furtherly give more incentive to cheat, in order to get a better displayed rank (see other games).

Slayer *gV* wrote:
matricks wrote:

Better friend list - Doesn't require an account system. Can be done with a player identification.

Dunno how you want to implement a global friend system (with chat possibility etc) without a server sharing information like IP.

Would work with some cypto, the server could send public keys or so.

Slayer *gV* wrote:
matricks wrote:

Division, skill ranking system, matchmaking, match history - This is such a huge can of worms I don't even know where to start. How do you measure someones skill? It requires a rethought about the drop-in/out system that Teeworlds have at the moment in order to solve I think.

Discussing about ranking algorithms would be a next (future) step. I was thinking about some kind of ELO rating (short: Win against a high rated player = many points; win against an even rated player = some points; lose against a higher rated player = lose a few points; etc).
I could imagine using such a skill system TAMS-wide, giving the possibility for linked server rankings.

Yes, that would probably be the way to go. However, I also see the higher cheating incentive as a bad side effect. hmm

47

Re: Are leagues "community business"?

I just read that specification (thanks Slayer!) and here are my thoughts about it:

First of all I would shrink the Authentication Service to the minimum:
A Player can register himself there and a (game)server can request challenges for authentication.

Scenario:
Player P joins Server S and says "Hi, I'm 'BeaR@auth1.teeworlds.com'"
S sends a challenge request to the AS 'auth1.teeworlds.com' for player 'BeaR'
AS returns a challenge to S
S sends the challenge to P, who should solve it and send it back to S

So you only have to register yourself at one AS. My intention is to decouple the actual game account data and the pure identification/authentication of a player as there might be other account server for different gametypes and groups of gameservers (a ctf server network, ddnet, instagib network), which all could have their on type of account data per player.

Scenario:
Player P joins CTF Gameserver S, which is part of a larger account system 'CTF Acc'
S auths P as in the scenario above
S notifys the account system 'CTF Acc' that a player has joined
The account system looks up it's database if this player already exists (if not it creates a new account for this player) and returns the account data to the server

48

Re: Are leagues "community business"?

matricks wrote:

A really lightweight version is just to do a player identification system using crypto keys and this doesn't require any extra servers at all.

This looks like the best way to go. Keeping it as small and simple as possible.

Remember the 80s - good times smile

49 (edited by invee01 2015-02-06 21:23:15)

Re: Are leagues "community business"?

The account system should be strictly optional. I want to be able to open the teeworlds client anywhere and only worry about typing in my alias and connecting with the game server.

For players like me who really don't give a shit about the competitive aspect of teeworlds, a mandatory account registration would turn me and possibly other casuals away from teeworlds for good.

Tbh what turns me off about the account concept most is being easily identifiable (for personal purposes), which is why I'd turn to other methods to keep my anonymity. This is especially true if the IP-tracking for flag purposes is ever implemented.
In fact, the flag-by-IP would be less effective than manual flag selection for honest purposes, as those using proxies could have the wrong flag. (Eg. someone who is american and wants to be recognized as one being forced to have some european flag appear, causing confusion and forcing them to either let the confusion continue or deal with explaining the situation to everyone)

matricks wrote:

I've been thinking if you could go the other way with the whole thing, making players more anonymous to each other. Strip away skins (random on join), no names and no chat. Blizzard have been trying this out a bit with hearthstone to get rid of a lot of issues. Would be a nice experiment to have as an option on the servers.

I'd participate in more tournaments if I could play under near-complete anonymity. This can actually be implemented already by modifying some source code.

50

Re: Are leagues "community business"?

invee01 wrote:

In fact, the flag-by-IP would be less effective than manual flag selection for honest purposes, as those using proxies could have the wrong flag. (Eg. someone who is american and wants to be recognized as one being forced to have some european flag appear, causing confusion and forcing them to either let the confusion continue or deal with explaining the situation to everyone)

Although this is true, flags are also being used because they look "cool", so no real identification possible anymore.