SceneGroup.java 5.24 KB
Newer Older
1
2
package emu.grasscutter.scripts.data;

Akka's avatar
Akka committed
3
4
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.ScriptLoader;
5
import emu.grasscutter.utils.Position;
Akka's avatar
Akka committed
6
7
import lombok.Setter;
import lombok.ToString;
8
import org.luaj.vm2.LuaValue;
9

Akka's avatar
Akka committed
10
11
12
import javax.script.Bindings;
import javax.script.CompiledScript;
import javax.script.ScriptException;
13

14
15
import java.util.List;
import java.util.Map;
Akka's avatar
Akka committed
16
import java.util.Optional;
Akka's avatar
Akka committed
17
18
import java.util.stream.Collectors;

Akka's avatar
Akka committed
19
20
@ToString
@Setter
21
public class SceneGroup {
github-actions's avatar
github-actions committed
22
    public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference
23

github-actions's avatar
github-actions committed
24
25
26
    public int id;
    public int refresh_id;
    public Position pos;
27

github-actions's avatar
github-actions committed
28
29
30
    public Map<Integer,SceneMonster> monsters; // <ConfigId, Monster>
    public Map<Integer, SceneGadget> gadgets; // <ConfigId, Gadgets>
    public Map<String, SceneTrigger> triggers;
Akka's avatar
Akka committed
31
    public Map<Integer, SceneRegion> regions;
github-actions's avatar
github-actions committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    public List<SceneSuite> suites;
    public List<SceneVar> variables;

    public SceneBusiness business;
    public SceneGarbage garbages;
    public SceneInitConfig init_config;

    private transient boolean loaded; // Not an actual variable in the scripts either
    private transient CompiledScript script;
    private transient Bindings bindings;
    public static SceneGroup of(int groupId) {
        var group = new SceneGroup();
        group.id = groupId;
        return group;
    }

    public boolean isLoaded() {
        return this.loaded;
    }

    public void setLoaded(boolean loaded) {
        this.loaded = loaded;
    }

    public int getBusinessType() {
        return this.business == null ? 0 : this.business.type;
    }

    public List<SceneGadget> getGarbageGadgets() {
        return this.garbages == null ? null : this.garbages.gadgets;
    }

    public CompiledScript getScript() {
        return this.script;
    }

    public SceneSuite getSuiteByIndex(int index) {
        return this.suites.get(index - 1);
    }

    public Bindings getBindings() {
        return this.bindings;
    }

    public synchronized SceneGroup load(int sceneId) {
        if (this.loaded) {
            return this;
        }
        // Set flag here so if there is no script, we don't call this function over and over again.
81
        this.setLoaded(true);
Akka's avatar
Akka committed
82

github-actions's avatar
github-actions committed
83
        this.bindings = ScriptLoader.getEngine().createBindings();
84

85
        CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua");
Akka's avatar
Akka committed
86

github-actions's avatar
github-actions committed
87
88
89
        if (cs == null) {
            return this;
        }
Akka's avatar
Akka committed
90

github-actions's avatar
github-actions committed
91
        this.script = cs;
92

github-actions's avatar
github-actions committed
93
94
95
        // Eval script
        try {
            cs.eval(this.bindings);
Akka's avatar
Akka committed
96

github-actions's avatar
github-actions committed
97
            // Set
98
            this.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, this.bindings.get("monsters")).stream()
github-actions's avatar
github-actions committed
99
                    .collect(Collectors.toMap(x -> x.config_id, y -> y));
100
            this.monsters.values().forEach(m -> m.group = this);
Akka's avatar
Akka committed
101

102
            this.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, this.bindings.get("gadgets")).stream()
github-actions's avatar
github-actions committed
103
                    .collect(Collectors.toMap(x -> x.config_id, y -> y));
104
            this.gadgets.values().forEach(m -> m.group = this);
Akka's avatar
Akka committed
105

106
            this.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, this.bindings.get("triggers")).stream()
github-actions's avatar
github-actions committed
107
                    .collect(Collectors.toMap(x -> x.name, y -> y));
108
            this.triggers.values().forEach(t -> t.currentGroup = this);
Akka's avatar
Akka committed
109

110
111
            this.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites"));
            this.regions = ScriptLoader.getSerializer().toList(SceneRegion.class, this.bindings.get("regions")).stream()
Akka's avatar
Akka committed
112
                .collect(Collectors.toMap(x -> x.config_id, y -> y));
113
            this.regions.values().forEach(m -> m.group = this);
Akka's avatar
Akka committed
114

115
            this.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, this.bindings.get("init_config"));
Akka's avatar
Akka committed
116

github-actions's avatar
github-actions committed
117
118
119
            // Garbages // TODO: fix properly later
            Object garbagesValue = this.bindings.get("garbages");
            if (garbagesValue instanceof LuaValue garbagesTable) {
120
                this.garbages = new SceneGarbage();
github-actions's avatar
github-actions committed
121
                if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) {
122
123
                    this.garbages.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable());
                    this.garbages.gadgets.forEach(m -> m.group = this);
github-actions's avatar
github-actions committed
124
125
                }
            }
126

github-actions's avatar
github-actions committed
127
128
            // Add variables to suite
            this.variables = ScriptLoader.getSerializer().toList(SceneVar.class, this.bindings.get("variables"));
Akka's avatar
Akka committed
129

github-actions's avatar
github-actions committed
130
            // Add monsters and gadgets to suite
131
            this.suites.forEach(i -> i.init(this));
Akka's avatar
Akka committed
132

github-actions's avatar
github-actions committed
133
134
135
        } catch (ScriptException e) {
            Grasscutter.getLogger().error("An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e);
        }
Akka's avatar
Akka committed
136

github-actions's avatar
github-actions committed
137
138
139
        Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId);
        return this;
    }
Akka's avatar
Akka committed
140

github-actions's avatar
github-actions committed
141
142
143
144
145
146
    public Optional<SceneBossChest> searchBossChestInGroup() {
        return this.gadgets.values().stream()
                .filter(g -> g.boss_chest != null && g.boss_chest.monster_config_id > 0)
                .map(g -> g.boss_chest)
                .findFirst();
    }
Akka's avatar
Akka committed
147

148
}