Jump to content
Age of History 3
Łukasz Jakowski

Map Editor for Age of History 3

Recommended Posts

Main map for AoH3 will be:

    BackgroundSize_X: 8,
    BackgroundSize_Y: 4,

 

It is:

17760 px width

8600px height

 

 

MAP_NAME=MapName
WIDTH=1920
HEIGHT=1080
MAXIMUM_SIZE=true
DRAW_POINTS=true
DRAW_PROVINCE_ID=false
CUT_FROM_PROVINCE_MODE=false

CONVERT_AOH2_MAP_PROVINCES_DATA_TO_AOH3=false

/** To convert a map from AoH2 to the AoH3, put the provinces points file from old mapEditor and name it "convertMapData.txt" in the same folder as mapEditor_2.jar. Open mapEditor_2.jar and click ENTER to save data. */

SPACE = Enable/Disable draw provinces
O = Enable/Disable draw provinces points
C = Enable/Disable draw cities
V = Enable/Disable draw cities names
Z = Enable/Disable background
X = Enable/Disable backgroundMapEditor
L = Rebuild provinces colors
Y = Follow the path of the province
P = Draw province ID
J = Delete a province


## Map -> Config.json

#### CODE

Quote

{
    Name: "MapName",
    Author: "AuthorName",
    
    NumOfProvinces: 1,
    DefaultMapScale: 4,
    WorldMap: true,
    
    BackgroundSize_X: 3,
    BackgroundSize_Y: 2,
    
    BackgroundZoomOut_Enable: true,
    BackgroundZoomOut_Size_X: 3,
    BackgroundZoomOut_Size_Y: 2,
    BackgroundZoomOut_Scale: 0.13,
    
    BackgroundZoomOut_AnimationDuration: 600,
    
    BackgroundColor: [13, 31, 49],
    BackgroundColor_ZoomIn: [5, 22, 40],
    BackgroundColor_ZoomOut: [11, 24, 33],
    
    WastelandColor: [200, 165, 130],
    
    DefaultScenario: "1440",
    Wiki: "Earth",
}

#### CODE END

## The width of every single image should be the same!
## The height of every single image should be the same!

## The width and height may be different.

## Example
    BackgroundSize_X: 3,
    BackgroundSize_Y: 2,
    
How many horizontal images and how many vertical images the map background is divided into.

In this example we have 3 horizontal images and two vertical images.

The naming of images:

It will be always: Y_X.png

0_0.png
0_1.png
0_2.png

Next line of images:

1_0.png
1_1.png
1_2.png

## Example 2
    BackgroundSize_X: 2,
    BackgroundSize_Y: 2,
    
It will be always: Y_X.png

0_0.png
0_1.png

Next line of images:

1_0.png
1_1.png


## Example 3
    BackgroundSize_X: 4,
    BackgroundSize_Y: 3,
    
It will be always: Y_X.png

0_0.png
0_1.png
0_2.png
0_3.png

Next line of images:

1_0.png
1_1.png
1_2.png
1_3.png

Next line of images:

2_0.png
2_1.png
2_2.png
2_3.png

Share this post


Link to post
Share on other sites

15 minutes ago, Shiite said:

This is great! props to releasing it early so modders can make maps before the game even comes out. Will there be a tool to convert images to maps, though? 

i asked him that and got no response from him

Share this post


Link to post
Share on other sites

Hmm.... I have no idea
    BackgroundSize_X: 8,
    BackgroundSize_Y: 4,
How calculator size resolutions?

I make new test image map 0_0.png 1792x1024

    BackgroundSize_X: 0,
    BackgroundSize_Y: 0,

    BackgroundZoomOut_Enable: true,
    BackgroundZoomOut_Size_X: 0,
    BackgroundZoomOut_Size_Y: 0,
    BackgroundZoomOut_Scale: 0.13,

but not work won't launch error

Error: Could not find or load main class MapEditor_2.jar
Caused by: java.lang.ClassNotFoundException: MapEditor_2.jar

Maybe you make new program auto image map to 0_0 0_1 0_2 0_3 1_0 1_1 1_2 1_3? (Map Converter Full Image to 0_0 0_1.. etc)

Share this post


Link to post
Share on other sites

39 minutes ago, GyLala said:

Hmm.... I have no idea
    BackgroundSize_X: 8,
    BackgroundSize_Y: 4,
How calculator size resolutions?

I make new test image map 0_0.png 1792x1024

    BackgroundSize_X: 0,
    BackgroundSize_Y: 0,

    BackgroundZoomOut_Enable: true,
    BackgroundZoomOut_Size_X: 0,
    BackgroundZoomOut_Size_Y: 0,
    BackgroundZoomOut_Scale: 0.13,

but not work won't launch error

Error: Could not find or load main class MapEditor_2.jar
Caused by: java.lang.ClassNotFoundException: MapEditor_2.jar

Maybe you make new program auto image map to 0_0 0_1 0_2 0_3 1_0 1_1 1_2 1_3? (Map Converter Full Image to 0_0 0_1.. etc)

the map tiles can be any resolution but as long as tile stays the same resolution for all tiles you can have as many tiles has you need 

for the program not running do you have Java Installed?

Edited by aunitydevteam

Share this post


Link to post
Share on other sites

4 minutes ago, aunitydevteam said:

the map tiles can be any resolution but as long as tile stays the same resolution for all tiles you can have as many tiles has you need 

for the program not running do you have Java Installed?

I know already I have Java
MapName worked (by dev)
but I created Test123 map not work 0_0.png image 1792x1024
I need Full image convert to auto 0_0 0_1 0_2 .. etc

Share this post


Link to post
Share on other sites

3 minutes ago, GyLala said:

I know already I have Java
MapName worked (by dev)
but I created Test123 map not work 0_0.png image 1792x1024
I need Full image convert to auto 0_0 0_1 0_2 .. etc

I used gimp with plugins that did all the hard work easy for me I'll tell you all how to use gimp with plugins to split your maps tomorrow because I'm not at my computer 

Share this post


Link to post
Share on other sites

20 minutes ago, aunitydevteam said:

I used gimp with plugins that did all the hard work easy for me I'll tell you all how to use gimp with plugins to split your maps tomorrow because I'm not at my computer 

Yea I got Photoshop with Split worked
thanks for helpful
https://imgur.com/a/Qjydsp4

Share this post


Link to post
Share on other sites

BackgroundSize_X: 0,
BackgroundSize_Y: 0,

It can't be 0. If you want to use only one image, it should be:

BackgroundSize_X: 1,
BackgroundSize_Y: 1,

 

Image name: 0_0.png

 

For two images like it was in AoH2 it would be:

BackgroundSize_X: 2,
BackgroundSize_Y: 1,

 

Image name: 0_0.png

Image name: 0_1.png

## The width of every single image should be the same!
## The height of every single image should be the same!

## The width and height may be different.

 

Read: MapEditorSettings.txt file, there is more tips!

 

 

BackgroundSize_X: 3,
BackgroundSize_Y: 2,

 

Image name: 0_0.png

Image name: 0_1.png

Image name: 0_2.png

 

Image name: 1_0.png

Image name: 1_1.png

Image name: 1_2.png

 

Share this post


Link to post
Share on other sites

Just now, 诸葛烤鱼 said:

Could you please make a complete tutorial and put it on YouTube?

@Lukasz jakowski

i just finished a text tutorial using gimp

Share this post


Link to post
Share on other sites

19 hours ago, Łukasz Jakowski said:

Map Editor for Age of History 3

 

It works almost the same as the old one, but is more convenient.

If you want, you can now create a province map in this map editor and once the game is released, your map will be playable in the game.

 

You can save the province by clicking Enter and continue adding another new province.

You can remove a province and add another one in its place by clicking "J". Do not close the editor until all deleted provinces have been added.

 

 

CUT_FROM_PROVINCE_MODE=true

New special version of the map, provinces created in this mode will crop the images of the main provinces.

 

All provinces are stored in one file: MapName/data/ProvincePoints.json

No more strange files with numbers like in AoH 2.

 

One tip: make map backgrounds larger than in AoH2, so your map will have more details.

For example with width: 6000 px or 8000 px or even more.

The main map for AoH3 will be: 17760 px width x 8600px height

 

Read: MapEditorSettings.txt file, there is more tips!

 

The map editor will also be included in the game files.

Required: Java JDK 21: https://www.oracle.com/java/technologies/downloads/#jdk21-windows

 

mapeditor.thumb.png.675f163462edd4e445e50ac1273d063e.png

MapEditor_2.zip 27.33 MB · 119 downloads

it should be updated to java 8, because java jdk 21 doesnt support 32 bit devices

Edited by uwut

Share this post


Link to post
Share on other sites

Are these json5 format?
I'm sure you know, but json is compressed. json5 may be more optimized and take up less space.
In Json, the expression starts with "" and ends with "value:" followed by the value of the data.
String is also written inside "". If it is boolean or number, it is not written.
Then, commas are not used in the definition that continues within the same object or series.

Quote

{
    Name: "MapName",
    Author: "AuthorName",
    
    NumOfProvinces: 1,
    DefaultMapScale: 3,
    WorldMap: true,
    
    BackgroundSize_X: 3,
    BackgroundSize_Y: 2,
    
    BackgroundZoomOut_Enable: true,
    BackgroundZoomOut_Size_X: 3,
    BackgroundZoomOut_Size_Y: 2,
    BackgroundZoomOut_Scale: 0.13,
    
    BackgroundZoomOut_AnimationDuration: 600,
    
    BackgroundColor: [13, 31, 49],
    BackgroundColor_ZoomIn: [5, 22, 40],
    BackgroundColor_ZoomOut: [11, 24, 33],
    
    WastelandColor: [200, 165, 130],
    
    DefaultScenario: "1440",
    Wiki: "Earth",
}

so:

Quote

{
    "Name": "MapName",
    "Author": "AuthorName",
    "NumOfProvinces": 1,
    "DefaultMapScale": 3,
    "WorldMap": true,
    "BackgroundSize_X": 3,
    "BackgroundSize_Y": 2,
    "BackgroundZoomOut_Enable": true,
    "BackgroundZoomOut_Size_X": 3,
    "BackgroundZoomOut_Size_Y": 2,
    "BackgroundZoomOut_Scale": 0.13,
    "BackgroundZoomOut_AnimationDuration": 600,
    "BackgroundColor": [13, 31, 49],
    "BackgroundColor_ZoomIn": [5, 22, 40],
    "BackgroundColor_ZoomOut": [11 ,24, 33],
    "WastelandColor": [200, 165, 130],
    "DefaultScenario": "1440",
    "Wiki": "Earth"
}

 

compress:

Quote

{"Name":"MapName","Author":"AuthorName","NumOfProvinces":1,"DefaultMapScale":3,"WorldMap":true,"BackgroundSize_X":3,"BackgroundSize_Y":2,"BackgroundZoomOut_Enable":true,"BackgroundZoomOut_Size_X":3,"BackgroundZoomOut_Size_Y":2,"BackgroundZoomOut_Scale":0.13,"BackgroundZoomOut_AnimationDuration":600,"BackgroundColor":[13,31,49],"BackgroundColor_ZoomIn":[5,22,40],"BackgroundColor_ZoomOut":[11,24,33],"WastelandColor":[200,165,130],"DefaultScenario":"1440","Wiki":"Earth"}

 

On the other hand, this is a universal standard and using the org.json library.
You can read and write faster without the names of the variables being the same as the tag names.
According to logicbdx.

Just a suggestion.

Share this post


Link to post
Share on other sites

11 minutes ago, aunitydevteam said:

I honestly hate the compressed version its literally like editing a paragraphs in a book i prefer it neat and clean because you can see it

The real problem isn't compression. compression is just an advantage.

So even with a char type " { : [ } ] , json can be read only with quotes and unnecessary commas, it does not create a new memory in memory.
to the reagent
private int a;
It can be done in variables such as.

 

Quote

package com.badlogic.gdx.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.JsonValue.ValueType;

public class JsonReader implements BaseJsonReader {
    public JsonValue parse (String json) {
        char[] data = json.toCharArray();
        return parse(data, 0, data.length);
    }

    public JsonValue parse (Reader reader) {
        try {
            char[] data = new char[1024];
            int offset = 0;
            while (true) {
                int length = reader.read(data, offset, data.length - offset);
                if (length == -1) break;
                if (length == 0) {
                    char[] newData = new char[data.length * 2];
                    System.arraycopy(data, 0, newData, 0, data.length);
                    data = newData;
                } else
                    offset += length;
            }
            return parse(data, 0, offset);
        } catch (IOException ex) {
            throw new SerializationException(ex);
        } finally {
            StreamUtils.closeQuietly(reader);
        }
    }

    public JsonValue parse (InputStream input) {
        try {
            return parse(new InputStreamReader(input, "UTF-8"));
        } catch (IOException ex) {
            throw new SerializationException(ex);
        } finally {
            StreamUtils.closeQuietly(input);
        }
    }

    public JsonValue parse (FileHandle file) {
        try {
            return parse(file.reader("UTF-8"));
        } catch (Exception ex) {
            throw new SerializationException("Error parsing file: " + file, ex);
        }
    }

    public JsonValue parse (char[] data, int offset, int length) {
        int cs, p = offset, pe = length, eof = pe, top = 0;
        int[] stack = new int[4];

        int s = 0;
        Array<String> names = new Array(8);
        boolean needsUnescape = false, stringIsName = false, stringIsUnquoted = false;
        RuntimeException parseRuntimeEx = null;

        boolean debug = false;
        if (debug) System.out.println();

        try {
        %%{
            machine json;

            prepush {
                if (top == stack.length) {
                    int[] newStack = new int[stack.length * 2];
                    System.arraycopy(stack, 0, newStack, 0, stack.length);
                    stack = newStack;
                }
            }

            action name {
                stringIsName = true;
            }
            action string {
                String value = new String(data, s, p - s);
                if (needsUnescape) value = unescape(value);
                outer:
                if (stringIsName) {
                    stringIsName = false;
                    if (debug) System.out.println("name: " + value);
                    names.add(value);
                } else {
                    String name = names.size > 0 ? names.pop() : null;
                    if (stringIsUnquoted) {
                        if (value.equals("true")) {
                            if (debug) System.out.println("boolean: " + name + "=true");
                            bool(name, true);
                            break outer;
                        } else if (value.equals("false")) {
                            if (debug) System.out.println("boolean: " + name + "=false");
                            bool(name, false);
                            break outer;
                        } else if (value.equals("null")) {
                            string(name, null);
                            break outer;
                        }
                        boolean couldBeDouble = false, couldBeLong = true;
                        outer2:
                        for (int i = s; i < p; i++) {
                            switch (data) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                            case '-':
                            case '+':
                                break;
                            case '.':
                            case 'e':
                            case 'E':
                                couldBeDouble = true;
                                couldBeLong = false;
                                break;
                            default:
                                couldBeDouble = false;
                                couldBeLong = false;
                                break outer2;
                            }
                        }
                        if (couldBeDouble) {
                            try {
                                if (debug) System.out.println("double: " + name + "=" + Double.parseDouble(value));
                                number(name, Double.parseDouble(value), value);
                                break outer;
                            } catch (NumberFormatException ignored) {
                            }
                        } else if (couldBeLong) {
                            if (debug) System.out.println("double: " + name + "=" + Double.parseDouble(value));
                            try {
                                number(name, Long.parseLong(value), value);
                                break outer;
                            } catch (NumberFormatException ignored) {
                            }
                        }
                    }
                    if (debug) System.out.println("string: " + name + "=" + value);
                    string(name, value);
                }
                stringIsUnquoted = false;
                s = p;
            }
            action startObject {
                String name = names.size > 0 ? names.pop() : null;
                if (debug) System.out.println("startObject: " + name);
                startObject(name);
                fcall object;
            }
            action endObject {
                if (debug) System.out.println("endObject");
                pop();
                fret;
            }
            action startArray {
                String name = names.size > 0 ? names.pop() : null;
                if (debug) System.out.println("startArray: " + name);
                startArray(name);
                fcall array;
            }
            action endArray {
                if (debug) System.out.println("endArray");
                pop();
                fret;
            }
            action comment {
                int start = p - 1;
                if (data[p++] == '/') {
                    while (p != eof && data[p] != '\n')
                        p++;
                    p--;
                } else {
                    while (p + 1 < eof && data[p] != '*' || data[p + 1] != '/')
                        p++;
                    p++;
                }
                if (debug) System.out.println("comment " + new String(data, start, p - start));
            }
            action unquotedChars {
                if (debug) System.out.println("unquotedChars");
                s = p;
                needsUnescape = false;
                stringIsUnquoted = true;
                if (stringIsName) {
                    outer:
                    while (true) {
                        switch (data[p]) {
                        case '\\':
                            needsUnescape = true;
                            break;
                        case '/':
                            if (p + 1 == eof) break;
                            char c = data[p + 1];
                            if (c == '/' || c == '*') break outer;
                            break;
                        case ':':
                        case '\r':
                        case '\n':
                            break outer;
                        }
                        if (debug) System.out.println("unquotedChar (name): '" + data[p] + "'");
                        p++;
                        if (p == eof) break;
                    }
                } else {
                    outer:
                    while (true) {
                        switch (data[p]) {
                        case '\\':
                            needsUnescape = true;
                            break;
                        case '/':
                            if (p + 1 == eof) break;
                            char c = data[p + 1];
                            if (c == '/' || c == '*') break outer;
                            break;
                        case '}':
                        case ']':
                        case ',':
                        case '\r':
                        case '\n':
                            break outer;
                        }
                        if (debug) System.out.println("unquotedChar (value): '" + data[p] + "'");
                        p++;
                        if (p == eof) break;
                    }
                }
                p--;
                while (Character.isSpace(data[p]))
                    p--;
            }
            action quotedChars {
                if (debug) System.out.println("quotedChars");
                s = ++p;
                needsUnescape = false;
                outer:
                while (true) {
                    switch (data[p]) {
                    case '\\':
                        needsUnescape = true;
                        p++;
                        break;
                    case '"':
                        break outer;
                    }
                    // if (debug) System.out.println("quotedChar: '" + data[p] + "'");
                    p++;
                    if (p == eof) break;
                }
                p--;
            }

            comment = ('//' | '/*') @comment;
            ws = [\r\n\t ] | comment;
            ws2 = [\t ] | comment;
            comma = ',' | ([\r\n] ws* ','?);
            quotedString = '"' @quotedChars %string '"';
            nameString = quotedString | ^[":,}/\r\n\t ] >unquotedChars %string;
            valueString = quotedString | ^[":,{[\]/\r\n\t ] >unquotedChars %string;
            value = '{' @startObject | '[' @startArray | valueString;
            nameValue = nameString >name ws* ':' ws* value;
            object := ws* nameValue? ws2* <: (comma ws* nameValue ws2*)** :>> (','? ws* '}' @endObject);
            array := ws* value? ws2* <: (comma ws* value ws2*)** :>> (','? ws* ']' @endArray);
            main := ws* value ws*;

            write init;
            write exec;
        }%%
        } catch (RuntimeException ex) {
            parseRuntimeEx = ex;
        }

        JsonValue root = this.root;
        this.root = null;
        current = null;
        lastChild.clear();

        if (p < pe) {
            int lineNumber = 1;
            for (int i = 0; i < p; i++)
                if (data == '\n') lineNumber++;
            int start = Math.max(0, p - 32);
            throw new SerializationException("Error parsing JSON on line " + lineNumber + " near: "
                + new String(data, start, p - start) + "*ERROR*" + new String(data, p, Math.min(64, pe - p)), parseRuntimeEx);
        } else if (elements.size != 0) {
            JsonValue element = elements.peek();
            elements.clear();
            if (element != null && element.isObject())
                throw new SerializationException("Error parsing JSON, unmatched brace.");
            else
                throw new SerializationException("Error parsing JSON, unmatched bracket.");
        } else if (parseRuntimeEx != null) {
            throw new SerializationException("Error parsing JSON: " + new String(data), parseRuntimeEx);
        }
        return root;
    }

    %% write data;

    private final Array<JsonValue> elements = new Array(8);
    private final Array<JsonValue> lastChild = new Array(8);
    private JsonValue root, current;

    private void addChild (String name, JsonValue child) {
        child.setName(name);
        if (current == null) {
            current = child;
            root = child;
        } else if (current.isArray() || current.isObject()) {
            child.parent = current;
            if (current.size == 0)
                current.child = child;
            else {
                JsonValue last = lastChild.pop();
                last.next = child;
                child.prev = last;
            }
            lastChild.add(child);
            current.size++;
        } else
            root = current;
    }

    protected void startObject (String name) {
        JsonValue value = new JsonValue(ValueType.object);
        if (current != null) addChild(name, value);
        elements.add(value);
        current = value;
    }

    protected void startArray (String name) {
        JsonValue value = new JsonValue(ValueType.array);
        if (current != null) addChild(name, value);
        elements.add(value);
        current = value;
    }

    protected void pop () {
        root = elements.pop();
        if (current.size > 0) lastChild.pop();
        current = elements.size > 0 ? elements.peek() : null;
    }

    protected void string (String name, String value) {
        addChild(name, new JsonValue(value));
    }

    protected void number (String name, double value, String stringValue) {
        addChild(name, new JsonValue(value, stringValue));
    }

    protected void number (String name, long value, String stringValue) {
        addChild(name, new JsonValue(value, stringValue));
    }

    protected void bool (String name, boolean value) {
        addChild(name, new JsonValue(value));
    }

    private String unescape (String value) {
        int length = value.length();
        StringBuilder buffer = new StringBuilder(length + 16);
        for (int i = 0; i < length;) {
            char c = value.charAt(i++);
            if (c != '\\') {
                buffer.append(c);
                continue;
            }
            if (i == length) break;
            c = value.charAt(i++);
            if (c == 'u') {
                buffer.append(Character.toChars(Integer.parseInt(value.substring(i, i + 4), 16)));
                i += 4;
                continue;
            }
            switch (c) {
            case '"':
            case '\\':
            case '/':
                break;
            case 'b':
                c = '\b';
                break;
            case 'f':
                c = '\f';
                break;
            case 'n':
                c = '\n';
                break;
            case 'r':
                c = '\r';
                break;
            case 't':
                c = '\t';
                break;
            default:
                throw new SerializationException("Illegal escaped character: \\" + c);
            }
            buffer.append(c);
        }
        return buffer.toString();
    }
}
 

So you don't need this code.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Age of History Games