# Marin's Compiler

Pokémon Essentials Version
This resource can be installed via the Universal Plugin Installer.

The main inspiration to make this was the lack of plug-and-play support of the standard Compiler that comes with Essentials. You can't add a PBS file in a new script section without editing the Compiler script, and you therefore lose plug-and-play support, which I think is super important.

This is more or less useless as-is, but it will be used for some of my future resources. That said, anyone else is free (and I actually advise) to use this for their own plugins. This means that you must have decent Ruby skills to understand any of what I'm gonna say. That said, if you ARE a programmer but are confused about anything, feel free to ask.

Installation
First off, install my Scripting Utilities.

If there are any plugins that use this compiler, you have to put it above that plugin. Currently, there are no plugins that use this, so you don't need to worry about this.
MarinCompiler

Documentation

To force the compiler to compile, hold SHIFT. Not CTRL, SHIFT. This so the default compiler and this custom compiler don't BOTH recompile.
That said, it will automatically compile anyway if it detects changes in any of the PBS files. It will ONLY recompile THOSE files with changes; not all of them!

MarinCompiler.compile_where_necessary goes through each file and determines whether or not it has to be recompiled, and if so, it will compile the PBS file. If the PBS does NOT exist but the data files DOES, it will try to decompile the PBS file into the PBS file. For this to work, your custom PBS file must implement a decompile option. This has to be done manually by loading the data file and writing those options to a text file, and then save it to your desired destination.

MarinCompiler.load Loads every single registered data file, whether they've previously been compiled or not.

First off, MarinCompiler.register(pbs_file,data_file,compile_proc,load_proc,decompile_proc = nil) is the method you need to use:

• pbs_file : This is the path of the file in the PBS folder.
• data_file : This is the path of the file in the Data that contains the compiled PBS file data.
• compile_proc : This is the code that will be run when this PBS file is compiled.
• load_proc : This is the code that will be run when this Data file needs to be loaded.
• decompile_proc (OPTIONAL) : If there is a Data file but not a PBS file, this is the code that will be run to create a PBS file with the Ruby data. This is completely optional, but similar to methods like pbSaveAbilities. It may come in handy when one has lost their PBS files but still has their data files; well-worth including.

The compile proc is different depending on the type of PBS file you have. There are two main types you can make with this resource; comma based and section based:

Comma based PBS looks like moves.txt, which works per-line. Each line is a new entry which follows a specific format, like so:
Code:
1,MEGAHORN,Megahorn,BUG,Physical,120
2,BUGBUZZ,Bug Buzz,BUG,Special,90

Let's say we put this in a file called new_pbs.txt, and we want to compile it to a data file called new_pbs.dat. The code would look like this:

Code:
MarinCompiler.register("new_pbs.txt", "new_pbs.dat",
proc do # Compile
lines = []
MarinCompiler.comma_based("icseei",
nil,nil,nil,PBTypes,["Physical","Special","Status"],nil
) do |line|
lines[line[0]] = line[1..-1]
end
MarinCompiler.save_file(lines)
end,
$NewPBS = MarinCompiler.load_file end) To break this down, the code that actually formats the text into data is this bit: Code:  MarinCompiler.comma_based("icseei", nil,nil,nil,PBTypes,["Physical","Special","Status"],nil ) do |line| lines[line[0]] = line[1..-1] end "icseei" is the format this PBS file should follow. Each character stands for one field and expects a certain data type (number, string, internal name, etc): • s : String. This is a raw piece of text. You don't need to surround this with double quotes, UNLESS you want a comma in your string. In that case, you must surround your text with quotes, like so: "Hello, world". Despite this, I suggest to always use quotes around your strings because they make it all the more obvious they're strings. It doesn't make a difference. • i : Integer. This is a whole number (negative or positive, doesn't matter) • e : Enumerable. This is a list of values the field can have. If your field has to be a move, for instance, you would use e with PBTypes (you'll see how that works further down). In this PBTypes case, you could use NORMAL, but also 1, because that is the ID of the Normal type. • b : Boolean. true/false, yes/no, y/n, YES/NO, etc. • c : Internal name. Cannot contain characters like !@#$%&^*()-= and some more.
• h : Hexadecimal. 0x3E for instance, but just 3E or 03E would also work. (moves.txt's function code is a hexadecimal)
• f : Float. This is any number with decimal places, such as 1.9 or 5.4.
• * : Repeats the last character infinitely many times.
Aside from this format, you can also pass extra options along with that format. This is optional, but for e, you have to give it an option.
This is what nil,nil,nil,PBTypes,["Physical","Special","Status"],nil means that you see there. It applies to the respective characters. So in the example above, it would be like so:
• i = nil
• c = nil
• s = nil
• e = PBTypes (this means it has to be the internal name of a type or its ID)
• e = ["Physical","Special","Status"] (means it has to be one of these three (without the quotes!))
• i = nil
These are referred to the "options" of the format. They always default to nil. This means that our last nil was redundant, because, if we took it out, it would still be nil anyway.

Each format has its own options it can accept:
• s : A number (e.g. 7). This is the maximum length of the string. It can have 7 characters or less, but not MORE than that (e.g. 8).
• i : A Range (e.g. 1..9) : This means it can have any number between 1 and 9, INCLUDING 9.
1...9, three dots, means it can have any number between 1 and 9 EXCLUDING 9.
An Array (e.g. [1,3,5,7,9]) means it can have any number inside of that array, and JUST those
• e : A Class/Module (e.g. PBMoves, PBSpecies, PBTypes, PBItems) which will use the constants inside as possible values (e.g. MEGAHORN, BULBASAUR, NORMAL, REPEL, respectively)
An Array (e.g. ["Physical","Special","Status"]). Here, the value in the PBS can be Physical, Special, or Status.
A Hash (e.g. {"Physical"=>0,"Special"=>1,"Status"=>2}). Here, the possible values will be the keys (Physical, Special, or Status, just like with arrays), but the formatted data will be the VALUES of those keys (so if you wrote down Special in the PBS file, the formatted data would be 1 rather than "Special")
• b : None.
• c : None.
• h : None.
• f : None.

So now, if we ran our example code, the generated results would be
[1,:MEGAHORN,"Megahorn",6,"Physical",120] and [2,:BUGBUZZ,"Bug Buzz",6,"Special",90] respectively. The line where I do lines[line[0]] = line[1..-1] takes the first element in these arrays (1 and 2) and uses them as array indexes on lines. It then sets the values of those elements to line[1..-1], which is every element EXCEPT for the first one, so that would be [:MEGAHORN,"Megahorn",6,"Physical",120], for instance.
Before you do that, however, you can add extra processing to your line. If there's a field you want be very special and that can't be done using the file format or options for those, you can modify it even more before lines[lines[0] = line[1..-1] to your liking. For example, if we wanted to upcase the "Megahorn", we would write:
Code:
   MarinCompiler.comma_based("icseei",
nil,nil,nil,PBTypes,["Physical","Special","Status"],nil
) do |line|
line[2].upcase!
lines[line[0]] = line[1..-1]
end

After all this processing has been done, lines is [nil,[:MEGAHORN,"MEGAHORN",6,"Physical",120],[:BUGBUZZ,"BUG BUZZ",6,"Special",90]].
We save it to the data file by writing MarinCompiler.save_file(lines). This saves the data to new_pbs.dat, which is what we called our Data file.

In the next proc, the load proc, we load the data file and save the content to a global variable, $NewPBS in this case: Code: proc do # Load$NewPBS = MarinCompiler.load_file
end

MarinCompiler.load_file loads the data in our specified Data file, new_pbs.dat in this case and sets $NewPBS to that. If we wanted an OPTIONAL field in our PBS, we would write the character in UPPERCASE. For instance, this below would be possible: Code: 1,REPEL,Repel 2,SUPERREPEL,Super Repel,Super Repels ... If our format was icsS. Here, the last S, a string, is OPTIONAL. If the format was icss, it would say we're missing a field on the first line, because it's not optional. Before reading this tab, make sure you've read the Comma based tab as well, because it introduces a few terms and explains some parameters that I also use here. Section based PBS looks like pokemon.txt, which works per header/section. It too follows a certain format, such as this below: Code: [1] InternalName=BULBASAUR Type1=GRASS Type2=POISON Height=0.7 [2] InternalName = IVYSAUR Type1 = GRASS Type2 = POISON Height = 1.0 # This is a comment; it's not actually part of the file when compiled. (As you can see, it doesn't matter if you have a space before or after the equal sign.) InternalName is an internal name, so that would be the c format. Type1 is a type, so we'd use e with PBTypes. Type2 is a type, so we'd use e with PBTypes, BUT, because it's optional, we use E rather than e. Height is a decimal number/float, so we'd use f for Float. MarinCompiler.register(pbs_file,data_file,compile_proc,load_proc,decompile_proc = nil) stays exactly the same as before. The full code to compile and load this would be as follows: Code: MarinCompiler.register("new_pbs.txt", "new_pbs.dat", proc do # Compile sections = {} MarinCompiler.section_based("i",{ "InternalName" => "c", "Type1" => ["e",PBTypes], "Type2" => ["E",PBTypes], "Height" => "f" }) do |header,section| sections[header] = section end MarinCompiler.save_file(sections) end, proc do # Load$NewPBS = MarinCompiler.load_file
end)

This produces a hash that looks like this:
Code:
{
1 => {
"InternalName" => :BULBASAUR,
"Type1" => 12,
"Type2" => 3,
"Height" => 0.7
},
2 => {
"InternalName" => :IVYSAUR,
"Type1" => 12,
"Type2" => 3,
"Height" => 1.0
}
}
So \$NewPBS[1]["InternalName"] would return :BULBASAUR, for example.

You can also use the comma based format INSIDE the section based format. For instance, if you wanted to have something like this:
Code:
[1]
Pokemon = BULBASAUR,10
EggMoves = MEGAHORN,ATTACKORDER,BUGBUZZ

Here, our code would be
Code:
 proc do # Compile
sections = {}
MarinCompiler.section_based("i",{
"Pokemon" => ["ei",PBSpecies,nil],
"EggMoves" => ["e*",PBMoves]
end
MarinCompiler.save_file(sections)
end

The result would be:
Code:
{
1 => {
"Pokemon" => [1, 10],
"EggMoves" => [1, 2, 3]
}
}

The 1 in [1, 10], is the species Bulbasaur, and the 10 is the integer we gave it.
The 1, 2 and 3 are the IDs of the moves MEGAHORN, ATTACKORDER and BUGBUZZ respectively.
Perhaps this will prove useful at some point.

Honestly, you can really mix and match all this stuff. I suggest messing around with it, and to leave a message here if you can't figure something out.

It's pretty hard properly documenting this type of stuff; please don't hesitate to leave a message if you don't understand anything at all.

I will include samples for decompiling later.
Credits
• Marin
itsazuretime
Author
Marin
Views
248
First release
Last update
Rating
0 ratings