Save/Load Catalogs

Level 31
Joined
Jul 10, 2007
Messages
6,307
http://www.hiveworkshop.com/forums/spells-569/save-load-snippets-v2-1-0-5-a-202714/?prev=mmr=6

Save/Load Catalogs for the GUI User


This tutorial isn't the greatest, but it accomplishes its goal. I don't exactly have a lot of time for this stuff and there seems to be a great need for this tutorial.




A good save/load system can't be made in GUI. The reason is because of what are called catalogs. Catalogs turn big numbers, like hero ids, into very small numbers. They have many constraints on them that are map-specific. Furthermore, the catalogs that are required of a map are also unique to that map.

Catalogs are only implemented in vJASS and can't be implemented in GUI. This is because they use what are called modules.

In order to create a good save/load system for your map, you must use at least a little bit of vJASS so that you can do the catalogs.



First, vJASS is just text. It is a language. If you already know programming concepts from GUI, then you are already halfway there. The only thing that you need to study is what to write and in what order to write it.

There is structure to programming and you have to follow this structure exactly. JASS is translated to vJASS just like GUI is. JASS is translated to something else. Structure is everything.

The structure that will be covered is the struct

JASS:
    struct NAME
    endstruct

A struct is just something that is used to organize code. The above srtuct actually generates quite a bit of garbage that we don't need. To drop that garbage, we put an "extends array" at the end of it.

JASS:
    struct NAME extends array
    endstruct

So the big thing to look at is first

JASS:
    struct
    endstruct


"struct" shows where the thing begins. "endstruct" shows where it ends. After "struct," you need a name for it.

JASS:
    struct MyStruct extends array
    endstruct

As this tutorial is going over catalogs, let's name it HeroCatalog

JASS:
    struct HeroCatalog extends array
    endstruct

After this, you need to implement what is called a module. A module is just something that copies and pastes code into a struct. This is the reason why it can't be done in GUI. GUI has nothing like this. Why not just make the code for each individual thing then? Good luck.

JASS:
    struct HeroCatalog extends array
        implement Catalog
    endstruct

First, the implement keyword implements the module. After it, you put in the module name. Catalog happens to be the name of a module from the Catalog resource, which you can find under core systems in save/load with snippets.

What does a basic hero catalog look like?

Before we delve into that, we need to cover what are called methods very quickly.

A method is just like a list of actions in a trigger. However, unlike actions, you can give it values and it can return a value. It also doesn't have events or anything like that.

The method block is as follows

JASS:
    private static method NAME takes nothing returns nothing
    endmethod

Because the aim of this tutorial is to make a save/load system for a map as quickly as possible, the details behind a method won't really be elaborated on.

The following should be clear

JASS:
    method NAME
    endmethod

private - refers to whether other code can see it or not. Anything outside of the struct can't see this. It can also be public or just nothing

JASS:
    private method NAME
    public method NAME
    method NAME //also public

static - refers to whether the method takes a value called "this" or not. Static means that it doesn't.

JASS:
    private static method NAME
    public static method NAME
    static method NAME

takes - what the method takes. This is a comma separated list of variables. If it doesn't take anything, the nothing keyword is used.
returns - the type of variable that the method returns. If it doesn't return anything, nothing is used. When I say type, think about variable types in the variable editor.

JASS:
    private static method NAME takes nothing returns nothing

The above is a method called NAME that takes no values and returns nothing

To call it, use the "call" keyword followed by the method name and then a "()".

JASS:
    call NAME()

The "()" can actually hold a comma separated list of values. This list of values must be in the same order as the list of values that the method takes.
If it doesn't take anything, then the "()" is just empty. If it took an Integer (think back to GUI), it would take a whole number value, like 5.

JASS:
    call NAME(5)    //if it took an integer

If it took two integers

JASS:
    call NAME(-1, -3)   //two random integers, notice the comma

Now to implement a Catalog.

The Catalog module copies a few methods and variables into the struct

This is straight from the Catalog documentation. Keep in mind that structs can be used as variable types.

JASS:
/*
*       readonly static Catalog catalog
*           -   Retrieves the instance id of the catalog. Used for adding it to other
*           -   catalogs.
*       readonly static integer count
*           -   Retrieves the total amount of values inside of the catalog. Includes totals
*           -   of added catalogs.
*       readonly integer raw
*           -   Gets the raw value given a catalog value. Raw values are the
*           -   original values that were added.
*
*           -   Ex: integer raw = Catalog[1].raw
*       readonly integer id
*           -   Gets the catalog id given a raw value
*
*           -   Ex: integer id = Catalog['hpea'].id
*
*       static method add takes integer value returns nothing
*           -   Adds a value to the catalog. Values already inside of the catalog
*           -   or inside of any catalog that it contains are not added.
*       static method addCatalog takes Catalog catalog returns nothing
*           -   Adds a catalog and all of its inner catalogs to the catalog.
*           -   Catalogs already inside of the catalog are not added.
*/

So now to create a basic Catalog.

JASS:
    struct HeroCatalog extends array
        implement Catalog
        
        private static method onInit takes nothing returns nothing
        endmethod
    endstruct

Methods named onInit are special. They run when the map loads.

This is the specific method of interest that will be used

JASS:
    static method add takes integer value returns nothing

The value it takes is a unit type id, which can be found in the object editor. Type Ctrl + D to view the objects as raw values. Type it again to revert back.
The four letter thing to the left of the (name) is the type id. This is what Catalogs take.

JASS:
    struct HeroCatalog extends array
        implement Catalog
        
        private static method onInit takes nothing returns nothing
            call add('Hpal')        //paladin
            call add('Hamg')        //archmage
            call add('Hmkg')        //mountain king
        endmethod
    endstruct

Why is the implement Catalog at the top of the struct? You should never call methods that are below you, always call ones that are above.

Note that implement Catalog is above onInit.

The calls to add put those type ids into the Catalog. From here, to use them

JASS:
    set udg_MyGlobal = HeroCatalog['Hpal'].id

The above will convert 'Hpal' into a small number, in this case 1.

First, [ ] is the syntax for arrays. However, HeroCatalog is not an array, it's a struct. What magic is this? [ ] is an operator just like +, -, *, and /. vJASS allows users to create methods for those operators. Pretty cool? The use of [ ] is actually a method call that takes a unit type id. It returns a value, like 1. This value is the struct type (not an integer). We'll get to why in a moment.

Just to show how one would create [] as a method

JASS:
    static method operator [] takes integer value returns integer
        return 0
    endmethod

So the operator thing is used to show that the method is an operator and then the name is passed in, in this case [].

The "." in

JASS:
    set udg_MyGlobal = HeroCatalog['Hpal'].id

Is an accessor. It accesses a member of the struct. Remember how earlier I said that non-static things inside of a struct take "this?" Notice HeroCatalog['Hpal'] returns a value. It then does value.id. Value is passed in as the "this." The id thing also happens to be a method. vJASS allows users to create methods that look like variables too...

So, when you are saving your values, you want to do

JASS:
    HeroCatalog['Hpal'].id

When you are loading them, you want to do

JASS:
    HeroCatalog[1].raw

Because 'Hpal' was the first value added to our catalog, it's raw value happens to be 1. HeroCatalog[1].raw would return 'Hpal'.

If you were to do this in GUI custom script, you'd have your GUI variable to store the unit type id

JASS:
    set udg_Hero = HeroCatalog[1].raw

Now that we know the basics of catalogs, let's move on. Under Catalog Tools, there are a variety of catalog filters.

LevelGroupSlotVersion Filter

This is primarily used for items.

Level: minimum level to us the item
Group: required hero class. Why group? Evolving heroes. Let's say that a rogue can evolve to a thief or an assassin. Thieves and assassins should be able to use rogue gear.
Slot: required equipment slot. For example, a sword can't fit into a chest slot.
Version: the current version of your *saver.* As you add more stuff to your game, you increase the version. Will hit on this more later.

LevelGroupVersion Filter

Same as above minus the slot stuff.

LevelVersionFilter
VersionFilter


Within Catalog tools are demos of each type. Just copy the demo, rename it to what you want, and then fill it up with your stuff. Be sure to detele the extra versions, you only need version 1 at the beginning.

When do you increase the version? Under this scenario.

You release your map. It's on version 1.
You add new items to it. Increase the version number. Then release it.
Only increase the version number *up to* one time between each release. If you didn't add anything, don't increase the version number.

Why are old version kept? For backwards compatible codes.


The filters have a more complicated API than the standard Catalog does.

This is the method from the really big filter

JASS:
    method get takes integer ver, integer groupId, integer slot, integer minLevel, integer maxLevel returns Catalog

You don't just do

JASS:
    Catalog['Hpal'].id

You need to do

JASS:
    HeroCatalog.get(1)['Hpal].id

The 1 would be the version of the catalog you want.

If we were to use the super giant filter

JASS:
    ItemCatalog.get(1, 1, 1, 1, 60)['item].id

Yes, I just filled it up with 1's for the hell of it and used 'item' for the item type id. ItemCatalog was also chosen on a whim for a name.

These filters have everything that Catalog has. They implement the Catalog module internally.

Don't continue to call .get over and over again, only call it once for each filter you need.

JASS:
    set udg_Catalog = ItemCatalog.get(1, 1, 1, 1, 60)

Then

JASS:
    Catalog(udg_Catalog)['item'].id

I repeat, do not call "get" over and over again.

Always use the bare minimum of the VersionFilter, always. If you do not use this, you will not be able to add anything to your catalog after your first release. You will be stuck.



The only thing that requires custom script are catalogs. The rest can be done with the GUI.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,307
Please read the very beginning :\

A good save/load system can't be made in GUI. The reason is because of what are called catalogs. Catalogs turn big numbers, like hero ids, into very small numbers. They have many constraints on them that are map-specific. Furthermore, the catalogs that are required of a map are also unique to that map.

Catalogs are only implemented in vJASS and can't be implemented in GUI. This is because they use what are called modules.

In order to create a good save/load system for your map, you must use at least a little bit of vJASS so that you can do the catalogs.
 
Top