diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index a87e0e168..e23bb0f32 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -79,6 +79,7 @@ public class GameData { private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap investigationMonsterDataMap = new Int2ObjectOpenHashMap<>(); // Cache private static Map> fetters = new HashMap<>(); @@ -352,4 +353,8 @@ public class GameData { public static Int2ObjectMap getGatherDataMap() { return gatherDataMap; } + public static Int2ObjectMap getInvestigationMonsterDataMap() { + return investigationMonsterDataMap; + } + } diff --git a/src/main/java/emu/grasscutter/data/def/InvestigationMonsterData.java b/src/main/java/emu/grasscutter/data/def/InvestigationMonsterData.java new file mode 100644 index 000000000..bdfa720fb --- /dev/null +++ b/src/main/java/emu/grasscutter/data/def/InvestigationMonsterData.java @@ -0,0 +1,29 @@ +package emu.grasscutter.data.def; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Data; + +import java.util.List; + +@ResourceType(name = "InvestigationMonsterConfigData.json") +@Data +public class InvestigationMonsterData extends GameResource { + private int Id; + private int CityId; + private List MonsterIdList; + private List GroupIdList; + private int RewardPreviewId; + private String MapMarkCreateType; + private String MonsterCategory; + + @Override + public int getId() { + return this.Id; + } + + @Override + public void onLoad() { + super.onLoad(); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java index 2b1e992f4..35e1407a8 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java @@ -125,7 +125,9 @@ public class DungeonChallenge { if (this.isSuccess()) { // Call success script event - this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, null); + this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, + // TODO record the time in PARAM2 and used in action + new ScriptArgs().setParam2(100)); // Settle settle(); @@ -139,8 +141,7 @@ public class DungeonChallenge { if(!stage){ getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, - // TODO record the time in PARAM2 and used in action - new ScriptArgs(this.isSuccess() ? 1 : 0, 100)); + new ScriptArgs(this.isSuccess() ? 1 : 0)); } } diff --git a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java index 099950226..efd3289ba 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java @@ -29,6 +29,7 @@ import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo; import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGadget; import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; import emu.grasscutter.utils.Position; @@ -51,6 +52,7 @@ public class EntityGadget extends EntityBaseGadget { private int state; private int pointType; private GadgetContent content; + private SceneGadget metaGadget; public EntityGadget(Scene scene, int gadgetId, Position pos) { super(scene); @@ -99,6 +101,7 @@ public class EntityGadget extends EntityBaseGadget { public void updateState(int state){ this.setState(state); this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state)); + getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_STATE_CHANGE, new ScriptArgs(state, this.getConfigId())); } public int getPointType() { @@ -117,7 +120,15 @@ public class EntityGadget extends EntityBaseGadget { public void setContent(GadgetContent content) { this.content = this.content == null ? content : this.content; } - + + public SceneGadget getMetaGadget() { + return metaGadget; + } + + public void setMetaGadget(SceneGadget metaGadget) { + this.metaGadget = metaGadget; + } + // TODO refactor public void buildContent() { if (getContent() != null || getGadgetData() == null || getGadgetData().getType() == null) { diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java index 51dca293f..038b7d6dd 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java @@ -1,53 +1,63 @@ package emu.grasscutter.game.entity.gadget; -import java.util.Random; - import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo; +import emu.grasscutter.net.proto.InterOpTypeOuterClass; +import emu.grasscutter.net.proto.InteractTypeOuterClass; import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; import emu.grasscutter.scripts.constants.ScriptGadgetState; import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; +import static emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType.INTER_OP_START; + public class GadgetChest extends GadgetContent { public GadgetChest(EntityGadget gadget) { super(gadget); } - public boolean onInteract(Player player) { - var chestRewardMap = getGadget().getScene().getWorld().getServer().getWorldDataManager().getChestRewardMap(); - var chestReward = chestRewardMap.get(getGadget().getGadgetData().getJsonName()); - if (chestReward == null) { - Grasscutter.getLogger().warn("Could not found the config of this type of Chests {}", getGadget().getGadgetData().getJsonName()); + public boolean onInteract(Player player, InterOpTypeOuterClass.InterOpType opType) { + var chestInteractHandlerMap = getGadget().getScene().getWorld().getServer().getWorldDataManager().getChestInteractHandlerMap(); + var handler = chestInteractHandlerMap.get(getGadget().getGadgetData().getJsonName()); + if(handler == null){ + Grasscutter.getLogger().warn("Could not found the handler of this type of Chests {}", getGadget().getGadgetData().getJsonName()); + return false; + } + + if(opType == INTER_OP_START && handler.isTwoStep()){ + player.sendPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_OPEN_CHEST, INTER_OP_START)); + return false; + }else{ + var success = handler.onInteract(this, player); + if (!success){ + return false; + } + + getGadget().updateState(ScriptGadgetState.ChestOpened); + player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_OPEN_CHEST)); return true; } - - player.earnExp(chestReward.getAdvExp()); - player.getInventory().addItem(201, chestReward.getResin()); - - var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5); - player.getInventory().addItem(202, (int)mora); - - for(int i=0;i rewards = new ArrayList<>(); + for (ItemParamData param : reward.getPreviewItems()) { + rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); + } + + player.getInventory().addItems(rewards, ActionReason.OpenWorldBossChest); + player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards)); + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/chest/ChestInteractHandler.java b/src/main/java/emu/grasscutter/game/entity/gadget/chest/ChestInteractHandler.java new file mode 100644 index 000000000..4dfea36fb --- /dev/null +++ b/src/main/java/emu/grasscutter/game/entity/gadget/chest/ChestInteractHandler.java @@ -0,0 +1,11 @@ +package emu.grasscutter.game.entity.gadget.chest; + +import emu.grasscutter.game.entity.gadget.GadgetChest; +import emu.grasscutter.game.player.Player; + +public interface ChestInteractHandler { + + boolean isTwoStep(); + + boolean onInteract(GadgetChest chest, Player player); +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java b/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java new file mode 100644 index 000000000..32c50691a --- /dev/null +++ b/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java @@ -0,0 +1,42 @@ +package emu.grasscutter.game.entity.gadget.chest; + +import emu.grasscutter.game.entity.gadget.GadgetChest; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.ChestReward; + +import java.util.Random; + +public class NormalChestInteractHandler implements ChestInteractHandler { + private final ChestReward chestReward; + + public NormalChestInteractHandler(ChestReward rewardData){ + this.chestReward = rewardData; + } + + @Override + public boolean isTwoStep() { + return false; + } + + @Override + public boolean onInteract(GadgetChest chest, Player player) { + player.earnExp(chestReward.getAdvExp()); + player.getInventory().addItem(201, chestReward.getResin()); + + var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5); + player.getInventory().addItem(202, (int)mora); + + for(int i=0;i chestRewardMap; + private final Map chestInteractHandlerMap; // chestType-Handler public WorldDataManager(GameServer gameServer){ this.gameServer = gameServer; - this.chestRewardMap = new HashMap<>(); - load(); + this.chestInteractHandlerMap = new HashMap<>(); + loadChestConfig(); } - public synchronized void load(){ + public synchronized void loadChestConfig(){ + // set the special chest first + chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler()); + try(InputStream is = DataLoader.load("ChestReward.json"); InputStreamReader isr = new InputStreamReader(is)) { List chestReward = Grasscutter.getGsonFactory().fromJson( isr, TypeToken.getParameterized(List.class, ChestReward.class).getType()); chestReward.forEach(reward -> - reward.getObjNames().forEach(name -> chestRewardMap.put(name, reward))); + reward.getObjNames().forEach( + name -> chestInteractHandlerMap.putIfAbsent(name, new NormalChestInteractHandler(reward)))); + } catch (Exception e) { Grasscutter.getLogger().error("Unable to load chest reward config.", e); } } - public Map getChestRewardMap() { - return chestRewardMap; + public Map getChestInteractHandlerMap() { + return chestInteractHandlerMap; + } + + public RewardPreviewData getRewardByBossId(int monsterId){ + var investigationMonsterData = GameData.getInvestigationMonsterDataMap().values().parallelStream() + .filter(imd -> imd.getMonsterIdList() != null && !imd.getMonsterIdList().isEmpty()) + .filter(imd -> imd.getMonsterIdList().get(0) == monsterId) + .findFirst(); + + if(investigationMonsterData.isEmpty()){ + return null; + } + return GameData.getRewardPreviewDataMap().get(investigationMonsterData.get().getRewardPreviewId()); } } diff --git a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java index 5dd25a1df..055bffe33 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java @@ -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> 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; } diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index e33deb860..7e67d8862 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -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 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; } } diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneBossChest.java b/src/main/java/emu/grasscutter/scripts/data/SceneBossChest.java new file mode 100644 index 000000000..f0009eb05 --- /dev/null +++ b/src/main/java/emu/grasscutter/scripts/data/SceneBossChest.java @@ -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; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java b/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java index bdf3d55ba..ca37ac953 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java @@ -9,4 +9,5 @@ public class SceneGadget extends SceneObject{ public int gadget_id; public int state; public int point_type; + public SceneBossChest boss_chest; } diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java index c0fb9ac78..197b80848 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java @@ -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)); diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneObject.java b/src/main/java/emu/grasscutter/scripts/data/SceneObject.java index f22f530ed..eb1f42d8c 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneObject.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneObject.java @@ -16,5 +16,5 @@ public class SceneObject { /** * not set by lua */ - public transient int groupId; + public transient SceneGroup group; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java index 6c8b6515a..1fb7a641b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java @@ -13,7 +13,7 @@ public class HandlerGadgetInteractReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { GadgetInteractReq req = GadgetInteractReq.parseFrom(payload); - session.getPlayer().interactWith(req.getGadgetEntityId()); + session.getPlayer().interactWith(req.getGadgetEntityId(), req.getOpType()); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java new file mode 100644 index 000000000..e3689a094 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetInvestigationMonsterReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetInvestigationMonsterRsp; + +@Opcodes(PacketOpcodes.GetInvestigationMonsterReq) +public class HandlerGetInvestigationMonsterReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = GetInvestigationMonsterReqOuterClass.GetInvestigationMonsterReq.parseFrom(payload); + + session.send(new PacketGetInvestigationMonsterRsp(req.getCityIdListList())); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java index c5e5d723e..57e5a8412 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java @@ -4,20 +4,27 @@ import emu.grasscutter.game.entity.EntityBaseGadget; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp; +import emu.grasscutter.net.proto.InterOpTypeOuterClass; import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; import emu.grasscutter.net.proto.RetcodeOuterClass; public class PacketGadgetInteractRsp extends BasePacket { public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) { + this(gadget, interact, null); + } + public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpTypeOuterClass.InterOpType opType) { super(PacketOpcodes.GadgetInteractRsp); - GadgetInteractRsp proto = GadgetInteractRsp.newBuilder() + var proto = GadgetInteractRsp.newBuilder() .setGadgetEntityId(gadget.getId()) .setInteractType(interact) - .setGadgetId(gadget.getGadgetId()) - .build(); + .setGadgetId(gadget.getGadgetId()); + + if(opType != null){ + proto.setOpType(opType); + } - this.setData(proto); + this.setData(proto.build()); } public PacketGadgetInteractRsp() { diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java new file mode 100644 index 000000000..d6e921711 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetActivityInfoRspOuterClass; + +import java.util.List; + +public class PacketGetInvestigationMonsterRsp extends BasePacket { + + public PacketGetInvestigationMonsterRsp(List cityIdListList) { + super(PacketOpcodes.GetInvestigationMonsterRsp); + + var resp = GetActivityInfoRspOuterClass.GetActivityInfoRsp.newBuilder(); + + + + this.setData(resp.build()); + } +}