mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-16 17:05:20 +01:00
Support Boss Chest
This commit is contained in:
@@ -14,6 +14,7 @@ import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.*;
|
||||
import emu.grasscutter.scripts.service.ScriptMonsterSpawnService;
|
||||
import emu.grasscutter.scripts.service.ScriptMonsterTideService;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.luaj.vm2.LuaError;
|
||||
@@ -21,6 +22,10 @@ import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SceneScriptManager {
|
||||
private final Scene scene;
|
||||
@@ -43,6 +48,12 @@ public class SceneScriptManager {
|
||||
* blockid - loaded groupSet
|
||||
*/
|
||||
private Int2ObjectMap<Set<SceneGroup>> loadedGroupSetPerBlock;
|
||||
public static final ExecutorService eventExecutor;
|
||||
static {
|
||||
eventExecutor = new ThreadPoolExecutor(4, 4,
|
||||
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100),
|
||||
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy());
|
||||
}
|
||||
public SceneScriptManager(Scene scene) {
|
||||
this.scene = scene;
|
||||
this.triggers = new HashMap<>();
|
||||
@@ -211,7 +222,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
var toCreate = gadgets.stream()
|
||||
.map(g -> createGadget(g.groupId, group.block_id, g))
|
||||
.map(g -> createGadget(g.group.id, group.block_id, g))
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
this.addEntities(toCreate);
|
||||
@@ -254,8 +265,17 @@ public class SceneScriptManager {
|
||||
getScene().addEntity(createMonster(group.id, group.block_id, group.monsters.get(configId)));
|
||||
}
|
||||
// Events
|
||||
|
||||
public void callEvent(int eventType, ScriptArgs params) {
|
||||
public void callEvent(int eventType, ScriptArgs params){
|
||||
/**
|
||||
* We use ThreadLocal to trans SceneScriptManager context to ScriptLib, to avoid eval script for every groups' trigger in every scene instances.
|
||||
* But when callEvent is called in a ScriptLib func, it may cause NPE because the inner call cleans the ThreadLocal so that outer call could not get it.
|
||||
* e.g. CallEvent -> set -> ScriptLib.xxx -> CallEvent -> set -> remove -> NPE -> (remove)
|
||||
* So we use thread pool to clean the stack to avoid this new issue.
|
||||
*/
|
||||
eventExecutor.submit(() -> this.realCallEvent(eventType, params));
|
||||
}
|
||||
|
||||
private void realCallEvent(int eventType, ScriptArgs params) {
|
||||
try{
|
||||
ScriptLoader.getScriptLib().setSceneScriptManager(this);
|
||||
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) {
|
||||
@@ -282,7 +302,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
}
|
||||
|
||||
public LuaValue callScriptFunc(String funcName, SceneGroup group, ScriptArgs params){
|
||||
private LuaValue callScriptFunc(String funcName, SceneGroup group, ScriptArgs params){
|
||||
LuaValue funcLua = null;
|
||||
if (funcName != null && !funcName.isEmpty()) {
|
||||
funcLua = (LuaValue) group.getBindings().get(funcName);
|
||||
@@ -332,10 +352,8 @@ public class SceneScriptManager {
|
||||
entity.getRotation().set(g.rot);
|
||||
entity.setState(g.state);
|
||||
entity.setPointType(g.point_type);
|
||||
entity.setMetaGadget(g);
|
||||
entity.buildContent();
|
||||
|
||||
// Lua event
|
||||
this.callEvent(EventType.EVENT_GADGET_CREATE, new ScriptArgs(entity.getConfigId()));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import emu.grasscutter.game.entity.gadget.GadgetWorktop;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify;
|
||||
import io.netty.util.concurrent.FastThreadLocal;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
@@ -16,7 +15,6 @@ import org.luaj.vm2.LuaValue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ScriptLib {
|
||||
@@ -68,34 +66,24 @@ public class ScriptLib {
|
||||
if (entity.isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(entity.get() instanceof EntityGadget)) {
|
||||
return 1;
|
||||
|
||||
if (entity.get() instanceof EntityGadget entityGadget) {
|
||||
entityGadget.updateState(gadgetState);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EntityGadget gadget = (EntityGadget) entity.get();
|
||||
gadget.setState(gadgetState);
|
||||
|
||||
getSceneScriptManager().getScene().broadcastPacket(new PacketGadgetStateNotify(gadget, gadgetState));
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) {
|
||||
logger.debug("[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}",
|
||||
groupId,configId,gadgetState);
|
||||
List<GameEntity> list = getSceneScriptManager().getScene().getEntities().values().stream()
|
||||
.filter(e -> e.getGroupId() == groupId).toList();
|
||||
|
||||
for (GameEntity entity : list) {
|
||||
if (!(entity instanceof EntityGadget)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityGadget gadget = (EntityGadget) entity;
|
||||
gadget.setState(gadgetState);
|
||||
|
||||
getSceneScriptManager().getScene().broadcastPacket(new PacketGadgetStateNotify(gadget, gadgetState));
|
||||
}
|
||||
|
||||
getSceneScriptManager().getScene().getEntities().values().stream()
|
||||
.filter(e -> e.getGroupId() == groupId)
|
||||
.filter(e -> e instanceof EntityGadget)
|
||||
.map(e -> (EntityGadget)e)
|
||||
.forEach(e -> e.updateState(gadgetState));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -450,8 +438,9 @@ public class ScriptLib {
|
||||
|
||||
if (entity instanceof EntityGadget entityGadget) {
|
||||
entityGadget.updateState(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Setter
|
||||
@ToString
|
||||
public class SceneBossChest {
|
||||
public int life_time;
|
||||
public int monster_config_id;
|
||||
public int resin;
|
||||
public int take_num;
|
||||
}
|
||||
@@ -9,4 +9,5 @@ public class SceneGadget extends SceneObject{
|
||||
public int gadget_id;
|
||||
public int state;
|
||||
public int point_type;
|
||||
public SceneBossChest boss_chest;
|
||||
}
|
||||
|
||||
@@ -98,11 +98,11 @@ public class SceneGroup {
|
||||
// Set
|
||||
monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, bindings.get("monsters")).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y));
|
||||
monsters.values().forEach(m -> m.groupId = id);
|
||||
monsters.values().forEach(m -> m.group = this);
|
||||
|
||||
gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, bindings.get("gadgets")).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y));
|
||||
gadgets.values().forEach(m -> m.groupId = id);
|
||||
gadgets.values().forEach(m -> m.group = this);
|
||||
|
||||
triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, bindings.get("triggers")).stream()
|
||||
.collect(Collectors.toMap(x -> x.name, y -> y));
|
||||
|
||||
@@ -16,5 +16,5 @@ public class SceneObject {
|
||||
/**
|
||||
* not set by lua
|
||||
*/
|
||||
public transient int groupId;
|
||||
public transient SceneGroup group;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user