SA-MP Forums Archive
[Tutorial] y_text and y_languages - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Tutorials (https://sampforum.blast.hk/forumdisplay.php?fid=70)
+---- Thread: [Tutorial] y_text and y_languages (/showthread.php?tid=570943)



y_text and y_languages - corne - 14.04.2015

ContentsIntroduction

y_text is the single most complex library in YSI 3.0, but using it is (hopefully) very simple. The library works on the idea from HTML/CSS/JavaScript of separation of content, style and logic. Most modes contain code like this:

PHP Code:
SendClientMessage(playeridCOLOUR_RED"Hello there"); 
That's all well and good, and VERY common. But if you have a typo you need to recompile your mode, if you want to change the colour you need to recompile your mode, and changing how the text displays (for example converting to text draws) is a lot more work. y_text on the other hand has just one display method:

PHP Code:
Text_Send(playerid$HELLO_MESSAGE); 
The "HELLO_MESSAGE" text is defined in files, along with the style of the text, and can come in multiple languages, making this more equivalent to:

PHP Code:
switch(PlayerLanguage(playerid)) 

    case 
ENGLISH
        
SendClientMessage(playeridCOLOUR_RED"Hello there"); 
    case 
FRANCAISES
        
SendClientMessage(playeridCOLOUR_RED"Bonjour il"); // Etc.. 

By default y_languages supports five languages at once, but this can be increased VERY easilly.

Text

There are three parts to displaying text: Creating the files, loading them, and displaying the text. Fortunately these are all quite simple.Let's say you decide you want two languages: English and Dutch (Nederlands)*. You first create two files, I'm going to name them "mode_text.EN" and "mode_text.NL" (the names aren't important, they just need to be consistent), and put them in "scriptfiles/YSI/text":
Code:
[all] 
HELLO_MESSAGE = Hello there 
BYE_MESSAGE = Goodbye
Code:
[all] 
HELLO_MESSAGE = Hallo daar
BYE_MESSAGE = Tot ziens
These are both INI files with standard "KEY = Value" pairs. They also MUST contain sections (here "[all]" is a section), but the simplest way is to just have one.

You also need a third file called "mode_text_LANG_DATA.yml" in "scriptfiles/YSI", but I'll come to that later.
There are two stages to loading a text file, both shown in the code below:

PHP Code:
loadtext mode_text[all];
public 
OnGameModeInit()
{
    
Langs_Add("EN""English");
    
Langs_Add("NL""Nederlands");

The "loadtext" line gives the current script file access to the items defined in the listed file and section. You can have up to about 5 items on one line and only one line (current code restriction) PER FILE:

PHP Code:
loadtext mode_text[section1], mode_text[section2], other_text[what], other_text[where]; 
The "Langs_Add" line tells the language system which languages to load and gives the name of that language in that language (hence "Dutch" is "Nederlands"). It also defines the two letter short code for that language, which is used to select the exact file to load. "English" is defined as "EN" and the file is "mode_text.EN", simillarly "Dutch" is defined as "NL" and the file is "mode_text.NL". Note that this is the ONLY function in YSI that will give a warning if it is not used because YSI needs to know what languages to load for internal text (even if you don't use the system yourself).This is possibly the simplest part:

PHP Code:
Text_Send(playerid$HELLO_MESSAGE); 
"Text_Send" is a VERY clever function:Targets

As mentioned, text can be sent to any number of people, meaning you no longer need "Text_SendToPlayer", "Text_SendToGroup", "Text_SendToAdmins", "Text_SendToAll" etc. The first three methods are designed to mimic existing code methods and make for simple integration in to existing modes. When you send a message to mutliple people using one of the methods below every player will get the message in their own language. These calls are also optimised for many people and multiple languages so are better than simply calling "Text_Send" in a loop (there is text buffering to re-use calculated output instead of re-running processing).
PHP Code:
new
    
bool:gIsAdmin[MAX_PLAYERS];
// Notice that this is only on one line, unlike the declaration above!  This is
// another system restriction but shouldn't be too bad.
loadtext some_file[some_section];
stock Func()
{
    
Text_Send(@ gIsAdmin$SOME_MESSAGE);

The above code will send the message "$SOME_MESSAGE" to everyone for whom "gIsAdmin" is TRUE (you can't do it for everyone who is FALSE). Note that "gIsAdmin" is not a YSI array (just a nomal array) so you need "@" on the front to convert it (another restriction I've tried to make as low-impact as possible).
PHP Code:
new
    
gAdmins[MAX_PLAYERS] = {04245INVALID_PLAYER_ID27, ...};
// Notice that this is only on one line, unlike the declaration above!  This is
// another system restriction but shouldn't be too bad.
loadtext some_file[some_section];
stock Func()
{
    
Text_Send(@ gAdmins$SOME_MESSAGE);

This code is very similar to the previous code, but instead of an array of true/false, this is a list of player IDs, with "INVALID_PLAYER_ID" (or the end of the array) denoting the end of the list. The code above will send the message to players 0, 42 and 45. 27 WILL NOT get a message as their ID appears AFTER "INVALID_PLAYER_ID", denoting the end of the list.The first two methods are common, but possibly the more common method of storing data on players is through an enum array:

PHP Code:
enum E_PLAYER_DATA
{
    
E_PLAYER_DATA_SOMETHING,
    
E_PLAYER_DATA_OTHER,
    
bool:E_PLAYER_DATA_ADMIN
}
new
    
gPlayerData[MAX_PLAYERS][E_PLAYER_DATA]; 
Often you will want to send a message to everyone for whom "E_PLAYER_DATA_ADMIN" is true. This is (in "y_text" speak) a "custom" array:

PHP Code:
stock Func()
{
    
Text_Send(@ gPlayerData<E_PLAYER_DATA_ADMIN>, $SOME_MESSAGE);

This specifies that "gPlayerData" is a 2d enum array and only the "E_PLAYER_DATA_ADMIN" slot should be used. It should be noted that this line MAY give a warning about index tag mismatches, I don't know how to avoid this so just ignore it.YSI has a system called "y_groups". This is an abstraction from any system which collects people together for some reason (admin levels, factions, teams, jailed players etc) - it is designed to handle them all and can allow for people to be in multiple groups at once (admins can also be in factions etc). Groups are apart of YSI so are handled natively - i.e. they don't need converting with "@":

PHP Code:
new
    
Group:gAdmins;
public 
OnGameModeInit()
{
    
gAdmins Group_Create("Admins");
}
stock Func()
{
    
// No "@" in front of the variable.
    
Text_Send(gAdmins$SOME_MESSAGE);

The code above will, unsurprisingly, send the message to everyone in the "gAdmins" group. Groups in general have been documented before in another tutorial so will not be covered further here.This is the last of the array style calls. Many people know that boolean arrays such as in the first example are very inefficient, being 32x larger than they need to. YSI (and, many years later, other systems) instead use binary arrays to pack this data down - "y_playerarray" is one of these systems (based on "y_bit"), specially designed for players and y_text.

PHP Code:
new
    
PlayerArray:gAdmins<MAX_PLAYERS> = {PA_INIT:false, ...};
stock Func()
{
    
// No "@" in front of the array.
    
Text_Send(gAdmins$SOME_MESSAGE);

This behaves exactly like the first target, but with less memory and slightly more efficiently.You can of course just pass a single player to "Text_Send":

PHP Code:
Text_Send(playerid$SOME_MESSAGE); 
All the above player passing examples are not actually part of "y_text" specifically, but another library called "y_playerset". Any custom function can be written to take all these input options:

PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerArray:players<MAX_PLAYERS>)
{
    
// "players" is now a YSI "PlayerArray" of all the players passed at once.
    
foreach (new playerid PA(players))
    {
        
// Uses "PA".
    
}

PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerVar:player)
{
    
// This function will be called multiple times automatically, once for every
    // player passed in any array.

PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerSet:players)
{
    
// "players" is now a special compact representation of all the players
    // passed and can be used in iterators.  This is different to using
    // "@PlayerArray" as it's just a single variable, not all players at once.
    
foreach (new playerid PS(players))
    {
        
// Uses "PS".
    
}

Styles

Obviously "Text_Send" has no included information as to HOW the text should be displayed - using "SendClientMessage", "GameText", "TextDraw" or anything else. This is all set in the "LANG_DATA" file:
Code:
[all]
HELLO_MESSAGE = Hello there
BYE_MESSAGE = Goodbye
Code:
[all]
HELLO_MESSAGE = Hallo daar
BYE_MESSAGE = Tot ziens
[/list]
Code:
<YML>
	<group name="all">
		<entry name="HELLO_MESSAGE" style="client" colour="X11_RED" />
		<entry name="BYE_MESSAGE" style="3" time="4000" />
	</group>
</YML>
This is an XML file holding the style information for all text entries in the given file (here "mode_text_LANG_DATA.yml" holds the information for "mode_text". These elements are grouped together and each entry has a separate line."style" can be any of the following:The other options depend on the selected styleThe selected style determines which sort of "GameText" you would like to use to display the data.These are not yet fully supported.

Format

"Text_Send" can take format parameters, and it has been extended with a greater number than the default "format" function.There are a few more from the old version of YSI that are not yet ported (including "p", "t" and "u").The default format can have specifiers like "%02s" to pad or restrict output length. YSI fully supports all these modifiers and adds two more experimental ones:


Re: y_text and y_languages - valych - 13.05.2015

I'm very interested in these includes and I have a question:
Is there any possibility to write specified text to an array depending on language, i.e. is there any function like Text_Get(Language:lang, identifier[], dest[]) - where lang - is a language, identifier is a key for text (like HELLO_MESSAGE) and dest - is a destination array?


Re: y_text and y_languages - andyandyy8 - 24.06.2015

How can I use y_dialogs with y_text?


Re: y_text and y_languages - andyandyy8 - 26.06.2015

Does anyone know?


Re: y_text and y_languages - Patchwerk - 26.06.2015

Quote:
Originally Posted by andyandyy8
View Post
Does anyone know?
https://github.com/Misiur/YSI-Includes/issues/17


Re: y_text and y_languages - Misiur - 27.06.2015

@valych it's on queue of things I have to do
@anyandyy8 fix is now in trunk


Re: y_text and y_languages - andyandyy8 - 28.06.2015

How can I set the color of a text?
I tried to change but it doesn't work. Take a look here: https://github.com/Misiur/YSI-Includes/issues/25.


Re: y_text and y_languages - Flashhiee - 26.04.2018

Sorry for the topic bumping..but is there any way to style a group of texts without creating a new line for every single one.
I tried doing it like shown bellow, but it doesn't work.


PHP Code:
<yml>
    <
group "whatevergroup" color "whatevercolor"/>
</
yml
The way i have to do it right now:

PHP Code:
<yml>
    <
group "whatevergroup">
        <
entry name "whatevertext1" color "whatevercolor/">
        <
entry name "whatevertext2" color "whatevercolor/">
        <
entry name "whatevertext3" color "whatevercolor/">
        <
entry name "whatevertext4" color "whatevercolor/">
        ....and 
so on...
    </
group>
</
yml
OffTopic: BTW this topic is so underrated, i think it deserves this bump.