mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-23 03:37:38 +00:00
MonsterInvestigation (boss icon in map)
This commit is contained in:
parent
d1606eb7d0
commit
fe2799c1fd
@ -2,15 +2,11 @@ syntax = "proto3";
|
|||||||
|
|
||||||
option java_package = "emu.grasscutter.net.proto";
|
option java_package = "emu.grasscutter.net.proto";
|
||||||
|
|
||||||
|
// CmdId: 1902
|
||||||
|
// EnetChannelId: 0
|
||||||
|
// EnetIsReliable: true
|
||||||
|
// IsAllowClient: true
|
||||||
message GetInvestigationMonsterReq {
|
message GetInvestigationMonsterReq {
|
||||||
enum CmdId {
|
repeated uint32 city_id_list = 13;
|
||||||
option allow_alias = true;
|
bool ABFECCDJENJ = 11;
|
||||||
ENET_CHANNEL_ID = 0;
|
|
||||||
NONE = 0;
|
|
||||||
ENET_IS_RELIABLE = 1;
|
|
||||||
IS_ALLOW_CLIENT = 1;
|
|
||||||
CMD_ID = 1916;
|
|
||||||
}
|
|
||||||
|
|
||||||
repeated uint32 city_id_list = 1;
|
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,12 @@ option java_package = "emu.grasscutter.net.proto";
|
|||||||
|
|
||||||
import "InvestigationMonster.proto";
|
import "InvestigationMonster.proto";
|
||||||
|
|
||||||
|
// CmdId: 1911
|
||||||
|
// EnetChannelId: 0
|
||||||
|
// EnetIsReliable: true
|
||||||
|
// IsAllowClient: true
|
||||||
message GetInvestigationMonsterRsp {
|
message GetInvestigationMonsterRsp {
|
||||||
enum CmdId {
|
int32 retcode = 9;
|
||||||
option allow_alias = true;
|
repeated InvestigationMonster monster_list = 7;
|
||||||
ENET_CHANNEL_ID = 0;
|
bool ABFECCDJENJ = 10;
|
||||||
NONE = 0;
|
|
||||||
ENET_IS_RELIABLE = 1;
|
|
||||||
IS_ALLOW_CLIENT = 1;
|
|
||||||
CMD_ID = 1928;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 retcode = 1;
|
|
||||||
repeated InvestigationMonster monster_list = 2;
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,9 @@ syntax = "proto3";
|
|||||||
|
|
||||||
option java_package = "emu.grasscutter.net.proto";
|
option java_package = "emu.grasscutter.net.proto";
|
||||||
|
|
||||||
|
// CmdId: 3476
|
||||||
|
// EnetChannelId: 0
|
||||||
|
// EnetIsReliable: true
|
||||||
message GroupSuiteNotify {
|
message GroupSuiteNotify {
|
||||||
enum CmdId {
|
map<uint32, uint32> group_map = 11;
|
||||||
option allow_alias = true;
|
|
||||||
NONE = 0;
|
|
||||||
ENET_CHANNEL_ID = 0;
|
|
||||||
ENET_IS_RELIABLE = 1;
|
|
||||||
CMD_ID = 3098;
|
|
||||||
}
|
|
||||||
|
|
||||||
map<uint32, uint32> group_map = 1;
|
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ public class GameData {
|
|||||||
private static final Int2ObjectMap<HomeWorldLevelData> homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<HomeWorldLevelData> homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<FurnitureMakeConfigData> furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<FurnitureMakeConfigData> furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<InvestigationMonsterData> investigationMonsterDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<InvestigationMonsterData> investigationMonsterDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
private static final Int2ObjectMap<CityData> cityDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
|
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
|
||||||
@ -411,4 +412,8 @@ public class GameData {
|
|||||||
public static Int2ObjectMap<InvestigationMonsterData> getInvestigationMonsterDataMap() {
|
public static Int2ObjectMap<InvestigationMonsterData> getInvestigationMonsterDataMap() {
|
||||||
return investigationMonsterDataMap;
|
return investigationMonsterDataMap;
|
||||||
}
|
}
|
||||||
|
public static Int2ObjectMap<CityData> getCityDataMap() {
|
||||||
|
return cityDataMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
30
src/main/java/emu/grasscutter/data/excels/CityData.java
Normal file
30
src/main/java/emu/grasscutter/data/excels/CityData.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameResource;
|
||||||
|
import emu.grasscutter.data.ResourceType;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ResourceType(name = "CityConfigData.json", loadPriority = ResourceType.LoadPriority.HIGH)
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
|
public class CityData extends GameResource {
|
||||||
|
int cityId;
|
||||||
|
int sceneId;
|
||||||
|
List<Integer> areaIdVec;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return this.cityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
super.onLoad();
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,28 @@
|
|||||||
package emu.grasscutter.data.excels;
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.GameResource;
|
import emu.grasscutter.data.GameResource;
|
||||||
import emu.grasscutter.data.ResourceType;
|
import emu.grasscutter.data.ResourceType;
|
||||||
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ResourceType(name = "InvestigationMonsterConfigData.json")
|
@ResourceType(name = "InvestigationMonsterConfigData.json", loadPriority = ResourceType.LoadPriority.LOW)
|
||||||
@Data
|
@Getter
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
public class InvestigationMonsterData extends GameResource {
|
public class InvestigationMonsterData extends GameResource {
|
||||||
private int id;
|
int id;
|
||||||
private int cityId;
|
int cityId;
|
||||||
private List<Integer> monsterIdList;
|
List<Integer> monsterIdList;
|
||||||
private List<Integer> groupIdList;
|
List<Integer> groupIdList;
|
||||||
private int rewardPreviewId;
|
int rewardPreviewId;
|
||||||
private String mapMarkCreateType;
|
String mapMarkCreateType;
|
||||||
private String monsterCategory;
|
String monsterCategory;
|
||||||
|
|
||||||
|
CityData cityData;
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
@ -24,6 +30,6 @@ public class InvestigationMonsterData extends GameResource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
super.onLoad();
|
this.cityData = GameData.getCityDataMap().get(cityId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,16 @@ import com.google.gson.reflect.TypeToken;
|
|||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
import emu.grasscutter.data.DataLoader;
|
import emu.grasscutter.data.DataLoader;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.data.excels.InvestigationMonsterData;
|
||||||
import emu.grasscutter.data.excels.RewardPreviewData;
|
import emu.grasscutter.data.excels.RewardPreviewData;
|
||||||
|
import emu.grasscutter.data.excels.WorldLevelData;
|
||||||
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
||||||
import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler;
|
import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler;
|
||||||
import emu.grasscutter.game.entity.gadget.chest.NormalChestInteractHandler;
|
import emu.grasscutter.game.entity.gadget.chest.NormalChestInteractHandler;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.net.proto.InvestigationMonsterOuterClass;
|
||||||
|
import emu.grasscutter.scripts.data.SceneGroup;
|
||||||
|
import emu.grasscutter.scripts.data.SceneMonster;
|
||||||
import emu.grasscutter.server.game.GameServer;
|
import emu.grasscutter.server.game.GameServer;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -15,14 +21,19 @@ import java.io.InputStreamReader;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class WorldDataManager {
|
public class WorldDataManager {
|
||||||
private final GameServer gameServer;
|
private final GameServer gameServer;
|
||||||
private final Map<String, ChestInteractHandler> chestInteractHandlerMap; // chestType-Handler
|
private final Map<String, ChestInteractHandler> chestInteractHandlerMap; // chestType-Handler
|
||||||
|
private final Map<String, SceneGroup> sceneInvestigationGroupMap; // <sceneId_groupId, Group>
|
||||||
|
|
||||||
public WorldDataManager(GameServer gameServer){
|
public WorldDataManager(GameServer gameServer){
|
||||||
this.gameServer = gameServer;
|
this.gameServer = gameServer;
|
||||||
this.chestInteractHandlerMap = new HashMap<>();
|
this.chestInteractHandlerMap = new HashMap<>();
|
||||||
|
this.sceneInvestigationGroupMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
loadChestConfig();
|
loadChestConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,4 +70,80 @@ public class WorldDataManager {
|
|||||||
}
|
}
|
||||||
return GameData.getRewardPreviewDataMap().get(investigationMonsterData.get().getRewardPreviewId());
|
return GameData.getRewardPreviewDataMap().get(investigationMonsterData.get().getRewardPreviewId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SceneGroup getInvestigationGroup(int sceneId, int groupId){
|
||||||
|
var key = sceneId + "_" + groupId;
|
||||||
|
if(!sceneInvestigationGroupMap.containsKey(key)){
|
||||||
|
var group = SceneGroup.of(groupId).load(sceneId);
|
||||||
|
sceneInvestigationGroupMap.putIfAbsent(key, group);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
return sceneInvestigationGroupMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMonsterLevel(SceneMonster monster, World world){
|
||||||
|
// Calculate level
|
||||||
|
int level = monster.level;
|
||||||
|
WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(world.getWorldLevel());
|
||||||
|
|
||||||
|
if (worldLevelData != null) {
|
||||||
|
level = worldLevelData.getMonsterLevel();
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
private InvestigationMonsterOuterClass.InvestigationMonster getInvestigationMonster(Player player, InvestigationMonsterData imd) {
|
||||||
|
var groupId = imd.getGroupIdList().get(0);
|
||||||
|
var monsterId = imd.getMonsterIdList().get(0);
|
||||||
|
var sceneId = imd.getCityData().getSceneId();
|
||||||
|
var group = getInvestigationGroup(sceneId, groupId);
|
||||||
|
|
||||||
|
if(group == null || group.monsters == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var monster = group.monsters.values().stream()
|
||||||
|
.filter(x -> x.monster_id == monsterId)
|
||||||
|
.findFirst();
|
||||||
|
if(monster.isEmpty()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = InvestigationMonsterOuterClass.InvestigationMonster.newBuilder();
|
||||||
|
|
||||||
|
builder.setId(imd.getId())
|
||||||
|
.setCityId(imd.getCityId())
|
||||||
|
.setSceneId(imd.getCityData().getSceneId())
|
||||||
|
.setGroupId(groupId)
|
||||||
|
.setMonsterId(monsterId)
|
||||||
|
.setLevel(getMonsterLevel(monster.get(), player.getWorld()))
|
||||||
|
.setIsAlive(true)
|
||||||
|
.setNextRefreshTime(Integer.MAX_VALUE)
|
||||||
|
.setRefreshInterval(Integer.MAX_VALUE)
|
||||||
|
.setPos(monster.get().pos.toProto());
|
||||||
|
|
||||||
|
if("Boss".equals(imd.getMonsterCategory())){
|
||||||
|
var bossChest = group.searchBossChestInGroup();
|
||||||
|
if(bossChest.isPresent()){
|
||||||
|
builder.setResin(bossChest.get().resin);
|
||||||
|
builder.setBossChestNum(bossChest.get().take_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InvestigationMonsterOuterClass.InvestigationMonster> getInvestigationMonstersByCityId(Player player, int cityId){
|
||||||
|
var cityData = GameData.getCityDataMap().get(cityId);
|
||||||
|
if(cityData == null){
|
||||||
|
Grasscutter.getLogger().warn("City not exist {}", cityId);
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
return GameData.getInvestigationMonsterDataMap().values()
|
||||||
|
.parallelStream()
|
||||||
|
.filter(imd -> imd.getCityId() == cityId)
|
||||||
|
.map(imd -> this.getInvestigationMonster(player, imd))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static emu.grasscutter.Configuration.SCRIPT;
|
import static emu.grasscutter.Configuration.SCRIPT;
|
||||||
@ -165,4 +166,12 @@ public class SceneGroup {
|
|||||||
Grasscutter.getLogger().info("group {} in scene {} is loaded successfully.", id, sceneId);
|
Grasscutter.getLogger().info("group {} in scene {} is loaded successfully.", id, sceneId);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<SceneBossChest> searchBossChestInGroup() {
|
||||||
|
return gadgets.values().stream()
|
||||||
|
.filter(g -> g.boss_chest != null && g.boss_chest.monster_config_id > 0)
|
||||||
|
.map(g -> g.boss_chest)
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,11 @@ public class HandlerGetInvestigationMonsterReq extends PacketHandler {
|
|||||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
var req = GetInvestigationMonsterReqOuterClass.GetInvestigationMonsterReq.parseFrom(payload);
|
var req = GetInvestigationMonsterReqOuterClass.GetInvestigationMonsterReq.parseFrom(payload);
|
||||||
|
|
||||||
session.send(new PacketGetInvestigationMonsterRsp(req.getCityIdListList()));
|
session.send(new PacketGetInvestigationMonsterRsp(
|
||||||
|
session.getPlayer(),
|
||||||
|
session.getServer().getWorldDataManager(),
|
||||||
|
req.getCityIdListList()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
package emu.grasscutter.server.packet.send;
|
package emu.grasscutter.server.packet.send;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.world.WorldDataManager;
|
||||||
import emu.grasscutter.net.packet.BasePacket;
|
import emu.grasscutter.net.packet.BasePacket;
|
||||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
import emu.grasscutter.net.proto.GetActivityInfoRspOuterClass;
|
import emu.grasscutter.net.proto.GetActivityInfoRspOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.GetInvestigationMonsterRspOuterClass;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PacketGetInvestigationMonsterRsp extends BasePacket {
|
public class PacketGetInvestigationMonsterRsp extends BasePacket {
|
||||||
|
|
||||||
public PacketGetInvestigationMonsterRsp(List<Integer> cityIdListList) {
|
public PacketGetInvestigationMonsterRsp(Player player, WorldDataManager worldDataManager, List<Integer> cityIdListList) {
|
||||||
|
|
||||||
super(PacketOpcodes.GetInvestigationMonsterRsp);
|
super(PacketOpcodes.GetInvestigationMonsterRsp);
|
||||||
|
|
||||||
var resp = GetActivityInfoRspOuterClass.GetActivityInfoRsp.newBuilder();
|
var resp = GetInvestigationMonsterRspOuterClass.GetInvestigationMonsterRsp.newBuilder();
|
||||||
|
|
||||||
|
cityIdListList.forEach(id -> resp.addAllMonsterList(worldDataManager.getInvestigationMonstersByCityId(player, id)));
|
||||||
|
|
||||||
|
|
||||||
this.setData(resp.build());
|
this.setData(resp.build());
|
||||||
|
Loading…
Reference in New Issue
Block a user