ScriptLib.java 14.8 KB
Newer Older
1
2
package emu.grasscutter.scripts;

Akka's avatar
Akka committed
3
import emu.grasscutter.game.dungeons.challenge.DungeonChallenge;
4
5
6
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;
Akka's avatar
Akka committed
8
import emu.grasscutter.game.dungeons.challenge.factory.ChallengeFactory;
9
import emu.grasscutter.scripts.data.SceneGroup;
Melledy's avatar
Melledy committed
10
import emu.grasscutter.scripts.data.SceneRegion;
11
import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify;
12
import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify;
13
import io.netty.util.concurrent.FastThreadLocal;
14
15
16
17
18
19
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
20
21

public class ScriptLib {
22
	public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class);
23
24
25
26
27
28
29
30
31
32
33
34
35
	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();
36
37
38
	}

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

	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
52
53
54
55
	public void setCurrentGroup(SceneGroup currentGroup){
		this.currentGroup.set(currentGroup);
	}
	public Optional<SceneGroup> getCurrentGroup(){
56
		return Optional.of(this.currentGroup.get());
Akka's avatar
Akka committed
57
58
59
60
	}
	public void removeCurrentGroup(){
		this.currentGroup.remove();
	}
61
	public int SetGadgetStateByConfigId(int configId, int gadgetState) {
62
63
		logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}",
				configId,gadgetState);
64
65
66
67
68
69
		Optional<GameEntity> entity = getSceneScriptManager().getScene().getEntities().values().stream()
				.filter(e -> e.getConfigId() == configId).findFirst();

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

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

		return 1;
77
78
79
	}

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

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

Melledy's avatar
Melledy committed
99
100

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

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

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

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

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

		if (!(gadget.getContent() instanceof GadgetWorktop worktop)) {
130
131
132
			return 1;
		}
		
Melledy's avatar
Melledy committed
133
		worktop.removeWorktopOption(option);
134
		getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget));
Melledy's avatar
Melledy committed
135
		
136
137
138
139
		return 0;
	}
	
	// Some fields are guessed
140
141
142
143
	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);

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

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

150
		this.getSceneScriptManager().startMonsterTideInGroup(group, ordersConfigId, tideCount, sceneLimit);
151
152
153
154
		
		return 0;
	}
	
155
	public int AddExtraGroupSuite(int groupId, int suite) {
156
157
		logger.debug("[LUA] Call AddExtraGroupSuite with {},{}",
				groupId,suite);
Melledy's avatar
Melledy committed
158
159
160
161
162
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
		
		if (group == null || group.monsters == null) {
			return 1;
		}
Akka's avatar
Akka committed
163
164
165
166
		var suiteData = group.getSuiteByIndex(suite);
		if(suiteData == null){
			return 1;
		}
167
168
169
170
171
172
		// avoid spawn wrong monster
		if(getSceneScriptManager().getScene().getChallenge() != null)
			if(!getSceneScriptManager().getScene().getChallenge().inProgress() ||
					getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId){
			return 0;
		}
Akka's avatar
Akka committed
173
174
		this.getSceneScriptManager().addGroupSuite(group, suiteData);

Melledy's avatar
Melledy committed
175
176
		return 0;
	}
Akka's avatar
Akka committed
177
178
179
	public int GoToGroupSuite(int groupId, int suite) {
		logger.debug("[LUA] Call GoToGroupSuite with {},{}",
				groupId,suite);
180
		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
Akka's avatar
Akka committed
181
182
183
184
185
186
187
		if (group == null || group.monsters == null) {
			return 1;
		}
		var suiteData = group.getSuiteByIndex(suite);
		if(suiteData == null){
			return 1;
		}
188

Akka's avatar
Akka committed
189
190
191
192
193
		for(var suiteItem : group.suites){
			if(suiteData == suiteItem){
				continue;
			}
			this.getSceneScriptManager().removeGroupSuite(group, suiteItem);
194
		}
Akka's avatar
Akka committed
195
196
197
198
199
200
201
202
203
		this.getSceneScriptManager().addGroupSuite(group, suiteData);

		return 0;
	}
	public int RemoveExtraGroupSuite(int groupId, int suite) {
		logger.debug("[LUA] Call RemoveExtraGroupSuite with {},{}",
				groupId,suite);

		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
204
205
206
		if (group == null || group.monsters == null) {
			return 1;
		}
Akka's avatar
Akka committed
207
208
209
210
		var suiteData = group.getSuiteByIndex(suite);
		if(suiteData == null){
			return 1;
		}
211

Akka's avatar
Akka committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
		this.getSceneScriptManager().removeGroupSuite(group, suiteData);

		return 0;
	}
	public int KillExtraGroupSuite(int groupId, int suite) {
		logger.debug("[LUA] Call KillExtraGroupSuite with {},{}",
				groupId,suite);

		SceneGroup group = getSceneScriptManager().getGroupById(groupId);
		if (group == null || group.monsters == null) {
			return 1;
		}
		var suiteData = group.getSuiteByIndex(suite);
		if(suiteData == null){
			return 1;
227
228
		}

Akka's avatar
Akka committed
229
		this.getSceneScriptManager().removeGroupSuite(group, suiteData);
230

Akka's avatar
Akka committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
		return 0;
	}
	// param3 (probably time limit for timed dungeons)
	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);

		var challenge = ChallengeFactory.getChallenge(
				challengeId,
				challengeIndex,
				timeLimitOrGroupId,
				groupId,
				objectiveKills,
				param5,
				getSceneScriptManager().getScene(),
				getCurrentGroup().get()
				);

		if(challenge == null){
			return 1;
		}
252

Akka's avatar
Akka committed
253
254
255
256
257
258
		if(challenge instanceof DungeonChallenge dungeonChallenge){
			// set if tower first stage (6-1)
			dungeonChallenge.setStage(getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0);
		}

		getSceneScriptManager().getScene().setChallenge(challenge);
259
260
261
262
		challenge.start();
		return 0;
	}
	
263
	public int GetGroupMonsterCountByGroupId(int groupId) {
264
265
		logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}",
				groupId);
266
267
268
269
270
		return (int) getSceneScriptManager().getScene().getEntities().values().stream()
								.filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId)
								.count();
	}
	
Melledy's avatar
Melledy committed
271
	public int GetGroupVariableValue(String var) {
272
273
		logger.debug("[LUA] Call GetGroupVariableValue with {}",
				var);
Melledy's avatar
Melledy committed
274
		return getSceneScriptManager().getVariables().getOrDefault(var, 0);
275
276
	}
	
277
	public int SetGroupVariableValue(String var, int value) {
278
279
		logger.debug("[LUA] Call SetGroupVariableValue with {},{}",
				var, value);
280
		getSceneScriptManager().getVariables().put(var, value);
281
282
283
284
		return 0;
	}
	
	public LuaValue ChangeGroupVariableValue(String var, int value) {
285
286
287
		logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}",
				var, value);

288
		getSceneScriptManager().getVariables().put(var, getSceneScriptManager().getVariables().get(var) + value);
289
290
		return LuaValue.ZERO;
	}
291
292
293
294

	/**
	 * Set the actions and triggers to designated group
	 */
295
	public int RefreshGroup(LuaTable table) {
296
		logger.debug("[LUA] Call RefreshGroup with {}",
297
				printTable(table));
298
299
300
301
302
303
304
305
306
307
		// 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;
		}
		
308
		getSceneScriptManager().refreshGroup(group, suite);
309
		
310
311
312
		return 0;
	}
	
Melledy's avatar
Melledy committed
313
	public int GetRegionEntityCount(LuaTable table) {
314
		logger.debug("[LUA] Call GetRegionEntityCount with {}",
Akka's avatar
Akka committed
315
				printTable(table));
Melledy's avatar
Melledy committed
316
317
318
319
320
321
322
323
324
325
326
327
		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();
	}
	
328
	public void PrintContextLog(String msg) {
329
		logger.info("[LUA] " + msg);
330
	}
Akka's avatar
Akka committed
331

332
333
334
335
	public int TowerCountTimeStatus(int isDone, int var2){
		logger.debug("[LUA] Call TowerCountTimeStatus with {},{}",
				isDone,var2);
		// TODO record time
Akka's avatar
Akka committed
336
337
		return 0;
	}
Akka's avatar
Akka committed
338
339
	public int GetGroupMonsterCount(){
		logger.debug("[LUA] Call GetGroupMonsterCount ");
340
341

		return (int) getSceneScriptManager().getScene().getEntities().values().stream()
Akka's avatar
Akka committed
342
343
				.filter(e -> e instanceof EntityMonster &&
						e.getGroupId() == getCurrentGroup().map(sceneGroup -> sceneGroup.id).orElse(-1))
344
				.count();
Akka's avatar
Akka committed
345
346
	}
	public int SetMonsterBattleByGroup(int var1, int var2, int var3){
347
348
		logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}",
				var1,var2,var3);
349
		// TODO
Akka's avatar
Akka committed
350
351
352
353
		return 0;
	}

	public int CauseDungeonFail(int var1){
354
355
356
357
358
		logger.debug("[LUA] Call CauseDungeonFail with {}",
				var1);

		return 0;
	}
359

360
361
362
	public int GetGroupVariableValueByGroup(String name, int groupId){
		logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}",
				name,groupId);
363

364
		return getSceneScriptManager().getVariables().getOrDefault(name, 0);
365
366
367
368
369
370
371
372
373
374
375
376
	}

	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 {}",
377
				printTable(table));
378
379
380
381
382
383
384
		var configId = table.get("config_id");
		if(configId == LuaValue.NIL){
			return 1;
		}

		var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint());
		if(entity == null){
Akka's avatar
Akka committed
385
			return 0;
386
387
		}
		getSceneScriptManager().getScene().killEntity(entity, 0);
Akka's avatar
Akka committed
388
389
		return 0;
	}
390

391
392
393
394
	public int SetGroupVariableValueByGroup(String key, int value, int groupId){
		logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}",
				key,value,groupId);

395
396
397
398
399
400
401
402
403
404
		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
405
406
407
408
409
		if(getCurrentGroup().isEmpty()){
			return 1;
		}

		getSceneScriptManager().spawnMonstersByConfigId(getCurrentGroup().get(), configId, delayTime);
410
411
412
413
414
415
416
		return 0;
	}

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

417
		getSceneScriptManager().unloadCurrentMonsterTide();
418
419
		getSceneScriptManager().getScene().getPlayers().get(0).getTowerManager().mirrorTeamSetUp(team-1);

420
421
422
		return 0;
	}

423
424
425
426
427
	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
428
		var group = getCurrentGroup();
429
430
		
		if (group.isEmpty()) {
Akka's avatar
Akka committed
431
432
			return 1;
		}
433
		
Akka's avatar
Akka committed
434
435
		var gadget = group.get().gadgets.get(configId);
		var entity = getSceneScriptManager().createGadget(group.get().id, group.get().block_id, gadget);
436
		
Akka's avatar
Akka committed
437
		getSceneScriptManager().addEntity(entity);
438

Akka's avatar
Akka committed
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
		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);
Akka's avatar
Akka committed
455
456
457
458
459

		if(groupId == 0){
			groupId = getCurrentGroup().get().id;
		}
		final int realGroupId = groupId;
Akka's avatar
Akka committed
460
		var gadget = getSceneScriptManager().getScene().getEntities().values().stream()
Akka's avatar
Akka committed
461
				.filter(g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == realGroupId)
Akka's avatar
Akka committed
462
463
464
				.filter(g -> g.getConfigId() == configId)
				.findFirst();
		if(gadget.isEmpty()){
Akka's avatar
Akka committed
465
			return 1;
Akka's avatar
Akka committed
466
		}
Akka's avatar
Akka committed
467
		return ((EntityGadget)gadget.get()).getState();
Akka's avatar
Akka committed
468
	}
Akka's avatar
Akka committed
469
470

	public int MarkPlayerAction(int var1, int var2, int var3, int var4){
Akka's avatar
Akka committed
471
472
		logger.debug("[LUA] Call MarkPlayerAction with {},{},{},{}",
				var1, var2,var3,var4);
Akka's avatar
Akka committed
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

		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;
		}

498
499
		if (entity instanceof EntityGadget entityGadget) {
			entityGadget.updateState(state);
Akka's avatar
Akka committed
500
			return 0;
Akka's avatar
Akka committed
501
		}
Akka's avatar
Akka committed
502

Akka's avatar
Akka committed
503
		return 1;
504
	}
505
}