mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-22 20:04:56 +01:00
Continue merging quests (pt. 2)
This commit is contained in:
@@ -319,12 +319,14 @@ public class World implements Iterable<Player> {
|
||||
var newScene = this.getSceneById(teleportProperties.getSceneId());
|
||||
newScene.addPlayer(player);
|
||||
player.setAvatarsAbilityForScene(newScene);
|
||||
|
||||
// Dungeon
|
||||
// Dungeon system is handling this already
|
||||
// if(dungeonData!=null){
|
||||
// var dungeonManager = new DungeonManager(newScene, dungeonData);
|
||||
// dungeonManager.startDungeon();
|
||||
// }
|
||||
|
||||
SceneConfig config = newScene.getScriptManager().getConfig();
|
||||
if (teleportProperties.getTeleportTo() == null && config != null) {
|
||||
if (config.born_pos != null) {
|
||||
|
||||
@@ -1,153 +1,160 @@
|
||||
package emu.grasscutter.game.world;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.DataLoader;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.InvestigationMonsterData;
|
||||
import emu.grasscutter.data.excels.RewardPreviewData;
|
||||
import emu.grasscutter.data.excels.world.WorldLevelData;
|
||||
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
||||
import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler;
|
||||
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.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class WorldDataSystem extends BaseGameSystem {
|
||||
private final Map<String, ChestInteractHandler> chestInteractHandlerMap; // chestType-Handler
|
||||
private final Map<String, SceneGroup> sceneInvestigationGroupMap; // <sceneId_groupId, Group>
|
||||
|
||||
public WorldDataSystem(GameServer server) {
|
||||
super(server);
|
||||
this.chestInteractHandlerMap = new HashMap<>();
|
||||
this.sceneInvestigationGroupMap = new ConcurrentHashMap<>();
|
||||
|
||||
loadChestConfig();
|
||||
}
|
||||
|
||||
public synchronized void loadChestConfig() {
|
||||
// set the special chest first
|
||||
chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler());
|
||||
|
||||
try {
|
||||
DataLoader.loadList("ChestReward.json", ChestReward.class)
|
||||
.forEach(
|
||||
reward ->
|
||||
reward
|
||||
.getObjNames()
|
||||
.forEach(
|
||||
name ->
|
||||
chestInteractHandlerMap.computeIfAbsent(
|
||||
name, x -> new NormalChestInteractHandler(reward))));
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error("Unable to load chest reward config.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ChestInteractHandler> 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());
|
||||
}
|
||||
|
||||
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) {
|
||||
if (imd.getGroupIdList().isEmpty() || imd.getMonsterIdList().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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.setMaxBossChestNum(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();
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.game.world;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.DataLoader;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.InvestigationMonsterData;
|
||||
import emu.grasscutter.data.excels.RewardPreviewData;
|
||||
import emu.grasscutter.data.excels.world.WorldLevelData;
|
||||
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
||||
import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler;
|
||||
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.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import org.luaj.vm2.LuaError;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class WorldDataSystem extends BaseGameSystem {
|
||||
private final Map<String, ChestInteractHandler> chestInteractHandlerMap; // chestType-Handler
|
||||
private final Map<String, SceneGroup> sceneInvestigationGroupMap; // <sceneId_groupId, Group>
|
||||
|
||||
public WorldDataSystem(GameServer server) {
|
||||
super(server);
|
||||
this.chestInteractHandlerMap = new HashMap<>();
|
||||
this.sceneInvestigationGroupMap = new ConcurrentHashMap<>();
|
||||
|
||||
loadChestConfig();
|
||||
}
|
||||
|
||||
public synchronized void loadChestConfig() {
|
||||
// set the special chest first
|
||||
chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler());
|
||||
|
||||
try {
|
||||
DataLoader.loadList("ChestReward.json", ChestReward.class)
|
||||
.forEach(
|
||||
reward ->
|
||||
reward
|
||||
.getObjNames()
|
||||
.forEach(
|
||||
name ->
|
||||
chestInteractHandlerMap.computeIfAbsent(
|
||||
name, x -> new NormalChestInteractHandler(reward))));
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error("Unable to load chest reward config.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ChestInteractHandler> 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());
|
||||
}
|
||||
|
||||
private SceneGroup getInvestigationGroup(int sceneId, int groupId) {
|
||||
var key = sceneId + "_" + groupId;
|
||||
if (!sceneInvestigationGroupMap.containsKey(key)) {
|
||||
try {
|
||||
var group = SceneGroup.of(groupId).load(sceneId);
|
||||
sceneInvestigationGroupMap.putIfAbsent(key, group);
|
||||
return group;
|
||||
} catch (LuaError luaError) {
|
||||
Grasscutter.getLogger()
|
||||
.error("failed to get investigationGroup {} in scene{}:", groupId, sceneId, luaError);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (imd.getGroupIdList().isEmpty() || imd.getMonsterIdList().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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.setMaxBossChestNum(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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user