SceneMeta.java 2.45 KB
Newer Older
Akka's avatar
Akka committed
1
2
package emu.grasscutter.scripts.data;

3
4
import com.github.davidmoten.rtreemulti.RTree;
import com.github.davidmoten.rtreemulti.geometry.Geometry;
Akka's avatar
Akka committed
5
6
7
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.SceneIndexManager;
import emu.grasscutter.scripts.ScriptLoader;
Akka's avatar
Akka committed
8
9
import lombok.Setter;
import lombok.ToString;
Akka's avatar
Akka committed
10
11
12
13

import javax.script.Bindings;
import javax.script.CompiledScript;
import javax.script.ScriptException;
14
15
16

import static emu.grasscutter.config.Configuration.SCRIPT;

Akka's avatar
Akka committed
17
18
19
20
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

Akka's avatar
Akka committed
21
22
@ToString
@Setter
Akka's avatar
Akka committed
23
24
25
26
27
28
29
public class SceneMeta {

    public SceneConfig config;
    public Map<Integer, SceneBlock> blocks;

    public Bindings context;

30
    public RTree<SceneBlock, Geometry> sceneBlockIndex;
Akka's avatar
Akka committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

    public static SceneMeta of(int sceneId) {
        return new SceneMeta().load(sceneId);
    }

    public SceneMeta load(int sceneId){
        // Get compiled script if cached
        CompiledScript cs = ScriptLoader.getScriptByPath(
                SCRIPT("Scene/" + sceneId + "/scene" + sceneId + "." + ScriptLoader.getScriptType()));

        if (cs == null) {
            Grasscutter.getLogger().warn("No script found for scene " + sceneId);
            return null;
        }

        // Create bindings
47
        this.context = ScriptLoader.getEngine().createBindings();
Akka's avatar
Akka committed
48
49
50

        // Eval script
        try {
51
            cs.eval(this.context);
Akka's avatar
Akka committed
52

53
            this.config = ScriptLoader.getSerializer().toObject(SceneConfig.class, this.context.get("scene_config"));
Akka's avatar
Akka committed
54
55
56

            // TODO optimize later
            // Create blocks
57
58
            List<Integer> blockIds = ScriptLoader.getSerializer().toList(Integer.class, this.context.get("blocks"));
            List<SceneBlock> blocks = ScriptLoader.getSerializer().toList(SceneBlock.class, this.context.get("block_rects"));
Akka's avatar
Akka committed
59
60
61
62
63
64
65
66

            for (int i = 0; i < blocks.size(); i++) {
                SceneBlock block = blocks.get(i);
                block.id = blockIds.get(i);

            }

            this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b));
67
68
            this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle);

69
70
        } catch (ScriptException exception) {
            Grasscutter.getLogger().error("An error occurred while running a script.", exception);
Akka's avatar
Akka committed
71
72
            return null;
        }
73
        Grasscutter.getLogger().debug("Successfully loaded metadata in scene {}.", sceneId);
Akka's avatar
Akka committed
74
75
76
        return this;
    }
}