ScriptLib.java 13.3 KB
Newer Older
1
2
3
4
5
6
package emu.grasscutter.scripts;

import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.GameEntity;
Melledy's avatar
Melledy committed
7
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
8
import emu.grasscutter.scripts.data.SceneGroup;
Melledy's avatar
Melledy committed
9
import emu.grasscutter.scripts.data.SceneRegion;
10
import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify;
11
import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify;
12
import io.netty.util.concurrent.FastThreadLocal;
13
14
15
16
17
18
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
19
20

public class ScriptLib {
21
	public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class);
22
23
24
25
26
27
28
29
30
31
32
33
34
	private final FastThreadLocal<SceneScriptManager> sceneScriptManager;
	private final FastThreadLocal<SceneGroup> currentGroup;
	public ScriptLib() {
		this.sceneScriptManager = new FastThreadLocal<>();
		this.currentGroup = new FastThreadLocal<>();
	}

	public void setSceneScriptManager(SceneScriptManager sceneScriptManager){
		this.sceneScriptManager.set(sceneScriptManager);
	}

	public void removeSceneScriptManager(){
		this.sceneScriptManager.remove();
35
36
37
	}

	public SceneScriptManager getSceneScriptManager() {
38
39
		// normally not null
		return Optional.of(sceneScriptManager.get()).get();
40
	}
41
42
43
44
45
46
47
48
49
50

	private String printTable(LuaTable table){
		StringBuilder sb = new StringBuilder();
		sb.append("{");
		for(var meta : table.keys()){
			sb.append(meta).append(":").append(table.get(meta)).append(",");
		}
		sb.append("}");
		return sb.toString();
	}
Akka's avatar
Akka committed
51
52
53
54
	public void setCurrentGroup(SceneGroup currentGroup){
		this.currentGroup.set(currentGroup);
	}
	public Optional<SceneGroup> getCurrentGroup(){
55
		return Optional.of(this.currentGroup.get());
Akka's avatar
Akka committed
56
57
58
59
	}
	public void removeCurrentGroup(){
		this.currentGroup.remove();
	}
60
	public int SetGadgetStateByConfigId(int configId, int gadgetState) {
61
62
		logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}",
				configId,gadgetState);
63
64
65
66
67
68
		Optional<GameEntity> entity = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(e -> e.getConfigId() == configId).findFirst();

		if (entity.isEmpty()) {
			return 1;
		}
Akka's avatar
Akka committed
69
70
71
72

		if (entity.get() instanceof EntityGadget entityGadget) {
			entityGadget.updateState(gadgetState);
			return 0;
73
		}
Akka's avatar
Akka committed
74
75

		return 1;
76
77
78
	}

	public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) {
79
80
		logger.debug("[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}",
				groupId,configId,gadgetState);
Akka's avatar
Akka committed
81
82
83
84
85
86

		getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(e -> e.getGroupId() == groupId)
				.filter(e -> e instanceof EntityGadget)
				.map(e -> (EntityGadget)e)
				.forEach(e -> e.updateState(gadgetState));
87
88
89
90
91
		
		return 0;
	}
	
	public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) {
92
93
		logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}",
				groupId,configId,options);
Melledy's avatar
Melledy committed
94
		
95
96
97
		Optional<GameEntity> entity = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst();

Melledy's avatar
Melledy committed
98
99

		if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) {
100
101
			return 1;
		}
Melledy's avatar
Melledy committed
102
103

		if (!(gadget.getContent() instanceof GadgetWorktop worktop)) {
104
105
106
			return 1;
		}
		
Melledy's avatar
Melledy committed
107
		worktop.addWorktopOptions(options);
108
		getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget));
Melledy's avatar
Melledy committed
109
		
110
111
		return 0;
	}
Akka's avatar
Akka committed
112
113
114
115
116
117

	public int SetWorktopOptions(LuaTable table){
		logger.debug("[LUA] Call SetWorktopOptions with {}", printTable(table));
		// TODO
		return 0;
	}
118
	public int DelWorktopOptionByGroupId(int groupId, int configId, int option) {
119
120
		logger.debug("[LUA] Call DelWorktopOptionByGroupId with {},{},{}",groupId,configId,option);

121
122
123
		Optional<GameEntity> entity = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst();

Melledy's avatar
Melledy committed
124
		if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) {
125
126
			return 1;
		}
Melledy's avatar
Melledy committed
127
128

		if (!(gadget.getContent() instanceof GadgetWorktop worktop)) {
129
130
131
			return 1;
		}
		
Melledy's avatar
Melledy committed
132
		worktop.removeWorktopOption(option);
133
		getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget));
Melledy's avatar
Melledy committed
134
		
135
136
137
138
		return 0;
	}
	
	// Some fields are guessed
139
140
141
142
	public int AutoMonsterTide(int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6) {
		logger.debug("[LUA] Call AutoMonsterTide with {},{},{},{},{},{}",
				challengeIndex,groupId,ordersConfigId,tideCount,sceneLimit,param6);

143
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
144

145
146
147
		if (group == null || group.monsters == null) {
			return 1;
		}
148

149
		this.getSceneScriptManager().startMonsterTideInGroup(group, ordersConfigId, tideCount, sceneLimit);
150
151
152
153
		
		return 0;
	}
	
154
	public int AddExtraGroupSuite(int groupId, int suite) {
155
156
		logger.debug("[LUA] Call AddExtraGroupSuite with {},{}",
				groupId,suite);
Melledy's avatar
Melledy committed
157
158
159
160
161
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
		
		if (group == null || group.monsters == null) {
			return 1;
		}
162

163
164
165
166
167
168
		// avoid spawn wrong monster
		if(getSceneScriptManager().getScene().getChallenge() != null)
			if(!getSceneScriptManager().getScene().getChallenge().inProgress() ||
					getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId){
			return 0;
		}
Melledy's avatar
Melledy committed
169
		this.getSceneScriptManager().spawnMonstersInGroup(group, suite);
Melledy's avatar
Melledy committed
170
		
Melledy's avatar
Melledy committed
171
172
173
		return 0;
	}
	
Melledy's avatar
Melledy committed
174
	// param3 (probably time limit for timed dungeons)
175
176
177
178
	public int ActiveChallenge(int challengeId, int challengeIndex, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5) {
		logger.debug("[LUA] Call ActiveChallenge with {},{},{},{},{},{}",
				challengeId,challengeIndex,timeLimitOrGroupId,groupId,objectiveKills,param5);

179
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
180
181
182
183
184
185
		var objective = objectiveKills;

		if(group == null){
			group = getSceneScriptManager().getGroupById(timeLimitOrGroupId);
			objective = groupId;
		}
186
187
188
189
		
		if (group == null || group.monsters == null) {
			return 1;
		}
190
191
192
193
194
195
196

		if(getSceneScriptManager().getScene().getChallenge() != null &&
				getSceneScriptManager().getScene().getChallenge().inProgress())
		{
			return 0;
		}

197
198
199
200
201
		DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(),
				group, challengeId, challengeIndex, objective);
		// set if tower first stage (6-1)
		challenge.setStage(getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0);

202
		getSceneScriptManager().getScene().setChallenge(challenge);
203

204
205
206
207
		challenge.start();
		return 0;
	}
	
208
	public int GetGroupMonsterCountByGroupId(int groupId) {
209
210
		logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}",
				groupId);
211
212
213
214
215
		return (int) getSceneScriptManager().getScene().getEntities().values().stream()
								.filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId)
								.count();
	}
	
Melledy's avatar
Melledy committed
216
	public int GetGroupVariableValue(String var) {
217
218
		logger.debug("[LUA] Call GetGroupVariableValue with {}",
				var);
Melledy's avatar
Melledy committed
219
		return getSceneScriptManager().getVariables().getOrDefault(var, 0);
220
221
	}
	
222
	public int SetGroupVariableValue(String var, int value) {
223
224
		logger.debug("[LUA] Call SetGroupVariableValue with {},{}",
				var, value);
225
		getSceneScriptManager().getVariables().put(var, value);
226
227
228
229
		return 0;
	}
	
	public LuaValue ChangeGroupVariableValue(String var, int value) {
230
231
232
		logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}",
				var, value);

233
		getSceneScriptManager().getVariables().put(var, getSceneScriptManager().getVariables().get(var) + value);
234
235
		return LuaValue.ZERO;
	}
236
237
238
239

	/**
	 * Set the actions and triggers to designated group
	 */
240
	public int RefreshGroup(LuaTable table) {
241
		logger.debug("[LUA] Call RefreshGroup with {}",
242
				printTable(table));
243
244
245
246
247
248
249
250
251
252
		// Kill and Respawn?
		int groupId = table.get("group_id").toint();
		int suite = table.get("suite").toint();
		
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
		
		if (group == null || group.monsters == null) {
			return 1;
		}
		
253
		getSceneScriptManager().refreshGroup(group, suite);
254
		
255
256
257
		return 0;
	}
	
Melledy's avatar
Melledy committed
258
	public int GetRegionEntityCount(LuaTable table) {
259
260
		logger.debug("[LUA] Call GetRegionEntityCount with {}",
				table);
Melledy's avatar
Melledy committed
261
262
263
264
265
266
267
268
269
270
271
272
		int regionId = table.get("region_eid").toint();
		int entityType = table.get("entity_type").toint();

		SceneRegion region = this.getSceneScriptManager().getRegionById(regionId);
		
		if (region == null) {
			return 0;
		}

		return (int) region.getEntities().intStream().filter(e -> e >> 24 == entityType).count();
	}
	
273
	public void PrintContextLog(String msg) {
274
		logger.info("[LUA] " + msg);
275
	}
Akka's avatar
Akka committed
276

277
278
279
280
	public int TowerCountTimeStatus(int isDone, int var2){
		logger.debug("[LUA] Call TowerCountTimeStatus with {},{}",
				isDone,var2);
		// TODO record time
Akka's avatar
Akka committed
281
282
283
		return 0;
	}
	public int GetGroupMonsterCount(int var1){
284
285
286
287
		logger.debug("[LUA] Call GetGroupMonsterCount with {}",
				var1);

		return (int) getSceneScriptManager().getScene().getEntities().values().stream()
Akka's avatar
Akka committed
288
289
				.filter(e -> e instanceof EntityMonster &&
						e.getGroupId() == getCurrentGroup().map(sceneGroup -> sceneGroup.id).orElse(-1))
290
				.count();
Akka's avatar
Akka committed
291
292
	}
	public int SetMonsterBattleByGroup(int var1, int var2, int var3){
293
294
		logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}",
				var1,var2,var3);
295
		// TODO
Akka's avatar
Akka committed
296
297
298
299
		return 0;
	}

	public int CauseDungeonFail(int var1){
300
301
302
303
304
		logger.debug("[LUA] Call CauseDungeonFail with {}",
				var1);

		return 0;
	}
305

306
307
308
	public int GetGroupVariableValueByGroup(String name, int groupId){
		logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}",
				name,groupId);
309

310
		return getSceneScriptManager().getVariables().getOrDefault(name, 0);
311
312
313
314
315
316
317
318
319
320
321
322
	}

	public int SetIsAllowUseSkill(int canUse, int var2){
		logger.debug("[LUA] Call SetIsAllowUseSkill with {},{}",
				canUse,var2);

		getSceneScriptManager().getScene().broadcastPacket(new PacketCanUseSkillNotify(canUse == 1));
		return 0;
	}

	public int KillEntityByConfigId(LuaTable table){
		logger.debug("[LUA] Call KillEntityByConfigId with {}",
323
				printTable(table));
324
325
326
327
328
329
330
331
332
333
		var configId = table.get("config_id");
		if(configId == LuaValue.NIL){
			return 1;
		}

		var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint());
		if(entity == null){
			return 1;
		}
		getSceneScriptManager().getScene().killEntity(entity, 0);
Akka's avatar
Akka committed
334
335
		return 0;
	}
336

337
338
339
340
	public int SetGroupVariableValueByGroup(String key, int value, int groupId){
		logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}",
				key,value,groupId);

341
342
343
344
345
346
347
348
349
350
		getSceneScriptManager().getVariables().put(key, value);
		return 0;
	}

	public int CreateMonster(LuaTable table){
		logger.debug("[LUA] Call CreateMonster with {}",
				printTable(table));
		var configId = table.get("config_id").toint();
		var delayTime = table.get("delay_time").toint();

Akka's avatar
Akka committed
351
352
353
354
355
		if(getCurrentGroup().isEmpty()){
			return 1;
		}

		getSceneScriptManager().spawnMonstersByConfigId(getCurrentGroup().get(), configId, delayTime);
356
357
358
359
360
361
362
		return 0;
	}

	public int TowerMirrorTeamSetUp(int team, int var1) {
		logger.debug("[LUA] Call TowerMirrorTeamSetUp with {},{}",
				team,var1);

363
		getSceneScriptManager().unloadCurrentMonsterTide();
364
365
		getSceneScriptManager().getScene().getPlayers().get(0).getTowerManager().mirrorTeamSetUp(team-1);

366
367
368
		return 0;
	}

369
370
371
372
373
	public int CreateGadget(LuaTable table){
		logger.debug("[LUA] Call CreateGadget with {}",
				printTable(table));
		var configId = table.get("config_id").toint();

Akka's avatar
Akka committed
374
		var group = getCurrentGroup();
375
376
		
		if (group.isEmpty()) {
Akka's avatar
Akka committed
377
378
			return 1;
		}
379
		
Akka's avatar
Akka committed
380
381
		var gadget = group.get().gadgets.get(configId);
		var entity = getSceneScriptManager().createGadget(group.get().id, group.get().block_id, gadget);
382
		
Akka's avatar
Akka committed
383
		getSceneScriptManager().addEntity(entity);
384

Akka's avatar
Akka committed
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
		return 0;
	}
	public int CheckRemainGadgetCountByGroupId(LuaTable table){
		logger.debug("[LUA] Call CheckRemainGadgetCountByGroupId with {}",
				printTable(table));
		var groupId = table.get("group_id").toint();

		var count = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == groupId)
				.count();
		return (int)count;
	}

	public int GetGadgetStateByConfigId(int groupId, int configId){
		logger.debug("[LUA] Call GetGadgetStateByConfigId with {},{}",
				groupId, configId);
		var gadget = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == groupId)
				.filter(g -> g.getConfigId() == configId)
				.findFirst();
		if(gadget.isEmpty()){
Akka's avatar
Akka committed
406
			return 1;
Akka's avatar
Akka committed
407
		}
Akka's avatar
Akka committed
408
		return ((EntityGadget)gadget.get()).getState();
Akka's avatar
Akka committed
409
	}
Akka's avatar
Akka committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

	public int MarkPlayerAction(int var1, int var2, int var3, int var4){
		logger.debug("[LUA] Call MarkPlayerAction with {},{}",
				var1, var2);

		return 0;
	}

	public int AddQuestProgress(String var1){
		logger.debug("[LUA] Call AddQuestProgress with {}",
				var1);

		return 0;
	}

	/**
	 * change the state of gadget
	 */
	public int ChangeGroupGadget(LuaTable table){
		logger.debug("[LUA] Call ChangeGroupGadget with {}",
				printTable(table));
		var configId = table.get("config_id").toint();
		var state = table.get("state").toint();

		var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId);
		if(entity == null){
			return 1;
		}

439
440
		if (entity instanceof EntityGadget entityGadget) {
			entityGadget.updateState(state);
Akka's avatar
Akka committed
441
			return 0;
Akka's avatar
Akka committed
442
		}
Akka's avatar
Akka committed
443

Akka's avatar
Akka committed
444
		return 1;
445
	}
446
}